]> www.ginac.de Git - cln.git/blob - src/rational/input/cl_RA_read_stream.cc
* */*: Removed problematic stdin, stdout and stderr definitions.
[cln.git] / src / rational / input / cl_RA_read_stream.cc
1 // read_rational().
2 // This file contains a slimmed down version of read_real().
3 // It does not pull in all the floating-point, complex and transcendental
4 // function code.
5
6 // General includes.
7 #include "cl_sysdep.h"
8
9 // Specification.
10 #include "cln/rational_io.h"
11
12
13 // Implementation.
14
15 #include "cln/input.h"
16 #include "cln/io.h"
17 #include "cl_spushstring.h"
18
19 namespace cln {
20
21 // We read an entire token (or even more, if it begins with #C) into a
22 // buffer and then call read_rational() on the buffer.
23
24 class pushstring_hack : public cl_spushstring {
25 public:
26         char* start_pointer (void) { return buffer; }
27         char* end_pointer (void) { return buffer+index; }
28 };
29
30 static cl_boolean number_char_p (char c)
31 {
32         if ((c >= '0') && (c <= '9'))
33                 return cl_true;
34         if (((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z')))
35                 return cl_true;
36         switch (c) {
37                 case '+': case '-': case '.': case '_': case '/':
38                         return cl_true;
39                 default:
40                         return cl_false;
41         }
42 }
43
44 const cl_RA read_rational (cl_istream stream, const cl_read_flags& flags)
45 {
46         // One pre-allocated buffer. This reduces the allocation/free cost.
47         static pushstring_hack buffer;
48
49         var int c;
50         // Skip whitespace at the beginning.
51         loop {
52                 c = freadchar(stream);
53                 if (c == cl_EOF) goto eof;
54                 if ((c == ' ') || (c == '\t') || (c == '\n'))
55                         continue;
56                 else
57                         break;
58         }
59         // Found first non-whitespace character.
60         // Numbers cannot cross lines. We can treat EOF and '\n' the same way.
61         buffer.reset();
62         if (c == '#') {
63                 if (!(flags.lsyntax & lsyntax_commonlisp))
64                         goto syntax1;
65                 buffer.push(c);
66                 // Read some digits, then a letter, then a token.
67                 loop {
68                         c = freadchar(stream);
69                         if (c == cl_EOF) goto eof;
70                         buffer.push(c);
71                         if ((c >= '0') && (c <= '9'))
72                                 continue;
73                         else
74                                 break;
75                 }
76                 if (!(((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z'))))
77                         goto syntax1;
78                 buffer.push(c);
79                 c = freadchar(stream);
80                 if (c == cl_EOF) goto eof;
81         }
82         // Read a number token.
83         if (!number_char_p(c))
84                 goto syntax1;
85         loop {
86                 buffer.push(c);
87                 c = freadchar(stream);
88                 if (c == cl_EOF)
89                         break;
90                 if (!number_char_p(c)) {
91                         funreadchar(stream,c);
92                         break;
93                 }
94         }
95         // Parse the number.
96         return read_rational(flags,
97                              buffer.start_pointer(), buffer.end_pointer(),
98                              NULL
99                             );
100
101         // Handle syntax error.
102 syntax1:        buffer.push(c);
103         read_number_bad_syntax(buffer.start_pointer(),buffer.end_pointer());
104
105         // Handle premature EOF.
106 eof:    read_number_eof();
107 }
108
109 }  // namespace cln