]> gcc.gnu.org Git - gcc.git/blob - gcc/cexp.y
(check_format): DEL isn't printable.
[gcc.git] / gcc / cexp.y
1 /* Parse C expressions for CCCP.
2 Copyright (C) 1987, 1992 Free Software Foundation.
3
4 This program is free software; you can redistribute it and/or modify it
5 under the terms of the GNU General Public License as published by the
6 Free Software Foundation; either version 2, or (at your option) any
7 later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 In other words, you are welcome to use, share and improve this program.
19 You are forbidden to forbid anyone else to use, share and improve
20 what you give them. Help stamp out software-hoarding!
21
22 Adapted from expread.y of GDB by Paul Rubin, July 1986.
23
24 /* Parse a C expression from text in a string */
25
26 %{
27 #include "config.h"
28 #include <setjmp.h>
29 /* #define YYDEBUG 1 */
30
31 #ifdef MULTIBYTE_CHARS
32 #include <stdlib.h>
33 #include <locale.h>
34 #endif
35
36 #include <stdio.h>
37
38 typedef unsigned char U_CHAR;
39
40 /* This is used for communicating lists of keywords with cccp.c. */
41 struct arglist {
42 struct arglist *next;
43 U_CHAR *name;
44 int length;
45 int argno;
46 };
47
48 /* Define a generic NULL if one hasn't already been defined. */
49
50 #ifndef NULL
51 #define NULL 0
52 #endif
53
54 #ifndef GENERIC_PTR
55 #if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
56 #define GENERIC_PTR void *
57 #else
58 #define GENERIC_PTR char *
59 #endif
60 #endif
61
62 #ifndef NULL_PTR
63 #define NULL_PTR ((GENERIC_PTR)0)
64 #endif
65
66 int yylex ();
67 void yyerror ();
68 int expression_value;
69
70 static jmp_buf parse_return_error;
71
72 /* Nonzero means count most punctuation as part of a name. */
73 static int keyword_parsing = 0;
74
75 /* some external tables of character types */
76 extern unsigned char is_idstart[], is_idchar[], is_hor_space[];
77
78 extern char *xmalloc ();
79
80 /* Flag for -pedantic. */
81 extern int pedantic;
82
83 /* Flag for -traditional. */
84 extern int traditional;
85
86 #ifndef CHAR_TYPE_SIZE
87 #define CHAR_TYPE_SIZE BITS_PER_UNIT
88 #endif
89
90 #ifndef INT_TYPE_SIZE
91 #define INT_TYPE_SIZE BITS_PER_WORD
92 #endif
93
94 #ifndef LONG_TYPE_SIZE
95 #define LONG_TYPE_SIZE BITS_PER_WORD
96 #endif
97
98 #ifndef WCHAR_TYPE_SIZE
99 #define WCHAR_TYPE_SIZE INT_TYPE_SIZE
100 #endif
101 %}
102
103 %union {
104 struct constant {long value; int unsignedp;} integer;
105 struct name {U_CHAR *address; int length;} name;
106 struct arglist *keywords;
107 int voidval;
108 char *sval;
109 }
110
111 %type <integer> exp exp1 start
112 %type <keywords> keywords
113 %token <integer> INT CHAR
114 %token <name> NAME
115 %token <integer> ERROR
116
117 %right '?' ':'
118 %left ','
119 %left OR
120 %left AND
121 %left '|'
122 %left '^'
123 %left '&'
124 %left EQUAL NOTEQUAL
125 %left '<' '>' LEQ GEQ
126 %left LSH RSH
127 %left '+' '-'
128 %left '*' '/' '%'
129 %right UNARY
130
131 /* %expect 40 */
132 \f
133 %%
134
135 start : exp1
136 { expression_value = $1.value; }
137 ;
138
139 /* Expressions, including the comma operator. */
140 exp1 : exp
141 | exp1 ',' exp
142 { if (pedantic)
143 pedwarn ("comma operator in operand of `#if'");
144 $$ = $3; }
145 ;
146
147 /* Expressions, not including the comma operator. */
148 exp : '-' exp %prec UNARY
149 { $$.value = - $2.value;
150 $$.unsignedp = $2.unsignedp; }
151 | '!' exp %prec UNARY
152 { $$.value = ! $2.value;
153 $$.unsignedp = 0; }
154 | '+' exp %prec UNARY
155 { $$ = $2; }
156 | '~' exp %prec UNARY
157 { $$.value = ~ $2.value;
158 $$.unsignedp = $2.unsignedp; }
159 | '#' NAME
160 { $$.value = check_assertion ($2.address, $2.length,
161 0, NULL_PTR);
162 $$.unsignedp = 0; }
163 | '#' NAME
164 { keyword_parsing = 1; }
165 '(' keywords ')'
166 { $$.value = check_assertion ($2.address, $2.length,
167 1, $5);
168 keyword_parsing = 0;
169 $$.unsignedp = 0; }
170 | '(' exp1 ')'
171 { $$ = $2; }
172 ;
173
174 /* Binary operators in order of decreasing precedence. */
175 exp : exp '*' exp
176 { $$.unsignedp = $1.unsignedp || $3.unsignedp;
177 if ($$.unsignedp)
178 $$.value = (unsigned) $1.value * $3.value;
179 else
180 $$.value = $1.value * $3.value; }
181 | exp '/' exp
182 { if ($3.value == 0)
183 {
184 error ("division by zero in #if");
185 $3.value = 1;
186 }
187 $$.unsignedp = $1.unsignedp || $3.unsignedp;
188 if ($$.unsignedp)
189 $$.value = (unsigned) $1.value / $3.value;
190 else
191 $$.value = $1.value / $3.value; }
192 | exp '%' exp
193 { if ($3.value == 0)
194 {
195 error ("division by zero in #if");
196 $3.value = 1;
197 }
198 $$.unsignedp = $1.unsignedp || $3.unsignedp;
199 if ($$.unsignedp)
200 $$.value = (unsigned) $1.value % $3.value;
201 else
202 $$.value = $1.value % $3.value; }
203 | exp '+' exp
204 { $$.value = $1.value + $3.value;
205 $$.unsignedp = $1.unsignedp || $3.unsignedp; }
206 | exp '-' exp
207 { $$.value = $1.value - $3.value;
208 $$.unsignedp = $1.unsignedp || $3.unsignedp; }
209 | exp LSH exp
210 { $$.unsignedp = $1.unsignedp;
211 if ($$.unsignedp)
212 $$.value = (unsigned) $1.value << $3.value;
213 else
214 $$.value = $1.value << $3.value; }
215 | exp RSH exp
216 { $$.unsignedp = $1.unsignedp;
217 if ($$.unsignedp)
218 $$.value = (unsigned) $1.value >> $3.value;
219 else
220 $$.value = $1.value >> $3.value; }
221 | exp EQUAL exp
222 { $$.value = ($1.value == $3.value);
223 $$.unsignedp = 0; }
224 | exp NOTEQUAL exp
225 { $$.value = ($1.value != $3.value);
226 $$.unsignedp = 0; }
227 | exp LEQ exp
228 { $$.unsignedp = 0;
229 if ($1.unsignedp || $3.unsignedp)
230 $$.value = (unsigned) $1.value <= $3.value;
231 else
232 $$.value = $1.value <= $3.value; }
233 | exp GEQ exp
234 { $$.unsignedp = 0;
235 if ($1.unsignedp || $3.unsignedp)
236 $$.value = (unsigned) $1.value >= $3.value;
237 else
238 $$.value = $1.value >= $3.value; }
239 | exp '<' exp
240 { $$.unsignedp = 0;
241 if ($1.unsignedp || $3.unsignedp)
242 $$.value = (unsigned) $1.value < $3.value;
243 else
244 $$.value = $1.value < $3.value; }
245 | exp '>' exp
246 { $$.unsignedp = 0;
247 if ($1.unsignedp || $3.unsignedp)
248 $$.value = (unsigned) $1.value > $3.value;
249 else
250 $$.value = $1.value > $3.value; }
251 | exp '&' exp
252 { $$.value = $1.value & $3.value;
253 $$.unsignedp = $1.unsignedp || $3.unsignedp; }
254 | exp '^' exp
255 { $$.value = $1.value ^ $3.value;
256 $$.unsignedp = $1.unsignedp || $3.unsignedp; }
257 | exp '|' exp
258 { $$.value = $1.value | $3.value;
259 $$.unsignedp = $1.unsignedp || $3.unsignedp; }
260 | exp AND exp
261 { $$.value = ($1.value && $3.value);
262 $$.unsignedp = 0; }
263 | exp OR exp
264 { $$.value = ($1.value || $3.value);
265 $$.unsignedp = 0; }
266 | exp '?' exp ':' exp
267 { $$.value = $1.value ? $3.value : $5.value;
268 $$.unsignedp = $3.unsignedp || $5.unsignedp; }
269 | INT
270 { $$ = yylval.integer; }
271 | CHAR
272 { $$ = yylval.integer; }
273 | NAME
274 { $$.value = 0;
275 $$.unsignedp = 0; }
276 ;
277
278 keywords :
279 { $$ = 0; }
280 | '(' keywords ')' keywords
281 { struct arglist *temp;
282 $$ = (struct arglist *) xmalloc (sizeof (struct arglist));
283 $$->next = $2;
284 $$->name = (U_CHAR *) "(";
285 $$->length = 1;
286 temp = $$;
287 while (temp != 0 && temp->next != 0)
288 temp = temp->next;
289 temp->next = (struct arglist *) xmalloc (sizeof (struct arglist));
290 temp->next->next = $4;
291 temp->next->name = (U_CHAR *) ")";
292 temp->next->length = 1; }
293 | NAME keywords
294 { $$ = (struct arglist *) xmalloc (sizeof (struct arglist));
295 $$->name = $1.address;
296 $$->length = $1.length;
297 $$->next = $2; }
298 ;
299 %%
300 \f
301 /* During parsing of a C expression, the pointer to the next character
302 is in this variable. */
303
304 static char *lexptr;
305
306 /* Take care of parsing a number (anything that starts with a digit).
307 Set yylval and return the token type; update lexptr.
308 LEN is the number of characters in it. */
309
310 /* maybe needs to actually deal with floating point numbers */
311
312 int
313 parse_number (olen)
314 int olen;
315 {
316 register char *p = lexptr;
317 register long n = 0;
318 register int c;
319 register int base = 10;
320 register int len = olen;
321
322 for (c = 0; c < len; c++)
323 if (p[c] == '.') {
324 /* It's a float since it contains a point. */
325 yyerror ("floating point numbers not allowed in #if expressions");
326 return ERROR;
327 }
328
329 yylval.integer.unsignedp = 0;
330
331 if (len >= 3 && (!strncmp (p, "0x", 2) || !strncmp (p, "0X", 2))) {
332 p += 2;
333 base = 16;
334 len -= 2;
335 }
336 else if (*p == '0')
337 base = 8;
338
339 while (len > 0) {
340 c = *p++;
341 len--;
342 if (c >= 'A' && c <= 'Z') c += 'a' - 'A';
343
344 if (c >= '0' && c <= '9') {
345 n *= base;
346 n += c - '0';
347 } else if (base == 16 && c >= 'a' && c <= 'f') {
348 n *= base;
349 n += c - 'a' + 10;
350 } else {
351 /* `l' means long, and `u' means unsigned. */
352 while (1) {
353 if (c == 'l' || c == 'L')
354 ;
355 else if (c == 'u' || c == 'U')
356 yylval.integer.unsignedp = 1;
357 else
358 break;
359
360 if (len == 0)
361 break;
362 c = *p++;
363 len--;
364 }
365 /* Don't look for any more digits after the suffixes. */
366 break;
367 }
368 }
369
370 if (len != 0) {
371 yyerror ("Invalid number in #if expression");
372 return ERROR;
373 }
374
375 /* If too big to be signed, consider it unsigned. */
376 if (n < 0)
377 yylval.integer.unsignedp = 1;
378
379 lexptr = p;
380 yylval.integer.value = n;
381 return INT;
382 }
383
384 struct token {
385 char *operator;
386 int token;
387 };
388
389 static struct token tokentab2[] = {
390 {"&&", AND},
391 {"||", OR},
392 {"<<", LSH},
393 {">>", RSH},
394 {"==", EQUAL},
395 {"!=", NOTEQUAL},
396 {"<=", LEQ},
397 {">=", GEQ},
398 {"++", ERROR},
399 {"--", ERROR},
400 {NULL, ERROR}
401 };
402
403 /* Read one token, getting characters through lexptr. */
404
405 int
406 yylex ()
407 {
408 register int c;
409 register int namelen;
410 register char *tokstart;
411 register struct token *toktab;
412 int wide_flag;
413
414 retry:
415
416 tokstart = lexptr;
417 c = *tokstart;
418 /* See if it is a special token of length 2. */
419 if (! keyword_parsing)
420 for (toktab = tokentab2; toktab->operator != NULL; toktab++)
421 if (c == *toktab->operator && tokstart[1] == toktab->operator[1]) {
422 lexptr += 2;
423 if (toktab->token == ERROR)
424 {
425 char *buf = (char *) alloca (40);
426 sprintf (buf, "`%s' not allowed in operand of `#if'", toktab->operator);
427 yyerror (buf);
428 }
429 return toktab->token;
430 }
431
432 switch (c) {
433 case 0:
434 return 0;
435
436 case ' ':
437 case '\t':
438 case '\r':
439 case '\n':
440 lexptr++;
441 goto retry;
442
443 case 'L':
444 /* Capital L may start a wide-string or wide-character constant. */
445 if (lexptr[1] == '\'')
446 {
447 lexptr++;
448 wide_flag = 1;
449 goto char_constant;
450 }
451 if (lexptr[1] == '"')
452 {
453 lexptr++;
454 wide_flag = 1;
455 goto string_constant;
456 }
457 break;
458
459 case '\'':
460 wide_flag = 0;
461 char_constant:
462 lexptr++;
463 if (keyword_parsing) {
464 char *start_ptr = lexptr - 1;
465 while (1) {
466 c = *lexptr++;
467 if (c == '\\')
468 c = parse_escape (&lexptr);
469 else if (c == '\'')
470 break;
471 }
472 yylval.name.address = (U_CHAR *) tokstart;
473 yylval.name.length = lexptr - start_ptr;
474 return NAME;
475 }
476
477 /* This code for reading a character constant
478 handles multicharacter constants and wide characters.
479 It is mostly copied from c-lex.c. */
480 {
481 register int result = 0;
482 register num_chars = 0;
483 unsigned width = CHAR_TYPE_SIZE;
484 int max_chars;
485 char *token_buffer;
486
487 if (wide_flag)
488 {
489 width = WCHAR_TYPE_SIZE;
490 #ifdef MULTIBYTE_CHARS
491 max_chars = MB_CUR_MAX;
492 #else
493 max_chars = 1;
494 #endif
495 }
496 else
497 max_chars = LONG_TYPE_SIZE / width;
498
499 token_buffer = (char *) alloca (max_chars + 1);
500
501 while (1)
502 {
503 c = *lexptr++;
504
505 if (c == '\'' || c == EOF)
506 break;
507
508 if (c == '\\')
509 {
510 c = parse_escape (&lexptr);
511 if (width < HOST_BITS_PER_INT
512 && (unsigned) c >= (1 << width))
513 pedwarn ("escape sequence out of range for character");
514 }
515
516 num_chars++;
517
518 /* Merge character into result; ignore excess chars. */
519 if (num_chars < max_chars + 1)
520 {
521 if (width < HOST_BITS_PER_INT)
522 result = (result << width) | (c & ((1 << width) - 1));
523 else
524 result = c;
525 token_buffer[num_chars - 1] = c;
526 }
527 }
528
529 token_buffer[num_chars] = 0;
530
531 if (c != '\'')
532 error ("malformatted character constant");
533 else if (num_chars == 0)
534 error ("empty character constant");
535 else if (num_chars > max_chars)
536 {
537 num_chars = max_chars;
538 error ("character constant too long");
539 }
540 else if (num_chars != 1 && ! traditional)
541 warning ("multi-character character constant");
542
543 /* If char type is signed, sign-extend the constant. */
544 if (! wide_flag)
545 {
546 int num_bits = num_chars * width;
547
548 if (lookup ("__CHAR_UNSIGNED__", sizeof ("__CHAR_UNSIGNED__")-1, -1)
549 || ((result >> (num_bits - 1)) & 1) == 0)
550 yylval.integer.value
551 = result & ((unsigned) ~0 >> (HOST_BITS_PER_INT - num_bits));
552 else
553 yylval.integer.value
554 = result | ~((unsigned) ~0 >> (HOST_BITS_PER_INT - num_bits));
555 }
556 else
557 {
558 #ifdef MULTIBYTE_CHARS
559 /* Set the initial shift state and convert the next sequence. */
560 result = 0;
561 /* In all locales L'\0' is zero and mbtowc will return zero,
562 so don't use it. */
563 if (num_chars > 1
564 || (num_chars == 1 && token_buffer[0] != '\0'))
565 {
566 wchar_t wc;
567 (void) mbtowc (NULL_PTR, NULL_PTR, 0);
568 if (mbtowc (& wc, token_buffer, num_chars) == num_chars)
569 result = wc;
570 else
571 warning ("Ignoring invalid multibyte character");
572 }
573 #endif
574 yylval.integer.value = result;
575 }
576 }
577
578 /* This is always a signed type. */
579 yylval.integer.unsignedp = 0;
580
581 return CHAR;
582
583 /* some of these chars are invalid in constant expressions;
584 maybe do something about them later */
585 case '/':
586 case '+':
587 case '-':
588 case '*':
589 case '%':
590 case '|':
591 case '&':
592 case '^':
593 case '~':
594 case '!':
595 case '@':
596 case '<':
597 case '>':
598 case '[':
599 case ']':
600 case '.':
601 case '?':
602 case ':':
603 case '=':
604 case '{':
605 case '}':
606 case ',':
607 case '#':
608 if (keyword_parsing)
609 break;
610 case '(':
611 case ')':
612 lexptr++;
613 return c;
614
615 case '"':
616 string_constant:
617 if (keyword_parsing) {
618 char *start_ptr = lexptr;
619 lexptr++;
620 while (1) {
621 c = *lexptr++;
622 if (c == '\\')
623 c = parse_escape (&lexptr);
624 else if (c == '"')
625 break;
626 }
627 yylval.name.address = (U_CHAR *) tokstart;
628 yylval.name.length = lexptr - start_ptr;
629 return NAME;
630 }
631 yyerror ("string constants not allowed in #if expressions");
632 return ERROR;
633 }
634
635 if (c >= '0' && c <= '9' && !keyword_parsing) {
636 /* It's a number */
637 for (namelen = 0;
638 c = tokstart[namelen], is_idchar[c] || c == '.';
639 namelen++)
640 ;
641 return parse_number (namelen);
642 }
643
644 /* It is a name. See how long it is. */
645
646 if (keyword_parsing) {
647 for (namelen = 0;; namelen++) {
648 if (is_hor_space[tokstart[namelen]])
649 break;
650 if (tokstart[namelen] == '(' || tokstart[namelen] == ')')
651 break;
652 if (tokstart[namelen] == '"' || tokstart[namelen] == '\'')
653 break;
654 }
655 } else {
656 if (!is_idstart[c]) {
657 yyerror ("Invalid token in expression");
658 return ERROR;
659 }
660
661 for (namelen = 0; is_idchar[tokstart[namelen]]; namelen++)
662 ;
663 }
664
665 lexptr += namelen;
666 yylval.name.address = (U_CHAR *) tokstart;
667 yylval.name.length = namelen;
668 return NAME;
669 }
670
671
672 /* Parse a C escape sequence. STRING_PTR points to a variable
673 containing a pointer to the string to parse. That pointer
674 is updated past the characters we use. The value of the
675 escape sequence is returned.
676
677 A negative value means the sequence \ newline was seen,
678 which is supposed to be equivalent to nothing at all.
679
680 If \ is followed by a null character, we return a negative
681 value and leave the string pointer pointing at the null character.
682
683 If \ is followed by 000, we return 0 and leave the string pointer
684 after the zeros. A value of 0 does not mean end of string. */
685
686 int
687 parse_escape (string_ptr)
688 char **string_ptr;
689 {
690 register int c = *(*string_ptr)++;
691 switch (c)
692 {
693 case 'a':
694 return TARGET_BELL;
695 case 'b':
696 return TARGET_BS;
697 case 'e':
698 return 033;
699 case 'f':
700 return TARGET_FF;
701 case 'n':
702 return TARGET_NEWLINE;
703 case 'r':
704 return TARGET_CR;
705 case 't':
706 return TARGET_TAB;
707 case 'v':
708 return TARGET_VT;
709 case '\n':
710 return -2;
711 case 0:
712 (*string_ptr)--;
713 return 0;
714 case '^':
715 c = *(*string_ptr)++;
716 if (c == '\\')
717 c = parse_escape (string_ptr);
718 if (c == '?')
719 return 0177;
720 return (c & 0200) | (c & 037);
721
722 case '0':
723 case '1':
724 case '2':
725 case '3':
726 case '4':
727 case '5':
728 case '6':
729 case '7':
730 {
731 register int i = c - '0';
732 register int count = 0;
733 while (++count < 3)
734 {
735 c = *(*string_ptr)++;
736 if (c >= '0' && c <= '7')
737 i = (i << 3) + c - '0';
738 else
739 {
740 (*string_ptr)--;
741 break;
742 }
743 }
744 if ((i & ~((1 << CHAR_TYPE_SIZE) - 1)) != 0)
745 {
746 i &= (1 << CHAR_TYPE_SIZE) - 1;
747 warning ("octal character constant does not fit in a byte");
748 }
749 return i;
750 }
751 case 'x':
752 {
753 register int i = 0;
754 for (;;)
755 {
756 c = *(*string_ptr)++;
757 if (c >= '0' && c <= '9')
758 i = (i << 4) + c - '0';
759 else if (c >= 'a' && c <= 'f')
760 i = (i << 4) + c - 'a' + 10;
761 else if (c >= 'A' && c <= 'F')
762 i = (i << 4) + c - 'A' + 10;
763 else
764 {
765 (*string_ptr)--;
766 break;
767 }
768 }
769 if ((i & ~((1 << BITS_PER_UNIT) - 1)) != 0)
770 {
771 i &= (1 << BITS_PER_UNIT) - 1;
772 warning ("hex character constant does not fit in a byte");
773 }
774 return i;
775 }
776 default:
777 return c;
778 }
779 }
780
781 void
782 yyerror (s)
783 char *s;
784 {
785 error (s);
786 longjmp (parse_return_error, 1);
787 }
788 \f
789 /* This page contains the entry point to this file. */
790
791 /* Parse STRING as an expression, and complain if this fails
792 to use up all of the contents of STRING. */
793 /* We do not support C comments. They should be removed before
794 this function is called. */
795
796 int
797 parse_c_expression (string)
798 char *string;
799 {
800 lexptr = string;
801
802 if (lexptr == 0 || *lexptr == 0) {
803 error ("empty #if expression");
804 return 0; /* don't include the #if group */
805 }
806
807 /* if there is some sort of scanning error, just return 0 and assume
808 the parsing routine has printed an error message somewhere.
809 there is surely a better thing to do than this. */
810 if (setjmp (parse_return_error))
811 return 0;
812
813 if (yyparse ())
814 return 0; /* actually this is never reached
815 the way things stand. */
816 if (*lexptr)
817 error ("Junk after end of expression.");
818
819 return expression_value; /* set by yyparse () */
820 }
821 \f
822 #ifdef TEST_EXP_READER
823 extern int yydebug;
824
825 /* Main program for testing purposes. */
826 int
827 main ()
828 {
829 int n, c;
830 char buf[1024];
831
832 /*
833 yydebug = 1;
834 */
835 initialize_random_junk ();
836
837 for (;;) {
838 printf ("enter expression: ");
839 n = 0;
840 while ((buf[n] = getchar ()) != '\n' && buf[n] != EOF)
841 n++;
842 if (buf[n] == EOF)
843 break;
844 buf[n] = '\0';
845 printf ("parser returned %d\n", parse_c_expression (buf));
846 }
847
848 return 0;
849 }
850
851 /* table to tell if char can be part of a C identifier. */
852 unsigned char is_idchar[256];
853 /* table to tell if char can be first char of a c identifier. */
854 unsigned char is_idstart[256];
855 /* table to tell if c is horizontal space. isspace () thinks that
856 newline is space; this is not a good idea for this program. */
857 char is_hor_space[256];
858
859 /*
860 * initialize random junk in the hash table and maybe other places
861 */
862 initialize_random_junk ()
863 {
864 register int i;
865
866 /*
867 * Set up is_idchar and is_idstart tables. These should be
868 * faster than saying (is_alpha (c) || c == '_'), etc.
869 * Must do set up these things before calling any routines tthat
870 * refer to them.
871 */
872 for (i = 'a'; i <= 'z'; i++) {
873 ++is_idchar[i - 'a' + 'A'];
874 ++is_idchar[i];
875 ++is_idstart[i - 'a' + 'A'];
876 ++is_idstart[i];
877 }
878 for (i = '0'; i <= '9'; i++)
879 ++is_idchar[i];
880 ++is_idchar['_'];
881 ++is_idstart['_'];
882 #if DOLLARS_IN_IDENTIFIERS
883 ++is_idchar['$'];
884 ++is_idstart['$'];
885 #endif
886
887 /* horizontal space table */
888 ++is_hor_space[' '];
889 ++is_hor_space['\t'];
890 }
891
892 error (msg)
893 {
894 printf ("error: %s\n", msg);
895 }
896
897 warning (msg)
898 {
899 printf ("warning: %s\n", msg);
900 }
901
902 struct hashnode *
903 lookup (name, len, hash)
904 char *name;
905 int len;
906 int hash;
907 {
908 return (DEFAULT_SIGNED_CHAR) ? 0 : ((struct hashnode *) -1);
909 }
910 #endif
This page took 1.204238 seconds and 5 git commands to generate.