]> andersk Git - splint.git/blame - src/cscanner.l
*** empty log message ***
[splint.git] / src / cscanner.l
CommitLineData
885824d3 1/*;-*-C-*-;
2** Copyright (c) Massachusetts Institute of Technology 1994-1998.
3** All Rights Reserved.
4** Unpublished rights reserved under the copyright laws of
5** the United States.
6**
7** THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
8** OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
9**
10** This code is distributed freely and may be used freely under the
11** following conditions:
12**
13** 1. This notice may not be removed or altered.
14**
15** 2. Works derived from this code are not distributed for
16** commercial gain without explicit permission from MIT
17** (for permission contact lclint-request@sds.lcs.mit.edu).
18*/
19/*
20 * Modified by Herbert 08/19/97:
21 * - added #include for IBM's OS/2 compiler.
22 * - fixed weird bug with lookup of tmp files (OS/2 and MSDOS only).
23 */
24
25/*
26 * Modified by Mike Smith
27 * Corrected missing 'line' in scanf() calls in handleSpecial().
28 * Without this, I get an error when LCLint hits a '#line' directive
29 * in the pre-pre-processed source files. For safety, I have made these
30 * conditional on OS2 and MSDOS because I don't understand why noone else
31 * has seen this problem.
32 *
33 * Modified by Mike Smith, 4th June 1997
34 * Finally resolved the #line problem. The scanf() calls have been fixed to
35 * allow the following #line forms:-
36 *
37 * #line 123 "filename"
38 * #line 123
39 * # 123 "filename"
40 * # 123
41 *
42 * The last two are generated by the GNU pre-processor, apparently
43 */
44
45Digit [0-9]
46Letter [a-zA-Z_$]
47H [a-fA-F0-9]
48E [Ee][+-]?{Digit}+
49U (u|U)
50L (l|L)
51FS (f|F|l|L)
52IS (u|U|l|L)*
53ULSuffix ({U}{L}|{L}{U})
54
55%{
56/*
57** based on original C lexer by Nate Osgood
58** from hacrat@catfish.lcs.mit.edu Mon Jun 14 13:06:32 1993
59**
60*/
61
62# include "lclintMacros.nf"
63# include "basic.h"
64
885824d3 65# include "cgrammar.h"
66# include "cgrammar_tokens.h"
885824d3 67
68# include "fileIdList.h"
69# include "portab.h"
70
71# if defined(OS2) && defined(__IBMC__)
72 /* needed for isatty()... */
73# include <io.h>
74# endif
75
76static bool lastWasString = FALSE;
77static char savechar = '\0';
78
79/*@notfunction@*/
80# define yyinput() (incColumn (), getc (yyin))
81
82/*@-noparams@*/
83/*@-incondefs@*/
84extern /*@external@*/ int read ();
85/*@=incondefs@*/
86/*@=noparams@*/
87
88static /*@owned@*/ cstring lastidprocessed = cstring_undefined;
89
90static int lminput (void);
91static int tokLength = 0;
92static bool inSpecPart = FALSE;
93static bool continueLine = FALSE;
94
95static int ninput (void);
96static char processChar (void);
97static double processFloat (void);
98static /*@only@*/ exprNode processString (void);
99static long processDec (void);
100static long processHex (void);
101static long processOctal (void);
102static int processIdentifier (/*@only@*/ cstring)
103 /*@globals undef lastidprocessed@*/ ;
104static bool processHashIdentifier (/*@only@*/ cstring)
105 /*@globals undef lastidprocessed@*/ ;
106
107static int processSpec (int);
108static bool handleSpecial (char *);
109static int handleLlSpecial (void);
110static void handleMacro (void);
111static bool processMacro (void);
112static /*@only@*/ cstring makeIdentifier (char *);
113
114/* yes, this is exported! */
115bool g_expectingTypeName = TRUE; /* beginning of file can be type name! */
116
117static int returnInt (ctype, long);
118static int returnFloat (ctype, double);
119static int returnChar (char);
120static void setTokLength (int) /*@modifies g_currentloc@*/ ;
121static void setTokLengthT (size_t) /*@modifies g_currentloc@*/ ;
122
123static void advanceLine (void)
124{
125 tokLength = 0;
126 beginLine ();
127}
128
129/*@-allmacros@*/
130# define RETURN_INT(c,i) \
131 do { lastWasString = FALSE; \
132 return (returnInt (c, i)); } while (FALSE)
133
134# define RETURN_FLOAT(c,f) \
135 do { lastWasString = FALSE; \
136 return (returnFloat (c, f)); \
137 } while (FALSE)
138
139# define RETURN_CHAR(c) \
140 do { lastWasString = FALSE; \
141 return (returnChar (c)); \
142 } while (FALSE)
143
144# define RETURN_TOK(t) \
145 do { yylval.tok = lltok_create (t, fileloc_decColumn (g_currentloc, tokLength)); \
146 tokLength = 0; \
147 lastWasString = FALSE; \
148 return (t); } while (FALSE)
149
150# define RETURN_TYPE(t, ct) \
151 do { yylval.ctyp = ct; tokLength = 0; return (t); } while (FALSE)
152
153/* don't fileloc_decColumn (g_currentloc, tokLength));
154 the string could have \n's in it!
155*/
156
157# define RETURN_STRING(c) \
158 do { yylval.expr = exprNode_stringLiteral (c, fileloc_decColumn (g_currentloc, tokLength)); \
159 tokLength = 0; \
160 lastWasString = TRUE; \
161 return (CCONSTANT); } while (FALSE)
162
163# define RETURN_EXPR(e) \
164 do { yylval.expr = e; \
165 tokLength = 0; \
166 lastWasString = TRUE; \
167 return (CCONSTANT); } while (FALSE)
168
169/*@=allmacros@*/
170
171static void setTokLength (int len)
172{
173 addColumn (len);
174 tokLength = len;
175}
176
177static void setTokLengthT (size_t len)
178{
179 setTokLength (size_toInt (len));
180}
181
182# include "flex.head"
28bf4b0b 183
184/*@-unrecog@*/ /*@i5343@*/
185
885824d3 186%}
187
188%%
189
190"/*" { llfatalbug (cstring_makeLiteral ("Comment in pre-processor output")); }
191
192"#"{Letter}({Letter}|{Digit})* {
193 context_saveLocation ();
194 setTokLength (longUnsigned_toInt (mstring_length (yytext)));
195
196 if (processHashIdentifier (makeIdentifier (yytext + 1)))
197 {
198 if (lastWasString)
199 {
28bf4b0b 200 /* was nothing! */ /*@i32@*/
201 RETURN_STRING (cstring_makeLiteral ("\"\""));
885824d3 202 }
203 else
204 {
205 RETURN_STRING (cstring_makeLiteral ("\"\""));
206 }
207 }
208 else
209 {
210 if (handleSpecial (yytext))
211 {
212 setTokLength (1);
213 RETURN_TOK (0);
214 }
215 }
216 }
217"#" { if (handleSpecial (yytext))
218 {
219 setTokLength (1); RETURN_TOK (0);
220 }
221 }
222"..." { setTokLength (3); RETURN_TOK (CTOK_ELIPSIS); }
223"break" { setTokLength (5); RETURN_TOK (BREAK); }
224"case" { setTokLength (4); RETURN_TOK (CASE); }
225"continue" { setTokLength (8); RETURN_TOK (CONTINUE); }
226"default" { setTokLength (7); RETURN_TOK (DEFAULT); }
227"do" { setTokLength (2); RETURN_TOK (DO); }
228"else" { setTokLength (4); RETURN_TOK (CELSE); }
229"for" { setTokLength (3); RETURN_TOK (CFOR); }
230"goto" { setTokLength (4); RETURN_TOK (GOTO); }
231"if" { setTokLength (2); RETURN_TOK (CIF); }
232"return" { setTokLength (6); RETURN_TOK (RETURN); }
233"sizeof" { setTokLength (6); RETURN_TOK (CSIZEOF); }
234"offsetof" { setTokLength (8); RETURN_TOK (COFFSETOF); }
235"switch" { setTokLength (6); RETURN_TOK (SWITCH); }
236"while" { setTokLength (5); RETURN_TOK (WHILE); }
237"va_arg" { setTokLength (6); RETURN_TOK (VA_ARG); }
238"va_dcl" { setTokLength (6); RETURN_TOK (VA_DCL); }
239"inline" {
240 /* gcc extension...this might not be appropriate */
241 setTokLength (6); RETURN_TOK (QINLINE); }
242
243"struct" { setTokLength (6); RETURN_TOK (CSTRUCT); }
244"typedef" { setTokLength (7); RETURN_TOK (CTYPEDEF); }
245
246"union" { setTokLength (5); RETURN_TOK (CUNION); }
247"enum" { setTokLength (4); RETURN_TOK (CENUM); }
248
249"void" { setTokLength (4); RETURN_TYPE (CVOID, ctype_void); }
250"int" { setTokLength (3); RETURN_TYPE (CINT, ctype_int); }
251"double" { setTokLength (6); RETURN_TYPE (CDOUBLE, ctype_double); }
252"char" { setTokLength (4); RETURN_TYPE (CGCHAR, ctype_char); }
253"float" { setTokLength (5); RETURN_TYPE (CGFLOAT, ctype_float); }
254
255"long" { setTokLength (4); RETURN_TOK (QLONG); }
256"short" { setTokLength (5); RETURN_TOK (QSHORT); }
257"unsigned" { setTokLength (8); RETURN_TOK (QUNSIGNED); }
258"signed" { setTokLength (6); RETURN_TOK (QSIGNED); }
259
260"volatile" { setTokLength (8); RETURN_TOK (QVOLATILE); }
261"const" { setTokLength (5); RETURN_TOK (QCONST); }
262
263 /* some systems expect this! [gack!] */
264"__const" { setTokLength (7); RETURN_TOK (QCONST); }
265
266"extern" { setTokLength (6); RETURN_TOK (QEXTERN); }
267"auto" { setTokLength (4); RETURN_TOK (QAUTO); }
268"register" { setTokLength (8); RETURN_TOK (QREGISTER); }
269"static" { setTokLength (6); RETURN_TOK (QSTATIC); }
270
271\"(\\.|[^\\"])*\"([ \t\n]*\"(\\.|[^\\"])*\")* { RETURN_EXPR (processString ()); }
7b1629ab 272L\"(\\.|[^\\"])*\"([ \t\n]*\"(\\.|[^\\"])*\")* { RETURN_EXPR (processString ()); }
885824d3 273"out" { return (processSpec (QOUT)); }
274"in" { return (processSpec (QIN)); }
275"partial" { return (processSpec (QPARTIAL)); }
276"special" { return (processSpec (QSPECIAL)); }
277"anytype" { return (processSpec (QANYTYPE)); }
278"integraltype" { return (processSpec (QINTEGRALTYPE)); }
279"unsignedintegraltype" { return (processSpec (QUNSIGNEDINTEGRALTYPE)); }
280"signedintegraltype" { return (processSpec (QSIGNEDINTEGRALTYPE)); }
281"keep" { return (processSpec (QKEEP)); }
282"null" { return (processSpec (QNULL)); }
283"notnull" { return (processSpec (QNOTNULL)); }
284"isnull" { return (processSpec (QISNULL)); }
285"truenull" { return (processSpec (QTRUENULL)); }
286"falsenull" { return (processSpec (QFALSENULL)); }
287"relnull" { return (processSpec (QRELNULL)); }
288"reldef" { return (processSpec (QRELDEF)); }
289"exposed" { return (processSpec (QEXPOSED)); }
290"newref" { return (processSpec (QNEWREF)); }
291"tempref" { return (processSpec (QTEMPREF)); }
292"killref" { return (processSpec (QKILLREF)); }
293"refcounted" { return (processSpec (QREFCOUNTED)); }
294"checked" { return (processSpec (QCHECKED)); }
295"checkmod" { return (processSpec (QCHECKMOD)); }
296"checkedstrict" { return (processSpec (QCHECKEDSTRICT)); }
297"unchecked" { return (processSpec (QUNCHECKED)); }
298"only" { return (processSpec (QONLY)); }
299"owned" { return (processSpec (QOWNED)); }
300"observer" { return (processSpec (QOBSERVER)); }
301"dependent" { return (processSpec (QDEPENDENT)); }
302"unused" { return (processSpec (QUNUSED)); }
303"external" { return (processSpec (QEXTERNAL)); }
304"sef" { return (processSpec (QSEF)); }
305"shared" { return (processSpec (QSHARED)); }
306"yield" { return (processSpec (QYIELD)); }
307"undef" { return (processSpec (QUNDEF)); }
308"killed" { return (processSpec (QKILLED)); }
1ac6313d 309"nullterminated" { return (processSpec (QNULLTERMINATED));}
93307a76 310"MaxSet" { return (processSpec (QMAXSET));}
311"MaxRead" { return (processSpec (QMAXREAD));}
11ed4f45 312
885824d3 313{Letter}({Letter}|{Digit})* { int tok;
314 context_saveLocation ();
315 setTokLength (longUnsigned_toInt (mstring_length (yytext)));
316 tok = processIdentifier (makeIdentifier (yytext));
317 if (tok != BADTOK)
318 {
319 return (tok);
320 }
321 }
3220[xX]{H}+ { setTokLengthT (mstring_length (yytext));
323 RETURN_INT (ctype_int, processHex ()); /* evs 2000-05-17 was ctype_uint */
324 }
3250[xX]{H}+{L} { setTokLengthT (mstring_length (yytext));
326 RETURN_INT (ctype_lint, processHex ()); }
3270[xX]{H}+{L}{L} { setTokLengthT (mstring_length (yytext));
328 RETURN_INT (ctype_llint, processHex ()); }
3290[xX]{H}+{U} { setTokLengthT (mstring_length (yytext));
330 RETURN_INT (ctype_uint, processHex ()); }
3310[xX]{H}+{ULSuffix} { setTokLengthT (mstring_length (yytext));
332 RETURN_INT (ctype_ulint, processHex ()); }
3330[xX]{H}+{U}{L}{L} { setTokLengthT (mstring_length (yytext));
334 RETURN_INT (ctype_ullint, processHex ()); }
3350[xX]{H}+{L}{L}{U} { setTokLengthT (mstring_length (yytext));
336 RETURN_INT (ctype_ullint, processHex ()); }
3370{Digit}+ { setTokLengthT (mstring_length (yytext));
338 RETURN_INT (ctype_int, processOctal ()); }
3390{Digit}+{U} { setTokLengthT (mstring_length (yytext));
340 RETURN_INT (ctype_uint, processOctal ()); }
3410{Digit}+{L} { setTokLengthT (mstring_length (yytext));
342 RETURN_INT (ctype_lint, processOctal ()); }
3430{Digit}+{L}{L} { setTokLengthT (mstring_length (yytext));
344 RETURN_INT (ctype_llint, processOctal ()); }
3450{Digit}+{ULSuffix} { setTokLengthT (mstring_length (yytext));
346 RETURN_INT (ctype_ulint, processOctal ()); }
3470{Digit}+{U}{L}{L} { setTokLengthT (mstring_length (yytext));
348 RETURN_INT (ctype_ullint, processOctal ()); }
3490{Digit}+{L}{L}{U} { setTokLengthT (mstring_length (yytext));
350 RETURN_INT (ctype_ullint, processOctal ()); }
351{Digit}+ { setTokLengthT (mstring_length (yytext));
352 RETURN_INT (ctype_int, processDec ()); }
353{Digit}+{U} { setTokLengthT (mstring_length (yytext));
354 RETURN_INT (ctype_uint, processDec ()); }
355{Digit}+{L} { setTokLengthT (mstring_length (yytext));
356 RETURN_INT (ctype_lint, processDec ()); }
357{Digit}+{L}{L} { setTokLengthT (mstring_length (yytext));
358 RETURN_INT (ctype_llint, processDec ()); }
359{Digit}+{ULSuffix} { setTokLengthT (mstring_length (yytext));
360 RETURN_INT (ctype_ulint, processDec ()); }
361{Digit}+{U}{L}{L} { setTokLengthT (mstring_length (yytext));
362 RETURN_INT (ctype_ullint, processDec ()); }
363{Digit}+{L}{L}{U} { setTokLengthT (mstring_length (yytext));
364 RETURN_INT (ctype_ullint, processDec ()); }
365'(\\.|[^\\'])+' { setTokLengthT (mstring_length (yytext));
366 RETURN_CHAR (processChar ()); }
367{Digit}+{E}[fF] { setTokLengthT (mstring_length (yytext));
368 RETURN_FLOAT (ctype_float, processFloat ()); }
369{Digit}+{E}[lL] { setTokLengthT (mstring_length (yytext));
370 RETURN_FLOAT (ctype_ldouble, processFloat ()); }
371{Digit}+{E} { setTokLengthT (mstring_length (yytext));
372 RETURN_FLOAT (ctype_double, processFloat ()); }
373
374{Digit}*"."{Digit}+({E})?[fF] { setTokLengthT (mstring_length (yytext));
375 RETURN_FLOAT (ctype_float, processFloat ()); }
376{Digit}*"."{Digit}+({E})?[lL] { setTokLengthT (mstring_length (yytext));
377 RETURN_FLOAT (ctype_ldouble, processFloat ()); }
378{Digit}*"."{Digit}+({E})? { setTokLengthT (mstring_length (yytext));
379 RETURN_FLOAT (ctype_double, processFloat ()); }
380
381{Digit}+"."{Digit}*({E})?[fF] { setTokLengthT (mstring_length (yytext));
382 RETURN_FLOAT (ctype_float, processFloat ()); }
383{Digit}+"."{Digit}*({E})?[lL] { setTokLengthT (mstring_length (yytext));
384 RETURN_FLOAT (ctype_ldouble, processFloat ()); }
385{Digit}+"."{Digit}*({E})? { setTokLengthT (mstring_length (yytext));
386 RETURN_FLOAT (ctype_double, processFloat ()); }
387
388">>=" { setTokLength (3); RETURN_TOK (RIGHT_ASSIGN); }
389"<<=" { setTokLength (3); RETURN_TOK (LEFT_ASSIGN); }
390"+=" { setTokLength (2); RETURN_TOK (ADD_ASSIGN); }
391"-=" { setTokLength (2); RETURN_TOK (SUB_ASSIGN); }
392"*=" { setTokLength (2); RETURN_TOK (MUL_ASSIGN); }
393"/=" { setTokLength (2); RETURN_TOK (DIV_ASSIGN); }
394"%=" { setTokLength (2); RETURN_TOK (MOD_ASSIGN); }
395"&=" { setTokLength (2); RETURN_TOK (AND_ASSIGN); }
396"^=" { setTokLength (2); RETURN_TOK (XOR_ASSIGN); }
397"|=" { setTokLength (2); RETURN_TOK (OR_ASSIGN); }
398">>" { setTokLength (2); RETURN_TOK (RIGHT_OP); }
399"<<" { setTokLength (2); RETURN_TOK (LEFT_OP); }
400"++" { setTokLength (2); RETURN_TOK (INC_OP); }
401"--" { setTokLength (2); RETURN_TOK (DEC_OP); }
402"->" { setTokLength (2); RETURN_TOK (ARROW_OP); }
403"&&" { setTokLength (2); RETURN_TOK (AND_OP); }
404"||" { setTokLength (2); RETURN_TOK (OR_OP); }
405"<=" { setTokLength (2); RETURN_TOK (LE_OP); }
406">=" { setTokLength (2); RETURN_TOK (GE_OP); }
407"==" { setTokLength (2); RETURN_TOK (EQ_OP); }
408"!=" { setTokLength (2); RETURN_TOK (NE_OP); }
409";" { setTokLength (1); RETURN_TOK (TSEMI); }
410"{" { setTokLength (1); RETURN_TOK (TLBRACE); }
411"}" { setTokLength (1); RETURN_TOK (TRBRACE); }
412"," { setTokLength (1); RETURN_TOK (TCOMMA); }
413":" { setTokLength (1); RETURN_TOK (TCOLON); }
414"=" { setTokLength (1); RETURN_TOK (TASSIGN); }
415"(" { setTokLength (1); RETURN_TOK (TLPAREN); }
416")" { setTokLength (1); RETURN_TOK (TRPAREN); }
417"[" { setTokLength (1); RETURN_TOK (TLSQBR); }
418"]" { setTokLength (1); RETURN_TOK (TRSQBR); }
419"." { setTokLength (1); RETURN_TOK (TDOT); }
420"&" { setTokLength (1); RETURN_TOK (TAMPERSAND); }
421"!" { setTokLength (1); RETURN_TOK (TEXCL); }
422
423
424"~" { setTokLength (1); RETURN_TOK (TTILDE); }
425"-" { setTokLength (1); RETURN_TOK (TMINUS); }
426"+" { setTokLength (1); RETURN_TOK (TPLUS); }
427"*" { setTokLength (1); RETURN_TOK (TMULT); }
428"/" { setTokLength (1); RETURN_TOK (TDIV); }
429"%" { setTokLength (1); RETURN_TOK (TPERCENT); }
430"<" { setTokLength (1); RETURN_TOK (TLT); }
431">" { setTokLength (1); RETURN_TOK (TGT); }
432"^" { setTokLength (1); RETURN_TOK (TCIRC); }
433"|" { setTokLength (1); RETURN_TOK (TBAR); }
434"?" { setTokLength (1); RETURN_TOK (TQUEST); }
435
dcaf75ea 436
437"/\\" { setTokLength (1); RETURN_TOK (TCAND); }
438
439
885824d3 440[ \t\v\f] { incColumn (); }
441\n { context_incLineno ();
442 if (continueLine)
443 {
444 continueLine = FALSE;
445 }
446 else
447 {
448 if (context_inMacro ())
449 {
450 /* Don't use RETURN_TOK */
451 yylval.tok = lltok_create (TENDMACRO, g_currentloc);
452 lastWasString = FALSE;
453 return (TENDMACRO);
454 }
455 }
456 }
457"@@MR@@" { setTokLength (6);
458
459 if (processMacro ()) {
460 if (context_inIterDef ())
461 {
462 RETURN_TOK (LLMACROITER);
463 }
464 if (context_inIterEnd ())
465 {
466 RETURN_TOK (LLMACROEND);
467 }
468 if (context_inMacro ())
469 {
470 RETURN_TOK (LLMACRO);
471 }
472 }
473 }
474"@QLMR" { if (context_inHeader () || context_inFunction ())
475 {
476 handleMacro ();
477 }
478 else
479 {
480 int nspchar = ninput ();
481 int nspaces;
482
483 /*
484 ** This is a hack to get the column number correct.
485 */
486
487 llassert (nspchar >= '0' && nspchar <= '9');
488
489 nspaces = nspchar - '0';
490
491 setTokLength (5 + nspaces);
492
493 if (processMacro ())
494 {
495 if (context_inIterDef ())
496 {
497 RETURN_TOK (LLMACROITER);
498 }
499 if (context_inIterEnd ())
500 {
501 RETURN_TOK (LLMACROEND);
502 }
503 if (context_inMacro ())
504 {
505 RETURN_TOK (LLMACRO);
506 }
507 }
508 }
509 }
510"@.CT" { setTokLength (4); lldiagmsg (ctype_unparseTable ()); }
28bf4b0b 511"@.FA" { setTokLength (4); lldiagmsg (message ("Access types: %q", typeIdSet_unparse (context_fileAccessTypes ()))); }
885824d3 512"@.F" { setTokLength (3);
513 lldiagmsg (message ("%q: *** marker ***", fileloc_unparse (g_currentloc)));
514 }
515"@.L" { setTokLength (3); usymtab_printLocal (); }
516"@.A" { setTokLength (3); lldiagmsg (usymtab_unparseAliases ()); }
517"@.C" { setTokLength (3); lldiagmsg (context_unparse ()); }
518"@.W" { setTokLength (3); lldiagmsg (context_unparseClauses ()); }
519"@.G" { setTokLength (3); usymtab_printGuards (); }
520"@.S" { setTokLength (3); usymtab_printOut (); }
521"@.X" { setTokLength (3); usymtab_printAll (); }
522"@.Z" { setTokLength (3); usymtab_printComplete (); }
523"@.T" { setTokLength (3); usymtab_printTypes (); }
524"@.K" { setTokLength (3); lldiagmsg (usymtab_unparseStack ()); }
525"@.M" { setTokLength (3);
526 lldiagmsg (message ("Can modify: %q",
527 sRefSet_unparse (context_modList ())));
528 }
529"%{" { /* BEFORE_COMMENT_MARKER */
530 int tok;
531 incColumn (); incColumn ();
532 tok = handleLlSpecial ();
28bf4b0b 533
885824d3 534 if (tok != BADTOK)
535 {
28bf4b0b 536 if (tok == CANNOTATION) {
537 return (tok);
538 } else {
539 /* Beware - this bashes yylval! */
540 RETURN_TOK (tok);
541 }
885824d3 542 }
543 }
544"%}" { /* AFTER_COMMENT_MARKER */
545 setTokLength (2);
546 inSpecPart = FALSE;
547 RETURN_TOK (QENDMACRO); }
548"\\" { incColumn (); continueLine = TRUE; }
549. { incColumn ();
28bf4b0b 550 if ((int) *yytext == 13 ) {
551 ;
552 } else {
553 voptgenerror
554 (FLG_SYNTAX,
555 message ("Invalid character (ascii: %d), skipping character",
556 (int)(*yytext)),
557 g_currentloc);
558 }
885824d3 559 }
560%%
561
562struct skeyword
563{
564 /*@null@*/ /*@observer@*/ char *name;
565 int token;
566} ;
567
568/*
569** These tokens are followed by syntax that is parsed by the
570** grammar proper.
571*/
572
573struct skeyword s_parsetable[] = {
574 { "modifies", QMODIFIES } ,
575 { "globals", QGLOBALS } ,
576 { "alt", QALT } ,
28bf4b0b 577 { "warn", QWARN } ,
885824d3 578 { "constant", QCONSTANT } ,
579 { "function", QFUNCTION } ,
580 { "iter", QITER } ,
581 { "defines", QDEFINES } ,
582 { "uses", QUSES } ,
583 { "allocates", QALLOCATES } ,
584 { "sets", QSETS } ,
585 { "releases", QRELEASES } ,
586 { "pre", QPRECLAUSE } ,
587 { "post", QPOSTCLAUSE } ,
60eced23 588 { "setBufferSize", QSETBUFFERSIZE},
60eced23 589 { "setStringLength", QSETSTRINGLENGTH},
590 { "testinRange", QTESTINRANGE},
28bf4b0b 591 { "requires", QPRECLAUSE } ,
592 { "ensures", QPOSTCLAUSE } ,
593 { NULL, BADTOK }
885824d3 594} ;
595
596/*
597** These tokens are either stand-alone tokens, or followed by
598** token-specific text.
599*/
600
601struct skeyword s_keytable[] = {
602 { "anytype", QANYTYPE } ,
603 { "integraltype", QINTEGRALTYPE } ,
604 { "unsignedintegraltype", QUNSIGNEDINTEGRALTYPE } ,
605 { "signedintegraltype", QSIGNEDINTEGRALTYPE } ,
606 { "out", QOUT } ,
607 { "in", QIN } ,
608 { "only", QONLY } ,
609 { "owned", QOWNED } ,
610 { "dependent", QDEPENDENT } ,
611 { "partial", QPARTIAL } ,
612 { "special", QSPECIAL } ,
613 { "truenull", QTRUENULL } ,
614 { "falsenull", QFALSENULL } ,
615 { "keep", QKEEP } ,
616 { "kept", QKEPT } ,
617 { "notnull", QNOTNULL } ,
618 { "abstract", QABSTRACT } ,
619 { "concrete", QCONCRETE } ,
620 { "mutable", QMUTABLE } ,
621 { "immutable", QIMMUTABLE } ,
622 { "unused", QUNUSED } ,
623 { "external", QEXTERNAL } ,
624 { "sef", QSEF } ,
625 { "unique", QUNIQUE } ,
626 { "returned", QRETURNED } ,
627 { "exposed", QEXPOSED } ,
628 { "refcounted", QREFCOUNTED } ,
629 { "refs", QREFS } ,
630 { "newref", QNEWREF } ,
631 { "tempref", QTEMPREF } ,
632 { "killref", QKILLREF } ,
633 { "null", QNULL } ,
634 { "relnull", QRELNULL } ,
1ac6313d 635 { "nullterminated", QNULLTERMINATED },
11ed4f45 636 { "setBufferSize", QSETBUFFERSIZE },
a0a162cd 637 { "testInRange", QTESTINRANGE},
93307a76 638 { "MaxSet", QMAXSET},
639 { "MaxRead", QMAXREAD},
885824d3 640 { "reldef", QRELDEF } ,
641 { "observer", QOBSERVER } ,
642 { "exits", QEXITS } ,
643 { "mayexit", QMAYEXIT } ,
644 { "trueexit", QTRUEEXIT } ,
645 { "falseexit", QFALSEEXIT } ,
646 { "neverexit", QNEVEREXIT } ,
647 { "temp", QTEMP } ,
648 { "shared", QSHARED } ,
649 { "ref", QREF } ,
650 { "unchecked", QUNCHECKED } ,
651 { "checked", QCHECKED } ,
652 { "checkmod", QCHECKMOD } ,
653 { "checkedstrict", QCHECKEDSTRICT } ,
654 { "innercontinue", QINNERCONTINUE } ,
655 { "innerbreak", QINNERBREAK } ,
656 { "loopbreak", QLOOPBREAK } ,
657 { "switchbreak", QSWITCHBREAK } ,
658 { "safebreak", QSAFEBREAK } ,
659 { "fallthrough", QFALLTHROUGH } ,
660 { "l_fallthrou", QLINTFALLTHROUGH } ,
661 { "l_fallth", QLINTFALLTHRU } ,
662 { "notreached", QNOTREACHED } ,
663 { "l_notreach", QLINTNOTREACHED } ,
664 { "printflike", QPRINTFLIKE } ,
665 { "l_printfli", QLINTPRINTFLIKE } ,
666 { "scanflike", QSCANFLIKE } ,
667 { "messagelike", QMESSAGELIKE } ,
668 { "l_argsus", QARGSUSED } ,
669 { NULL, BADTOK }
670} ;
671
672/*
673** would be better if these weren't hard coded...
674*/
675
676static bool isArtificial (cstring s)
677{
678 return (cstring_equalLit (s, "modifies")
679 || cstring_equalLit (s, "globals")
28bf4b0b 680 || cstring_equalLit (s, "warn")
885824d3 681 || cstring_equalLit (s, "alt"));
682}
683
684void swallowMacro (void)
685{
686 int i;
687 bool skipnext = FALSE;
688
689 while ((i = lminput ()) != EOF)
690 {
691 char c = (char) i;
692
693
694 if (c == '\\')
695 {
696 skipnext = TRUE;
697 }
698 else if (c == '\n')
699 {
700 if (skipnext)
701 {
702 skipnext = FALSE;
703 }
704 else
705 {
28bf4b0b 706 reader_checkUngetc (i, yyin);
885824d3 707 return;
708 }
709 }
710 }
711
712 if (i != EOF)
713 {
28bf4b0b 714 reader_checkUngetc (i, yyin);
885824d3 715 }
716}
717
718static int commentMarkerToken (cstring s)
719{
720 int i = 0;
721
722 while (s_parsetable[i].name != NULL)
723 {
28bf4b0b 724 DPRINTF (("Try :%s:%s:", s, s_parsetable[i].name));
725
885824d3 726 if (cstring_equalLit (s, s_parsetable[i].name))
727 {
728 return s_parsetable[i].token;
729 }
730
731 i++;
732 }
733
734 return BADTOK;
735}
736
737static int tokenMacroCode (cstring s)
738{
739 int i = 0;
740
741 while (s_keytable[i].name != NULL)
742 {
743 if (cstring_equalLit (s, s_keytable[i].name))
744 {
745 if (s_keytable[i].token == QLINTFALLTHROUGH)
746 {
747 voptgenerror
748 (FLG_WARNLINTCOMMENTS,
749 cstring_makeLiteral
750 ("Traditional lint comment /*FALLTHROUGH*/ used. "
751 "This is interpreted by "
752 "LCLint in the same way as most Unix lints, but it is "
753 "preferable to replace it with the /*@fallthrough@*/ "
28bf4b0b 754 "semantic comment"),
885824d3 755 g_currentloc);
756 return QFALLTHROUGH;
757 }
758 else if (s_keytable[i].token == QLINTFALLTHRU)
759 {
760 voptgenerror
761 (FLG_WARNLINTCOMMENTS,
762 cstring_makeLiteral
763 ("Traditional lint comment /*FALLTHRU*/ used. "
764 "This is interpreted by "
765 "LCLint in the same way as most Unix lints, but it is "
766 "preferable to replace it with the /*@fallthrough@*/ "
28bf4b0b 767 "semantic comment"),
885824d3 768 g_currentloc);
769 return QFALLTHROUGH;
770 }
771 else if (s_keytable[i].token == QLINTNOTREACHED)
772 {
773 voptgenerror
774 (FLG_WARNLINTCOMMENTS,
775 cstring_makeLiteral
776 ("Traditional lint comment /*NOTREACHED*/ used. "
777 "This is interpreted by "
778 "LCLint in the same way as most Unix lints, but it is "
779 "preferable to replace it with the /*@notreached@*/ "
28bf4b0b 780 "semantic comment."),
885824d3 781 g_currentloc);
782
783 return QNOTREACHED;
784 }
785 else if (s_keytable[i].token == QPRINTFLIKE)
786 {
28bf4b0b 787 setSpecialFunction (qual_createPrintfLike ());
885824d3 788 return SKIPTOK;
789 }
790 else if (s_keytable[i].token == QLINTPRINTFLIKE)
791 {
792 voptgenerror
793 (FLG_WARNLINTCOMMENTS,
794 cstring_makeLiteral
795 ("Traditional lint comment /*PRINTFLIKE*/ used. "
796 "This is interpreted by "
797 "LCLint in the same way as most Unix lints, but it is "
798 "preferable to replace it with either /*@printflike@*/, "
799 "/*@scanflike@*/ or /*@messagelike@*/."),
800 g_currentloc);
801
28bf4b0b 802 setSpecialFunction (qual_createPrintfLike ());
885824d3 803 return SKIPTOK;
804 }
805 else if (s_keytable[i].token == QSCANFLIKE)
806 {
28bf4b0b 807 setSpecialFunction (qual_createScanfLike ());
885824d3 808 return SKIPTOK;
809 }
810 else if (s_keytable[i].token == QMESSAGELIKE)
811 {
28bf4b0b 812 setSpecialFunction (qual_createMessageLike ());
885824d3 813 return SKIPTOK;
814 }
815 else if (s_keytable[i].token == QARGSUSED)
816 {
817 voptgenerror
818 (FLG_WARNLINTCOMMENTS,
819 cstring_makeLiteral
820 ("Traditional lint comment /*ARGSUSED*/ used. "
821 "This is interpreted by "
822 "LCLint in the same way as most Unix lints, but it is "
823 "preferable to use /*@unused@*/ annotations on "
824 "the unused parameters."),
825 g_currentloc);
826
827 setArgsUsed ();
828 return SKIPTOK;
829 }
830
831 return s_keytable[i].token;
832 }
833
834 i++;
835 }
836
837 return BADTOK;
838}
839
840static int lminput ()
841{
842 if (savechar == '\0')
843 {
844 incColumn ();
845 return (input ());
846 }
847 else
848 {
849 int save = (int) savechar;
850 savechar = '\0';
851 return save;
852 }
853}
854
855static void lmsavechar (char c)
856{
857 if (savechar == '\0') savechar = c;
858 else
859 {
860 llbuglit ("lmsavechar: override");
861 }
862}
863
864static int returnFloat (ctype ct, double f)
865{
866 yylval.expr = exprNode_floatLiteral (f, ct, cstring_fromChars (yytext),
867 fileloc_decColumn (g_currentloc, tokLength));
868 tokLength = 0;
869 return (CCONSTANT);
870}
871
872static int returnInt (ctype ct, long i)
873{
874 ctype c = ct;
875
876 if (ctype_equal (ct, ctype_int))
877 {
878 if (i == 0)
879 {
880 c = context_typeofZero ();
881 }
882 else if (i == 1)
883 {
884 c = context_typeofOne ();
885 }
886 }
887
888 yylval.expr = exprNode_numLiteral (c, cstring_fromChars (yytext),
889 fileloc_decColumn (g_currentloc, tokLength), i);
890 tokLength = 0;
891 return (CCONSTANT);
892}
893
894static int returnChar (char c)
895{
896 yylval.expr = exprNode_charLiteral (c, cstring_fromChars (yytext),
897 fileloc_decColumn (g_currentloc, tokLength));
898 tokLength = 0;
899 return (CCONSTANT);
900}
901
902static int ninput ()
903{
904 int c = lminput ();
905
906 if (c != EOF && ((char)c == '\n'))
907 {
908 context_incLineno ();
909 }
910
911 return c;
912}
913
914static char macro_nextChar ()
915{
916 static bool in_quote = FALSE, in_escape = FALSE, in_char = FALSE;
917 int ic;
918 char c;
919
920 ic = lminput ();
921 c = char_fromInt (ic);
922
923 if (!in_quote && !in_char && (c == '\\' || c == BEFORE_COMMENT_MARKER[0]))
924 {
925 if (c == '\\')
926 {
927 while ((c = char_fromInt (lminput ())) != '\0' && c != '\n')
928 {
929 ; /* skip to newline */
930 }
931
932 context_incLineno ();
933
934 if (c != '\0')
935 {
936 return macro_nextChar ();
937 }
938 else
939 {
940 return c;
941 }
942 }
943 else /* if (c == '@') */
944 {
28bf4b0b 945 llassert (FALSE); /*@i23@*/
885824d3 946 if (handleLlSpecial () != BADTOK)
947 {
948 llerrorlit (FLG_SYNTAX, "Macro cannot use special syntax");
949 }
950
951 return macro_nextChar ();
952 }
953 }
954 else if (!in_escape && c == '\"')
955 {
956 in_quote = !in_quote;
957 }
958 else if (!in_escape && c == '\'')
959 {
960 in_char = !in_char;
961 }
962 else if ((in_quote || in_char) && c == '\\')
963 {
964 in_escape = !in_escape;
965 }
966 else if ((in_quote || in_char) && in_escape)
967 {
968 in_escape = FALSE;
969 }
970 else if (!in_quote && c == '/')
971 {
972 char c2;
973
974 if ((c2 = char_fromInt (lminput ())) == '*')
975 {
976 while (c2 != '\0')
977 {
978 while ((c2 = char_fromInt (lminput ())) != '\0'
979 && c2 != '\n' && c2 != '*')
980 {
981 ;
982 }
983
984 if (c2 == '*')
985 {
986 while ((c2 = char_fromInt (lminput ())) != '\0'
987 && c2 == '*')
988 {
989 ;
990 }
991
992 if (c2 == '/')
993 {
994 goto outofcomment;
995 }
996 }
997 else
998 {
999 llfatalerror (cstring_makeLiteral ("Macro: bad comment!"));
1000 }
1001 }
1002 outofcomment:
1003 return macro_nextChar ();
1004 }
1005 else
1006 {
1007 /*** putchar does not work! why? puts to stdio...??! ***/
1008 lmsavechar (c2);
1009 }
1010 }
1011 return c;
1012}
1013
1014/*
28bf4b0b 1015** keeps semantic comments
885824d3 1016*/
1017
1018static char macro_nextCharC ()
1019{
1020 static bool in_quote = FALSE, in_escape = FALSE, in_char = FALSE;
1021 char c;
1022
1023 c = char_fromInt (lminput ());
1024
1025 if (!in_quote && !in_char && c == '\\')
1026 {
1027 while ((c = char_fromInt (lminput ())) != '\0' && c != '\n')
1028 {
1029 ; /* skip to newline */
1030 }
1031
1032 context_incLineno ();
1033
1034 if (c != '\0')
1035 {
1036 return macro_nextCharC ();
1037 }
1038 else
1039 {
1040 return c;
1041 }
1042 }
1043 else if (!in_escape && c == '\"')
1044 {
1045 in_quote = !in_quote;
1046 }
1047 else if (!in_escape && c == '\'')
1048 {
1049 in_char = !in_char;
1050 }
1051 else if ((in_quote || in_char) && c == '\\')
1052 {
1053 in_escape = !in_escape;
1054 }
1055 else if ((in_quote || in_char) && in_escape)
1056 {
1057 in_escape = FALSE;
1058 }
1059 else if (!in_quote && c == '/')
1060 {
1061 char c2;
1062
1063 if ((c2 = char_fromInt (lminput ())) == '*')
1064 {
1065 while (c2 != '\0')
1066 {
1067 while ((c2 = char_fromInt (lminput ())) != '\0'
1068 && c2 != '\n' && c2 != '*')
1069 {
1070 ;
1071 }
1072
1073 if (c2 == '*')
1074 {
1075 while ((c2 = char_fromInt (lminput ())) != '\0'
1076 && c2 == '*')
1077 {
1078 ;
1079 }
1080
1081 if (c2 == '/')
1082 {
1083 goto outofcomment;
1084 }
1085 }
1086 else
1087 {
1088 llfatalerror (cstring_makeLiteral ("Macro: bad comment!"));
1089 }
1090 }
1091 outofcomment:
1092 return macro_nextCharC ();
1093 }
1094 else
1095 {
1096 lmsavechar (c2);
1097 }
1098 }
1099 return c;
1100}
1101
1102/*
1103** skips whitespace (handles line continuations)
1104** returns first non-whitespace character
1105*/
1106
1107static char skip_whitespace ()
1108{
1109 char c;
1110
1111 while ((c = macro_nextChar ()) == ' ' || c == '\t')
1112 {
1113 ;
1114 }
1115
1116 return c;
1117}
1118
1119static void handleMacro ()
1120{
1121 cstring mac = cstring_undefined;
1122 int macrocode;
1123 char c;
1124
1125 while (currentColumn () > 2)
1126 {
1127 mac = cstring_appendChar (mac, ' ');
1128 setTokLength (-1);
1129 }
1130
1131 c = macro_nextCharC ();
1132
1133 if (c >= '0' && c <= '9')
1134 {
1135 int i;
1136
1137 for (i = 0; i < ((c - '0') + 1); i++)
1138 {
1139 mac = cstring_appendChar (mac, ' ');
1140 }
1141 }
1142 else
1143 {
1144 BADBRANCH;
1145 }
1146
1147 while (((c = macro_nextCharC ()) != '\0') && (c != '\n'))
1148 {
1149 mac = cstring_appendChar (mac, c);
1150 }
1151
1152
1153 macrocode = tokenMacroCode (mac);
1154
1155 if (macrocode == BADTOK && !isArtificial (mac))
1156 {
885824d3 1157 context_addMacroCache (mac);
1158 }
1159 else
1160 {
1161 cstring_free (mac);
1162 }
1163
1164 if (c == '\n')
1165 {
1166 context_incLineno ();
1167 }
1168}
1169
1170static bool processMacro (void)
1171{
1172 uentry e2;
1173 ctype ct;
1174 int noparams = 0;
1175 cstring fname = cstring_undefined;
1176 bool res = TRUE;
1177 bool isspecfcn = FALSE;
1178 bool isiter = FALSE;
1179 bool skipparam = FALSE;
1180 bool isenditer = FALSE;
1181 bool unknownm = FALSE;
1182 bool hasParams = FALSE;
1183 bool emptyMacro = FALSE;
1184 char c = skip_whitespace ();
1185 fileloc loc = fileloc_noColumn (g_currentloc);
1186
1187 /* are both of these necessary? what do they mean? */
1188 uentryList specparams = uentryList_undefined;
1189 uentryList pn = uentryList_undefined;
1190
1191 context_resetMacroMissingParams ();
1192
1193 if (c == '\0' || c == '\n')
1194 {
1195 llcontbug (cstring_makeLiteral ("Bad macro"));
1196 fileloc_free (loc);
1197 return FALSE;
1198 }
1199
1200 fname = cstring_appendChar (fname, c);
1201
1202 while ((c = macro_nextChar ()) != '(' && c != '\0'
1203 && c != ' ' && c != '\t' && c != '\n')
1204 {
1205 fname = cstring_appendChar (fname, c);
1206 }
1207
1208 if (c == ' ' || c == '\t' || c == '\n')
1209 {
1210 char oldc = c;
1211
1212 if (c != '\n')
1213 {
1214 while (c == ' ' || c == '\t')
1215 {
1216 c = macro_nextChar ();
1217 }
1218 unput (c);
1219 }
1220
1221 if (c == '\n')
1222 {
1223 emptyMacro = TRUE;
1224 unput (c);
1225 }
1226
1227 c = oldc;
1228 }
1229
1230 hasParams = (c == '(');
1231
1232
1233 if (usymtab_exists (fname))
1234 {
1235 e2 = usymtab_lookupExpose (fname);
1236 ct = uentry_getType (e2);
1237
1238
1239 if (uentry_isCodeDefined (e2)
1240 && fileloc_isUser (uentry_whereDefined (e2)))
1241 {
1242 if (optgenerror
1243 (FLG_MACROREDEF,
1244 message ("Macro %s already defined", fname),
1245 loc))
1246 {
1247 uentry_showWhereDefined (e2);
1248 uentry_clearDefined (e2);
1249 }
1250
1251 if (uentry_isFunction (e2))
1252 {
1253 uentry_setType (e2, ctype_unknown);
1254 ct = ctype_unknown;
1255 unknownm = TRUE;
1256 context_enterUnknownMacro (e2);
1257 }
1258 else
1259 {
1260 context_enterConstantMacro (e2);
1261 }
1262 }
1263 else
1264 {
1265 if (uentry_isForward (e2) && uentry_isFunction (e2))
1266 {
1267 unknownm = TRUE;
1268
1269 voptgenerror
1270 (FLG_MACROFCNDECL,
1271 message
1272 ("Parameterized macro has no prototype or specification: %s ",
1273 fname),
1274 loc);
1275
1276 ct = ctype_unknown;
1277 uentry_setType (e2, ctype_unknown);
1278 uentry_setFunctionDefined (e2, loc);
1279 uentry_setUsed (e2, fileloc_undefined);
1280 context_enterUnknownMacro (e2);
1281 }
1282 else
1283 {
1284 if (uentry_isIter (e2))
1285 {
1286 isiter = TRUE;
1287 specparams = uentry_getParams (e2);
1288 noparams = uentryList_size (specparams);
1289 uentry_setDefined (e2, loc);
1290 context_enterIterDef (e2);
1291 }
1292 else if (uentry_isEndIter (e2))
1293 {
1294 isenditer = TRUE;
1295 uentry_setDefined (e2, loc);
1296 context_enterIterEnd (e2); /* don't care about it now */
1297 /* but should parse like an iter! */
1298 }
1299 else if (uentry_isConstant (e2))
1300 {
1301 if (hasParams)
1302 {
1303 voptgenerror
1304 (FLG_INCONDEFS,
1305 message ("Constant %s implemented as parameterized macro",
1306 fname),
1307 g_currentloc);
1308
1309 uentry_showWhereSpecified (e2);
1310 uentry_setType (e2, ctype_unknown);
1311 uentry_makeVarFunction (e2);
1312 uentry_setDefined (e2, g_currentloc);
1313 uentry_setFunctionDefined (e2, g_currentloc);
1314 context_enterUnknownMacro (e2);
1315 }
1316 else
1317 {
1318 if (!uentry_isSpecified (e2))
1319 {
1320 fileloc oloc = uentry_whereDeclared (e2);
1321
1322 if (fileloc_isLib (oloc))
1323 {
1324 ;
1325 }
1326 else if (fileloc_isUndefined (oloc)
1327 || fileloc_isPreproc (oloc))
1328 {
1329 if (!emptyMacro)
1330 {
1331 voptgenerror
1332 (FLG_MACROCONSTDECL,
1333 message
1334 ("Macro constant %q not declared",
1335 uentry_getName (e2)),
1336 loc);
1337 }
1338 }
1339 else if (!fileloc_withinLines (oloc, loc, 2))
1340 { /* bogus! will give errors if there is too much whitespace */
1341 voptgenerror
1342 (FLG_SYNTAX,
1343 message
1344 ("Macro constant name %s does not match name in "
1345 "previous constant declaration. This constant "
1346 "is declared at %q", fname,
1347 fileloc_unparse (oloc)),
1348 loc);
1349 }
1350 }
1351
1352 context_enterConstantMacro (e2);
1353 cstring_free (fname);
1354 fileloc_free (loc);
1355 return res;
1356 }
1357
1358 }
1359 else if (ctype_isFunction (ct))
1360 {
1361 isspecfcn = TRUE;
1362 specparams = ctype_argsFunction (ct);
1363 noparams = uentryList_size (specparams);
1364
1365 uentry_setFunctionDefined (e2, loc);
1366 context_enterMacro (e2);
1367 }
1368 else if (uentry_isVar (e2))
1369 {
1370 if (hasParams)
1371 {
1372 voptgenerror
1373 (FLG_INCONDEFS,
1374 message ("Variable %s implemented as parameterized macro",
1375 fname),
1376 loc);
1377
1378 uentry_showWhereSpecified (e2);
1379 uentry_setType (e2, ctype_unknown);
1380 uentry_makeVarFunction (e2);
1381 uentry_setDefined (e2, g_currentloc);
1382 uentry_setFunctionDefined (e2, g_currentloc);
1383 context_enterUnknownMacro (e2);
1384 }
1385 else
1386 {
1387 uentry ucons = uentry_makeConstant (fname,
1388 ctype_unknown,
1389 loc);
1390 if (uentry_isExpandedMacro (e2))
1391 {
1392 ; /* okay */
1393 }
1394 else
1395 {
1396 if (optgenerror
1397 (FLG_INCONDEFS,
1398 message ("Variable %s implemented by a macro",
1399 fname),
1400 loc))
1401 {
1402 uentry_showWhereSpecified (e2);
1403 }
1404 }
1405
1406 uentry_setDefined (e2, loc);
1407 uentry_setUsed (ucons, loc);
1408
1409 context_enterConstantMacro (ucons);
1410 uentry_markOwned (ucons);
1411 cstring_free (fname);
1412 return res;
1413 }
1414 }
1415 else
1416 {
1417 if (uentry_isDatatype (e2))
1418 {
1419 vgenhinterror
1420 (FLG_SYNTAX,
1421 message ("Type implemented as macro: %x",
1422 uentry_getName (e2)),
1423 message ("A type is implemented using a macro definition. A "
1424 "typedef should be used instead."),
1425 g_currentloc);
1426
1427 swallowMacro ();
1428 /* Must exit scope (not sure why a new scope was entered?) */
1429 usymtab_quietExitScope (g_currentloc);
1430 uentry_setDefined (e2, g_currentloc);
1431 res = FALSE;
1432 }
1433 else
1434 {
1435 llcontbug
1436 (message ("Unexpanded macro not function or constant: %q",
1437 uentry_unparse (e2)));
1438 uentry_setType (e2, ctype_unknown);
1439
1440 if (hasParams)
1441 {
1442 uentry_makeVarFunction (e2);
1443 uentry_setDefined (e2, g_currentloc);
1444 uentry_setFunctionDefined (e2, g_currentloc);
1445 context_enterUnknownMacro (e2);
1446 }
1447 }
1448 }
1449 }
1450 }
1451 }
1452 else
1453 {
1454 uentry ce;
1455
1456 voptgenerror
1457 (FLG_MACROMATCHNAME,
1458 message ("Unexpanded macro %s does not match name of a constant "
1459 "or iter declaration. The name used in the control "
1460 "comment on the previous line should match. "
1461 "(Assuming macro defines a constant.)",
1462 fname),
1463 loc);
1464
1465
1466 ce = uentry_makeConstant (fname, ctype_unknown, fileloc_undefined);
1467 uentry_setUsed (ce, loc); /* perhaps bogus? */
1468 e2 = usymtab_supEntryReturn (ce);
1469
1470 context_enterConstantMacro (e2);
1471 cstring_free (fname);
1472 fileloc_free (loc);
1473 return res;
1474 }
1475
1476 /* in macros, ( must follow immediatetly after name */
1477
1478 if (hasParams)
1479 {
1480 int paramno = 0;
1481
1482 c = skip_whitespace ();
1483
1484 while (c != ')' && c != '\0')
1485 {
1486 uentry param;
1487 bool suppress = context_inSuppressRegion ();
1488 cstring paramname = cstring_undefined;
1489
1490 /*
1491 ** save the parameter location
1492 */
1493
1494 decColumn ();
1495 context_saveLocation ();
1496 incColumn ();
1497
1498 while (c != ' ' && c != '\t' && c != ',' && c != '\0' && c != ')')
1499 {
1500 paramname = cstring_appendChar (paramname, c);
1501 c = macro_nextChar ();
1502 }
1503
1504 if (c == ' ' || c == '\t') c = skip_whitespace ();
1505
1506 if (c == ',')
1507 {
1508 c = macro_nextChar ();
1509 if (c == ' ' || c == '\t') c = skip_whitespace ();
1510 }
1511
1512 if (c == '\0')
1513 {
1514 llfatalerror (cstring_makeLiteral
1515 ("Bad macro syntax: uentryList"));
1516 }
1517
1518 if ((isspecfcn || isiter) && (paramno < noparams)
1519 && !uentry_isElipsisMarker (uentryList_getN
1520 (specparams, paramno)))
1521 {
1522 uentry decl = uentryList_getN (specparams, paramno);
1523 sRef sr;
1524
1525 param = uentry_nameCopy (paramname, decl);
1526
1527
1528 uentry_setParam (param);
1529 sr = sRef_makeParam (paramno, uentry_getType (param));
1530
1531 if (sRef_getNullState (sr) == NS_ABSNULL)
1532 {
1533 ctype pt = ctype_realType (uentry_getType (param));
1534
1535 if (ctype_isUser (pt))
1536 {
1537 uentry te = usymtab_getTypeEntrySafe (ctype_typeId (pt));
1538
1539 if (uentry_isValid (te))
1540 {
1541 sRef_setStateFromUentry (sr, te);
1542 }
1543 }
1544 else
1545 {
1546 sRef_setNullState (sr, NS_UNKNOWN, g_currentloc);
1547 }
1548 }
1549
1550 uentry_setSref (param, sr);
1551 uentry_setDeclaredForceOnly (param, context_getSaveLocation ());
1552
1553 skipparam = isiter && uentry_isOut (uentryList_getN (specparams, paramno));
1554 }
1555 else
1556 {
1557 fileloc sloc = context_getSaveLocation ();
1558
1559 param = uentry_makeVariableSrefParam
1560 (paramname, ctype_unknown, sRef_makeParam (paramno, ctype_unknown));
1561 cstring_free (paramname);
1562
1563 sRef_setPosNull (uentry_getSref (param), sloc);
1564
1565 uentry_setDeclaredForce (param, sloc);
1566
1567 skipparam = FALSE;
1568 fileloc_free (sloc);
1569 }
1570
1571 if (!skipparam)
1572 {
1573 llassert (!uentry_isElipsisMarker (param));
1574
1575 if (!suppress)
1576 {
1577 sRef_makeUnsafe (uentry_getSref (param));
1578 }
1579
1580 pn = uentryList_add (pn, uentry_copy (param));
1581 usymtab_supEntry (param);
1582 }
1583 else
1584 {
1585 /* don't add param */
1586 uentry_free (param);
1587 }
1588
1589 if (c == ',')
1590 {
1591 (void) macro_nextChar ();
1592 c = skip_whitespace ();
1593 }
1594
1595 paramno++;
1596 }
1597
1598 if (c == ')')
1599 {
1600 if (isspecfcn || isiter)
1601 {
1602 if (paramno != noparams && noparams >= 0)
1603 {
1604 advanceLine ();
1605
1606 voptgenerror
1607 (FLG_INCONDEFS,
1608 message ("Macro %s specified with %d args, defined with %d",
1609 fname, noparams, paramno),
1610 g_currentloc);
1611
1612 uentry_showWhereSpecified (e2);
1613 uentry_resetParams (e2, pn);
1614 }
1615 }
1616 else
1617 {
1618 uentry_resetParams (e2, pn);
1619 }
1620 }
1621 }
1622 else
1623 {
1624 /*
1625 ** the form should be:
1626 **
1627 ** # define newname oldname
1628 ** where oldname refers to a function matching the specification
1629 ** of newname.
1630 */
1631
1632 if (unknownm)
1633 {
1634 sRef_setGlobalScope ();
1635 usymtab_supGlobalEntry (uentry_makeVariableLoc (fname, ctype_unknown));
1636 sRef_clearGlobalScope ();
1637 }
1638 else
1639 {
1640 context_setMacroMissingParams ();
1641 }
1642 }
1643
1644
1645 /* context_setuentryList (pn); */
1646 usymtab_enterScope ();
1647
1648 fileloc_free (loc);
1649 cstring_free (fname);
1650
1651 return res;
1652}
1653
1654static bool handleSpecial (char *yyt)
1655{
1656 char *l = mstring_create (MAX_NAME_LENGTH);
1657 static bool reportcpp = FALSE;
1658 int lineno = 0;
1659 char c;
1660 char *ol;
1661 cstring olc;
1662
1663 strcpy (l, yyt + 1);
1664
1665 /* Need to safe original l for deallocating. */
1666 ol = l;
1667
1668 l += strlen (yyt) - 1;
1669
1670 while ((c = char_fromInt (lminput ())) != '\n' && c != '\0')
1671 {
1672 *l++ = c;
1673 }
1674
1675 *l = '\0';
1676 olc = cstring_fromChars (ol);
1677
1678 if (cstring_equalPrefix (olc, "pragma"))
1679 {
1680 char *pname = mstring_create (longUnsigned_fromInt (MAX_PRAGMA_LEN));
1681 char *opname = pname;
1682 char *ptr = ol + 6; /* pragma is six characters, plus space */
1683 int len = 0;
1684
1685
1686 /* skip whitespace */
1687 while (((c = *ptr) != '\0') && isspace (c))
1688 {
1689 ptr++;
1690 }
1691
1692
1693 while (((c = *ptr) != '\0') && !isspace (c))
1694 {
1695 len++;
1696
1697 if (len > MAX_PRAGMA_LEN)
1698 {
1699 break;
1700 }
1701
1702 ptr++;
1703 *pname++ = c;
1704 }
1705
1706 *pname = '\0';
1707
1708 if (len == PRAGMA_LEN_EXPAND
1709 && mstring_equal (opname, PRAGMA_EXPAND))
1710 {
1711 cstring exname = cstring_undefined;
1712 uentry ue;
1713
1714 ptr++;
1715 while (((c = *ptr) != '\0') && !isspace (c))
1716 {
1717 exname = cstring_appendChar (exname, c);
1718 ptr++;
1719 }
1720
1721
1722 ue = usymtab_lookupExposeGlob (exname);
1723
1724 if (uentry_isExpandedMacro (ue))
1725 {
1726 if (fileloc_isPreproc (uentry_whereDefined (ue)))
1727 {
1728 fileloc_setColumn (g_currentloc, 1);
1729 uentry_setDefined (ue, g_currentloc);
1730 }
1731 }
1732
1733 cstring_free (exname);
1734 }
1735 }
1736 else if (cstring_equalPrefix (olc, "ident"))
1737 {
1738 /* Some pre-processors will leave these in the code. Ignore rest of line */
1739 }
1740 /*
1741 ** Yuk...Win32 filenames can have spaces in them...we need to read
1742 ** to the matching end quote.
1743 */
1744 else if ((sscanf (ol, "line %d \"", &lineno) == 1)
1745 || (sscanf (ol, " %d \"", &lineno) == 1))
1746 {
1747 char *tmp = ol;
28bf4b0b 1748 cstring fname;
885824d3 1749 fileId fid;
1750
28bf4b0b 1751 /*@access cstring@*/
885824d3 1752 while (*tmp != '\"' && *tmp != '\0')
1753 {
1754 tmp++;
1755 }
1756
1757 llassert (*tmp == '\"');
1758
1759 tmp++;
28bf4b0b 1760
885824d3 1761 fname = tmp;
1762
1763 while (*tmp != '\"' && *tmp != '\0')
1764 {
1765 tmp++;
1766 }
1767
1768 llassert (*tmp == '\"');
1769
1770 *tmp = '\0';
1771
885824d3 1772# if defined(OS2) || defined(MSDOS) || defined(WIN32)
1773
1774 /*
1775 ** DOS-like path delimiters get delivered in pairs, something like
1776 ** \"..\\\\file.h\", so we have to make it normal again. We do NOT
1777 ** remove the pre dirs yet as we usually specify tmp paths relative
1778 ** to the current directory, so tmp files would not get found in
1779 ** the hash table. If this method fails we try it again later.
1780 */
1781
1782 {
1783 char *stmp = fname;
1784
1785 /*
1786 ** Skip past the drive marker.
1787 */
1788
885824d3 1789 if (strchr (stmp, ':') != NULL)
1790 {
1791 stmp = strchr (stmp, ':') + 1;
1792 }
1793
885824d3 1794 while ((stmp = strchr (stmp, CONNECTCHAR)) != NULL )
1795 {
1796 if (*(stmp+1) == CONNECTCHAR)
1797 {
1798 memmove (stmp, stmp+1, strlen (stmp));
1799 }
1800
1801 stmp++;
885824d3 1802 }
1803
28bf4b0b 1804 fid = fileTable_lookupBase (context_fileTable (), fname);
885824d3 1805 if (!(fileId_isValid (fid)))
1806 {
1807 fname = removePreDirs (fname);
28bf4b0b 1808 fid = fileTable_lookupBase (context_fileTable (), fname);
885824d3 1809 }
1810 }
1811# else /* !defined(OS2) && !defined(MSDOS) */
1812 fname = removePreDirs (fname);
28bf4b0b 1813 fid = fileTable_lookupBase (context_fileTable (), fname);
885824d3 1814# endif /* !defined(OS2) && !defined(MSDOS) */
1815
1816 if (!(fileId_isValid (fid)))
1817 {
28bf4b0b 1818 if (isHeaderFile (fname))
885824d3 1819 {
28bf4b0b 1820 fid = fileTable_addHeaderFile (context_fileTable (), fname);
885824d3 1821 }
1822 else
1823 {
28bf4b0b 1824 fid = fileTable_addFile (context_fileTable (), fname);
885824d3 1825 }
1826 }
1827
1828 setFileLine (fid, lineno);
28bf4b0b 1829 /*@noaccess cstring@*/
885824d3 1830 }
1831 else if ((sscanf (ol, "line %d", &lineno) == 1)
1832 || (sscanf (ol, " %d", &lineno) == 1))
1833 {
1834 setLine (lineno); /* next line is <cr> */
1835 }
1836 else
1837 {
1838 if (mstring_equal (ol, "")) {
1839 DPRINTF (("Empty pp command!"));
1840 /*
1841 ** evs 2000-05-16: This is a horrible kludge, to get around a bug (well, difficulty) in the pre-processor.
1842 ** We handle a plain # in the input file, by echoing it, and ignoring it in the post-pp-file.
1843 */
1844 mstring_free (ol);
1845 return FALSE;
1846 } else {
1847 if (!reportcpp)
1848 {
1849
1850 } else {
1851 llbug (message ("File contains preprocessor command: #%s",
1852 cstring_fromChars (ol)));
1853 reportcpp = TRUE;
1854 }
1855 }
1856
1857 sfree (ol);
1858 return TRUE;
1859 }
1860
1861 sfree (ol);
1862 return FALSE;
1863}
1864
1865static int handleLlSpecial ()
1866{
1867 int ic;
1868 char c;
1869 char *s = mstring_createEmpty ();
1870 char *os;
1871 int tok;
1872 int charsread = 0;
28bf4b0b 1873 fileloc loc;
1874
1875 loc = fileloc_copy (g_currentloc);
1876 DPRINTF (("Handle special: %s", fileloc_unparse (loc)));
885824d3 1877
1878 while (((ic = ninput ()) != 0) && isalpha (ic))
1879 {
1880 c = (char) ic;
1881 s = mstring_append (s, c);
1882 charsread++;
1883 }
1884
28bf4b0b 1885 DPRINTF (("Read: %s / %s", s, fileloc_unparse (g_currentloc)));
885824d3 1886 os = s;
1887
1888 if (charsread == 0 && ic == (int) AFTER_COMMENT_MARKER[0])
1889 {
1890 ic = ninput ();
1891
1892 llassert (ic == AFTER_COMMENT_MARKER[1]);
885824d3 1893
28bf4b0b 1894 if (*s == '\0')
885824d3 1895 {
1896 sfree (os);
28bf4b0b 1897 fileloc_free (loc);
885824d3 1898 return QNOMODS; /* special token no modifications token */
1899 }
885824d3 1900 }
1901
28bf4b0b 1902 DPRINTF (("Coment marker: %s", os));
885824d3 1903 tok = commentMarkerToken (cstring_fromChars (os));
1904
1905 if (tok != BADTOK)
1906 {
1907 tokLength = charsread;
1908 sfree (os);
1909 inSpecPart = TRUE;
28bf4b0b 1910 fileloc_free (loc);
885824d3 1911 return tok;
1912 }
28bf4b0b 1913
1914 DPRINTF (("Not a comment marker..."));
885824d3 1915 /* Add rest of the comment */
1916
1917 if (ic != 0 && ic != EOF)
1918 {
1919 c = (char) ic;
885824d3 1920
1921 s = mstring_append (s, c);
1922 charsread++;
1923
1924 while (((ic = ninput ()) != 0) && (ic != EOF)
1925 && (ic != AFTER_COMMENT_MARKER[0]))
1926 {
1927 c = (char) ic;
1928 s = mstring_append (s, c);
1929 charsread++;
1930 }
1931 }
1932
28bf4b0b 1933 DPRINTF (("Read: %s / %s", s, fileloc_unparse (g_currentloc)));
1934
885824d3 1935 if (ic == AFTER_COMMENT_MARKER[0])
1936 {
1937 int nc = ninput ();
1938 llassert ((char) nc == AFTER_COMMENT_MARKER[1]);
1939 charsread++;
1940 }
1941
885824d3 1942 os = s;
1943
1944 while (*s == ' ' || *s == '\t' || *s == '\n')
1945 {
1946 s++;
1947 }
1948
1949 if (*s == '-' || *s == '+' || *s == '=') /* setting flags */
1950 {
1951 c = *s;
1952
1953 while (c == '-' || c == '+' || c == '=')
1954 {
1955 ynm set = ynm_fromCodeChar (c);
1956 cstring thisflag;
1957
1958 s++;
1959
1960 thisflag = cstring_fromChars (s);
1961
1962 while ((c = *s) != '\0' && (c != '-') && (c != '=')
1963 && (c != '+') && (c != ' ') && (c != '\t') && (c != '\n'))
1964 {
1965 s++;
1966 }
1967
1968 *s = '\0';
1969
1970 if (!context_getFlag (FLG_NOCOMMENTS))
1971 {
1972 cstring flagname = thisflag;
1973 flagcode fflag = identifyFlag (flagname);
a0a162cd 1974
885824d3 1975 if (flagcode_isSkip (fflag))
1976 {
1977 ;
1978 }
1979 else if (flagcode_isInvalid (fflag))
1980 {
1981 if (isMode (flagname))
1982 {
1983 if (ynm_isMaybe (set))
1984 {
1985 llerror
1986 (FLG_BADFLAG,
1987 message
28bf4b0b 1988 ("Semantic comment attempts to restore flag %s. "
885824d3 1989 "A mode flag cannot be restored.",
1990 flagname));
1991 }
1992 else
1993 {
1994 context_setMode (flagname);
1995 }
1996 }
1997 else
1998 {
990ec868 1999 voptgenerror
2000 (FLG_UNRECOGFLAGCOMMENTS,
28bf4b0b 2001 message ("Unrecognized option in semantic comment: %s",
990ec868 2002 flagname),
2003 g_currentloc);
885824d3 2004 }
2005 }
2006 else if (flagcode_isGlobalFlag (fflag))
2007 {
990ec868 2008 voptgenerror
885824d3 2009 (FLG_BADFLAG,
2010 message
28bf4b0b 2011 ("Semantic comment attempts to set global flag %s. "
885824d3 2012 "A global flag cannot be set locally.",
990ec868 2013 flagname),
2014 g_currentloc);
885824d3 2015 }
2016 else
2017 {
2018 context_fileSetFlag (fflag, set);
a0a162cd 2019
885824d3 2020 if (flagcode_hasArgument (fflag))
2021 {
2022 if (ynm_isMaybe (set))
2023 {
990ec868 2024 voptgenerror
885824d3 2025 (FLG_BADFLAG,
2026 message
28bf4b0b 2027 ("Semantic comment attempts to restore flag %s. "
885824d3 2028 "A flag for setting a value cannot be restored.",
990ec868 2029 flagname),
2030 g_currentloc);
885824d3 2031 }
2032 else
2033 { /* cut-and-pastied from llmain...blecch */
2034 cstring extra = cstring_undefined;
2035 char *rest;
2036 char *orest;
2037 char rchar;
2038
2039 *s = c;
2040 rest = mstring_copy (s);
2041 orest = rest;
2042 *s = '\0';
2043
2044 while ((rchar = *rest) != '\0'
2045 && (isspace (rchar)))
2046 {
2047 rest++;
2048 s++;
2049 }
2050
2051 while ((rchar = *rest) != '\0'
2052 && !isspace (rchar))
2053 {
2054 extra = cstring_appendChar (extra, rchar);
2055 rest++;
2056 s++;
2057 }
2058
2059 sfree (orest);
a0a162cd 2060
885824d3 2061 if (cstring_isUndefined (extra))
2062 {
2063 llerror
2064 (FLG_BADFLAG,
2065 message
28bf4b0b 2066 ("Flag %s (in semantic comment) must be followed by an argument",
885824d3 2067 flagcode_unparse (fflag)));
2068 }
2069 else
2070 {
2071 s--;
2072
2073 if (flagcode_hasValue (fflag))
2074 {
2075 setValueFlag (fflag, extra);
2076 }
2077 else if (flagcode_hasString (fflag))
2078 {
2079 setStringFlag (fflag, extra);
2080 }
2081 else
2082 {
2083 BADEXIT;
2084 }
2085 }
2086 }
2087 }
2088 }
2089 }
2090 else
2091 {
a0a162cd 2092 ;
2093 }
885824d3 2094
2095 *s = c;
2096 while ((c == ' ') || (c == '\t') || (c == '\n'))
2097 {
2098 c = *(++s);
2099 }
2100 }
2101
2102 if (context_inHeader () && !isArtificial (cstring_fromChars (os)))
2103 {
28bf4b0b 2104 DPRINTF (("Here adding comment: %s", os));
2105 context_addComment (cstring_fromCharsNew (os));
885824d3 2106 }
2107 else
2108 {
2109 ;
2110 }
2111 }
2112 else
2113 {
2114 char *t = s;
2115 int macrocode;
2116 char tchar = '\0';
28bf4b0b 2117 annotationInfo ainfo;
885824d3 2118
2119 while (*s != '\0' && *s != ' ' && *s != '\t' && *s != '\n')
2120 {
2121 s++;
2122 }
2123
2124 if (*s != '\0')
2125 {
2126 tchar = *s;
2127 *s = '\0';
2128 s++;
2129 }
2130
2131 t = cstring_toCharsSafe (cstring_downcase (cstring_fromChars (t)));
2132 macrocode = tokenMacroCode (cstring_fromChars (t));
2133
2134 if (macrocode != BADTOK)
2135 {
2136 tokLength = mstring_length (t);
885824d3 2137
2138 sfree (t);
2139 sfree (os);
28bf4b0b 2140 fileloc_free (loc);
885824d3 2141
2142 if (macrocode == SKIPTOK)
2143 {
2144 return BADTOK;
2145 }
2146
2147 return macrocode;
2148 }
2149
28bf4b0b 2150 ainfo = context_lookupAnnotation (cstring_fromChars (os));
2151
2152 if (annotationInfo_isDefined (ainfo)) {
2153 DPRINTF (("Found annotation: %s", annotationInfo_unparse (ainfo)));
2154 /*@i324@*/ yylval.annotation = ainfo;
2155 tokLength = 0;
2156 sfree (os);
2157 sfree (t);
2158 fileloc_free (loc);
2159 return CANNOTATION;
2160 }
2161
885824d3 2162 if (context_inHeader ())
2163 {
2164 if (tchar != '\0')
2165 {
2166 *(s-1) = tchar;
2167 }
2168
2169 if ((context_inMacro () || context_inGlobalContext ())
2170 && macrocode != SKIPTOK
2171 && !isArtificial (cstring_fromChars (os)))
2172 {
28bf4b0b 2173 DPRINTF (("Add comment: %s", os));
885824d3 2174 context_addComment (cstring_fromCharsNew (os));
2175 }
2176 else
2177 {
2178 ;
2179 }
2180
2181 if (tchar != '\0')
2182 {
2183 *(s-1) = '\0';
2184 }
2185 }
2186
2187 if (mstring_equal (t, "ignore"))
2188 {
2189 if (!context_getFlag (FLG_NOCOMMENTS))
2190 {
2191 context_enterSuppressRegion ();
2192 }
2193 }
2194 else if ((*t == 'i' || *t == 't')
2195 && (*(t + 1) == '\0'))
2196 {
2197 if (!context_getFlag (FLG_NOCOMMENTS)
2198 && (*t == 'i' || context_getFlag (FLG_TMPCOMMENTS)))
2199 {
2200 context_enterSuppressLine (-1); /* infinite suppression */
2201 }
2202 }
2203 else if (((*t == 'i') || (*t == 't'))
2204 && ((*(t + 1) >= '0' && *(t + 1) <= '9')))
2205 {
2206 bool tmpcomment = (*t == 't');
2207 int val = -1;
2208 char *tt = t; /* don't mangle t, since it is free'd */
2209 char lc = *(++tt);
2210
2211 if (lc >= '0' && lc <= '9')
2212 {
2213 val = (int)(lc - '0');
2214
2215 lc = *(++tt);
2216 while (lc >= '0' && lc <= '9')
2217 {
2218 val *= 10;
2219 val += lc - '0';
2220 lc = *(++tt);
2221 }
2222 }
2223
2224
2225 if (!context_getFlag (FLG_NOCOMMENTS)
2226 && (!tmpcomment || context_getFlag (FLG_TMPCOMMENTS)))
2227 {
2228 context_enterSuppressLine (val);
2229 }
2230 }
2231 else if (mstring_equal (t, "end"))
2232 {
2233 if (!context_getFlag (FLG_NOCOMMENTS))
2234 {
2235 context_exitSuppressRegion ();
2236 }
2237 }
2238 else if (mstring_equal (t, "notfunction"))
2239 {
2240 ; /* handled by pcpp */
2241 }
2242 else if (mstring_equal (t, "access"))
2243 {
2244 cstring tname;
2245
2246 while (TRUE)
2247 {
2248 while ((c = *s) && (c == ' ' || c == '\t' || c == '\n'))
2249 {
2250 s++;
2251 }
2252
2253 if (c == '\0')
2254 {
2255 break;
2256 }
2257
2258 tname = cstring_fromChars (s);
2259
2260 while ((c = *s) != '\0' && c != ' '
2261 && c != '\t' && c != '\n' && c != ',')
2262 {
2263 s++;
2264 }
2265
2266 *s = '\0';
2267
28bf4b0b 2268 DPRINTF (("Access %s", tname));
2269
885824d3 2270 if (!context_getFlag (FLG_NOCOMMENTS)
2271 && !context_getFlag (FLG_NOACCESS))
2272 {
2273 if (usymtab_existsType (tname))
2274 {
28bf4b0b 2275 typeId uid = usymtab_getTypeId (tname);
2276 uentry ue = usymtab_getTypeEntry (uid);
2277
2278 if (uentry_isAbstractDatatype (ue))
2279 {
2280 context_addFileAccessType (uid);
2281 DPRINTF (("Adding access to: %s / %d", tname, uid));
2282 }
2283 else
2284 {
2285 voptgenerror
2286 (FLG_COMMENTERROR,
2287 message
2288 ("Non-abstract type %s used in access comment",
2289 tname),
2290 g_currentloc);
2291 }
885824d3 2292 }
2293 else
2294 {
2295 if (!(context_inSuppressRegion ()
2296 || context_inSuppressZone (g_currentloc)))
2297 {
28bf4b0b 2298 voptgenerror
2299 (FLG_COMMENTERROR,
2300 message
2301 ("Unrecognized type %s used in access comment",
2302 tname),
2303 g_currentloc);
885824d3 2304 }
2305 }
2306 }
2307
2308 if (c != '\0')
2309 {
2310 s++;
2311 }
2312
2313 if (c != ',' && c != ' ')
2314 {
2315 break;
2316 }
2317 }
2318 }
2319 else if (mstring_equal (t, "noaccess"))
2320 {
2321 cstring tname;
2322 char lc;
2323
2324 while (TRUE)
2325 {
2326 while ((lc = *s) && (lc == ' ' || lc == '\t' || lc == '\n'))
2327 {
2328 s++;
2329 }
2330
2331 if (lc == '\0')
2332 {
2333 break;
2334 }
2335
2336 tname = cstring_fromChars (s);
2337
2338 while ((lc = *s) != '\0' && lc != ' ' && lc != '\t'
2339 && lc != '\n' && lc != ',')
2340 {
2341 s++;
2342 }
2343
2344 *s = '\0';
2345
2346 if (!context_getFlag (FLG_NOCOMMENTS)
2347 && !context_getFlag (FLG_NOACCESS))
2348 {
2349 if (usymtab_existsType (tname))
2350 {
2351 typeId tuid = usymtab_getTypeId (tname);
2352
2353 if (context_couldHaveAccess (tuid))
2354 {
28bf4b0b 2355 DPRINTF (("Removing access: %s", tname));
885824d3 2356 context_removeFileAccessType (tuid);
2357 }
2358 else
2359 {
2360 if (!(context_inSuppressRegion ()
2361 || context_inSuppressZone (g_currentloc)))
2362 {
2363 uentry ue = usymtab_getTypeEntry (tuid);
2364
2365 if (uentry_isAbstractDatatype (ue))
2366 {
28bf4b0b 2367 voptgenerror
2368 (FLG_COMMENTERROR,
2369 message
2370 ("Non-accessible abstract type %s used in noaccess comment",
2371 tname),
2372 g_currentloc);
885824d3 2373 }
2374 else
2375 {
28bf4b0b 2376 voptgenerror
2377 (FLG_COMMENTERROR,
2378 message
2379 ("Non-abstract type %s used in noaccess comment",
2380 tname),
2381 g_currentloc);
885824d3 2382 }
2383 }
2384 }
2385 }
2386 else
2387 {
2388 if (!(context_inSuppressRegion ()
2389 || context_inSuppressZone (g_currentloc)))
2390 {
28bf4b0b 2391 voptgenerror
2392 (FLG_COMMENTERROR,
2393 message
2394 ("Unrecognized type %s used in noaccess comment",
2395 tname),
2396 g_currentloc);
885824d3 2397 }
2398 }
2399 }
2400
2401 if (lc != '\0')
2402 {
2403 s++;
2404 }
2405
2406 if (lc != ',' && lc != ' ')
2407 {
2408 break;
2409 }
2410 }
2411 }
2412 else
2413 {
885824d3 2414 voptgenerror (FLG_UNRECOGCOMMENTS,
28bf4b0b 2415 message ("Semantic comment unrecognized: %s",
2416 cstring_fromChars (os)), loc);
885824d3 2417 }
2418
2419 sfree (t);
2420 }
2421
28bf4b0b 2422 sfree (os);
2423 fileloc_free (loc);
885824d3 2424 return BADTOK;
2425}
2426
2427static /*@only@*/ cstring makeIdentifier (char *s)
2428{
2429 char *c = mstring_create (size_toInt (strlen (s)) + 1);
2430 cstring id = cstring_fromChars (c);
2431
2432 while (isalnum (*s) || (*s == '_') || (*s == '$'))
2433 {
2434 *c++ = *s++;
2435 }
2436
2437 *c = '\0';
2438 return (id);
2439}
2440
2441/*@observer@*/ /*@dependent@*/ uentry coerceId (cstring cn)
2442{
2443 if (!(usymtab_exists (cn)))
2444 {
2445 fileloc loc = fileloc_createExternal ();
2446
2447 /*
2448 ** We need to put this in a global scope, otherwise the sRef will be deallocated.
2449 */
2450
2451 uentry ce = uentry_makeUnrecognized (cn, loc);
2452
2453 if (!context_inIterEnd ())
2454 {
2455 voptgenerror
2456 (FLG_SYSTEMUNRECOG,
2457 message ("Unrecognized (possibly system) identifier: %q",
2458 uentry_getName (ce)),
2459 g_currentloc);
2460 }
2461
2462 return ce;
2463 }
2464
2465 return (usymtab_lookup (cn));
2466}
2467
2468/*
2469** like, coerceId, but doesn't supercede for iters
2470*/
2471
2472/*@observer@*/ uentry coerceIterId (cstring cn)
2473{
2474 if (!(usymtab_exists (cn)))
2475 {
2476 return uentry_undefined;
2477 }
2478
2479 return (usymtab_lookup (cn));
2480}
2481
2482/*@observer@*/ cstring LastIdentifier ()
2483{
2484 return (lastidprocessed);
2485}
2486
2487static int processIdentifier (cstring id)
2488{
2489 uentry le;
2490
28bf4b0b 2491 DPRINTF (("Process identifier: %s / %s / %s", id, fileloc_unparse (g_currentloc),
2492 bool_unparse (context_inFunctionHeader ())));
885824d3 2493
2494 context_clearJustPopped ();
2495 lastidprocessed = id;
2496
28bf4b0b 2497 if (context_inFunctionHeader ())
885824d3 2498 {
2499 int tok = commentMarkerToken (id);
28bf4b0b 2500 DPRINTF (("in function decl..."));
885824d3 2501
2502 if (tok != BADTOK)
2503 {
2504 return tok;
2505 }
2506 else
2507 {
2508 tok = tokenMacroCode (id);
2509
2510 if (tok != BADTOK)
2511 {
2512 return tok;
2513 }
28bf4b0b 2514 else
2515 {
2516 annotationInfo ainfo = context_lookupAnnotation (id);
2517
2518 if (annotationInfo_isDefined (ainfo))
2519 {
2520 DPRINTF (("Found annotation: %s", annotationInfo_unparse (ainfo)));
2521 /*@i324@*/ yylval.annotation = ainfo;
2522 return CANNOTATION;
2523 }
2524 else
2525 {
2526 DPRINTF (("Not annotation: %s", id));
2527 }
2528 }
885824d3 2529 }
2530 }
2531
2532 /* Consider handling: Defined by C99 as static const char __func__[] */
2533
2534 if (context_getFlag (FLG_GNUEXTENSIONS))
2535 {
2536 int tok = BADTOK;
2537
2538 if (cstring_equalLit (id, "__stdcall")
2539 || cstring_equalLit (id, "__cdecl")
2540 || cstring_equalLit (id, "__extension__"))
2541 {
2542 return BADTOK;
2543 }
2544 else if (cstring_equalLit (id, "__volatile__"))
2545 {
2546 tok = QVOLATILE;
2547 }
2548 else if (cstring_equalLit (id, "__signed"))
2549 {
2550 tok = QSIGNED;
2551 }
2552 else if (cstring_equalLit (id, "__unsigned"))
2553 {
2554 tok = QUNSIGNED;
2555 }
2556 else if (cstring_equalLit (id, "__const__"))
2557 {
2558 tok = QCONST;
2559 }
2560 else if (cstring_equalLit (id, "__alignof__"))
2561 {
2562 tok = CALIGNOF; /* alignof is parsed like sizeof */
2563 }
2564 else if (cstring_equalLit (id, "__FUNCTION__")
2565 || cstring_equalLit (id, "__PRETTY_FUNCTION__"))
2566 {
2567 /* These tokens hold the name of the current function as strings */
2568 yylval.expr = exprNode_stringLiteral (id, fileloc_copy (g_currentloc));
2569 tokLength = 0;
2570 lastWasString = TRUE;
2571 tok = CCONSTANT;
2572 return tok;
2573 }
2574 else if (cstring_equalLit (id, "__attribute__")
2575 || cstring_equalLit (id, "__asm__")
2576 || cstring_equalLit (id, "_asm")
2577 || cstring_equalLit (id, "__asm")
2578 || cstring_equalLit (id, "__declspec"))
2579 {
2580 int depth = 0;
2581 bool useparens = FALSE;
2582 bool usebraces = FALSE;
2583 bool inquote = FALSE;
2584 bool inescape = FALSE;
2585 int ic;
2586
2587 while ((ic = input ()) != EOF)
2588 {
2589
2590 if (inescape)
2591 {
2592 inescape = FALSE;
2593 }
2594 else if (ic == '\\')
2595 {
2596 inescape = TRUE;
2597 }
2598 else if (ic == '\"')
2599 {
2600 inquote = !inquote;
2601 }
2602 else if (!inquote)
2603 {
2604 if (ic == '(')
2605 {
2606 if (!useparens)
2607 {
2608 if (!usebraces)
2609 {
2610 useparens = TRUE;
2611 }
2612 }
2613
2614 if (useparens)
2615 {
2616 depth++;
2617 }
2618 }
2619 else if (ic == '{')
2620 {
2621 if (!usebraces)
2622 {
2623 if (!useparens)
2624 {
2625 usebraces = TRUE;
2626 }
2627 }
2628
2629 if (usebraces)
2630 {
2631 depth++;
2632 }
2633 }
2634 else if (ic == ')' && useparens)
2635 {
2636 depth--;
2637 if (depth == 0) break;
2638 }
2639 else if (ic == '}' && usebraces)
2640 {
2641 depth--;
2642 if (depth == 0) break;
2643 }
2644 else if (ic == '}'
2645 && !usebraces && !useparens
2646 && cstring_equalLit (id, "__asm"))
2647 {
2648 /*
2649 ** We need this because some MS VC++ include files
2650 ** have __asm mov ... }
2651 ** Its a kludge, but otherwise would need to parse
2652 ** the asm code!
2653 */
2654 return TRBRACE;
2655 }
2656 }
2657
2658 if (ic == '\n')
2659 {
2660 context_incLineno ();
2661
2662 if (cstring_equalLit (id, "__asm")
2663 && !useparens && !usebraces)
2664 {
2665 break;
2666 }
2667 }
2668 }
2669
2670 llassert ((useparens && ic == ')')
2671 || (usebraces && ic == '}')
2672 || (!useparens && !usebraces));
2673
2674 return BADTOK;
2675 }
2676 else if (cstring_equalLit (id, "inline")
2677 || cstring_equalLit (id, "__inline")
2678 || cstring_equalLit (id, "_inline")
2679 || cstring_equalLit (id, "__inline__"))
2680 {
2681 tok = QINLINE;
2682 }
2683
2684 if (tok != BADTOK)
2685 {
2686 RETURN_TOK (tok);
2687 }
2688 }
2689
2690 le = usymtab_lookupSafe (id);
2691
2692 /*@-dependenttrans@*/
2693
2694 if (uentry_isIter (le))
2695 {
28bf4b0b 2696 /*@i32@*/ yylval.entry = le;
885824d3 2697 return (ITER_NAME);
2698 }
2699 else if (uentry_isEndIter (le))
2700 {
28bf4b0b 2701 /*@i32@*/ yylval.entry = le;
885824d3 2702 return (ITER_ENDNAME);
2703 }
2704 else if (uentry_isUndefined (le))
2705 {
2706 yylval.cname = id;
2707
2708 /* avoid parse errors for certain system built ins */
2709
2710 if (g_expectingTypeName && (cstring_firstChar (id) == '_')
2711 && (cstring_secondChar (id) == '_'))
2712 {
2713 return (TYPE_NAME_OR_ID);
2714 }
2715
2716 return (NEW_IDENTIFIER);
2717 }
2718 else if (!uentry_isDeclared (le) && !uentry_isCodeDefined (le))
2719 {
2720 if (uentry_isDatatype (le))
2721 {
2722 yylval.cname = id;
2723 return (NEW_IDENTIFIER);
2724 }
2725 else
2726 {
28bf4b0b 2727 /*@i32@*/ yylval.entry = le;
885824d3 2728 return (IDENTIFIER);
2729 }
2730 }
2731 else if (uentry_isDatatype (le))
2732 {
2733 if (!g_expectingTypeName)
2734 {
2735 yylval.cname = id;
2736
2737 return (NEW_IDENTIFIER);
2738 }
2739 else
2740 {
2741 yylval.ctyp = uentry_getAbstractType (le);
2742
2743 uentry_setUsed (le, g_currentloc);
2744 return (TYPE_NAME);
2745 }
2746 }
2747 else
2748 {
28bf4b0b 2749 /*@i32@*/ yylval.entry = le;
885824d3 2750 return (IDENTIFIER);
2751 }
2752
2753 /*@=dependenttrans@*/
2754}
2755
2756static bool processHashIdentifier (/*@only@*/ cstring id)
2757{
2758 if (context_inMacro () || context_inIterDef () ||
2759 context_inIterEnd ())
2760 {
2761 uentry le;
2762
2763 context_clearJustPopped ();
2764
2765 lastidprocessed = id;
2766 le = usymtab_lookupSafe (id);
2767
2768 if (uentry_isParam (le) || uentry_isRefParam (le))
2769 {
2770 return TRUE;
2771 }
2772 else
2773 {
2774 return FALSE;
2775 }
2776 }
2777 else
2778 {
2779 cstring_free (id);
2780 return FALSE;
2781 }
2782}
2783
2784
2785static /*@only@*/ exprNode processString ()
2786{
2787 exprNode res;
2788 fileloc loc;
2789 char *nl = strchr (yytext, '\n');
2790 cstring ns = cstring_fromCharsNew (yytext);
2791
2792 if (nl == NULL)
2793 {
2794 loc = fileloc_copy (g_currentloc);
2795 addColumn (cstring_length (ns));
2796 }
2797 else
2798 {
2799 char *lastnl = nl;
2800
2801 loc = fileloc_copy (g_currentloc);
2802
2803 context_incLineno ();
2804
2805 while ((nl = strchr ((nl + 1), '\n')) != NULL)
2806 {
2807 context_incLineno ();
2808 lastnl = nl;
2809 }
2810 }
2811
2812
2813 res = exprNode_stringLiteral (ns, loc);
2814 return (res);
2815}
2816
2817static
2818char processChar ()
2819{
2820 char fchar;
2821 char next;
2822
2823 llassert (*yytext != '\0');
2824 fchar = *(yytext + 1);
2825 if (fchar != '\\') return fchar;
2826
2827 next = *(yytext + 2);
2828
2829 switch (next)
2830 {
2831 case 'n': return '\n';
2832 case 't': return '\t';
2833 case '\"': return '\"';
2834 case '\'': return '\'';
2835 case '\\': return '\\';
2836 default: return '\0';
2837 }
2838}
2839
2840static
2841double processFloat ()
2842{
2843 double ret = atof (yytext);
2844
2845 return (ret);
2846}
2847
2848static
2849long processHex ()
2850{
2851 int index = 2;
2852 long val = 0;
2853
2854 llassert (yytext[0] == '0'
2855 && (yytext[1] == 'X' || yytext[1] == 'x'));
2856
2857 while (yytext[index] != '\0') {
2858 int tval;
2859 char c = yytext[index];
2860
2861 if (c >= '0' && c <= '9') {
2862 tval = (int) c - (int) '0';
2863 } else if (c >= 'A' && c <= 'F') {
2864 tval = (int) c - (int) 'A' + 10;
2865 } else if (c >= 'a' && c <= 'f') {
2866 tval = (int) c - (int) 'a' + 10;
a0a162cd 2867 } else if (c == 'U' || c == 'L' || c == 'u' || c == 'l') {
2868 index++;
2869 while (yytext[index] != '\0') {
2870 if (c == 'U' || c == 'L' || c == 'u' || c == 'l') {
2871 ;
2872 } else {
2873 voptgenerror
2874 (FLG_SYNTAX,
2875 message ("Invalid character (%c) following specifier in hex constant: %s",
2876 c, cstring_fromChars (yytext)),
2877 g_currentloc);
2878 }
2879 index++;
2880 }
2881
2882 break;
885824d3 2883 } else {
2884 voptgenerror
2885 (FLG_SYNTAX,
2886 message ("Invalid character (%c) in hex constant: %s",
2887 c, cstring_fromChars (yytext)),
2888 g_currentloc);
2889 break;
2890 }
2891
2892 val = (val * 16) + tval;
2893 index++;
2894 }
2895
2896 DPRINTF (("Hex constant: %s = %ld", yytext, val));
2897 return val;
2898}
2899
2900static
2901long processOctal ()
2902{
2903 int index = 1;
2904 long val = 0;
2905
2906 llassert (yytext[0] == '0' && yytext[1] != 'X' && yytext[1] != 'x');
2907
2908 while (yytext[index] != '\0') {
2909 int tval;
2910 char c = yytext[index];
2911
2912 if (c >= '0' && c <= '7') {
2913 tval = (int) c - (int) '0';
2914 } else {
2915 voptgenerror
2916 (FLG_SYNTAX,
2917 message ("Invalid character (%c) in octal constant: %s",
2918 c, cstring_fromChars (yytext)),
2919 g_currentloc);
2920 break;
2921 }
2922
2923 val = (val * 8) + tval;
2924 index++;
2925 }
2926
2927 DPRINTF (("Octal constant: %s = %ld", yytext, val));
2928 return val;
2929}
2930
2931static
2932long processDec ()
2933{
2934 return (atol (yytext));
2935}
2936
2937static int
2938processSpec (int tok)
2939{
2940 size_t length = strlen (yytext);
2941
2942
2943 if (inSpecPart)
2944 {
2945 setTokLengthT (length);
2946 RETURN_TOK (tok);
2947 }
2948 else
2949 {
2950
2951 context_saveLocation ();
2952 setTokLengthT (length);
2953 return (processIdentifier (makeIdentifier (yytext)));
2954 }
2955}
This page took 0.434796 seconds and 5 git commands to generate.