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