1 /********************************************************************/
2 /* */
3 /* s7 Seed7 interpreter */
4 /* Copyright (C) 1990 - 2000 Thomas Mertes */
5 /* */
6 /* This program is free software; you can redistribute it and/or */
7 /* modify it under the terms of the GNU General Public License as */
8 /* published by the Free Software Foundation; either version 2 of */
9 /* the License, or (at your option) any later version. */
10 /* */
11 /* This program is distributed in the hope that it will be useful, */
12 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
13 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
14 /* GNU General Public License for more details. */
15 /* */
16 /* You should have received a copy of the GNU General Public */
17 /* License along with this program; if not, write to the */
18 /* Free Software Foundation, Inc., 51 Franklin Street, */
19 /* Fifth Floor, Boston, MA 02110-1301, USA. */
20 /* */
21 /* Module: Analyzer - Scanner */
22 /* File: seed7/src/numlit.c */
23 /* Changes: 1990, 1991, 1992, 1993, 1994 Thomas Mertes */
24 /* Content: Read the next number from the source file. */
25 /* */
26 /********************************************************************/
27
28 #define LOG_FUNCTIONS 0
29 #define VERBOSE_EXCEPTIONS 0
30
31 #include "version.h"
32
33 #include "stdlib.h"
34 #include "stdio.h"
35 #include "string.h"
36
37 #include "common.h"
38 #include "data.h"
39 #include "chclsutl.h"
40 #include "identutl.h"
41 #include "error.h"
42 #include "symbol.h"
43 #include "infile.h"
44 #include "stat.h"
45 #include "findid.h"
46 #include "big_drv.h"
47
48 #undef EXTERN
49 #define EXTERN
50 #include "numlit.h"
51
52
53
readDecimal(register sySizeType position)54 static void readDecimal (register sySizeType position)
55
56 {
57 register int character;
58
59 /* readDecimal */
60 logFunction(printf("readDecimal\n"););
61 check_symb_length(position);
62 symbol.name[position++] = (ucharType) in_file.character;
63 while (char_class(character = next_character()) == DIGITCHAR) {
64 check_symb_length(position);
65 symbol.name[position++] = (ucharType) character;
66 } /* while */
67 symbol.name[position] = '\0';
68 in_file.character = character;
69 logFunction(printf("readDecimal -->\n"););
70 } /* readDecimal */
71
72
73
decimalValue(const const_ustriType digits)74 static uintType decimalValue (const const_ustriType digits)
75
76 {
77 boolType tooBig = FALSE;
78 unsigned int position = 0;
79 uintType digitval;
80 uintType uintValue = 0;
81
82 /* decimalValue */
83 logFunction(printf("decimalValue(\"%s\")\n", digits););
84 while (digits[position] != '\0') {
85 digitval = ((uintType) digits[position]) - ((uintType) '0');
86 if (unlikely(uintValue > MAX_DIV_10)) {
87 tooBig = TRUE;
88 } else {
89 uintValue = ((uintType) 10) * uintValue + digitval;
90 } /* if */
91 position++;
92 } /* while */
93 if (unlikely(tooBig || uintValue > (uintType) INTTYPE_MAX)) {
94 err_string(CARD_DECIMAL_TOO_BIG, digits);
95 uintValue = 0;
96 } /* if */
97 logFunction(printf("decimalValue --> " FMT_U "\n",
98 uintValue););
99 return uintValue;
100 } /* decimalValue */
101
102
103
basedValue(const uintType base,const const_ustriType digits)104 static inline intType basedValue (const uintType base, const const_ustriType digits)
105
106 {
107 boolType illegalDigit = FALSE;
108 boolType tooBig = FALSE;
109 uintType max_div_base;
110 unsigned int position = 0;
111 uintType digitval;
112 uintType uintValue = 0;
113
114 /* basedValue */
115 logFunction(printf("basedValue(" FMT_U ", \"%s\")\n",
116 base, digits););
117 max_div_base = (uintType) INTTYPE_MAX / base;
118 while (digits[position] != '\0') {
119 digitval = digit_value[(int) digits[position]];
120 if (unlikely(digitval >= base)) {
121 if (!illegalDigit) {
122 err_num_stri(ILLEGALBASEDDIGIT, (int) digits[position], (int) base, digits);
123 illegalDigit = TRUE;
124 } /* if */
125 } else if (unlikely(uintValue > max_div_base)) {
126 tooBig = TRUE;
127 } else {
128 uintValue = base * uintValue + digitval;
129 } /* if */
130 position++;
131 } /* while */
132 if (unlikely(illegalDigit)) {
133 uintValue = 0;
134 } else if (unlikely(tooBig || uintValue > (uintType) INTTYPE_MAX)) {
135 err_num_stri(CARD_BASED_TOO_BIG, 0, (int) base, digits);
136 uintValue = 0;
137 } /* if */
138 logFunction(printf("basedValue --> " FMT_D "\n",
139 (intType) uintValue););
140 return (intType) uintValue;
141 } /* basedValue */
142
143
144
readBased(void)145 static inline boolType readBased (void)
146
147 {
148 register sySizeType position;
149 register int character;
150 boolType okay;
151
152 /* readBased */
153 position = 0;
154 character = next_character();
155 if (char_class(character) == DIGITCHAR ||
156 char_class(character) == LETTERCHAR) {
157 do {
158 check_symb_length(position);
159 symbol.name[position++] = (ucharType) character;
160 character = next_character();
161 } while (char_class(character) == DIGITCHAR ||
162 char_class(character) == LETTERCHAR);
163 okay = TRUE;
164 } else {
165 err_cchar(EXTDIGITEXPECTED, character);
166 okay = FALSE;
167 } /* if */
168 symbol.name[position] = '\0';
169 in_file.character = character;
170 return okay;
171 } /* readBased */
172
173
174
readBigBased(uintType base)175 static inline bigIntType readBigBased (uintType base)
176
177 {
178 memSizeType pos;
179 boolType okay = TRUE;
180 uintType digitval;
181 bigIntType result;
182
183 /* readBigBased */
184 logFunction(printf("readBigBased(" FMT_U ")\n", base););
185 in_file.character = next_character();
186 pos = 0;
187 do {
188 while (pos != symbol.stri_max && symbol.name[pos] != '\0') {
189 digitval = digit_value[(int) symbol.name[pos]];
190 if (unlikely(digitval >= base)) {
191 if (okay) {
192 err_num_stri(ILLEGALBASEDDIGIT,
193 (int) symbol.name[pos], (int) base, symbol.name);
194 okay = FALSE;
195 } /* if */
196 } /* if */
197 symbol.striValue->mem[pos] = (strElemType) symbol.name[pos];
198 pos++;
199 } /* while */
200 check_stri_length(pos);
201 } while (symbol.name[pos] != '\0');
202 symbol.striValue->size = pos;
203 bigDestr(symbol.bigIntValue);
204 if (okay) {
205 result = bigParseBased(symbol.striValue, (intType) base);
206 } else {
207 result = bigZero();
208 } /* if */
209 logFunction(printf("readBigBased -->\n"););
210 return result;
211 } /* readBigBased */
212
213
214
basedInteger(uintType base)215 static inline void basedInteger (uintType base)
216
217 { /* basedInteger */
218 if (base < 2 || base > 36) {
219 err_integer(BASE2TO36ALLOWED, (intType) base);
220 base = 36; /* Avoid subsequent errors */
221 } /* if */
222 if (readBased()) {
223 if (in_file.character == '_') {
224 symbol.bigIntValue = readBigBased(base);
225 symbol.sycategory = BIGINTLITERAL;
226 } else {
227 symbol.intValue = basedValue(base, symbol.name);
228 symbol.sycategory = INTLITERAL;
229 } /* if */
230 } else {
231 symbol.intValue = 0;
232 symbol.sycategory = INTLITERAL;
233 } /* if */
234 } /* basedInteger */
235
236
237
intExponent(uintType * ivalue)238 static inline void intExponent (uintType *ivalue)
239
240 {
241 uintType uintValue;
242 uintType exponent;
243
244 /* intExponent */
245 uintValue = *ivalue;
246 in_file.character = next_character();
247 if (in_file.character == '+') {
248 in_file.character = next_character();
249 } else {
250 if (in_file.character == '-') {
251 err_warning(NEGATIVEEXPONENT);
252 uintValue = 0;
253 in_file.character = next_character();
254 } /* if */
255 } /* if */
256 if (char_class(in_file.character) == DIGITCHAR) {
257 readDecimal(0);
258 if (uintValue != 0) {
259 exponent = decimalValue(symbol.name);
260 while (exponent > 0) {
261 exponent--;
262 if (uintValue <= MAX_DIV_10) {
263 uintValue *= 10;
264 } else {
265 err_num_stri(CARD_WITH_EXPONENT_TOO_BIG,
266 0, (int) *ivalue, &symbol.name[0]);
267 exponent = 0;
268 uintValue = 0;
269 } /* if */
270 } /* while */
271 } /* if */
272 } else {
273 err_cchar(DIGITEXPECTED, in_file.character);
274 uintValue = 0;
275 } /* if */
276 *ivalue = uintValue;
277 } /* intExponent */
278
279
280
readBigInteger(void)281 static inline bigIntType readBigInteger (void)
282
283 {
284 memSizeType pos;
285 bigIntType result;
286
287 /* readBigInteger */
288 in_file.character = next_character();
289 pos = 0;
290 do {
291 while (pos != symbol.stri_max && symbol.name[pos] != '\0') {
292 symbol.striValue->mem[pos] = (strElemType) symbol.name[pos];
293 pos++;
294 } /* while */
295 check_stri_length(pos);
296 } while (symbol.name[pos] != '\0');
297 symbol.striValue->size = pos;
298 bigDestr(symbol.bigIntValue);
299 result = bigParse(symbol.striValue);
300 return result;
301 } /* readBigInteger */
302
303
304
readFloat(void)305 static inline floatType readFloat (void)
306
307 {
308 register sySizeType position;
309 floatType result;
310
311 /* readFloat */
312 logFunction(printf("readFloat\n"););
313 position = strlen((cstriType) symbol.name);
314 check_symb_length(position);
315 symbol.name[position++] = (ucharType) in_file.character;
316 in_file.character = next_character();
317 if (char_class(in_file.character) == DIGITCHAR) {
318 readDecimal(position);
319 if (in_file.character == 'E' || in_file.character == 'e') {
320 position += strlen((cstriType) &symbol.name[position]);
321 check_symb_length(position);
322 symbol.name[position++] = (ucharType) in_file.character;
323 in_file.character = next_character();
324 if (in_file.character == '+' || in_file.character == '-') {
325 check_symb_length(position);
326 symbol.name[position++] = (ucharType) in_file.character;
327 in_file.character = next_character();
328 } /* if */
329 if (char_class(in_file.character) == DIGITCHAR) {
330 readDecimal(position);
331 } else {
332 err_cchar(DIGITEXPECTED, in_file.character);
333 } /* if */
334 } /* if */
335 #if ATOF_ACCEPTS_DENORMAL_NUMBERS
336 result = (floatType) atof((cstriType) symbol.name);
337 #else
338 result = (floatType) strtod((cstriType) symbol.name, NULL);
339 #endif
340 if (in_file.character == '\'') {
341 in_file.character = next_character();
342 if (char_class(in_file.character) == DIGITCHAR) {
343 readDecimal(position);
344 } else {
345 err_cchar(DIGITEXPECTED, in_file.character);
346 } /* if */
347 } /* if */
348 } else {
349 #if ATOF_ACCEPTS_DENORMAL_NUMBERS
350 result = (floatType) atof((cstriType) symbol.name);
351 #else
352 result = (floatType) strtod((cstriType) symbol.name, NULL);
353 #endif
354 if (in_file.character == '\'') {
355 in_file.character = next_character();
356 if (char_class(in_file.character) == DIGITCHAR) {
357 readDecimal(position);
358 } else {
359 err_cchar(DIGITEXPECTED, in_file.character);
360 } /* if */
361 } else {
362 err_cchar(DIGITEXPECTED, in_file.character);
363 } /* if */
364 } /* if */
365 if (in_file.character == '~') {
366 in_file.character = next_character();
367 } /* if */
368 if (in_file.character == 'E' || in_file.character == 'e') {
369 in_file.character = next_character();
370 if (in_file.character == '+' || in_file.character == '-') {
371 in_file.character = next_character();
372 } /* if */
373 if (char_class(in_file.character) == DIGITCHAR) {
374 readDecimal(position);
375 } else {
376 err_cchar(DIGITEXPECTED, in_file.character);
377 } /* if */
378 } /* if */
379 logFunction(printf("readFloat --> " FMT_E "\n", result););
380 return result;
381 } /* readFloat */
382
383
384
385 /**
386 * Read a numeric literal.
387 * The function assumes that the next character in in_file
388 * is the first character of the numeric literal.
389 * A numeric literal can be:
390 * - Decimal integer, e.g.: 12345
391 * - Decimal bigInteger, e.g.: 12345_
392 * - Based integer, e.g.: 16#fedcba
393 * - Based bigInteger, e.g.: 16#fedcba_
394 * - Decimal integer with exponent, e.g.: 123e3
395 * - Simple float, e.g.: 123.456
396 * - Float with exponent, e.g.: 12.3e-12
397 */
lit_number(void)398 void lit_number (void)
399
400 {
401 uintType number;
402
403 /* lit_number */
404 logFunction(printf("lit_number\n"););
405 readDecimal(0);
406 if (in_file.character == '.') {
407 #if WITH_FLOAT
408 symbol.floatValue = readFloat();
409 #endif
410 symbol.sycategory = FLOATLITERAL;
411 } else if (in_file.character == '_') {
412 symbol.bigIntValue = readBigInteger();
413 symbol.sycategory = BIGINTLITERAL;
414 } else {
415 number = decimalValue(symbol.name);
416 if (in_file.character == '#') {
417 basedInteger(number);
418 } else if (in_file.character == 'E' || in_file.character == 'e') {
419 intExponent(&number);
420 symbol.intValue = (intType) number;
421 symbol.sycategory = INTLITERAL;
422 } else {
423 symbol.intValue = (intType) number;
424 symbol.sycategory = INTLITERAL;
425 } /* if */
426 } /* if */
427 find_literal_ident();
428 symbol.syNumberInLine++;
429 #if WITH_STATISTIC
430 literal_count++;
431 #endif
432 logFunction(printf("lit_number -->\n"););
433 } /* lit_number */
434