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