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