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