1 #include "ucl.h"
2 #include "lex.h"
3 #include "keyword.h"
4 
5 #define CURSOR      (Input.cursor)
6 #define LINE        (Input.line)
7 #define LINEHEAD    (Input.lineHead)
8 
9 typedef int (*Scanner)(void);
10 
11 static unsigned char *PeekPoint;
12 static union value    PeekValue;
13 static struct coord   PeekCoord;
14 static Scanner        Scanners[256];
15 
16 union value  TokenValue;
17 struct coord TokenCoord;
18 struct coord PrevCoord;
19 char* TokenStrings[] =
20 {
21 #define TOKEN(k, s) s,
22 #include "token.h"
23 #undef  TOKEN
24 };
25 
26 /**
27  * Scans preprocessing directive which specify the line number and filename such as:
28  * # line 6 "C:\\Program Files\\Visual Stduio 6\\VC6\\Include\\stdio.h" or
29  * # 6 "/usr/include/stdio.h"
30  * Ignores other preprocessing directive.
31  */
ScanPPLine(void)32 static void ScanPPLine(void)
33 {
34 	int line = 0;
35 
36 	CURSOR++;
37 	while (*CURSOR == ' ' || *CURSOR == '\t')
38 	{
39 		CURSOR++;
40 	}
41 
42 	if (IsDigit(*CURSOR))
43 	{
44 		goto read_line;
45 	}
46 	else if (strncmp(CURSOR, "line", 4) == 0)
47 	{
48 		CURSOR += 4;
49 		while (*CURSOR == ' ' || *CURSOR == '\t')
50 		{
51 			CURSOR++;
52 		}
53 read_line:
54 		while (IsDigit(*CURSOR))
55 		{
56 			line = 10 * line + *CURSOR - '0';
57 			CURSOR++;
58 		}
59 		TokenCoord.ppline = line - 1;
60 
61 		while (*CURSOR == ' ' || *CURSOR == '\t')
62 		{
63 			CURSOR++;
64 		}
65 		TokenCoord.filename = ++CURSOR;
66 		while (*CURSOR != '"' && *CURSOR != END_OF_FILE && *CURSOR != '\n')
67 		{
68 			CURSOR++;
69 		}
70 		TokenCoord.filename = InternName(TokenCoord.filename, (char *)CURSOR - TokenCoord.filename);
71 	}
72 
73 	while (*CURSOR != '\n' && *CURSOR != END_OF_FILE)
74 	{
75 		CURSOR++;
76 	}
77 }
78 
SkipWhiteSpace(void)79 static void SkipWhiteSpace(void)
80 {
81 	int ch;
82 
83 again:
84 	ch = *CURSOR;
85 	while (ch == '\t' || ch == '\v' || ch == '\f' || ch == ' ' ||
86 	       ch == '\r' || ch == '\n' || ch == '/'  || ch == '#')
87 	{
88 		switch (ch)
89 		{
90 		case '\n':
91 			TokenCoord.ppline++;
92 			LINE++;
93 			LINEHEAD = ++CURSOR;
94 			break;
95 
96 		case '#':
97 			ScanPPLine();
98 			break;
99 
100 		case '/':
101 			if (CURSOR[1] != '/' && CURSOR[1] != '*')
102 				return;
103 			CURSOR++;
104 			if (*CURSOR == '/')
105 			{
106 				CURSOR++;
107 				while (*CURSOR != '\n' && *CURSOR != END_OF_FILE)
108 				{
109 					CURSOR++;
110 				}
111 			}
112 			else
113 			{
114 				CURSOR += 2;
115 				while (CURSOR[0] != '*' || CURSOR[1] != '/')
116 				{
117 					if (*CURSOR == '\n')
118 					{
119 						TokenCoord.ppline++;
120 						LINE++;
121 					}
122 					else if (CURSOR[0] == END_OF_FILE || CURSOR[1] == END_OF_FILE)
123 					{
124 						Error(&TokenCoord, "Comment is not closed");
125 						return;
126 					}
127 					CURSOR++;
128 				}
129 				CURSOR += 2;
130 			}
131 			break;
132 
133 		default:
134 			CURSOR++;
135 			break;
136 		}
137 		ch = *CURSOR;
138 	}
139 
140 	if (ExtraWhiteSpace != NULL)
141 	{
142 		char *p;
143 
144 		FOR_EACH_ITEM(char*, p, ExtraWhiteSpace)
145 			if (strncmp(CURSOR, p, strlen(p)) == 0)
146 			{
147 				CURSOR += strlen(p);
148 				goto again;
149 			}
150 		ENDFOR
151 	}
152 }
153 
ScanEscapeChar(int wide)154 static int ScanEscapeChar(int wide)
155 {
156 	int v, overflow;
157 
158 	CURSOR++;
159 	switch (*CURSOR++)
160 	{
161 	case 'a':
162 		return '\a';
163 
164 	case 'b':
165 		return '\b';
166 
167 	case 'f':
168 		return '\f';
169 
170 	case 'n':
171 		return '\n';
172 
173 	case 'r':
174 		return '\r';
175 
176 	case 't':
177 		return '\t';
178 
179 	case 'v':
180 		return '\v';
181 
182 	case '\'':
183 	case '"':
184 	case '\\':
185 	case '\?':
186 		return *(CURSOR - 1);
187 
188 	case 'x':
189 		if (! IsHexDigit(*CURSOR))
190 		{
191 			Error(&TokenCoord, "Expect hex digit");
192 			return 'x';
193 		}
194 		v = 0;
195 		while (IsHexDigit(*CURSOR))
196 		{
197 			if (v >> (WCharType->size - 4))
198 			{
199 				overflow = 1;
200 			}
201 			if (IsDigit(*CURSOR))
202 			{
203 				v = (v << 4) + *CURSOR - '0';
204 			}
205 			else
206 			{
207 				v = (v << 4) + ToUpper(*CURSOR) - 'A' + 10;
208 			}
209 			CURSOR++;
210 		}
211 		if (overflow || (! wide && v > 255))
212 		{
213 			Warning(&TokenCoord, "Hexademical espace sequence overflow");
214 		}
215 		return v;
216 
217 	case '0': case '1': case '2': case '3':
218 	case '4': case '5': case '6': case '7':
219 		v = *(CURSOR - 1) - '0';
220 		if (IsOctDigit(*CURSOR))
221 		{
222 			v = (v << 3) + *CURSOR++ - '0';
223 			if (IsOctDigit(*CURSOR))
224 				v = (v << 3) + *CURSOR++ - '0';
225 		}
226 		return v;
227 
228 	default:
229 		Warning(&TokenCoord, "Unrecognized escape sequence:\\%c", *CURSOR);
230 		return *CURSOR;
231 	}
232 }
233 
FindKeyword(char * str,int len)234 static int FindKeyword(char *str, int len)
235 {
236 	struct keyword *p = NULL;
237 	int index = 0;
238 
239 	if (*str != '_')
240 		index = ToUpper(*str) - 'A' + 1;
241 
242 	p = keywords[index];
243 	while (p->name)
244 	{
245 		if (p->len == len && strncmp(str, p->name, len) == 0)
246 			break;
247 		p++;
248 	}
249 	return p->tok;
250 }
251 
ScanIntLiteral(unsigned char * start,int len,int base)252 static int ScanIntLiteral(unsigned char *start, int len, int base)
253 {
254 	unsigned char *p =  start;
255 	unsigned char *end = start + len;
256 	unsigned int i[2] = {0, 0};
257 	int tok = TK_INTCONST;
258 	int d = 0;
259 	int carry0 = 0, carry1 = 0;
260 	int overflow = 0;
261 
262 	while (p != end)
263 	{
264 		if (base == 16)
265 		{
266 			if ((*p >= 'A' && *p <= 'F') ||
267 				(*p >= 'a' && *p <= 'f'))
268 			{
269 				d = ToUpper(*p) - 'A' + 10;
270 			}
271 			else
272 			{
273 				d = *p - '0';
274 			}
275 		}
276 		else
277 		{
278 			d = *p - '0';
279 		}
280 
281 		switch (base)
282 		{
283 		case 16:
284 			carry0 = HIGH_4BIT(i[0]);
285 			carry1 = HIGH_4BIT(i[1]);
286 			i[0] = i[0] << 4;
287 			i[1] = i[1] << 4;
288 			break;
289 
290 		case 8:
291 			carry0 = HIGH_3BIT(i[0]);
292 			carry1 = HIGH_3BIT(i[1]);
293 			i[0] = i[0] << 3;
294 			i[1] = i[1] << 3;
295 			break;
296 
297 		case 10:
298 			{
299 				unsigned int t1, t2;
300 
301 				carry0 = HIGH_3BIT(i[0]) + HIGH_1BIT(i[0]);
302 				carry1 = HIGH_3BIT(i[1]) + HIGH_1BIT(i[1]);
303 				t1 = i[0] << 3;
304 				t2 = i[0] << 1;
305 				if (t1 > UINT_MAX - t2)
306 				{
307 					carry0++;
308 				}
309 				i[0] = t1 + t2;
310 				t1 = i[1] << 3;
311 				t2 = i[1] << 1;
312 				if (t1 > UINT_MAX - t2)
313 				{
314 					carry1++;
315 				}
316 				i[1] = t1 + t2;
317 			}
318 			break;
319 		}
320 		if (i[0] > UINT_MAX - d)
321 		{
322 			carry0 += i[0] - (UINT_MAX - d);
323 		}
324 		if (carry1 || (i[1] > UINT_MAX - carry0))
325 		{
326 			overflow = 1;
327 		}
328 		i[0] += d;
329 		i[1] += carry0;
330 		p++;
331 	}
332 
333 	if (overflow || i[1] != 0)
334 	{
335 		Warning(&TokenCoord, "Integer literal is too big");
336 	}
337 
338 	TokenValue.i[1] = 0;
339 	TokenValue.i[0] = i[0];
340 	tok = TK_INTCONST;
341 
342 	if (*CURSOR == 'U' || *CURSOR == 'u')
343 	{
344 		CURSOR++;
345 		if (tok == TK_INTCONST)
346 		{
347 			tok = TK_UINTCONST;
348 		}
349 		else if (tok == TK_LLONGCONST)
350 		{
351 			tok = TK_ULLONGCONST;
352 		}
353 	}
354 
355 	if (*CURSOR == 'L' || *CURSOR == 'l')
356 	{
357 		CURSOR++;
358 		if (tok == TK_INTCONST)
359 		{
360 			tok = TK_LONGCONST;
361 		}
362 		else if (tok == TK_UINTCONST)
363 		{
364 			tok = TK_ULONGCONST;
365 		}
366 		if (*CURSOR == 'L' || *CURSOR == 'l')
367 		{
368 			CURSOR++;
369 			if (tok < TK_LLONGCONST)
370 			{
371 				tok = TK_LLONGCONST;
372 			}
373 		}
374 	}
375 
376 	return tok;
377 }
378 
ScanFloatLiteral(unsigned char * start)379 static int ScanFloatLiteral(unsigned char *start)
380 {
381 	double d;
382 
383 	if (*CURSOR == '.')
384 	{
385 		CURSOR++;
386 		while (IsDigit(*CURSOR))
387 		{
388 			CURSOR++;
389 		}
390 	}
391 	if (*CURSOR == 'e' || *CURSOR == 'E')
392 	{
393 		CURSOR++;
394 		if (*CURSOR == '+' || *CURSOR == '-')
395 		{
396 			CURSOR++;
397 		}
398 		if (! IsDigit(*CURSOR))
399 		{
400 			Error(&TokenCoord, "Expect exponent value");
401 		}
402 		else
403 		{
404 			while (IsDigit(*CURSOR))
405 			{
406 				CURSOR++;
407 			}
408 		}
409 	}
410 
411 	errno = 0;
412 	d = strtod((char *)start, NULL);
413 	if (errno == ERANGE)
414 	{
415 		Warning(&TokenCoord, "Float literal overflow");
416 	}
417 	TokenValue.d = d;
418 	if (*CURSOR == 'f' || *CURSOR == 'F')
419 	{
420 		CURSOR++;
421 		TokenValue.f = (float)d;
422 		return TK_FLOATCONST;
423 	}
424 	else if (*CURSOR == 'L' || *CURSOR == 'l')
425 	{
426 		CURSOR++;
427 		return TK_LDOUBLECONST;
428 	}
429 	else
430 	{
431 		return TK_DOUBLECONST;
432 	}
433 }
434 
ScanNumericLiteral(void)435 static int ScanNumericLiteral(void)
436 {
437 	unsigned char *start = CURSOR;
438 	int base = 10;
439 
440 	if (*CURSOR == '.')
441 	{
442 		return ScanFloatLiteral(start);
443 	}
444 
445 	if (*CURSOR == '0' && (CURSOR[1] == 'x' || CURSOR[1] == 'X'))
446 	{
447 		CURSOR += 2;
448 		start = CURSOR;
449 		base = 16;
450 		if (! IsHexDigit(*CURSOR))
451 		{
452 			Error(&TokenCoord, "Expect hex digit");
453 			TokenValue.i[0] = 0;
454 			return TK_INTCONST;
455 		}
456 		while (IsHexDigit(*CURSOR))
457 		{
458 			CURSOR++;
459 		}
460 	}
461 	else if (*CURSOR == '0')
462 	{
463 		CURSOR++;
464 		base = 8;
465 		while (IsOctDigit(*CURSOR))
466 		{
467 			CURSOR++;
468 		}
469 	}
470 	else
471 	{
472 		CURSOR++;
473 		while (IsDigit(*CURSOR))
474 		{
475 			CURSOR++;
476 		}
477 	}
478 
479 	if (base == 16 || (*CURSOR != '.' && *CURSOR != 'e' && *CURSOR != 'E'))
480 	{
481 		return ScanIntLiteral(start, (int)(CURSOR - start), base);
482 	}
483 	else
484 	{
485 		return ScanFloatLiteral(start);
486 	}
487 }
488 
ScanCharLiteral(void)489 static int ScanCharLiteral(void)
490 {
491 	int ch = 0;
492 	int count = 0;
493 	int wide = 0;
494 
495 	if (*CURSOR == 'L')
496 	{
497 		CURSOR++;
498 		wide = 1;
499 	}
500 	CURSOR++;
501 	while (*CURSOR != '\'')
502 	{
503 		if (*CURSOR == '\n' || *CURSOR == END_OF_FILE)
504 			break;
505 
506 		ch = *CURSOR == '\\' ? ScanEscapeChar(wide) : *CURSOR++;
507 		count++;
508 	}
509 
510 	if (*CURSOR != '\'')
511 	{
512 		Error(&TokenCoord, "Expect '");
513 		goto end_char;
514 	}
515 
516 	CURSOR++;
517 	if (count > 1)
518 	{
519 		Warning(&TokenCoord, "Two many characters");
520 	}
521 
522 end_char:
523 	TokenValue.i[0] = ch;
524 	TokenValue.i[1] = 0;
525 
526 	return TK_INTCONST;
527 }
528 
ScanStringLiteral(void)529 static int ScanStringLiteral(void)
530 {
531 	char tmp[512];
532 	char *cp = tmp;
533 	int *wcp = (int *)tmp;
534 	int wide = 0;
535 	int len = 0;
536 	int maxlen = 512;
537 	int ch;
538 	String str;
539 
540 	CALLOC(str);
541 
542 	if (*CURSOR == 'L')
543 	{
544 		CURSOR++;
545 		wide = 1;
546 		maxlen /= sizeof(int);
547 	}
548 	CURSOR++;
549 
550 next_string:
551 	while (*CURSOR != '"')
552 	{
553 		if (*CURSOR == '\n' || *CURSOR == END_OF_FILE)
554 			break;
555 
556 		ch = *CURSOR == '\\' ? ScanEscapeChar(wide) : *CURSOR++;
557 		if (wide)
558 		{
559 			wcp[len] = ch;
560 		}
561 		else
562 		{
563 			cp[len] = (char)ch;
564 		}
565 		len++;
566 		if (len >= maxlen)
567 		{
568 			AppendSTR(str, tmp, len, wide);
569 			len = 0;
570 		}
571 	}
572 
573 	if (*CURSOR != '"')
574 	{
575 		Error(&TokenCoord, "Expect \"");
576 		goto end_string;
577 	}
578 
579 	CURSOR++;
580 	SkipWhiteSpace();
581 	if (CURSOR[0] == '"')
582 	{
583 		if (wide == 1)
584 		{
585 			Error(&TokenCoord, "String wideness mismatch");
586 		}
587 		CURSOR++;
588 		goto next_string;
589 	}
590 	else if (CURSOR[0] == 'L' && CURSOR[1] == '"')
591 	{
592 		if (wide == 0)
593 		{
594 			Error(&TokenCoord, "String wideness mismatch");
595 		}
596 		CURSOR += 2;
597 		goto next_string;
598 	}
599 
600 end_string:
601 	AppendSTR(str, tmp, len, wide);
602 	TokenValue.p = str;
603 
604 	return wide ? TK_WIDESTRING : TK_STRING;
605 }
606 
ScanIdentifier(void)607 static int ScanIdentifier(void)
608 {
609 	unsigned char *start = CURSOR;
610 	int tok;
611 
612 	if (*CURSOR == 'L')
613 	{
614 		if (CURSOR[1] == '\'')
615 		{
616 			return ScanCharLiteral();
617 		}
618 		if (CURSOR[1] == '"')
619 		{
620 			return ScanStringLiteral();
621 		}
622 	}
623 
624 	CURSOR++;
625 	while (IsLetterOrDigit(*CURSOR))
626 	{
627 		CURSOR++;
628 	}
629 
630 	tok = FindKeyword((char *)start, (int)(CURSOR - start));
631 	if (tok == TK_ID)
632 	{
633 		TokenValue.p = InternName((char *)start, (int)(CURSOR - start));
634 	}
635 
636 	return tok;
637 }
638 
ScanPlus(void)639 static int ScanPlus(void)
640 {
641 	CURSOR++;
642 	if (*CURSOR == '+')
643 	{
644 		CURSOR++;
645 		return TK_INC;
646 	}
647 	else if (*CURSOR == '=')
648 	{
649 		CURSOR++;
650 		return TK_ADD_ASSIGN;
651 	}
652 	else
653 	{
654 		return TK_ADD;
655 	}
656 }
657 
ScanMinus(void)658 static int ScanMinus(void)
659 {
660 	CURSOR++;
661 	if (*CURSOR == '-')
662 	{
663 		CURSOR++;
664 		return TK_DEC;
665 	}
666 	else if (*CURSOR == '=')
667 	{
668 		CURSOR++;
669 		return TK_SUB_ASSIGN;
670 	}
671 	else if (*CURSOR == '>')
672 	{
673 		CURSOR++;
674 		return TK_POINTER;
675 	}
676 	else
677 	{
678 		return TK_SUB;
679 	}
680 }
681 
ScanStar(void)682 static int ScanStar(void)
683 {
684 	CURSOR++;
685 	if (*CURSOR == '=')
686 	{
687 		CURSOR++;
688 		return TK_MUL_ASSIGN;
689 	}
690 	else
691 	{
692 		return TK_MUL;
693 	}
694 }
695 
ScanSlash(void)696 static int ScanSlash(void)
697 {
698 	CURSOR++;
699 	if (*CURSOR == '=')
700 	{
701 		CURSOR++;
702 		return TK_DIV_ASSIGN;
703 	}
704 	else
705 	{
706 		return TK_DIV;
707 	}
708 }
709 
ScanPercent(void)710 static int ScanPercent(void)
711 {
712 	CURSOR++;
713 	if (*CURSOR == '=')
714 	{
715 		CURSOR++;
716 		return TK_MOD_ASSIGN;
717 	}
718 	else
719 	{
720 		return TK_MOD;
721 	}
722 }
723 
ScanLess(void)724 static int ScanLess(void)
725 {
726 	CURSOR++;
727 	if (*CURSOR == '<')
728 	{
729 		CURSOR++;
730 		if (*CURSOR == '=')
731 		{
732 			CURSOR++;
733 			return TK_LSHIFT_ASSIGN;
734 		}
735 		return TK_LSHIFT;
736 	}
737 	else if (*CURSOR == '=')
738 	{
739 		CURSOR++;
740 		return TK_LESS_EQ;
741 	}
742 	else
743 	{
744 		return TK_LESS;
745 	}
746 }
747 
ScanGreat(void)748 static int ScanGreat(void)
749 {
750 	CURSOR++;
751 	if (*CURSOR == '>')
752 	{
753 		CURSOR++;
754 		if (*CURSOR == '=')
755 		{
756 			CURSOR++;
757 			return TK_RSHIFT_ASSIGN;
758 		}
759 		return TK_RSHIFT;
760 	}
761 	else if (*CURSOR == '=')
762 	{
763 		CURSOR++;
764 		return TK_GREAT_EQ;
765 	}
766 	else
767 	{
768 		return TK_GREAT;
769 	}
770 }
771 
ScanExclamation(void)772 static int ScanExclamation(void)
773 {
774 	CURSOR++;
775 	if (*CURSOR == '=')
776 	{
777 		CURSOR++;
778 		return TK_UNEQUAL;
779 	}
780 	else
781 	{
782 		return TK_NOT;
783 	}
784 }
785 
ScanEqual(void)786 static int ScanEqual(void)
787 {
788 	CURSOR++;
789 	if (*CURSOR == '=')
790 	{
791 		CURSOR++;
792 		return TK_EQUAL;
793 	}
794 	else
795 	{
796 		return TK_ASSIGN;
797 	}
798 }
799 
ScanBar(void)800 static int ScanBar(void)
801 {
802 	CURSOR++;
803 	if (*CURSOR == '|')
804 	{
805 		CURSOR++;
806 		return TK_OR;
807 	}
808 	else if (*CURSOR == '=')
809 	{
810 		CURSOR++;
811 		return TK_BITOR_ASSIGN;
812 	}
813 	else
814 	{
815 		return TK_BITOR;
816 	}
817 }
818 
ScanAmpersand(void)819 static int ScanAmpersand(void)
820 {
821 	CURSOR++;
822 	if (*CURSOR == '&')
823 	{
824 		CURSOR++;
825 		return TK_AND;
826 	}
827 	else if (*CURSOR == '=')
828 	{
829 		CURSOR++;
830 		return TK_BITAND_ASSIGN;
831 	}
832 	else
833 	{
834 		return TK_BITAND;
835 	}
836 }
837 
ScanCaret(void)838 static int ScanCaret(void)
839 {
840 	CURSOR++;
841 	if (*CURSOR == '=')
842 	{
843 		CURSOR++;
844 		return TK_BITXOR_ASSIGN;
845 	}
846 	else
847 	{
848 		return TK_BITXOR;
849 	}
850 }
851 
ScanDot(void)852 static int ScanDot(void)
853 {
854 	if (IsDigit(CURSOR[1]))
855 	{
856 		return ScanFloatLiteral(CURSOR);
857 	}
858 	else if (CURSOR[1] == '.' && CURSOR[2] == '.')
859 	{
860 		CURSOR += 3;
861 		return TK_ELLIPSE;
862 	}
863 	else
864 	{
865 		CURSOR++;
866 		return TK_DOT;
867 	}
868 }
869 
870 #define SINGLE_CHAR_SCANNER(t) \
871 static int Scan##t(void)       \
872 {                              \
873     CURSOR++;                  \
874     return TK_##t;             \
875 }
876 
877 SINGLE_CHAR_SCANNER(LBRACE)
SINGLE_CHAR_SCANNER(RBRACE)878 SINGLE_CHAR_SCANNER(RBRACE)
879 SINGLE_CHAR_SCANNER(LBRACKET)
880 SINGLE_CHAR_SCANNER(RBRACKET)
881 SINGLE_CHAR_SCANNER(LPAREN)
882 SINGLE_CHAR_SCANNER(RPAREN)
883 SINGLE_CHAR_SCANNER(COMMA)
884 SINGLE_CHAR_SCANNER(SEMICOLON)
885 SINGLE_CHAR_SCANNER(COMP)
886 SINGLE_CHAR_SCANNER(QUESTION)
887 SINGLE_CHAR_SCANNER(COLON)
888 
889 static int ScanBadChar(void)
890 {
891 	Error(&TokenCoord, "illegal character:\\x%x", *CURSOR);
892 	return GetNextToken();
893 }
894 
ScanEOF(void)895 static int ScanEOF(void)
896 {
897 	return TK_END;
898 }
899 
SetupLexer(void)900 void SetupLexer(void)
901 {
902 	int i;
903 
904 	for (i = 0; i < END_OF_FILE + 1; i++)
905 	{
906 		if (IsLetter(i))
907 		{
908 			Scanners[i] = ScanIdentifier;
909 		}
910 		else if (IsDigit(i))
911 		{
912 			Scanners[i] = ScanNumericLiteral;
913 		}
914 		else
915 		{
916 			Scanners[i] = ScanBadChar;
917 		}
918 	}
919 
920 	Scanners[END_OF_FILE] = ScanEOF;
921 	Scanners['\''] = ScanCharLiteral;
922 	Scanners['"']  = ScanStringLiteral;
923 	Scanners['+']  = ScanPlus;
924 	Scanners['-']  = ScanMinus;
925 	Scanners['*']  = ScanStar;
926 	Scanners['/']  = ScanSlash;
927 	Scanners['%']  = ScanPercent;
928 	Scanners['<']  = ScanLess;
929 	Scanners['>']  = ScanGreat;
930 	Scanners['!']  = ScanExclamation;
931 	Scanners['=']  = ScanEqual;
932 	Scanners['|']  = ScanBar;
933 	Scanners['&']  = ScanAmpersand;
934 	Scanners['^']  = ScanCaret;
935 	Scanners['.']  = ScanDot;
936 	Scanners['{']  = ScanLBRACE;
937 	Scanners['}']  = ScanRBRACE;
938 	Scanners['[']  = ScanLBRACKET;
939 	Scanners[']']  = ScanRBRACKET;
940 	Scanners['(']  = ScanLPAREN;
941 	Scanners[')']  = ScanRPAREN;
942 	Scanners[',']  = ScanCOMMA;
943 	Scanners[';']  = ScanSEMICOLON;
944 	Scanners['~']  = ScanCOMP;
945 	Scanners['?']  = ScanQUESTION;
946 	Scanners[':']  = ScanCOLON;
947 
948 	if (ExtraKeywords != NULL)
949 	{
950 		char *str;
951 		struct keyword *p;
952 
953 		FOR_EACH_ITEM(char*, str, ExtraKeywords)
954 			p = keywords_;
955 			while (p->name)
956 			{
957 				if (strcmp(str, p->name) == 0)
958 				{
959 					p->len = strlen(str);
960 					break;
961 				}
962 				p++;
963 			}
964 		ENDFOR
965 	}
966 }
967 
GetNextToken(void)968 int GetNextToken(void)
969 {
970 	int tok;
971 
972 	PrevCoord = TokenCoord;
973 	SkipWhiteSpace();
974 	TokenCoord.line = LINE;
975 	TokenCoord.col  = (int)(CURSOR - LINEHEAD + 1);
976 
977 	tok = (*Scanners[*CURSOR])();
978 	return tok;
979 }
980 
BeginPeekToken(void)981 void BeginPeekToken(void)
982 {
983 	PeekPoint = CURSOR;
984 	PeekValue = TokenValue;
985 	PeekCoord = TokenCoord;
986 }
987 
EndPeekToken(void)988 void EndPeekToken(void)
989 {
990 	CURSOR = PeekPoint;
991 	TokenValue = PeekValue;
992 	TokenCoord = PeekCoord;
993 }
994 
995 
996