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