|
|
1.1 root 1: /*
2: *-IMPORTS:
3: * <sys/compat.h>
4: * USE_PROTO
5: * LOCAL
6: * ARGS ()
7: * <limits.h>
8: * LONG_MAX
9: * LONG_MIN
10: * ULONG_MAX
11: * <string.h>
12: * memchr ()
13: * "buildobj.h"
14: * BUILD_OK
15: * build_t
16: * builder_alloc ()
17: * build_addchar ()
18: * build_begin ()
19: * build_end ()
20: * build_error ()
21: * build_release ()
22: * "ehand.h"
23: * ehand_t
24: * CHAIN_ERROR ()
25: * POP_HANDLER ()
26: * PUSH_HANDLER ()
27: * throw_error ()
28: * "input.h"
29: * IN_EOF
30: * input_t
31: * "lex.h"
32: * CLASS_FLUSH
33: * CLASS_SEP
34: * lex_t
35: * classify ()
36: */
37:
38: #include <sys/compat.h>
39: #include <limits.h>
40: #include <string.h>
41:
42: #include "buildobj.h"
43: #include "ehand.h"
44: #include "input.h"
45: #include "lex.h"
46:
47: #include "read.h"
48:
49:
50: /*
51: * Simple glue functions to encapsulate the input system.
52: */
53:
54: #if USE_PROTO
55: int (read_char) (input_t * input)
56: #else
57: int
58: read_char ARGS ((input))
59: input_t * input;
60: #endif
61: {
62: if (input == NULL)
63: throw_error ("NULL parameter passed to read_char ()");
64:
65: return (* input->in_read) (input);
66: }
67:
68:
69: #if USE_PROTO
70: void (unread_char) (input_t * input)
71: #else
72: void
73: unread_char ARGS ((input))
74: input_t * input;
75: #endif
76: {
77: if (input == NULL)
78: throw_error ("NULL parameter passed to unread_char ()");
79:
80: (* input->in_unread) (input);
81: }
82:
83:
84: #if USE_PROTO
85: void (read_error) (input_t * input)
86: #else
87: void
88: read_error ARGS ((input))
89: input_t * input;
90: #endif
91: {
92: if (input == NULL)
93: throw_error ("NULL parameter passed to read_error ()");
94:
95: (* input->in_error) (input);
96: }
97:
98:
99: #if USE_PROTO
100: void (read_close) (input_t * input)
101: #else
102: void
103: read_close ARGS ((input))
104: input_t * input;
105: #endif
106: {
107: if (input == NULL)
108: throw_error ("NULL parameter passed to read_close ()");
109:
110: (* input->in_close) (input);
111: }
112:
113:
114: /*
115: * Simple helper to ensure that we don't bump into EOF or EOL too early.
116: */
117:
118: #if USE_PROTO
119: void (check_not_eol) (int ch)
120: #else
121: void
122: check_not_eol ARGS ((ch))
123: int ch;
124: #endif
125: {
126: if (ch == '\n')
127: throw_error ("premature end of line");
128:
129: if (ch == READ_EOF)
130: throw_error ("premature end of input");
131: }
132:
133:
134: /*
135: * We use this function to eat anything that the lexical specification
136: * considers flushable until we see an end-of-line or end-of-file.
137: */
138:
139: #if USE_PROTO
140: int (expect_eol) (input_t * input, lex_t * lexp, int ch)
141: #else
142: int
143: expect_eol ARGS ((input, lexp, ch))
144: input_t * input;
145: lex_t * lexp;
146: int ch;
147: #endif
148: {
149: if (ch != '\n' && ch != READ_EOF)
150: while ((ch = (* input->in_read) (input)) != '\n') {
151:
152: if (ch == IN_EOF)
153: return READ_EOF;
154:
155: if (classify (lexp, ch, 1) != CLASS_FLUSH)
156: break;
157: }
158:
159: return ch;
160: }
161:
162:
163: /*
164: * Read a token from a file; this function may use the subclassed version to
165: * support more efficient tokenization if possible.
166: *
167: * Note that we don't null-terminate the data or do any other funky stuff. If
168: * our caller wants to to that, well that's fine, and we don't finish the
169: * object so that the caller can extend it. Note that by returning the token
170: * length that we built, this function can be used to incrementally extend
171: * variable-length data and allow the positions of the subparts to be properly
172: * recovered.
173: */
174:
175: #if USE_PROTO
176: int (read_token) (input_t * input, lex_t * lexp, build_t * heap,
177: token_t * tokenp)
178: #else
179: int
180: read_token ARGS ((input, lexp, heap, tokenp))
181: input_t * input;
182: lex_t * lexp;
183: build_t * heap;
184: token_t * tokenp;
185: #endif
186: {
187: int ch;
188: int err;
189:
190: if (input == NULL || lexp == NULL || heap == NULL || tokenp == NULL)
191: throw_error ("invalid parameters in read_token ()");
192:
193: if (input->in_readtok != NULL) {
194: /*
195: * Use the subclassed version. Since we won't actually be
196: * building the token on the passed-in heap, terminate the
197: * current build on that heap.
198: */
199:
200: build_end (heap, NULL);
201:
202: tokenp->tok_heap = NULL;
203: tokenp->tok_data = (* input->in_readtok) (input, lexp,
204: & tokenp->tok_len);
205:
206: return (* input->in_read) (input);
207: }
208:
209:
210: tokenp->tok_heap = heap;
211: tokenp->tok_data = NULL;
212: tokenp->tok_len = 0;
213:
214: for (;;) {
215: if ((ch = (* input->in_read) (input)) == IN_EOF)
216: return ch;
217:
218: switch (classify (lexp, ch, tokenp->tok_len == 0)) {
219:
220: case CLASS_FLUSH:
221: continue;
222:
223: case CLASS_SEP:
224: return ch;
225:
226: default:
227: break;
228: }
229:
230:
231: /*
232: * We have read a valid non-separator character, add it to the
233: * current input symbol.
234: */
235:
236: tokenp->tok_len ++;
237:
238: if ((err = build_addchar (heap, ch)) != BUILD_OK)
239: throw_error ("build_addchar () reported %d (%s)", err,
240: build_error (err));
241: }
242: }
243:
244:
245: /*
246: * Handy function for clients of read_token () to finish up any build-heap
247: * allocation in the usual case where read_token () is simply expected to copy
248: * data to the heap.
249: *
250: * If it was adding data to the heap, add a NULL terminator for the usual case
251: * where we would also like the object to be useable as a string.
252: */
253:
254: #if USE_PROTO
255: void (token_end) (token_t * tok)
256: #else
257: void
258: token_end ARGS ((tok))
259: token_t * tok;
260: #endif
261: {
262: char null;
263:
264: if (tok->tok_heap == NULL)
265: return;
266:
267: null = 0;
268:
269: if (tok->tok_len != 0 ?
270: (build_add (tok->tok_heap, 1, & null) != 0) ||
271: (tok->tok_data =
272: build_end (tok->tok_heap, NULL)) == NULL :
273: build_end (tok->tok_heap, NULL) != NULL)
274: throw_error ("Error ending token construction");
275: }
276:
277:
278: /*
279: * In the case where a token was able to be scanned in-place, it is often
280: * necessary to copy it to a heap, even if only temporarily. As with the above
281: * token_end, we terminate the token as if it was a string.
282: *
283: * If the token is actually in a different heap from the one given, we move it
284: * to the new heap. This works in with some special behaviour in the build
285: * system where object building can be temporarily suspended, allowing some
286: * kinds of recursive operations to work on borrowed heap space.
287: */
288:
289: #if USE_PROTO
290: void (token_copy) (token_t * tok, build_t * heap)
291: #else
292: void
293: token_copy ARGS ((tok, heap))
294: token_t * tok;
295: build_t * heap;
296: #endif
297: {
298: char null;
299: unsigned char * data;
300: int err;
301:
302: if (tok->tok_heap == heap)
303: return;
304:
305: null = 0;
306:
307: if ((err = build_begin (heap, tok->tok_len, tok->tok_data)) != 0 ||
308: (err = build_add (heap, 1, & null)) != 0 ||
309: (err = BUILD_NO_OBJECT,
310: (data = build_end (heap, NULL)) == NULL))
311: throw_error ("Cannot copy token data to heap, %s",
312: build_error (err));
313:
314: if (tok->tok_heap != NULL &&
315: (err = build_release (heap, tok->tok_data)) != 0)
316: throw_error ("Cannot release data from old heap, %s",
317: build_error (err));
318:
319: tok->tok_data = data;
320: tok->tok_heap = heap;
321: }
322:
323:
324: /*
325: * If a read token has been found to be not needed, it may be discarded with
326: * this function. If it was copied to a heap, then the heap memory is
327: * released.
328: */
329:
330: #if USE_PROTO
331: void (token_discard) (token_t * tok)
332: #else
333: void
334: token_discard ARGS ((tok))
335: token_t * tok;
336: #endif
337: {
338: int err;
339:
340: if (tok->tok_heap != NULL &&
341: (err = build_release (tok->tok_heap, tok->tok_data)) != 0)
342: throw_error ("Cannot release token data, error %s",
343: build_error (err));
344: }
345:
346:
347: /*
348: * Simply discard flushable input until the next non-flushable input
349: * character.
350: */
351:
352: #if USE_PROTO
353: void (read_flush) (input_t * input, lex_t * lexp)
354: #else
355: void
356: read_flush ARGS ((input, lexp))
357: input_t * input;
358: lex_t * lexp;
359: #endif
360: {
361: int ch;
362:
363: while ((ch = (* input->in_read) (input)) != IN_EOF) {
364:
365: if (classify (lexp, ch, 1) != CLASS_FLUSH) {
366:
367: (* input->in_unread) (input);
368: break;
369: }
370: }
371: }
372:
373:
374: /*
375: * To help with the numeric conversions, here we define a simple conversion
376: * utility that converts a character to a digit independent of character set
377: * and digit case.
378: *
379: * ... a truly general way of doing this would be nice ... maybe some kind of
380: * virtual-machine interpreter would be up to it ... hmmm.
381: */
382:
383: enum {
384: NOT_DIGIT = -1
385: };
386:
387: #if USE_PROTO
388: LOCAL int (char_to_digit) (int ch, int radix)
389: #else
390: LOCAL int
391: char_to_digit ARGS ((ch, radix))
392: int ch;
393: int radix;
394: #endif
395: {
396: static CONST char digits [] = {
397: '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
398: 'A', 'B', 'C', 'D', 'E', 'F',
399: 'a', 'b', 'c', 'd', 'e', 'f'
400: };
401: static CONST char values [sizeof (digits)] = {
402: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
403: 10, 11, 12, 13, 14, 15,
404: 10, 11, 12, 13, 14, 15
405: };
406: CONST char * temp;
407:
408:
409: if ((temp = (CONST char *) memchr (digits, ch,
410: sizeof (digits))) == NULL ||
411: (ch = values [temp - digits]) >= radix)
412: return -1;
413:
414: return ch;
415: }
416:
417:
418: /*
419: * Both read_ulong () and read_long () need to be able to select a radix for
420: * the number in question based on an explicit radix prefix. This code does
421: * that for both functions; under certain circumstances, the numeric input
422: * might be completed by this code.
423: */
424:
425: #if USE_PROTO
426: LOCAL int (choose_radix) (input_t * input, unsigned long * ulongp,
427: int * radixp)
428: #else
429: LOCAL int
430: choose_radix ARGS ((input, ulongp, radixp))
431: input_t * input;
432: unsigned long * ulongp;
433: int * radixp;
434: #endif
435: {
436: int ch;
437: int errflag;
438:
439: * ulongp = 0;
440:
441: /*
442: * Perform a radix-selection step, looking for 0, 1-9, 0X, or 0x as
443: * indications of what radix to read the rest of the number in.
444: */
445:
446: switch (ch = (* input->in_read) (input)) {
447:
448: case IN_EOF:
449: return 1;
450:
451: case '0': /* octal or hexadecimal */
452: switch (ch = (* input->in_read) (input)) {
453:
454: case IN_EOF:
455: return 1;
456:
457: case 'x':
458: case 'X':
459: /*
460: * For the case of radix-16 numbers with an explicit
461: * radix in the text, we have a special error case,
462: * consisting of an 0x or 0X followed by something
463: * that is not a valid digit.
464: *
465: * The easiest way to test for this is to try
466: * converting the first digit right here.
467: */
468:
469: * radixp = 16;
470: errflag = -1;
471:
472: if ((ch = (* input->in_read) (input))
473: == IN_EOF)
474: return -1;
475: break;
476:
477: default:
478: * radixp = 8;
479: errflag = 1;
480: break;
481: }
482: break;
483:
484: default:
485: * radixp = 10;
486: errflag = 0;
487: break;
488: }
489:
490:
491: /*
492: * The need for the extra error check required by hexadecimal numbers
493: * could have made life difficult for the caller in terms of working
494: * out whether this function actually began reading a number or not.
495: *
496: * To simplify this, we ensure that this function always consumes at
497: * least the first digit. Of course, the actual response to the next
498: * character not being a valid digit is different in each case, so we
499: * also deal with that.
500: */
501:
502: if ((ch = char_to_digit (ch, * radixp)) == -1) {
503:
504: (* input->in_unread) (input);
505: return errflag;
506: }
507:
508: * ulongp = ch;
509: return 0;
510: }
511:
512:
513: /*
514: * Read an unsigned long number from the input. No initial whitespace is
515: * skipped, no sign character is permitted, and the first value that is not
516: * valid for a number of the given radix ends conversion.
517: *
518: * If "radix" is 0, the usual C radix specifiers are recognized. This version
519: * of the code has a maximum "radix" value of 16.
520: *
521: * A return value of 0 indicates no number was seen, a return value of -1
522: * indicates an invalid number was seen (such as 0xZ, or a number that is too
523: * large to be represented accurately with an unsigned long), and a return
524: * value of 1 indicates a number was successfully read.
525: */
526:
527: #if USE_PROTO
528: int (read_ulong) (input_t * input, unsigned long * ulongp, int radix)
529: #else
530: int
531: read_ulong ARGS ((input, ulongp, radix))
532: input_t * input;
533: unsigned long * ulongp;
534: int radix;
535: #endif
536: {
537: char ch;
538: unsigned long temp;
539: unsigned long radix_max;
540: int read_something;
541:
542: if (input == NULL || ulongp == NULL || radix < 0 || radix > 16)
543: throw_error ("Invalid parameter passed to read_ulong ()");
544:
545: * ulongp = 0;
546:
547: if (radix == 0) {
548:
549: switch (ch = choose_radix (input, ulongp, & radix)) {
550:
551: case 0:
552: break;
553:
554: default:
555: return ch;
556: }
557:
558: read_something = 1;
559: } else
560: read_something = 0;
561:
562: /*
563: * In order to detect overflow portably, we figure out the smallest
564: * value that will cause overflow when multiplied by the radix, and
565: * test against that before the multiplication. If the addition of the
566: * value of "ch" causes overflow, that can be detected by a value of
567: * "temp" that is smaller after the addition, according to the rules
568: * of ANSI/ISO unsigned arithmetic. Note that unsigned overflow is
569: * required to be non-signalling in an ANSI/ISO environment.
570: */
571:
572: temp = * ulongp;
573: radix_max = ULONG_MAX / radix;
574:
575: for (;;) {
576:
577: if ((ch = (* input->in_read) (input)) == IN_EOF)
578: break;
579:
580: if ((ch = char_to_digit (ch, radix)) == -1) {
581:
582: (* input->in_unread) (input);
583: break;
584: }
585:
586: if (temp > radix_max) {
587: /*
588: * Will overflow during the multiplication.
589: */
590:
591: read_something = -1;
592: temp = ULONG_MAX;
593:
594: continue;
595: }
596:
597: read_something = 1;
598: temp = (temp * radix) + ch;
599:
600: if (temp < ch) {
601: /*
602: * Overflowed during the addition.
603: */
604:
605: read_something = -1;
606: temp = ULONG_MAX;
607:
608: continue;
609: }
610: }
611:
612: * ulongp = temp;
613:
614: return read_something;
615: }
616:
617:
618: /*
619: * Read a signed long number from the input. No initial whitespace is skipped,
620: * and the sign character must immediately precede the digits of the number
621: * (or the redix specifier), and the first value that is not valid for a
622: * number of the given radix ends conversion.
623: *
624: * If "radix" is 0, the usual C radix specifiers are recognized. This version
625: * of the code has a maximum "radix" value of 16.
626: *
627: * A return value of 0 indicates no number was seen, a return value of -1
628: * indicates an invalid number was seen (such as 0xZ, or a number that is too
629: * large to be represented accurately with a signed long), and a return value
630: * of 1 indicates a number was successfully read.
631: */
632:
633: #if USE_PROTO
634: int (read_long) (input_t * input, long * longp, int radix)
635: #else
636: int
637: read_long ARGS ((input, longp, radix))
638: input_t * input;
639: long * longp;
640: int radix;
641: #endif
642: {
643: int ch;
644: unsigned long temp;
645: int sign;
646:
647: /*
648: * To save time and effort, we simply test for an initial sign flag,
649: * use read_ulong () to convert a number, and then range check the
650: * result before converting it to signed form.
651: */
652:
653: switch (ch = (* input->in_read) (input)) {
654:
655: case IN_EOF:
656: return 1;
657:
658: case '-':
659: sign = -1;
660: break;
661:
662: case '+':
663: sign = 1;
664: break;
665:
666: default:
667: /*
668: * There is no sign character that we can see, return the
669: * lookahead character to the input source so that it will be
670: * checked by read_ulong ().
671: */
672:
673: sign = 0;
674: (* input->in_unread) (input);
675: }
676:
677: ch = read_ulong (input, & temp, radix);
678:
679:
680: /*
681: * Before we range-check the result that we are going to return, it
682: * pays to note that the range of signed numbers may well not be
683: * symmetric. Typically, there are more negative numbers than non-zero
684: * positive numbers, so that "- LONG_MIN" is not a legal long integer.
685: *
686: * Producing a value of LONG_MIN without getting into implementation-
687: * defined (or undefined, in K&R) territory is tricky because of the
688: * integral promotions. We'll work around it by subtracting from -1
689: * rather than zero.
690: *
691: * We'd better test that the range of negative integers is at most one
692: * greater than the range of non-zero positive integers. We can't do
693: * the test if the preprocessor does arithmetic wrong, though, and
694: * many do.
695: */
696:
697: #if -23UL > 0
698: # if (- (LONG_MIN + 0UL)) - 1 > LONG_MAX
699: # error There are too many negative integers!
700: # endif
701: #else
702: /* Your preprocessor does arithmetic wrong */
703: #endif
704:
705:
706: if (sign < 0 && temp != 0) {
707:
708: temp -= 1;
709:
710: if (temp > - (unsigned long) LONG_MIN - 1) {
711:
712: * longp = LONG_MIN;
713: return -1;
714: } else
715: * longp = -1 - (long) temp;
716:
717: } else if (temp > LONG_MAX) {
718:
719: * longp = LONG_MAX;
720: return -1;
721: } else
722: * longp = temp;
723:
724:
725: /*
726: * If we saw a sign (of either kind) and nothing else, that's an
727: * error.
728: */
729:
730: return (sign != 0 && ch == 0) ? -1 : ch;
731: }
732:
733:
734: /*
735: * Read a single unsigned long or a numeric range (indicated by a pair of
736: * unsigned longs separated by a hyphen without any intervening whitespace).
737: */
738:
739: #if USE_PROTO
740: int (read_ulongs) (input_t * input, lex_t * lexp, unsigned long * number,
741: int rangeflag)
742: #else
743: int
744: read_ulongs ARGS ((input, lexp, number, rangeflag))
745: input_t * input;
746: lex_t * lexp;
747: unsigned long * number;
748: int rangeflag;
749: #endif
750: {
751: if ((rangeflag != RANGE && rangeflag != NO_RANGE) ||
752: input == NULL || lexp == NULL || number == NULL)
753: throw_error ("Invalid parameter to read_ulongs ()");
754:
755: /*
756: * We permit initial whitespace according to the current lexical
757: * idea of what whitespace is.
758: */
759:
760: read_flush (input, lexp);
761:
762: if (read_ulong (input, number, 0) != 1)
763: throw_error ("Illegal unsigned long number");
764:
765: if (rangeflag == RANGE) {
766: int ch;
767:
768: if ((ch = (* input->in_read) (input)) != IN_EOF &&
769: ((* input->in_unread) (input), /* for effect */
770: ch == '-')) {
771: /*
772: * Read the second part of the range.
773: */
774:
775: if (read_ulong (input, number + 1, 0) != 1)
776: throw_error ("Illegal second half of unsigned long range");
777: } else
778: number [1] = number [0];
779: }
780:
781: return (* input->in_read) (input);
782: }
783:
784:
785: /*
786: * Read a single integer or a numeric range (indicated by a pair of integers
787: * separated by a hyphen without any intervening whitespace).
788: */
789:
790: #if USE_PROTO
791: int (read_ints) (input_t * input, lex_t * lexp, int * number, int rangeflag)
792: #else
793: int
794: read_ints ARGS ((input, lexp, number, rangeflag))
795: input_t * input;
796: lex_t * lexp;
797: int * number;
798: int rangeflag;
799: #endif
800: {
801: long value;
802:
803: if ((rangeflag != RANGE && rangeflag != NO_RANGE) ||
804: input == NULL || lexp == NULL || number == NULL)
805: throw_error ("Invalid parameter to read_ints ()");
806:
807: /*
808: * We permit initial whitespace according to the current lexical
809: * idea of what whitespace is.
810: */
811:
812: read_flush (input, lexp);
813:
814: if (read_long (input, & value, 0) != 1 ||
815: #ifdef __COHERENT__
816: 0) /* Coherent compiles the test below to bad code */
817: #else
818: value > INT_MAX || value < INT_MIN)
819: #endif
820: throw_error ("Illegal integer number");
821:
822: number [0] = (int) value;
823:
824: if (rangeflag == RANGE) {
825: int ch;
826:
827: if ((ch = (* input->in_read) (input)) != IN_EOF &&
828: ((* input->in_unread) (input), /* for effect */
829: ch == '-')) {
830: /*
831: * Read the second part of the range.
832: */
833:
834: if (read_long (input, & value, 0) != 1 ||
835: #ifdef __COHERENT__
836: 0) /* Coherent compiles to bad code */
837: #else
838: value > INT_MAX || value < INT_MIN)
839: #endif
840: throw_error ("Illegal second half of integer range");
841: }
842:
843: number [1] = (int) value;
844: }
845:
846: return (* input->in_read) (input);
847: }
848:
849:
850: /*
851: * Read a single integer or a numeric range (indicated by a pair of integers
852: * separated by a hyphen without any intervening whitespace).
853: */
854:
855: #if USE_PROTO
856: int (read_longs) (input_t * input, lex_t * lexp, long * number, int rangeflag)
857: #else
858: int
859: read_longs ARGS ((input, lexp, number, rangeflag))
860: input_t * input;
861: lex_t * lexp;
862: long * number;
863: int rangeflag;
864: #endif
865: {
866: if ((rangeflag != RANGE && rangeflag != NO_RANGE) ||
867: input == NULL || lexp == NULL || number == NULL)
868: throw_error ("Invalid parameter to read_longs ()");
869:
870: /*
871: * We permit initial whitespace according to the current lexical
872: * idea of what whitespace is.
873: */
874:
875: read_flush (input, lexp);
876:
877: if (read_long (input, number, 0) != 1)
878: throw_error ("Illegal long-integer number");
879:
880: if (rangeflag == RANGE) {
881: int ch;
882:
883: if ((ch = (* input->in_read) (input)) != IN_EOF &&
884: ((* input->in_unread) (input), /* for effect */
885: ch == '-')) {
886: /*
887: * Read the second part of the range.
888: */
889:
890: if (read_long (input, number + 1, 0) != 1)
891: throw_error ("Illegal second half of long-integer range");
892: }
893: }
894:
895: return (* input->in_read) (input);
896: }
897:
898:
899: /*
900: * Read a single unsigned integer or a numeric range (indicated by a pair of
901: * unsigned integers separated by a hyphen without any intervening
902: * whitespace).
903: */
904:
905: #if USE_PROTO
906: int (read_uints) (input_t * input, lex_t * lexp, unsigned int * number,
907: int rangeflag)
908: #else
909: int
910: read_uints ARGS ((input, lexp, number, rangeflag))
911: input_t * input;
912: lex_t * lexp;
913: unsigned int * number;
914: int rangeflag;
915: #endif
916: {
917: unsigned long value;
918:
919: if ((rangeflag != RANGE && rangeflag != NO_RANGE) ||
920: input == NULL || lexp == NULL || number == NULL)
921: throw_error ("Invalid parameter to read_ints ()");
922:
923: /*
924: * We permit initial whitespace according to the current lexical
925: * idea of what whitespace is.
926: */
927:
928: read_flush (input, lexp);
929:
930: if (read_ulong (input, & value, 0) != 1 || value > UINT_MAX)
931: throw_error ("Illegal unsigned integer number");
932:
933: number [0] = (unsigned int) value;
934:
935: if (rangeflag == RANGE) {
936: int ch;
937:
938: if ((ch = (* input->in_read) (input)) != IN_EOF &&
939: ((* input->in_unread) (input), /* for effect */
940: ch == '-')) {
941: /*
942: * Read the second part of the range.
943: */
944:
945: if (read_ulong (input, & value, 0) != 1 ||
946: value > UINT_MAX)
947: throw_error ("Illegal second half of unsigned integer range");
948: }
949:
950: number [1] = (unsigned int) value;
951: }
952:
953: return (* input->in_read) (input);
954: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.