8 enum { BLANK
=01, NEWLINE
=02, LETTER
=04,
9 DIGIT
=010, HEX
=020, OTHER
=040 };
11 static unsigned char map
[256] = { /* 000 nul */ 0,
76 /* 101 A */ LETTER
|HEX
,
77 /* 102 B */ LETTER
|HEX
,
78 /* 103 C */ LETTER
|HEX
,
79 /* 104 D */ LETTER
|HEX
,
80 /* 105 E */ LETTER
|HEX
,
81 /* 106 F */ LETTER
|HEX
,
108 /* 141 a */ LETTER
|HEX
,
109 /* 142 b */ LETTER
|HEX
,
110 /* 143 c */ LETTER
|HEX
,
111 /* 144 d */ LETTER
|HEX
,
112 /* 145 e */ LETTER
|HEX
,
113 /* 146 f */ LETTER
|HEX
,
137 /* 176 ~ */ OTHER
, };
138 static struct symbol tval
;
139 static char cbuf
[BUFSIZE
+1];
140 static unsigned int wcbuf
[BUFSIZE
+1];
142 Coordinate src
; /* current source coordinate */
144 char *token
; /* current token */
145 Symbol tsym
; /* symbol table entry for current token */
147 static void *cput(int c
, void *cl
);
148 static void *wcput(int c
, void *cl
);
149 static void *scon(int q
, void *put(int c
, void *cl
), void *cl
);
150 static int backslash(int q
);
151 static Symbol
fcon(void);
152 static Symbol
icon(unsigned long, int, int);
153 static void ppnumber(char *);
157 register unsigned char *rcp
= cp
;
158 while (map
[*rcp
]&BLANK
)
160 if (limit
- rcp
< MAXTOKEN
) {
166 src
.x
= (char *)rcp
- line
;
170 case '/': if (*rcp
== '*') {
172 for (rcp
++; *rcp
!= '/' || c
!= '*'; )
173 if (map
[*rcp
]&NEWLINE
) {
186 error("unclosed comment\n");
192 if (*rcp
== '=') return cp
++, LEQ
;
193 if (*rcp
== '<') return cp
++, LSHIFT
;
196 if (*rcp
== '=') return cp
++, GEQ
;
197 if (*rcp
== '>') return cp
++, RSHIFT
;
200 if (*rcp
== '>') return cp
++, DEREF
;
201 if (*rcp
== '-') return cp
++, DECR
;
203 case '=': return *rcp
== '=' ? cp
++, EQL
: '=';
204 case '!': return *rcp
== '=' ? cp
++, NEQ
: '!';
205 case '|': return *rcp
== '|' ? cp
++, OROR
: '|';
206 case '&': return *rcp
== '&' ? cp
++, ANDAND
: '&';
207 case '+': return *rcp
== '+' ? cp
++, INCR
: '+';
208 case ';': case ',': case ':':
209 case '*': case '~': case '%': case '^': case '?':
210 case '[': case ']': case '{': case '}': case '(': case ')':
212 case '\n': case '\v': case '\r': case '\f':
222 && !(map
[rcp
[1]]&(DIGIT
|LETTER
))) {
228 && !(map
[rcp
[2]]&(DIGIT
|LETTER
))) {
230 tsym
= inttype
->u
.sym
;
234 case 'h': case 'j': case 'k': case 'm': case 'n': case 'o':
235 case 'p': case 'q': case 'x': case 'y': case 'z':
236 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
237 case 'G': case 'H': case 'I': case 'J': case 'K':
238 case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
239 case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
242 if (limit
- rcp
< MAXLINE
) {
248 token
= (char *)rcp
- 1;
249 while (map
[*rcp
]&(DIGIT
|LETTER
))
251 token
= stringn(token
, (char *)rcp
- token
);
252 tsym
= lookup(token
, identifiers
);
255 case '0': case '1': case '2': case '3': case '4':
256 case '5': case '6': case '7': case '8': case '9': {
258 if (limit
- rcp
< MAXLINE
) {
264 token
= (char *)rcp
- 1;
265 if (*token
== '0' && (*rcp
== 'x' || *rcp
== 'X')) {
270 else if (*rcp
>= 'a' && *rcp
<= 'f')
272 else if (*rcp
>= 'A' && *rcp
<= 'F')
281 if ((char *)rcp
- token
<= 2)
282 error("invalid hexadecimal constant `%S'\n", token
, (char *)rcp
-token
);
284 tsym
= icon(n
, overflow
, 16);
285 } else if (*token
== '0') {
286 int err
= 0, overflow
= 0;
287 for ( ; map
[*rcp
]&DIGIT
; rcp
++) {
288 if (*rcp
== '8' || *rcp
== '9')
293 n
= (n
<<3) + (*rcp
- '0');
295 if (*rcp
== '.' || *rcp
== 'e' || *rcp
== 'E') {
301 tsym
= icon(n
, overflow
, 8);
303 error("invalid octal constant `%S'\n", token
, (char*)cp
-token
);
306 for (n
= *token
- '0'; map
[*rcp
]&DIGIT
; ) {
307 int d
= *rcp
++ - '0';
308 if (n
> (ULONG_MAX
- d
)/10)
313 if (*rcp
== '.' || *rcp
== 'e' || *rcp
== 'E') {
319 tsym
= icon(n
, overflow
, 10);
324 if (rcp
[0] == '.' && rcp
[1] == '.') {
328 if ((map
[*rcp
]&DIGIT
) == 0)
330 if (limit
- rcp
< MAXLINE
) {
342 unsigned int *s
= scon(*cp
, wcput
, wcbuf
);
344 warning("excess characters in wide-character literal ignored\n");
345 tval
.type
= widechar
;
346 tval
.u
.c
.v
.u
= wcbuf
[0];
349 } else if (*rcp
== '"') {
350 unsigned int *s
= scon(*cp
, wcput
, wcbuf
);
351 tval
.type
= array(widechar
, s
- wcbuf
, 0);
352 tval
.u
.c
.v
.p
= wcbuf
;
358 char *s
= scon(*--cp
, cput
, cbuf
);
360 warning("excess characters in multibyte character literal ignored\n");
362 if (chartype
->op
== INT
)
363 tval
.u
.c
.v
.i
= extend(cbuf
[0], chartype
);
365 tval
.u
.c
.v
.i
= cbuf
[0]&0xFF;
370 char *s
= scon(*--cp
, cput
, cbuf
);
371 tval
.type
= array(chartype
, s
- cbuf
, 0);
380 && !(map
[rcp
[3]]&(DIGIT
|LETTER
))) {
390 && !(map
[rcp
[4]]&(DIGIT
|LETTER
))) {
399 && !(map
[rcp
[3]]&(DIGIT
|LETTER
))) {
406 && !(map
[rcp
[3]]&(DIGIT
|LETTER
))) {
408 tsym
= chartype
->u
.sym
;
415 && !(map
[rcp
[4]]&(DIGIT
|LETTER
))) {
426 && !(map
[rcp
[7]]&(DIGIT
|LETTER
))) {
438 && !(map
[rcp
[6]]&(DIGIT
|LETTER
))) {
447 && !(map
[rcp
[5]]&(DIGIT
|LETTER
))) {
449 tsym
= doubletype
->u
.sym
;
453 && !(map
[rcp
[1]]&(DIGIT
|LETTER
))) {
462 && !(map
[rcp
[3]]&(DIGIT
|LETTER
))) {
469 && !(map
[rcp
[3]]&(DIGIT
|LETTER
))) {
478 && !(map
[rcp
[5]]&(DIGIT
|LETTER
))) {
488 && !(map
[rcp
[4]]&(DIGIT
|LETTER
))) {
490 tsym
= floattype
->u
.sym
;
495 && !(map
[rcp
[2]]&(DIGIT
|LETTER
))) {
504 && !(map
[rcp
[3]]&(DIGIT
|LETTER
))) {
513 && !(map
[rcp
[3]]&(DIGIT
|LETTER
))) {
526 && !(map
[rcp
[7]]&(DIGIT
|LETTER
))) {
535 && !(map
[rcp
[5]]&(DIGIT
|LETTER
))) {
545 && !(map
[rcp
[4]]&(DIGIT
|LETTER
))) {
554 && !(map
[rcp
[5]]&(DIGIT
|LETTER
))) {
563 && !(map
[rcp
[5]]&(DIGIT
|LETTER
))) {
572 && !(map
[rcp
[5]]&(DIGIT
|LETTER
))) {
581 && !(map
[rcp
[5]]&(DIGIT
|LETTER
))) {
590 && !(map
[rcp
[5]]&(DIGIT
|LETTER
))) {
602 && !(map
[rcp
[6]]&(DIGIT
|LETTER
))) {
612 && !(map
[rcp
[4]]&(DIGIT
|LETTER
))) {
623 && !(map
[rcp
[7]]&(DIGIT
|LETTER
))) {
632 && !(map
[rcp
[3]]&(DIGIT
|LETTER
))) {
634 tsym
= voidtype
->u
.sym
;
644 && !(map
[rcp
[7]]&(DIGIT
|LETTER
))) {
654 && !(map
[rcp
[4]]&(DIGIT
|LETTER
))) {
669 && !(map
[rcp
[9]]&(DIGIT
|LETTER
))) {
682 && !(map
[rcp
[9]]&(DIGIT
|LETTER
))) {
688 if ((map
[cp
[-1]]&BLANK
) == 0) {
689 if (cp
[-1] < ' ' || cp
[-1] >= 0177)
690 error("illegal character `\\0%o'\n", cp
[-1]);
692 error("illegal character `%c'\n", cp
[-1]);
697 static Symbol
icon(unsigned long n
, int overflow
, int base
) {
698 if (((*cp
=='u'||*cp
=='U') && (cp
[1]=='l'||cp
[1]=='L'))
699 || ((*cp
=='l'||*cp
=='L') && (cp
[1]=='u'||cp
[1]=='U'))) {
700 tval
.type
= unsignedlong
;
702 } else if (*cp
== 'u' || *cp
== 'U') {
703 if (overflow
|| n
> unsignedtype
->u
.sym
->u
.limits
.max
.i
)
704 tval
.type
= unsignedlong
;
706 tval
.type
= unsignedtype
;
708 } else if (*cp
== 'l' || *cp
== 'L') {
709 if (overflow
|| n
> longtype
->u
.sym
->u
.limits
.max
.i
)
710 tval
.type
= unsignedlong
;
712 tval
.type
= longtype
;
714 } else if (overflow
|| n
> longtype
->u
.sym
->u
.limits
.max
.i
)
715 tval
.type
= unsignedlong
;
716 else if (n
> inttype
->u
.sym
->u
.limits
.max
.i
)
717 tval
.type
= longtype
;
718 else if (base
!= 10 && n
> inttype
->u
.sym
->u
.limits
.max
.i
)
719 tval
.type
= unsignedtype
;
722 switch (tval
.type
->op
) {
724 if (overflow
|| n
> tval
.type
->u
.sym
->u
.limits
.max
.i
) {
725 warning("overflow in constant `%S'\n", token
,
727 tval
.u
.c
.v
.i
= tval
.type
->u
.sym
->u
.limits
.max
.i
;
732 if (overflow
|| n
> tval
.type
->u
.sym
->u
.limits
.max
.u
) {
733 warning("overflow in constant `%S'\n", token
,
735 tval
.u
.c
.v
.u
= tval
.type
->u
.sym
->u
.limits
.max
.u
;
744 static void ppnumber(char *which
) {
745 unsigned char *rcp
= cp
--;
747 for ( ; (map
[*cp
]&(DIGIT
|LETTER
)) || *cp
== '.'; cp
++)
748 if ((cp
[0] == 'E' || cp
[0] == 'e')
749 && (cp
[1] == '-' || cp
[1] == '+'))
752 error("`%S' is a preprocessing number but an invalid %s constant\n", token
,
754 (char*)cp
-token
, which
);
756 static Symbol
fcon(void) {
760 while (map
[*cp
]&DIGIT
);
761 if (*cp
== 'e' || *cp
== 'E') {
762 if (*++cp
== '-' || *cp
== '+')
767 while (map
[*cp
]&DIGIT
);
769 error("invalid floating constant `%S'\n", token
,
774 tval
.u
.c
.v
.d
= strtod(token
, NULL
);
776 warning("overflow in floating constant `%S'\n", token
,
778 if (*cp
== 'f' || *cp
== 'F') {
780 if (tval
.u
.c
.v
.d
> floattype
->u
.sym
->u
.limits
.max
.d
)
781 warning("overflow in floating constant `%S'\n", token
,
783 tval
.type
= floattype
;
784 } else if (*cp
== 'l' || *cp
== 'L') {
786 tval
.type
= longdouble
;
788 if (tval
.u
.c
.v
.d
> doubletype
->u
.sym
->u
.limits
.max
.d
)
789 warning("overflow in floating constant `%S'\n", token
,
791 tval
.type
= doubletype
;
793 ppnumber("floating");
797 static void *cput(int c
, void *cl
) {
800 if (c
< 0 || c
> 255)
801 warning("overflow in escape sequence with resulting value `%d'\n", c
);
806 static void *wcput(int c
, void *cl
) {
807 unsigned int *s
= cl
;
813 static void *scon(int q
, void *put(int c
, void *cl
), void *cl
) {
820 if (map
[*cp
]&NEWLINE
) {
831 if (map
[*cp
]&NEWLINE
) {
837 if (limit
- cp
< MAXTOKEN
)
840 } else if (c
< 0 || c
> 255 || map
[c
] == 0)
848 error("missing %c\n", q
);
849 } while (q
== '"' && getchr() == '"');
852 error("%s literal too long\n", q
== '"' ? "string" : "character");
853 if (Aflag
>= 2 && q
== '"' && n
> 509)
854 warning("more than 509 characters in a string literal\n");
855 if (Aflag
>= 2 && nbad
> 0)
856 warning("%s literal contains non-portable characters\n",
857 q
== '"' ? "string" : "character");
862 while (map
[*cp
]&BLANK
)
864 if (!(map
[*cp
]&NEWLINE
))
872 static int backslash(int q
) {
877 case 'b': return '\b';
878 case 'f': return '\f';
879 case 'n': return '\n';
880 case 'r': return '\r';
881 case 't': return '\t';
882 case 'v': return '\v';
883 case '\'': case '"': case '\\': case '\?': break;
886 if ((map
[*cp
]&(DIGIT
|HEX
)) == 0) {
887 if (*cp
< ' ' || *cp
== 0177)
888 error("ill-formed hexadecimal escape sequence\n");
890 error("ill-formed hexadecimal escape sequence `\\x%c'\n", *cp
);
895 for (c
= 0; map
[*cp
]&(DIGIT
|HEX
); cp
++) {
896 if (c
>> (8*widechar
->size
- 4))
899 c
= (c
<<4) + *cp
- '0';
901 c
= (c
<<4) + (*cp
&~040) - 'A' + 10;
904 warning("overflow in hexadecimal escape sequence\n");
905 return c
&ones(8*widechar
->size
);
907 case '0': case '1': case '2': case '3':
908 case '4': case '5': case '6': case '7':
910 if (*cp
>= '0' && *cp
<= '7') {
911 c
= (c
<<3) + *cp
++ - '0';
912 if (*cp
>= '0' && *cp
<= '7')
913 c
= (c
<<3) + *cp
++ - '0';
917 if (cp
[-1] < ' ' || cp
[-1] >= 0177)
918 warning("unrecognized character escape sequence\n");
920 warning("unrecognized character escape sequence `\\%c'\n", cp
[-1]);