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