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