]> andersk Git - splint.git/blob - src/cscanner.l
Added the code for setBufferSize and setStringLegnth annotations.
[splint.git] / src / cscanner.l
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
45 Digit                   [0-9]
46 Letter                  [a-zA-Z_$]
47 H                       [a-fA-F0-9]
48 E                       [Ee][+-]?{Digit}+
49 U                       (u|U)
50 L                       (l|L)
51 FS                      (f|F|l|L)
52 IS                      (u|U|l|L)*
53 ULSuffix                ({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
81 static bool lastWasString = FALSE;
82 static char savechar = '\0';
83
84 /*@notfunction@*/
85 # define yyinput() (incColumn (), getc (yyin))
86
87 /*@-noparams@*/
88 /*@-incondefs@*/
89 extern /*@external@*/ int read ();
90 /*@=incondefs@*/
91 /*@=noparams@*/
92
93 static /*@owned@*/ cstring lastidprocessed = cstring_undefined;
94
95 static int lminput (void);
96 static int tokLength = 0;
97 static bool inSpecPart = FALSE;
98 static bool continueLine = FALSE;
99
100 static int ninput (void);
101 static char processChar (void);
102 static double processFloat (void);
103 static /*@only@*/ exprNode processString (void);
104 static long processDec (void);
105 static long processHex (void);
106 static long processOctal (void);
107 static int processIdentifier (/*@only@*/ cstring)
108    /*@globals undef lastidprocessed@*/ ;
109 static bool processHashIdentifier (/*@only@*/ cstring)
110    /*@globals undef lastidprocessed@*/ ;
111
112 static int processSpec (int);
113 static bool handleSpecial (char *);
114 static int handleLlSpecial (void);
115 static void handleMacro (void);
116 static bool processMacro (void);
117 static /*@only@*/ cstring makeIdentifier (char *);
118
119 /* yes, this is exported! */
120 bool g_expectingTypeName = TRUE; /* beginning of file can be type name! */
121
122 static int returnInt (ctype, long);
123 static int returnFloat (ctype, double);
124 static int returnChar (char);
125 static void setTokLength (int) /*@modifies g_currentloc@*/ ;
126 static void setTokLengthT (size_t) /*@modifies g_currentloc@*/ ;
127
128 static 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
176 static void setTokLength (int len) 
177 {
178   addColumn (len);
179   tokLength = len;
180 }
181
182 static 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)); }
309 "nullterminated"        { return (processSpec (QNULLTERMINATED));}
310
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                             }
320 0[xX]{H}+               { setTokLengthT (mstring_length (yytext)); 
321                           RETURN_INT (ctype_int, processHex ());  /* evs 2000-05-17 was ctype_uint */
322                         }
323 0[xX]{H}+{L}            { setTokLengthT (mstring_length (yytext)); 
324                           RETURN_INT (ctype_lint, processHex ()); }
325 0[xX]{H}+{L}{L}         { setTokLengthT (mstring_length (yytext)); 
326                           RETURN_INT (ctype_llint, processHex ()); }
327 0[xX]{H}+{U}            { setTokLengthT (mstring_length (yytext)); 
328                           RETURN_INT (ctype_uint, processHex ()); }
329 0[xX]{H}+{ULSuffix}     { setTokLengthT (mstring_length (yytext)); 
330                           RETURN_INT (ctype_ulint, processHex ()); }
331 0[xX]{H}+{U}{L}{L}      { setTokLengthT (mstring_length (yytext)); 
332                           RETURN_INT (ctype_ullint, processHex ()); }
333 0[xX]{H}+{L}{L}{U}      { setTokLengthT (mstring_length (yytext)); 
334                           RETURN_INT (ctype_ullint, processHex ()); }
335 0{Digit}+               { setTokLengthT (mstring_length (yytext)); 
336                           RETURN_INT (ctype_int, processOctal ()); } 
337 0{Digit}+{U}            { setTokLengthT (mstring_length (yytext)); 
338                           RETURN_INT (ctype_uint, processOctal ()); } 
339 0{Digit}+{L}            { setTokLengthT (mstring_length (yytext)); 
340                           RETURN_INT (ctype_lint, processOctal ()); } 
341 0{Digit}+{L}{L}         { setTokLengthT (mstring_length (yytext)); 
342                           RETURN_INT (ctype_llint, processOctal ()); } 
343 0{Digit}+{ULSuffix}     { setTokLengthT (mstring_length (yytext)); 
344                           RETURN_INT (ctype_ulint, processOctal ()); } 
345 0{Digit}+{U}{L}{L}      { setTokLengthT (mstring_length (yytext)); 
346                           RETURN_INT (ctype_ullint, processOctal ()); } 
347 0{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
545 struct 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
556 struct 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 } ,
570   {"setBufferSize", QSETBUFFERSIZE},
571   {"setStringLength", QSETSTRINGLENGTH},
572   { NULL, BADTOK }
573 } ;
574
575 /*
576 ** These tokens are either stand-alone tokens, or followed by 
577 ** token-specific text.
578 */
579
580 struct 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 } ,
614   { "nullterminated", QNULLTERMINATED }, 
615   { "setBufferSize", QSETBUFFERSIZE },
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
652 static bool isArtificial (cstring s)
653 {
654   return (cstring_equalLit (s, "modifies") 
655           || cstring_equalLit (s, "globals") 
656           || cstring_equalLit (s, "alt"));
657 }
658
659 void 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
693 static 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
710 static 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
813 static 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
828 static void lmsavechar (char c)
829 {
830   if (savechar == '\0') savechar = c;
831   else
832     {
833       llbuglit ("lmsavechar: override");
834     }
835 }
836
837 static 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
845 static 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
867 static 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
875 static 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
887 static 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
990 static 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
1079 static char skip_whitespace ()
1080 {
1081   char c;
1082
1083   while ((c = macro_nextChar ()) == ' ' || c == '\t')
1084     {
1085       ;
1086     }
1087
1088   return c;
1089 }
1090
1091 static 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
1143 static 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
1627 static 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   
1849 static 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
2366 static /*@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
2426 static 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
2678 static 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
2707 static /*@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
2739 static 
2740 char 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
2762 static
2763 double processFloat ()
2764 {
2765   double ret = atof (yytext);
2766
2767     return (ret);
2768 }
2769
2770 static
2771 long 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
2806 static
2807 long 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
2837 static
2838 long processDec ()
2839 {
2840   return (atol (yytext));
2841 }
2842
2843 static int
2844 processSpec (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 0.283747 seconds and 5 git commands to generate.