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