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