scan.l revision 1.56 1 %{
2 /* $NetBSD: scan.l,v 1.56 2014/04/18 01:39:57 christos Exp $ */
3
4 /*
5 * Copyright (c) 1996 Christopher G. Demetriou. All Rights Reserved.
6 * Copyright (c) 1994, 1995 Jochen Pohl
7 * All Rights Reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by Jochen Pohl for
20 * The NetBSD Project.
21 * 4. The name of the author may not be used to endorse or promote products
22 * derived from this software without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 */
35
36 #include <sys/cdefs.h>
37 #if defined(__RCSID) && !defined(lint)
38 __RCSID("$NetBSD: scan.l,v 1.56 2014/04/18 01:39:57 christos Exp $");
39 #endif
40
41 #include <stdlib.h>
42 #include <string.h>
43 #include <limits.h>
44 #include <float.h>
45 #include <ctype.h>
46 #include <errno.h>
47 #include <math.h>
48
49 #include "lint1.h"
50 #include "cgram.h"
51
52 #define CHAR_MASK (~(~0 << CHAR_BIT))
53
54 /* Current position (its also updated when an included file is parsed) */
55 pos_t curr_pos = { 1, "", 0 };
56
57 /*
58 * Current position in C source (not updated when an included file is
59 * parsed).
60 */
61 pos_t csrc_pos = { 1, "", 0 };
62
63 /* Are we parsing a gcc attribute? */
64 int attron;
65
66 static void incline(void);
67 static void badchar(int);
68 static sbuf_t *allocsb(void);
69 static void freesb(sbuf_t *);
70 static int inpc(void);
71 static int hash(const char *);
72 static sym_t *search(sbuf_t *);
73 static int name(void);
74 static int keyw(sym_t *);
75 static int icon(int);
76 static int fcon(void);
77 static int operator(int, op_t);
78 static int ccon(void);
79 static int wccon(void);
80 static int getescc(int);
81 static void directive(void);
82 static void comment(void);
83 static void slashslashcomment(void);
84 static int string(void);
85 static int wcstrg(void);
86
87 %}
88
89 L [_A-Za-z]
90 D [0-9]
91 NZD [1-9]
92 OD [0-7]
93 HD [0-9A-Fa-f]
94 EX ([eE][+-]?[0-9]+)
95 HX (p[+-]?[0-9A-Fa-f]+)
96 TL ([fFlL]?[i]?)
97
98 %option nounput
99
100 %%
101
102 {L}({L}|{D})* return (name());
103 0{OD}*[lLuU]* return (icon(8));
104 {NZD}{D}*[lLuU]* return (icon(10));
105 0[xX]{HD}+[lLuU]* return (icon(16));
106 {D}+\.{D}*{EX}?{TL} |
107 {D}+{EX}{TL} |
108 0[xX]{HD}+\.{HD}*{HX}{TL} |
109 0[xX]{HD}+{HX}{TL} |
110 \.{D}+{EX}?{TL} return (fcon());
111 "=" return (operator(T_ASSIGN, ASSIGN));
112 "*=" return (operator(T_OPASS, MULASS));
113 "/=" return (operator(T_OPASS, DIVASS));
114 "%=" return (operator(T_OPASS, MODASS));
115 "+=" return (operator(T_OPASS, ADDASS));
116 "-=" return (operator(T_OPASS, SUBASS));
117 "<<=" return (operator(T_OPASS, SHLASS));
118 ">>=" return (operator(T_OPASS, SHRASS));
119 "&=" return (operator(T_OPASS, ANDASS));
120 "^=" return (operator(T_OPASS, XORASS));
121 "|=" return (operator(T_OPASS, ORASS));
122 "||" return (operator(T_LOGOR, LOGOR));
123 "&&" return (operator(T_LOGAND, LOGAND));
124 "|" return (operator(T_OR, OR));
125 "&" return (operator(T_AND, AND));
126 "^" return (operator(T_XOR, XOR));
127 "==" return (operator(T_EQOP, EQ));
128 "!=" return (operator(T_EQOP, NE));
129 "<" return (operator(T_RELOP, LT));
130 ">" return (operator(T_RELOP, GT));
131 "<=" return (operator(T_RELOP, LE));
132 ">=" return (operator(T_RELOP, GE));
133 "<<" return (operator(T_SHFTOP, SHL));
134 ">>" return (operator(T_SHFTOP, SHR));
135 "++" return (operator(T_INCDEC, INC));
136 "--" return (operator(T_INCDEC, DEC));
137 "->" return (operator(T_STROP, ARROW));
138 "." return (operator(T_STROP, POINT));
139 "+" return (operator(T_ADDOP, PLUS));
140 "-" return (operator(T_ADDOP, MINUS));
141 "*" return (operator(T_MULT, MULT));
142 "/" return (operator(T_DIVOP, DIV));
143 "%" return (operator(T_DIVOP, MOD));
144 "!" return (operator(T_UNOP, NOT));
145 "~" return (operator(T_UNOP, COMPL));
146 "\"" return (string());
147 "L\"" return (wcstrg());
148 ";" return (T_SEMI);
149 "{" return (T_LBRACE);
150 "}" return (T_RBRACE);
151 "," return (T_COMMA);
152 ":" return (T_COLON);
153 "?" return (T_QUEST);
154 "[" return (T_LBRACK);
155 "]" return (T_RBRACK);
156 "(" return (T_LPARN);
157 ")" return (T_RPARN);
158 "..." return (T_ELLIPSE);
159 "'" return (ccon());
160 "L'" return (wccon());
161 ^#.*$ directive();
162 \n incline();
163 \t|" "|\f|\v ;
164 "/*" comment();
165 "//" slashslashcomment();
166 . badchar(yytext[0]);
167
168 %%
169
170 static void
171 incline(void)
172 {
173 curr_pos.p_line++;
174 curr_pos.p_uniq = 0;
175 if (curr_pos.p_file == csrc_pos.p_file) {
176 csrc_pos.p_line++;
177 csrc_pos.p_uniq = 0;
178 }
179 }
180
181 static void
182 badchar(int c)
183 {
184
185 /* unknown character \%o */
186 error(250, c);
187 }
188
189 /*
190 * Keywords.
191 * During initialisation they are written to the symbol table.
192 */
193 static struct kwtab {
194 const char *kw_name; /* keyword */
195 int kw_token; /* token returned by yylex() */
196 scl_t kw_scl; /* storage class if kw_token T_SCLASS */
197 tspec_t kw_tspec; /* type spec. if kw_token T_TYPE or T_SOU */
198 tqual_t kw_tqual; /* type qual. fi kw_token T_QUAL */
199 u_int kw_c89 : 1; /* c89 keyword */
200 u_int kw_c99 : 1; /* c99 keyword */
201 u_int kw_gcc : 1; /* GCC keyword */
202 u_int kw_attr : 1; /* GCC attribute, keyword */
203 } kwtab[] = {
204 { "__alignof__", T_ALIGNOF, 0, 0, 0, 0, 0, 0, 0 },
205 { "__attribute__",T_ATTRIBUTE, 0, 0, 0, 0, 0, 1, 0 },
206 { "attribute", T_ATTRIBUTE, 0, 0, 0, 0, 0, 1, 0 },
207 { "__packed__", T_AT_PACKED, 0, 0, 0, 0, 0, 1, 1 },
208 { "packed", T_AT_PACKED, 0, 0, 0, 0, 0, 1, 1 },
209 { "__aligned__",T_AT_ALIGNED, 0, 0, 0, 0, 0, 1, 1 },
210 { "aligned", T_AT_ALIGNED, 0, 0, 0, 0, 0, 1, 1 },
211 { "__transparent_union__",T_AT_TUNION,0,0, 0, 0, 0, 1, 1 },
212 { "transparent_union",T_AT_TUNION,0, 0, 0, 0, 0, 1, 1 },
213 { "__unused__", T_AT_UNUSED, 0, 0, 0, 0, 0, 1, 1 },
214 { "unused", T_AT_UNUSED, 0, 0, 0, 0, 0, 1, 1 },
215 { "__deprecated__",T_AT_DEPRECATED,0, 0, 0, 0, 0, 1, 1 },
216 { "deprecated", T_AT_DEPRECATED,0, 0, 0, 0, 0, 1, 1 },
217 { "__may_alias__",T_AT_MAY_ALIAS,0, 0, 0, 0, 0, 1, 1 },
218 { "may_alias", T_AT_MAY_ALIAS, 0, 0, 0, 0, 0, 1, 1 },
219 { "format", T_AT_FORMAT, 0, 0, 0, 0, 0, 1, 1 },
220 { "__format__", T_AT_FORMAT, 0, 0, 0, 0, 0, 1, 1 },
221 { "printf", T_AT_FORMAT_PRINTF,0, 0, 0, 0, 0, 1, 1 },
222 { "__printf__", T_AT_FORMAT_PRINTF,0, 0, 0, 0, 0, 1, 1 },
223 { "scanf", T_AT_FORMAT_SCANF,0, 0, 0, 0, 0, 1, 1 },
224 { "__scanf__", T_AT_FORMAT_SCANF,0, 0, 0, 0, 0, 1, 1 },
225 { "strftime", T_AT_FORMAT_SCANF,0, 0, 0, 0, 0, 1, 1 },
226 { "__strftime__",T_AT_FORMAT_STRFTIME,0,0, 0, 0, 0, 1, 1 },
227 { "pure", T_AT_PURE, 0, 0, 0, 0, 0, 1, 1 },
228 { "__pure__", T_AT_PURE, 0, 0, 0, 0, 0, 1, 1 },
229 { "noreturn", T_AT_NORETURN, 0, 0, 0, 0, 0, 1, 1 },
230 { "__noreturn__",T_AT_NORETURN, 0, 0, 0, 0, 0, 1, 1 },
231 { "asm", T_ASM, 0, 0, 0, 0, 0, 1, 1 },
232 { "__asm", T_ASM, 0, 0, 0, 0, 0, 0, 0 },
233 { "__asm__", T_ASM, 0, 0, 0, 0, 0, 0, 0 },
234 { "auto", T_SCLASS, AUTO, 0, 0, 0, 0, 0, 0 },
235 { "break", T_BREAK, 0, 0, 0, 0, 0, 0, 0 },
236 { "_Bool", T_TYPE, 0, BOOL, 0, 0, 1, 0, 0 },
237 { "case", T_CASE, 0, 0, 0, 0, 0, 0, 0 },
238 { "char", T_TYPE, 0, CHAR, 0, 0, 0, 0, 0 },
239 { "const", T_QUAL, 0, 0, CONST, 1, 0, 0, 0 },
240 { "_Complex", T_TYPE, 0, COMPLEX,0, 0, 1, 0, 0 },
241 { "__const__", T_QUAL, 0, 0, CONST, 0, 0, 0, 0 },
242 { "__const", T_QUAL, 0, 0, CONST, 0, 0, 0, 0 },
243 { "continue", T_CONTINUE, 0, 0, 0, 0, 0, 0, 0 },
244 { "default", T_DEFAULT, 0, 0, 0, 0, 0, 0, 0 },
245 { "do", T_DO, 0, 0, 0, 0, 0, 0, 0 },
246 { "double", T_TYPE, 0, DOUBLE, 0, 0, 0, 0, 0 },
247 { "else", T_ELSE, 0, 0, 0, 0, 0, 0, 0 },
248 { "enum", T_ENUM, 0, 0, 0, 0, 0, 0, 0 },
249 { "__extension__", T_EXTENSION, 0, 0, 0, 0, 0, 1, 0 },
250 { "extern", T_SCLASS, EXTERN, 0, 0, 0, 0, 0, 0 },
251 { "float", T_TYPE, 0, FLOAT, 0, 0, 0, 0, 0 },
252 { "for", T_FOR, 0, 0, 0, 0, 0, 0, 0 },
253 { "goto", T_GOTO, 0, 0, 0, 0, 0, 0, 0 },
254 { "if", T_IF, 0, 0, 0, 0, 0, 0, 0 },
255 { "__imag__", T_IMAG, 0, 0, 0, 0, 1, 0, 0 },
256 { "inline", T_SCLASS, INLINE, 0, 0, 0, 1, 0, 0 },
257 { "__inline__", T_SCLASS, INLINE, 0, 0, 0, 0, 0, 0 },
258 { "__inline", T_SCLASS, INLINE, 0, 0, 0, 0, 0, 0 },
259 { "int", T_TYPE, 0, INT, 0, 0, 0, 0, 0 },
260 { "__symbolrename", T_SYMBOLRENAME, 0, 0, 0, 0, 0, 0, 0 },
261 { "long", T_TYPE, 0, LONG, 0, 0, 0, 0, 0 },
262 { "__real__", T_REAL, 0, 0, 0, 0, 1, 0, 0 },
263 { "register", T_SCLASS, REG, 0, 0, 0, 0, 0, 0 },
264 { "__restrict__",T_QUAL, 0, 0, RESTRICT, 0, 1, 0, 0 },
265 { "restrict", T_QUAL, 0, 0, RESTRICT, 0, 1, 0, 0 },
266 { "return", T_RETURN, 0, 0, 0, 0, 0, 0, 0 },
267 { "__packed", T_PACKED, 0, 0, 0, 0, 0, 0, 0 },
268 { "short", T_TYPE, 0, SHORT, 0, 0, 0, 0, 0 },
269 { "signed", T_TYPE, 0, SIGNED, 0, 1, 0, 0, 0 },
270 { "__signed__", T_TYPE, 0, SIGNED, 0, 0, 0, 0, 0 },
271 { "__signed", T_TYPE, 0, SIGNED, 0, 0, 0, 0, 0 },
272 { "sizeof", T_SIZEOF, 0, 0, 0, 0, 0, 0, 0 },
273 { "static", T_SCLASS, STATIC, 0, 0, 0, 0, 0, 0 },
274 { "struct", T_SOU, 0, STRUCT, 0, 0, 0, 0, 0 },
275 { "switch", T_SWITCH, 0, 0, 0, 0, 0, 0, 0 },
276 { "typedef", T_SCLASS, TYPEDEF, 0, 0, 0, 0, 0, 0 },
277 { "typeof", T_TYPEOF, 0, 0, 0, 0, 0, 1, 0 },
278 { "__typeof", T_TYPEOF, 0, 0, 0, 0, 0, 1, 0 },
279 { "__typeof__", T_TYPEOF, 0, 0, 0, 0, 0, 1, 0 },
280 { "union", T_SOU, 0, UNION, 0, 0, 0, 0, 0 },
281 { "unsigned", T_TYPE, 0, UNSIGN, 0, 0, 0, 0, 0 },
282 { "void", T_TYPE, 0, VOID, 0, 0, 0, 0, 0 },
283 { "volatile", T_QUAL, 0, 0, VOLATILE, 1, 0, 0, 0 },
284 { "__volatile__", T_QUAL, 0, 0, VOLATILE, 0, 0, 0, 0 },
285 { "__volatile", T_QUAL, 0, 0, VOLATILE, 0, 0, 0, 0 },
286 { "while", T_WHILE, 0, 0, 0, 0, 0, 0, 0 },
287 { NULL, 0, 0, 0, 0, 0, 0, 0, 0 }
288 };
289
290 /* Symbol table */
291 static sym_t *symtab[HSHSIZ1];
292
293 /* bit i of the entry with index i is set */
294 uint64_t qbmasks[sizeof(uint64_t) * CHAR_BIT];
295
296 /* least significant i bits are set in the entry with index i */
297 uint64_t qlmasks[sizeof(uint64_t) * CHAR_BIT + 1];
298
299 /* least significant i bits are not set in the entry with index i */
300 uint64_t qumasks[sizeof(uint64_t) * CHAR_BIT + 1];
301
302 /* free list for sbuf structures */
303 static sbuf_t *sbfrlst;
304
305 /* Typ of next expected symbol */
306 symt_t symtyp;
307
308
309 /*
310 * All keywords are written to the symbol table. This saves us looking
311 * in a extra table for each name we found.
312 */
313 void
314 initscan(void)
315 {
316 struct kwtab *kw;
317 sym_t *sym;
318 size_t h, i;
319 uint64_t uq;
320
321 for (kw = kwtab; kw->kw_name != NULL; kw++) {
322 if ((kw->kw_c89 || kw->kw_c99) && tflag)
323 continue;
324 if (kw->kw_c99 && !(Sflag || gflag))
325 continue;
326 if (kw->kw_gcc && !gflag)
327 continue;
328 sym = getblk(sizeof (sym_t));
329 sym->s_name = kw->kw_name;
330 sym->s_keyw = kw;
331 sym->s_value.v_quad = kw->kw_token;
332 if (kw->kw_token == T_TYPE || kw->kw_token == T_SOU) {
333 sym->s_tspec = kw->kw_tspec;
334 } else if (kw->kw_token == T_SCLASS) {
335 sym->s_scl = kw->kw_scl;
336 } else if (kw->kw_token == T_QUAL) {
337 sym->s_tqual = kw->kw_tqual;
338 }
339 h = hash(sym->s_name);
340 if ((sym->s_link = symtab[h]) != NULL)
341 symtab[h]->s_rlink = &sym->s_link;
342 sym->s_rlink = &symtab[h];
343 symtab[h] = sym;
344 }
345
346 /* initialize bit-masks for quads */
347 for (i = 0; i < sizeof (uint64_t) * CHAR_BIT; i++) {
348 qbmasks[i] = (uint64_t)1 << i;
349 uq = ~(uint64_t)0 << i;
350 qumasks[i] = uq;
351 qlmasks[i] = ~uq;
352 }
353 qumasks[i] = 0;
354 qlmasks[i] = ~(uint64_t)0;
355 }
356
357 /*
358 * Get a free sbuf structure, if possible from the free list
359 */
360 static sbuf_t *
361 allocsb(void)
362 {
363 sbuf_t *sb;
364
365 if ((sb = sbfrlst) != NULL) {
366 sbfrlst = sb->sb_nxt;
367 #ifdef BLKDEBUG
368 (void)memset(sb, 0, sizeof (*sb));
369 #else
370 sb->sb_nxt = NULL;
371 #endif
372 } else {
373 sb = xmalloc(sizeof (sbuf_t));
374 (void)memset(sb, 0, sizeof (*sb));
375 }
376 return (sb);
377 }
378
379 /*
380 * Put a sbuf structure to the free list
381 */
382 static void
383 freesb(sbuf_t *sb)
384 {
385
386 (void)memset(sb, ZERO, sizeof (*sb));
387 sb->sb_nxt = sbfrlst;
388 sbfrlst = sb;
389 }
390
391 /*
392 * Read a character and ensure that it is positive (except EOF).
393 * Increment line count(s) if necessary.
394 */
395 static int
396 inpc(void)
397 {
398 int c;
399
400 if ((c = input()) != EOF && (c &= CHAR_MASK) == '\n')
401 incline();
402 return (c);
403 }
404
405 static int
406 hash(const char *s)
407 {
408 u_int v;
409 const u_char *us;
410
411 v = 0;
412 for (us = (const u_char *)s; *us != '\0'; us++) {
413 v = (v << sizeof (v)) + *us;
414 v ^= v >> (sizeof (v) * CHAR_BIT - sizeof (v));
415 }
416 return (v % HSHSIZ1);
417 }
418
419 /*
420 * Lex has found a letter followed by zero or more letters or digits.
421 * It looks for a symbol in the symbol table with the same name. This
422 * symbol must either be a keyword or a symbol of the type required by
423 * symtyp (label, member, tag, ...).
424 *
425 * If it is a keyword, the token is returned. In some cases it is described
426 * more deeply by data written to yylval.
427 *
428 * If it is a symbol, T_NAME is returned and the pointer to a sbuf struct
429 * is stored in yylval. This struct contains the name of the symbol, it's
430 * length and hash value. If there is already a symbol of the same name
431 * and type in the symbol table, the sbuf struct also contains a pointer
432 * to the symbol table entry.
433 */
434 static int
435 name(void)
436 {
437 char *s;
438 sbuf_t *sb;
439 sym_t *sym;
440 int tok;
441
442 sb = allocsb();
443 sb->sb_name = yytext;
444 sb->sb_len = yyleng;
445 sb->sb_hash = hash(yytext);
446 if ((sym = search(sb)) != NULL && sym->s_keyw) {
447 freesb(sb);
448 return (keyw(sym));
449 }
450
451 sb->sb_sym = sym;
452
453 if (sym != NULL) {
454 if (blklev < sym->s_blklev)
455 LERROR("name()");
456 sb->sb_name = sym->s_name;
457 sb->sb_len = strlen(sym->s_name);
458 tok = sym->s_scl == TYPEDEF ? T_TYPENAME : T_NAME;
459 } else {
460 s = getblk(yyleng + 1);
461 (void)memcpy(s, yytext, yyleng + 1);
462 sb->sb_name = s;
463 sb->sb_len = yyleng;
464 tok = T_NAME;
465 }
466
467 yylval.y_sb = sb;
468 return (tok);
469 }
470
471 static sym_t *
472 search(sbuf_t *sb)
473 {
474 sym_t *sym;
475
476 for (sym = symtab[sb->sb_hash]; sym != NULL; sym = sym->s_link) {
477 if (strcmp(sym->s_name, sb->sb_name) == 0) {
478 if (sym->s_keyw) {
479 struct kwtab *kw = sym->s_keyw;
480 if (!kw->kw_attr || attron)
481 return (sym);
482 } else if (sym->s_kind == symtyp)
483 return sym;
484 }
485 }
486
487 return (NULL);
488 }
489
490 static int
491 keyw(sym_t *sym)
492 {
493 int t;
494
495 if ((t = (int)sym->s_value.v_quad) == T_SCLASS) {
496 yylval.y_scl = sym->s_scl;
497 } else if (t == T_TYPE || t == T_SOU) {
498 yylval.y_tspec = sym->s_tspec;
499 } else if (t == T_QUAL) {
500 yylval.y_tqual = sym->s_tqual;
501 }
502 return (t);
503 }
504
505 /*
506 * Convert a string representing an integer into internal representation.
507 * The value is returned in yylval. icon() (and yylex()) returns T_CON.
508 */
509 static int
510 icon(int base)
511 {
512 int l_suffix, u_suffix;
513 int len;
514 const char *cp;
515 char c, *eptr;
516 tspec_t typ;
517 uint64_t uq = 0;
518 int ansiu;
519 static tspec_t contypes[2][3] = {
520 { INT, LONG, QUAD },
521 { UINT, ULONG, UQUAD }
522 };
523
524 cp = yytext;
525 len = yyleng;
526
527 /* skip 0x */
528 if (base == 16) {
529 cp += 2;
530 len -= 2;
531 }
532
533 /* read suffixes */
534 l_suffix = u_suffix = 0;
535 for ( ; ; ) {
536 if ((c = cp[len - 1]) == 'l' || c == 'L') {
537 l_suffix++;
538 } else if (c == 'u' || c == 'U') {
539 u_suffix++;
540 } else {
541 break;
542 }
543 len--;
544 }
545 if (l_suffix > 2 || u_suffix > 1) {
546 /* malformed integer constant */
547 warning(251);
548 if (l_suffix > 2)
549 l_suffix = 2;
550 if (u_suffix > 1)
551 u_suffix = 1;
552 }
553 if (tflag && u_suffix != 0) {
554 /* suffix U is illegal in traditional C */
555 warning(97);
556 }
557 typ = contypes[u_suffix][l_suffix];
558
559 errno = 0;
560
561 uq = strtouq(cp, &eptr, base);
562 if (eptr != cp + len)
563 LERROR("icon()");
564 if (errno != 0)
565 /* integer constant out of range */
566 warning(252);
567
568 /*
569 * If the value is too big for the current type, we must choose
570 * another type.
571 */
572 ansiu = 0;
573 switch (typ) {
574 case INT:
575 if (uq <= TARG_INT_MAX) {
576 /* ok */
577 } else if (uq <= TARG_UINT_MAX && base != 10) {
578 typ = UINT;
579 } else if (uq <= TARG_LONG_MAX) {
580 typ = LONG;
581 } else {
582 typ = ULONG;
583 if (uq > TARG_ULONG_MAX) {
584 /* integer constant out of range */
585 warning(252);
586 }
587 }
588 if (typ == UINT || typ == ULONG) {
589 if (tflag) {
590 typ = LONG;
591 } else if (!sflag) {
592 /*
593 * Remember that the constant is unsigned
594 * only in ANSI C
595 */
596 ansiu = 1;
597 }
598 }
599 break;
600 case UINT:
601 if (uq > TARG_UINT_MAX) {
602 typ = ULONG;
603 if (uq > TARG_ULONG_MAX) {
604 /* integer constant out of range */
605 warning(252);
606 }
607 }
608 break;
609 case LONG:
610 if (uq > TARG_LONG_MAX && !tflag) {
611 typ = ULONG;
612 if (!sflag)
613 ansiu = 1;
614 if (uq > TARG_ULONG_MAX) {
615 /* integer constant out of range */
616 warning(252);
617 }
618 }
619 break;
620 case ULONG:
621 if (uq > TARG_ULONG_MAX) {
622 /* integer constant out of range */
623 warning(252);
624 }
625 break;
626 case QUAD:
627 if (uq > TARG_QUAD_MAX && !tflag) {
628 typ = UQUAD;
629 if (!sflag)
630 ansiu = 1;
631 }
632 break;
633 case UQUAD:
634 if (uq > TARG_UQUAD_MAX) {
635 /* integer constant out of range */
636 warning(252);
637 }
638 break;
639 /* LINTED206: (enumeration values not handled in switch) */
640 case STRUCT:
641 case VOID:
642 case LDOUBLE:
643 case FUNC:
644 case ARRAY:
645 case PTR:
646 case ENUM:
647 case UNION:
648 case SIGNED:
649 case NOTSPEC:
650 case DOUBLE:
651 case FLOAT:
652 case USHORT:
653 case SHORT:
654 case UCHAR:
655 case SCHAR:
656 case CHAR:
657 case BOOL:
658 case UNSIGN:
659 case FCOMPLEX:
660 case DCOMPLEX:
661 case LCOMPLEX:
662 case COMPLEX:
663 break;
664
665 case NTSPEC: /* this value unused */
666 break;
667 }
668
669 uq = (uint64_t)xsign((int64_t)uq, typ, -1);
670
671 (yylval.y_val = xcalloc(1, sizeof (val_t)))->v_tspec = typ;
672 yylval.y_val->v_ansiu = ansiu;
673 yylval.y_val->v_quad = (int64_t)uq;
674
675 return (T_CON);
676 }
677
678 /*
679 * Returns 1 if t is a signed type and the value is negative.
680 *
681 * len is the number of significant bits. If len is -1, len is set
682 * to the width of type t.
683 */
684 int
685 sign(int64_t q, tspec_t t, int len)
686 {
687
688 if (t == PTR || isutyp(t))
689 return (0);
690 return (msb(q, t, len));
691 }
692
693 int
694 msb(int64_t q, tspec_t t, int len)
695 {
696
697 if (len <= 0)
698 len = size(t);
699 return ((q & qbmasks[len - 1]) != 0);
700 }
701
702 /*
703 * Extends the sign of q.
704 */
705 int64_t
706 xsign(int64_t q, tspec_t t, int len)
707 {
708
709 if (len <= 0)
710 len = size(t);
711
712 if (t == PTR || isutyp(t) || !sign(q, t, len)) {
713 q &= qlmasks[len];
714 } else {
715 q |= qumasks[len];
716 }
717 return (q);
718 }
719
720 /*
721 * Convert a string representing a floating point value into its interal
722 * representation. Type and value are returned in yylval. fcon()
723 * (and yylex()) returns T_CON.
724 * XXX Currently it is not possible to convert constants of type
725 * long double which are greater than DBL_MAX.
726 */
727 static int
728 fcon(void)
729 {
730 const char *cp;
731 int len;
732 tspec_t typ;
733 char c, *eptr;
734 double d;
735 float f = 0;
736
737 cp = yytext;
738 len = yyleng;
739
740 if (cp[len - 1] == 'i') {
741 /* imaginary, do nothing for now */
742 len--;
743 }
744 if ((c = cp[len - 1]) == 'f' || c == 'F') {
745 typ = FLOAT;
746 len--;
747 } else if (c == 'l' || c == 'L') {
748 typ = LDOUBLE;
749 len--;
750 } else {
751 if (c == 'd' || c == 'D')
752 len--;
753 typ = DOUBLE;
754 }
755
756 if (tflag && typ != DOUBLE) {
757 /* suffixes F and L are illegal in traditional C */
758 warning(98);
759 }
760
761 errno = 0;
762 d = strtod(cp, &eptr);
763 if (eptr != cp + len) {
764 switch (*eptr) {
765 /*
766 * XXX: non-native non-current strtod() may not handle hex
767 * floats, ignore the rest if we find traces of hex float
768 * syntax...
769 */
770 case 'p':
771 case 'P':
772 case 'x':
773 case 'X':
774 d = 0;
775 errno = 0;
776 break;
777 default:
778 LERROR("fcon(%s->%s)", cp, eptr);
779 }
780 }
781 if (errno != 0)
782 /* floating-point constant out of range */
783 warning(248);
784
785 if (typ == FLOAT) {
786 f = (float)d;
787 if (!finite(f)) {
788 /* floating-point constant out of range */
789 warning(248);
790 f = f > 0 ? FLT_MAX : -FLT_MAX;
791 }
792 }
793
794 (yylval.y_val = xcalloc(1, sizeof (val_t)))->v_tspec = typ;
795 if (typ == FLOAT) {
796 yylval.y_val->v_ldbl = f;
797 } else {
798 yylval.y_val->v_ldbl = d;
799 }
800
801 return (T_CON);
802 }
803
804 static int
805 operator(int t, op_t o)
806 {
807
808 yylval.y_op = o;
809 return (t);
810 }
811
812 /*
813 * Called if lex found a leading \'.
814 */
815 static int
816 ccon(void)
817 {
818 size_t n;
819 int val, c;
820 char cv;
821
822 n = 0;
823 val = 0;
824 while ((c = getescc('\'')) >= 0) {
825 val = (val << CHAR_BIT) + c;
826 n++;
827 }
828 if (c == -2) {
829 /* unterminated character constant */
830 error(253);
831 } else {
832 if (n > sizeof (int) || (n > 1 && (pflag || hflag))) {
833 /* too many characters in character constant */
834 error(71);
835 } else if (n > 1) {
836 /* multi-character character constant */
837 warning(294);
838 } else if (n == 0) {
839 /* empty character constant */
840 error(73);
841 }
842 }
843 if (n == 1) {
844 cv = (char)val;
845 val = cv;
846 }
847
848 yylval.y_val = xcalloc(1, sizeof (val_t));
849 yylval.y_val->v_tspec = INT;
850 yylval.y_val->v_quad = val;
851
852 return (T_CON);
853 }
854
855 /*
856 * Called if lex found a leading L\'
857 */
858 static int
859 wccon(void)
860 {
861 static char buf[MB_LEN_MAX + 1];
862 size_t i;
863 int c;
864 wchar_t wc;
865
866 i = 0;
867 while ((c = getescc('\'')) >= 0) {
868 if (i < MB_CUR_MAX)
869 buf[i] = (char)c;
870 i++;
871 }
872
873 wc = 0;
874
875 if (c == -2) {
876 /* unterminated character constant */
877 error(253);
878 } else if (c == 0) {
879 /* empty character constant */
880 error(73);
881 } else {
882 if (i > MB_CUR_MAX) {
883 i = MB_CUR_MAX;
884 /* too many characters in character constant */
885 error(71);
886 } else {
887 buf[i] = '\0';
888 (void)mbtowc(NULL, NULL, 0);
889 if (mbtowc(&wc, buf, MB_CUR_MAX) < 0)
890 /* invalid multibyte character */
891 error(291);
892 }
893 }
894
895 yylval.y_val = xcalloc(1, sizeof (val_t));
896 yylval.y_val->v_tspec = WCHAR;
897 yylval.y_val->v_quad = wc;
898
899 return (T_CON);
900 }
901
902 /*
903 * Read a character which is part of a character constant or of a string
904 * and handle escapes.
905 *
906 * The Argument is the character which delimits the character constant or
907 * string.
908 *
909 * Returns -1 if the end of the character constant or string is reached,
910 * -2 if the EOF is reached, and the character otherwise.
911 */
912 static int
913 getescc(int d)
914 {
915 static int pbc = -1;
916 int n, c, v;
917
918 if (pbc == -1) {
919 c = inpc();
920 } else {
921 c = pbc;
922 pbc = -1;
923 }
924 if (c == d)
925 return (-1);
926 switch (c) {
927 case '\n':
928 if (tflag) {
929 /* newline in string or char constant */
930 error(254);
931 return (-2);
932 }
933 return (c);
934 case EOF:
935 return (-2);
936 case '\\':
937 switch (c = inpc()) {
938 case '"':
939 if (tflag && d == '\'')
940 /* \" inside character constant undef. ... */
941 warning(262);
942 return ('"');
943 case '\'':
944 return ('\'');
945 case '?':
946 if (tflag)
947 /* \? undefined in traditional C */
948 warning(263);
949 return ('?');
950 case '\\':
951 return ('\\');
952 case 'a':
953 if (tflag)
954 /* \a undefined in traditional C */
955 warning(81);
956 return ('\a');
957 case 'b':
958 return ('\b');
959 case 'f':
960 return ('\f');
961 case 'n':
962 return ('\n');
963 case 'r':
964 return ('\r');
965 case 't':
966 return ('\t');
967 case 'v':
968 if (tflag)
969 /* \v undefined in traditional C */
970 warning(264);
971 return ('\v');
972 case '8': case '9':
973 /* bad octal digit %c */
974 warning(77, c);
975 /* FALLTHROUGH */
976 case '0': case '1': case '2': case '3':
977 case '4': case '5': case '6': case '7':
978 n = 3;
979 v = 0;
980 do {
981 v = (v << 3) + (c - '0');
982 c = inpc();
983 } while (--n && isdigit(c) && (tflag || c <= '7'));
984 if (tflag && n > 0 && isdigit(c))
985 /* bad octal digit %c */
986 warning(77, c);
987 pbc = c;
988 if (v > TARG_UCHAR_MAX) {
989 /* character escape does not fit in char. */
990 warning(76);
991 v &= CHAR_MASK;
992 }
993 return (v);
994 case 'x':
995 if (tflag)
996 /* \x undefined in traditional C */
997 warning(82);
998 v = 0;
999 n = 0;
1000 while ((c = inpc()) >= 0 && isxdigit(c)) {
1001 c = isdigit(c) ?
1002 c - '0' : toupper(c) - 'A' + 10;
1003 v = (v << 4) + c;
1004 if (n >= 0) {
1005 if ((v & ~CHAR_MASK) != 0) {
1006 /* overflow in hex escape */
1007 warning(75);
1008 n = -1;
1009 } else {
1010 n++;
1011 }
1012 }
1013 }
1014 pbc = c;
1015 if (n == 0) {
1016 /* no hex digits follow \x */
1017 error(74);
1018 } if (n == -1) {
1019 v &= CHAR_MASK;
1020 }
1021 return (v);
1022 case '\n':
1023 return (getescc(d));
1024 case EOF:
1025 return (-2);
1026 default:
1027 if (isprint(c)) {
1028 /* dubious escape \%c */
1029 warning(79, c);
1030 } else {
1031 /* dubious escape \%o */
1032 warning(80, c);
1033 }
1034 }
1035 }
1036 return (c);
1037 }
1038
1039 /*
1040 * Called for preprocessor directives. Currently implemented are:
1041 * # lineno
1042 * # lineno "filename"
1043 */
1044 static void
1045 directive(void)
1046 {
1047 const char *cp, *fn;
1048 char c, *eptr;
1049 size_t fnl;
1050 long ln;
1051 static int first = 1;
1052
1053 /* Go to first non-whitespace after # */
1054 for (cp = yytext + 1; (c = *cp) == ' ' || c == '\t'; cp++)
1055 continue;
1056
1057 if (!isdigit((unsigned char)c)) {
1058 error:
1059 /* undefined or invalid # directive */
1060 warning(255);
1061 return;
1062 }
1063 ln = strtol(--cp, &eptr, 10);
1064 if (cp == eptr)
1065 goto error;
1066 if ((c = *(cp = eptr)) != ' ' && c != '\t' && c != '\0')
1067 goto error;
1068 while ((c = *cp++) == ' ' || c == '\t')
1069 continue;
1070 if (c != '\0') {
1071 if (c != '"')
1072 goto error;
1073 fn = cp;
1074 while ((c = *cp) != '"' && c != '\0')
1075 cp++;
1076 if (c != '"')
1077 goto error;
1078 if ((fnl = cp++ - fn) > PATH_MAX)
1079 goto error;
1080 while ((c = *cp++) == ' ' || c == '\t')
1081 continue;
1082 #if 0
1083 if (c != '\0')
1084 warning("extra character(s) after directive");
1085 #endif
1086
1087 /* empty string means stdin */
1088 if (fnl == 0) {
1089 fn = "{standard input}";
1090 fnl = 16; /* strlen (fn) */
1091 }
1092 curr_pos.p_file = fnnalloc(fn, fnl);
1093 /*
1094 * If this is the first directive, the name is the name
1095 * of the C source file as specified at the command line.
1096 * It is written to the output file.
1097 */
1098 if (first) {
1099 csrc_pos.p_file = curr_pos.p_file;
1100 outsrc(curr_pos.p_file);
1101 first = 0;
1102 }
1103 }
1104 curr_pos.p_line = (int)ln - 1;
1105 curr_pos.p_uniq = 0;
1106 if (curr_pos.p_file == csrc_pos.p_file) {
1107 csrc_pos.p_line = (int)ln - 1;
1108 csrc_pos.p_uniq = 0;
1109 }
1110 }
1111
1112 /*
1113 * Handle lint comments. Following comments are currently understood:
1114 * ARGSUSEDn
1115 * BITFIELDTYPE
1116 * CONSTCOND CONSTANTCOND CONSTANTCONDITION
1117 * FALLTHRU FALLTHROUGH
1118 * LINTLIBRARY
1119 * LINTEDn NOSTRICTn
1120 * LONGLONG
1121 * NOTREACHED
1122 * PRINTFLIKEn
1123 * PROTOLIB
1124 * SCANFLIKEn
1125 * VARARGSn
1126 * If one of this comments is recognized, the arguments, if any, are
1127 * parsed and a function which handles this comment is called.
1128 */
1129 static void
1130 comment(void)
1131 {
1132 int c, lc;
1133 static struct {
1134 const char *keywd;
1135 int arg;
1136 void (*func)(int);
1137 } keywtab[] = {
1138 { "ARGSUSED", 1, argsused },
1139 { "BITFIELDTYPE", 0, bitfieldtype },
1140 { "CONSTCOND", 0, constcond },
1141 { "CONSTANTCOND", 0, constcond },
1142 { "CONSTANTCONDITION", 0, constcond },
1143 { "FALLTHRU", 0, fallthru },
1144 { "FALLTHROUGH", 0, fallthru },
1145 { "LINTLIBRARY", 0, lintlib },
1146 { "LINTED", 1, linted },
1147 { "LONGLONG", 0, longlong },
1148 { "NOSTRICT", 1, linted },
1149 { "NOTREACHED", 0, notreach },
1150 { "PRINTFLIKE", 1, printflike },
1151 { "PROTOLIB", 1, protolib },
1152 { "SCANFLIKE", 1, scanflike },
1153 { "VARARGS", 1, varargs },
1154 };
1155 char keywd[32];
1156 char arg[32];
1157 size_t l, i;
1158 int a;
1159 int eoc;
1160
1161 eoc = 0;
1162
1163 /* Skip white spaces after the start of the comment */
1164 while ((c = inpc()) != EOF && isspace(c))
1165 continue;
1166
1167 /* Read the potential keyword to keywd */
1168 l = 0;
1169 while (c != EOF && isupper(c) && l < sizeof (keywd) - 1) {
1170 keywd[l++] = (char)c;
1171 c = inpc();
1172 }
1173 keywd[l] = '\0';
1174
1175 /* look for the keyword */
1176 for (i = 0; i < sizeof (keywtab) / sizeof (keywtab[0]); i++) {
1177 if (strcmp(keywtab[i].keywd, keywd) == 0)
1178 break;
1179 }
1180 if (i == sizeof (keywtab) / sizeof (keywtab[0]))
1181 goto skip_rest;
1182
1183 /* skip white spaces after the keyword */
1184 while (c != EOF && isspace(c))
1185 c = inpc();
1186
1187 /* read the argument, if the keyword accepts one and there is one */
1188 l = 0;
1189 if (keywtab[i].arg) {
1190 while (c != EOF && isdigit(c) && l < sizeof (arg) - 1) {
1191 arg[l++] = (char)c;
1192 c = inpc();
1193 }
1194 }
1195 arg[l] = '\0';
1196 a = l != 0 ? atoi(arg) : -1;
1197
1198 /* skip white spaces after the argument */
1199 while (c != EOF && isspace(c))
1200 c = inpc();
1201
1202 if (c != '*' || (c = inpc()) != '/') {
1203 if (keywtab[i].func != linted)
1204 /* extra characters in lint comment */
1205 warning(257);
1206 } else {
1207 /*
1208 * remember that we have already found the end of the
1209 * comment
1210 */
1211 eoc = 1;
1212 }
1213
1214 if (keywtab[i].func != NULL)
1215 (*keywtab[i].func)(a);
1216
1217 skip_rest:
1218 while (!eoc) {
1219 lc = c;
1220 if ((c = inpc()) == EOF) {
1221 /* unterminated comment */
1222 error(256);
1223 break;
1224 }
1225 if (lc == '*' && c == '/')
1226 eoc = 1;
1227 }
1228 }
1229
1230 /*
1231 * Handle // style comments
1232 */
1233 static void
1234 slashslashcomment(void)
1235 {
1236 int c;
1237
1238 if (!Sflag && !gflag)
1239 /* // comments only supported in C99 */
1240 (void)gnuism(312, tflag ? "traditional" : "ANSI");
1241
1242 while ((c = inpc()) != EOF && c != '\n')
1243 continue;
1244 }
1245
1246 /*
1247 * Clear flags for lint comments LINTED, LONGLONG and CONSTCOND.
1248 * clrwflgs() is called after function definitions and global and
1249 * local declarations and definitions. It is also called between
1250 * the controlling expression and the body of control statements
1251 * (if, switch, for, while).
1252 */
1253 void
1254 clrwflgs(void)
1255 {
1256
1257 lwarn = LWARN_ALL;
1258 quadflg = 0;
1259 ccflg = 0;
1260 }
1261
1262 /*
1263 * Strings are stored in a dynamically alloceted buffer and passed
1264 * in yylval.y_xstrg to the parser. The parser or the routines called
1265 * by the parser are responsible for freeing this buffer.
1266 */
1267 static int
1268 string(void)
1269 {
1270 u_char *s;
1271 int c;
1272 size_t len, max;
1273 strg_t *strg;
1274
1275 s = xmalloc(max = 64);
1276
1277 len = 0;
1278 while ((c = getescc('"')) >= 0) {
1279 /* +1 to reserve space for a trailing NUL character */
1280 if (len + 1 == max)
1281 s = xrealloc(s, max *= 2);
1282 s[len++] = (char)c;
1283 }
1284 s[len] = '\0';
1285 if (c == -2)
1286 /* unterminated string constant */
1287 error(258);
1288
1289 strg = xcalloc(1, sizeof (strg_t));
1290 strg->st_tspec = CHAR;
1291 strg->st_len = len;
1292 strg->st_cp = s;
1293
1294 yylval.y_strg = strg;
1295 return (T_STRING);
1296 }
1297
1298 static int
1299 wcstrg(void)
1300 {
1301 char *s;
1302 int c, n;
1303 size_t i, wi;
1304 size_t len, max, wlen;
1305 wchar_t *ws;
1306 strg_t *strg;
1307
1308 s = xmalloc(max = 64);
1309 len = 0;
1310 while ((c = getescc('"')) >= 0) {
1311 /* +1 to save space for a trailing NUL character */
1312 if (len + 1 >= max)
1313 s = xrealloc(s, max *= 2);
1314 s[len++] = (char)c;
1315 }
1316 s[len] = '\0';
1317 if (c == -2)
1318 /* unterminated string constant */
1319 error(258);
1320
1321 /* get length of wide-character string */
1322 (void)mblen(NULL, 0);
1323 for (i = 0, wlen = 0; i < len; i += n, wlen++) {
1324 if ((n = mblen(&s[i], MB_CUR_MAX)) == -1) {
1325 /* invalid multibyte character */
1326 error(291);
1327 break;
1328 }
1329 if (n == 0)
1330 n = 1;
1331 }
1332
1333 ws = xmalloc((wlen + 1) * sizeof (wchar_t));
1334
1335 /* convert from multibyte to wide char */
1336 (void)mbtowc(NULL, NULL, 0);
1337 for (i = 0, wi = 0; i < len; i += n, wi++) {
1338 if ((n = mbtowc(&ws[wi], &s[i], MB_CUR_MAX)) == -1)
1339 break;
1340 if (n == 0)
1341 n = 1;
1342 }
1343 ws[wi] = 0;
1344 free(s);
1345
1346 strg = xcalloc(1, sizeof (strg_t));
1347 strg->st_tspec = WCHAR;
1348 strg->st_len = wlen;
1349 strg->st_wcp = ws;
1350
1351 yylval.y_strg = strg;
1352 return (T_STRING);
1353 }
1354
1355 /*
1356 * As noted above the scanner does not create new symbol table entries
1357 * for symbols it cannot find in the symbol table. This is to avoid
1358 * putting undeclared symbols into the symbol table if a syntax error
1359 * occurs.
1360 *
1361 * getsym() is called as soon as it is probably ok to put the symbol to
1362 * the symbol table. This does not mean that it is not possible that
1363 * symbols are put to the symbol table which are than not completely
1364 * declared due to syntax errors. To avoid too many problems in this
1365 * case symbols get type int in getsym().
1366 *
1367 * XXX calls to getsym() should be delayed until decl1*() is called
1368 */
1369 sym_t *
1370 getsym(sbuf_t *sb)
1371 {
1372 dinfo_t *di;
1373 char *s;
1374 sym_t *sym;
1375
1376 sym = sb->sb_sym;
1377
1378 /*
1379 * During member declaration it is possible that name() looked
1380 * for symbols of type FVFT, although it should have looked for
1381 * symbols of type FTAG. Same can happen for labels. Both cases
1382 * are compensated here.
1383 */
1384 if (symtyp == FMOS || symtyp == FLAB) {
1385 if (sym == NULL || sym->s_kind == FVFT)
1386 sym = search(sb);
1387 }
1388
1389 if (sym != NULL) {
1390 if (sym->s_kind != symtyp)
1391 LERROR("storesym(%d, %d)", sym->s_kind, symtyp);
1392 symtyp = FVFT;
1393 freesb(sb);
1394 return (sym);
1395 }
1396
1397 /* create a new symbol table entry */
1398
1399 /* labels must always be allocated at level 1 (outhermost block) */
1400 if (symtyp == FLAB) {
1401 sym = getlblk(1, sizeof (sym_t));
1402 s = getlblk(1, sb->sb_len + 1);
1403 (void)memcpy(s, sb->sb_name, sb->sb_len + 1);
1404 sym->s_name = s;
1405 sym->s_blklev = 1;
1406 di = dcs;
1407 while (di->d_nxt != NULL && di->d_nxt->d_nxt != NULL)
1408 di = di->d_nxt;
1409 if (di->d_ctx != AUTO)
1410 LERROR("storesym()");
1411 } else {
1412 sym = getblk(sizeof (sym_t));
1413 sym->s_name = sb->sb_name;
1414 sym->s_blklev = blklev;
1415 di = dcs;
1416 }
1417
1418 UNIQUE_CURR_POS(sym->s_dpos);
1419 if ((sym->s_kind = symtyp) != FLAB)
1420 sym->s_type = gettyp(INT);
1421
1422 symtyp = FVFT;
1423
1424 if ((sym->s_link = symtab[sb->sb_hash]) != NULL)
1425 symtab[sb->sb_hash]->s_rlink = &sym->s_link;
1426 sym->s_rlink = &symtab[sb->sb_hash];
1427 symtab[sb->sb_hash] = sym;
1428
1429 *di->d_ldlsym = sym;
1430 di->d_ldlsym = &sym->s_dlnxt;
1431
1432 freesb(sb);
1433 return (sym);
1434 }
1435
1436 /*
1437 * Construct a temporary symbol. The symbol starts with a digit, so that
1438 * it is illegal.
1439 */
1440 sym_t *
1441 mktempsym(type_t *t)
1442 {
1443 static int n = 0;
1444 int h;
1445 char *s = getlblk(blklev, 64);
1446 sym_t *sym = getblk(sizeof (sym_t));
1447
1448 (void)snprintf(s, 64, "%.8d_tmp", n++);
1449 h = hash(s);
1450
1451 sym->s_name = s;
1452 sym->s_type = t;
1453 sym->s_blklev = blklev;
1454 sym->s_scl = AUTO;
1455 sym->s_kind = FVFT;
1456 sym->s_used = 1;
1457 sym->s_set = 1;
1458
1459 if ((sym->s_link = symtab[h]) != NULL)
1460 symtab[h]->s_rlink = &sym->s_link;
1461 sym->s_rlink = &symtab[h];
1462 symtab[h] = sym;
1463
1464 *dcs->d_ldlsym = sym;
1465 dcs->d_ldlsym = &sym->s_dlnxt;
1466
1467 return sym;
1468 }
1469
1470 /*
1471 * Remove a symbol forever from the symbol table. s_blklev
1472 * is set to -1 to avoid that the symbol will later be put
1473 * back to the symbol table.
1474 */
1475 void
1476 rmsym(sym_t *sym)
1477 {
1478
1479 if ((*sym->s_rlink = sym->s_link) != NULL)
1480 sym->s_link->s_rlink = sym->s_rlink;
1481 sym->s_blklev = -1;
1482 sym->s_link = NULL;
1483 }
1484
1485 /*
1486 * Remove a list of symbols declared at one level from the symbol
1487 * table.
1488 */
1489 void
1490 rmsyms(sym_t *syms)
1491 {
1492 sym_t *sym;
1493
1494 for (sym = syms; sym != NULL; sym = sym->s_dlnxt) {
1495 if (sym->s_blklev != -1) {
1496 if ((*sym->s_rlink = sym->s_link) != NULL)
1497 sym->s_link->s_rlink = sym->s_rlink;
1498 sym->s_link = NULL;
1499 sym->s_rlink = NULL;
1500 }
1501 }
1502 }
1503
1504 /*
1505 * Put a symbol into the symbol table
1506 */
1507 void
1508 inssym(int bl, sym_t *sym)
1509 {
1510 int h;
1511
1512 h = hash(sym->s_name);
1513 if ((sym->s_link = symtab[h]) != NULL)
1514 symtab[h]->s_rlink = &sym->s_link;
1515 sym->s_rlink = &symtab[h];
1516 symtab[h] = sym;
1517 sym->s_blklev = bl;
1518 if (sym->s_link != NULL && sym->s_blklev < sym->s_link->s_blklev)
1519 LERROR("inssym()");
1520 }
1521
1522 /*
1523 * Called at level 0 after syntax errors
1524 * Removes all symbols which are not declared at level 0 from the
1525 * symbol table. Also frees all memory which is not associated with
1526 * level 0.
1527 */
1528 void
1529 cleanup(void)
1530 {
1531 sym_t *sym, *nsym;
1532 int i;
1533
1534 for (i = 0; i < HSHSIZ1; i++) {
1535 for (sym = symtab[i]; sym != NULL; sym = nsym) {
1536 nsym = sym->s_link;
1537 if (sym->s_blklev >= 1) {
1538 if ((*sym->s_rlink = nsym) != NULL)
1539 nsym->s_rlink = sym->s_rlink;
1540 }
1541 }
1542 }
1543
1544 for (i = mblklev; i > 0; i--)
1545 freelblk(i);
1546 }
1547
1548 /*
1549 * Create a new symbol with the name of an existing symbol.
1550 */
1551 sym_t *
1552 pushdown(sym_t *sym)
1553 {
1554 int h;
1555 sym_t *nsym;
1556
1557 h = hash(sym->s_name);
1558 nsym = getblk(sizeof (sym_t));
1559 if (sym->s_blklev > blklev)
1560 LERROR("pushdown()");
1561 nsym->s_name = sym->s_name;
1562 UNIQUE_CURR_POS(nsym->s_dpos);
1563 nsym->s_kind = sym->s_kind;
1564 nsym->s_blklev = blklev;
1565
1566 if ((nsym->s_link = symtab[h]) != NULL)
1567 symtab[h]->s_rlink = &nsym->s_link;
1568 nsym->s_rlink = &symtab[h];
1569 symtab[h] = nsym;
1570
1571 *dcs->d_ldlsym = nsym;
1572 dcs->d_ldlsym = &nsym->s_dlnxt;
1573
1574 return (nsym);
1575 }
1576
1577 /*
1578 * Free any dynamically allocated memory referenced by
1579 * the value stack or yylval.
1580 * The type of information in yylval is described by tok.
1581 */
1582 void
1583 freeyyv(void *sp, int tok)
1584 {
1585 if (tok == T_NAME || tok == T_TYPENAME) {
1586 sbuf_t *sb = *(sbuf_t **)sp;
1587 freesb(sb);
1588 } else if (tok == T_CON) {
1589 val_t *val = *(val_t **)sp;
1590 free(val);
1591 } else if (tok == T_STRING) {
1592 strg_t *strg = *(strg_t **)sp;
1593 if (strg->st_tspec == CHAR) {
1594 free(strg->st_cp);
1595 } else if (strg->st_tspec == WCHAR) {
1596 free(strg->st_wcp);
1597 } else {
1598 LERROR("fryylv()");
1599 }
1600 free(strg);
1601 }
1602 }
1603