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