]> andersk Git - splint.git/blame - src/cscannerHelp.c
Fixes after removing -unrecogcomments flag for make splintme.
[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"
8b63eb37 36# include "osd.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 == '\"');
16c024b5 750 tmp++;
16c024b5 751 fname = tmp;
752
753 while (*tmp != '\"' && *tmp != '\0')
754 {
755 tmp++;
756 }
757
758 llassert (*tmp == '\"');
16c024b5 759 *tmp = '\0';
760
761# if defined(OS2) || defined(MSDOS) || defined(WIN32)
762
763 /*
764 ** DOS-like path delimiters get delivered in pairs, something like
765 ** \"..\\\\file.h\", so we have to make it normal again. We do NOT
766 ** remove the pre dirs yet as we usually specify tmp paths relative
767 ** to the current directory, so tmp files would not get found in
768 ** the hash table. If this method fails we try it again later.
769 */
770
771 {
772 char *stmp = fname;
773
774 /*
775 ** Skip past the drive marker.
776 */
777
778 if (strchr (stmp, ':') != NULL)
779 {
780 stmp = strchr (stmp, ':') + 1;
781 }
782
783 while ((stmp = strchr (stmp, CONNECTCHAR)) != NULL )
784 {
785 if (*(stmp+1) == CONNECTCHAR)
786 {
787 memmove (stmp, stmp+1, strlen (stmp));
788 }
789
790 stmp++;
791 }
792
793 fid = fileTable_lookupBase (context_fileTable (), fname);
794 if (!(fileId_isValid (fid)))
795 {
796 fname = removePreDirs (fname);
797 fid = fileTable_lookupBase (context_fileTable (), fname);
798 }
799 }
800# else /* !defined(OS2) && !defined(MSDOS) */
801 fname = removePreDirs (fname);
802 fid = fileTable_lookupBase (context_fileTable (), fname);
803# endif /* !defined(OS2) && !defined(MSDOS) */
804
805 if (!(fileId_isValid (fid)))
806 {
807 if (context_inXHFile ())
808 {
809 fid = fileTable_addXHFile (context_fileTable (), fname);
810 }
811 else if (isHeaderFile (fname))
812 {
813 fid = fileTable_addHeaderFile (context_fileTable (), fname);
814 }
815 else
816 {
817 fid = fileTable_addFile (context_fileTable (), fname);
818 }
819 }
820
821 setFileLine (fid, lineno);
822 /*@noaccess cstring@*/
823 }
824 else if ((sscanf (ol, "line %d", &lineno) == 1)
825 || (sscanf (ol, " %d", &lineno) == 1))
826 {
827 setLine (lineno); /* next line is <cr> */
828 }
829 else
830 {
831 if (mstring_equal (ol, "")) {
832 DPRINTF (("Empty pp command!"));
833 /*
834 ** evs 2000-05-16: This is a horrible kludge, to get around a bug (well, difficulty) in the pre-processor.
835 ** We handle a plain # in the input file, by echoing it, and ignoring it in the post-pp-file.
836 */
837 mstring_free (ol);
838 return FALSE;
839 } else {
840 voptgenerror
841 (FLG_UNRECOGDIRECTIVE,
842 message ("Unrecognized pre-processor directive: #%s",
843 cstring_fromChars (ol)),
844 g_currentloc);
845 }
846
847 sfree (ol);
848 return FALSE; /* evans 2001-12-30: was: TRUE; */
849 }
850
851 sfree (ol);
852 return FALSE;
853}
854
855int cscannerHelp_handleLlSpecial (void)
856{
857 bool hasnl = FALSE;
858 int ic;
859 char c;
860 char *s = mstring_createEmpty ();
861 char *os;
862 int tok;
863 int charsread = 0;
864 fileloc loc;
865
866 loc = fileloc_copy (g_currentloc);
867 DPRINTF (("Handle special: %s", fileloc_unparse (loc)));
868
869 while (((ic = cscannerHelp_ninput ()) != 0) && isalpha (ic))
870 {
871 c = (char) ic;
872 s = mstring_append (s, c);
873 charsread++;
874 }
875
876 DPRINTF (("Read: %s / %s", s, fileloc_unparse (g_currentloc)));
877 os = s;
878
879 if (charsread == 0 && ic == (int) AFTER_COMMENT_MARKER[0])
880 {
881 ic = cscannerHelp_ninput ();
882
883 llassert (ic == (int) AFTER_COMMENT_MARKER[1]);
884
885 if (*s == '\0')
886 {
887 sfree (os);
888 fileloc_free (loc);
889 return QNOMODS; /* special token no modifications token */
890 }
891 }
892
893 DPRINTF (("Coment marker: %s", os));
894 tok = commentMarkerToken (cstring_fromChars (os));
895
896 if (tok != BADTOK)
897 {
898 s_tokLength = charsread;
899 sfree (os);
900 s_inSpecPart = TRUE;
901 s_whichSpecPart = tok;
902 fileloc_free (loc);
903 return tok;
904 }
905
906 DPRINTF (("Not a comment marker..."));
907 /* Add rest of the comment */
908
909 if (ic != 0 && ic != EOF)
910 {
911 c = (char) ic;
912
913 s = mstring_append (s, c);
914 charsread++;
915
916 while (((ic = cscannerHelp_ninput ()) != 0) && (ic != EOF)
917 && (ic != (int) AFTER_COMMENT_MARKER[0]))
918 {
919 c = (char) ic;
920
921 /* evans 2001-09-01 added to prevent assertion failures for uncloses syntactic comments */
922
923 if (c == '\n') {
924 hasnl = TRUE; /* This prevents tokLength from being set later. */
925 s_tokLength = 0;
926
927 voptgenerror
928 (FLG_SYNTAX,
929 message ("Likely parse error: syntactic comment token spans multiple lines: %s",
930 cstring_fromChars (s)),
931 loc);
932 }
933
934 s = mstring_append (s, c);
935 charsread++;
936 }
b73d1009 937 /*@-branchstate@*/
938 } /* spurious (?) warnings about s */
939 /*@=branchstate@*/
16c024b5 940
941 DPRINTF (("Read: %s / %s", s, fileloc_unparse (g_currentloc)));
942
943 if (ic == (int) AFTER_COMMENT_MARKER[0])
944 {
945 int nc = cscannerHelp_ninput ();
946 llassert ((char) nc == AFTER_COMMENT_MARKER[1]);
947 charsread++;
948 }
949
950 os = s;
951
952 while (*s == ' ' || *s == '\t' || *s == '\n')
953 {
954 s++;
955 }
956
957 if (*s == '-' || *s == '+' || *s == '=') /* setting flags */
958 {
959 c = *s;
960
961 while (c == '-' || c == '+' || c == '=')
962 {
963 ynm set = ynm_fromCodeChar (c);
964 cstring thisflag;
965
966 s++;
967
968 thisflag = cstring_fromChars (s);
969
970 while ((c = *s) != '\0' && (c != '-') && (c != '=')
971 && (c != '+') && (c != ' ') && (c != '\t') && (c != '\n'))
972 {
973 s++;
974 }
975
976 *s = '\0';
977
978 if (!context_getFlag (FLG_NOCOMMENTS))
979 {
980 cstring flagname = thisflag;
981 flagcode fflag = flags_identifyFlag (flagname);
982
983 if (flagcode_isSkip (fflag))
984 {
985 ;
986 }
987 else if (flagcode_isModeName (fflag))
988 {
989 if (ynm_isMaybe (set))
990 {
991 llerror
992 (FLG_BADFLAG,
993 message
994 ("Semantic comment attempts to restore flag %s. "
995 "A mode flag cannot be restored.",
996 flagname));
997 }
998 else
999 {
1000 context_setMode (flagname);
1001 }
1002 }
1003 else if (flagcode_isInvalid (fflag))
1004 {
1005 voptgenerror
1006 (FLG_UNRECOGFLAGCOMMENTS,
1007 message ("Unrecognized option in semantic comment: %s",
1008 flagname),
1009 loc);
1010 }
1011 else if (flagcode_isGlobalFlag (fflag))
1012 {
1013 voptgenerror
1014 (FLG_BADFLAG,
1015 message
1016 ("Semantic comment attempts to set global flag %s. "
1017 "A global flag cannot be set locally.",
1018 flagname),
1019 loc);
1020 }
1021 else
1022 {
1023 context_fileSetFlag (fflag, set, loc);
1024
1025 if (flagcode_hasArgument (fflag))
1026 {
1027 if (ynm_isMaybe (set))
1028 {
1029 voptgenerror
1030 (FLG_BADFLAG,
1031 message
1032 ("Semantic comment attempts to restore flag %s. "
1033 "A flag for setting a value cannot be restored.",
1034 flagname),
1035 loc);
1036 }
1037 else
1038 { /* cut-and-pastied from llmain...blecch */
1039 cstring extra = cstring_undefined;
1040 char *rest;
1041 char *orest;
1042 char rchar;
1043
1044 *s = c;
1045 rest = mstring_copy (s);
1046 orest = rest;
1047 *s = '\0';
1048
1049 while ((rchar = *rest) != '\0'
1050 && (isspace (rchar)))
1051 {
1052 rest++;
1053 s++;
1054 }
1055
1056 while ((rchar = *rest) != '\0'
1057 && !isspace (rchar))
1058 {
1059 extra = cstring_appendChar (extra, rchar);
1060 rest++;
1061 s++;
1062 }
1063 s--; /* evans 2002-07-12: this was previously only in the else branch.
1064 Leads to an invalid read on the true branch.
1065 */
1066
1067 sfree (orest);
1068
1069 if (cstring_isUndefined (extra))
1070 {
1071 llerror
1072 (FLG_BADFLAG,
1073 message
1074 ("Flag %s (in semantic comment) must be followed by an argument",
1075 flagcode_unparse (fflag)));
1076
1077 cstring_free (extra);
1078 }
1079 else
1080 {
1081 if (flagcode_hasNumber (fflag))
1082 {
1083 flags_setValueFlag (fflag, extra);
1084 }
1085 else if (flagcode_hasChar (fflag))
1086 {
1087 flags_setValueFlag (fflag, extra);
1088 }
1089 else if (flagcode_hasString (fflag))
1090 {
1091 flags_setStringFlag (fflag, extra);
1092 }
1093 else
1094 {
1095 cstring_free (extra);
1096 BADEXIT;
1097 }
1098 }
1099 }
1100 }
1101 }
1102 }
1103 else
1104 {
1105 ;
1106 }
1107
1108 *s = c;
1109 while ((c == ' ') || (c == '\t') || (c == '\n'))
1110 {
1111 c = *(++s);
1112 }
1113 }
1114
1115 if (context_inHeader () && !isArtificial (cstring_fromChars (os)))
1116 {
1117 DPRINTF (("Here adding comment: %s", os));
1118 context_addComment (cstring_fromCharsNew (os), loc);
1119 }
1120 else
1121 {
1122 ;
1123 }
1124 }
1125 else
1126 {
1127 char *t = s;
1128 int macrocode;
1129 char tchar = '\0';
1130 annotationInfo ainfo;
1131
1132 while (*s != '\0' && *s != ' ' && *s != '\t' && *s != '\n')
1133 {
1134 s++;
1135 }
1136
1137 if (*s != '\0')
1138 {
1139 tchar = *s;
1140 *s = '\0';
1141 s++;
1142 }
1143
1144 t = cstring_toCharsSafe (cstring_downcase (cstring_fromChars (t)));
1145 macrocode = tokenMacroCode (cstring_fromChars (t));
1146
1147 if (macrocode != BADTOK)
1148 {
1149 s_tokLength = hasnl ? 0 : size_toInt (mstring_length (t));
1150
1151 sfree (t);
1152 sfree (os);
1153 fileloc_free (loc);
1154
1155 if (macrocode == SKIPTOK)
1156 {
1157 return BADTOK;
1158 }
1159
1160 return macrocode;
1161 }
1162
1163 ainfo = context_lookupAnnotation (cstring_fromChars (os));
1164
1165 if (annotationInfo_isDefined (ainfo)) {
1166 DPRINTF (("Found annotation: %s", annotationInfo_unparse (ainfo)));
b73d1009 1167 yylval.annotation = ainfo;
16c024b5 1168 s_tokLength = 0;
1169 sfree (os);
1170 sfree (t);
1171 fileloc_free (loc);
1172 return CANNOTATION;
1173 }
1174
1175 if (context_inHeader ())
1176 {
1177 if (tchar != '\0')
1178 {
1179 *(s-1) = tchar;
1180 }
1181
1182 if ((context_inMacro () || context_inGlobalContext ())
1183 && macrocode != SKIPTOK
1184 && !isArtificial (cstring_fromChars (os)))
1185 {
1186 if (context_processingMacros ())
1187 {
1188 /* evans 2002-02-24: don't add comments when procssing macros */
1189 }
1190 else
1191 {
1192 context_addComment (cstring_fromCharsNew (os), loc);
1193 }
1194 }
1195 else
1196 {
1197 ;
1198 }
1199
1200 if (tchar != '\0')
1201 {
1202 *(s-1) = '\0';
1203 }
1204 }
1205
1206 if (mstring_equal (t, "ignore"))
1207 {
1208 if (!context_getFlag (FLG_NOCOMMENTS))
1209 {
1210 context_enterSuppressRegion (loc);
1211 }
1212 }
1213 else if ((*t == 'i' || *t == 't')
1214 && (*(t + 1) == '\0'))
1215 {
1216 if (!context_getFlag (FLG_NOCOMMENTS)
1217 && (*t == 'i' || context_getFlag (FLG_TMPCOMMENTS)))
1218 {
1219 context_enterSuppressLine (-1, loc); /* infinite suppression */
1220 }
1221 }
1222 else if (((*t == 'i') || (*t == 't'))
1223 && ((*(t + 1) >= '0' && *(t + 1) <= '9')))
1224 {
1225 bool tmpcomment = (*t == 't');
1226 int val = -1;
1227 char *tt = t; /* don't mangle t, since it is free'd */
1228 char lc = *(++tt);
1229
1230 if (lc >= '0' && lc <= '9')
1231 {
1232 val = (int)(lc - '0');
1233
1234 lc = *(++tt);
1235 while (lc >= '0' && lc <= '9')
1236 {
1237 val *= 10;
1238 val += (int) (lc - '0');
1239 lc = *(++tt);
1240 }
1241 }
1242
1243 if (!context_getFlag (FLG_NOCOMMENTS)
1244 && (!tmpcomment || context_getFlag (FLG_TMPCOMMENTS)))
1245 {
1246 DPRINTF (("Here: enter suppress: %s", fileloc_unparse (loc)));
1247 context_enterSuppressLine (val, loc);
1248 }
1249 }
1250 else if (mstring_equal (t, "end"))
1251 {
1252 if (!context_getFlag (FLG_NOCOMMENTS))
1253 {
1254 context_exitSuppressRegion (loc);
1255 }
1256 }
1257 else if (mstring_equal (t, "notfunction"))
1258 {
1259 ; /* handled by pcpp */
1260 }
1261 else if (mstring_equal (t, "access"))
1262 {
1263 cstring tname;
1264
1265 while (TRUE)
1266 {
1267 while (((c = *s) != '\0') && (c == ' ' || c == '\t' || c == '\n'))
1268 {
1269 s++;
1270 }
1271
1272 if (c == '\0')
1273 {
1274 break;
1275 }
1276
1277 tname = cstring_fromChars (s);
1278
1279 while ((c = *s) != '\0' && c != ' '
1280 && c != '\t' && c != '\n' && c != ',')
1281 {
1282 s++;
1283 }
1284
1285 *s = '\0';
1286
1287 DPRINTF (("Access %s", tname));
1288
1289 if (!context_getFlag (FLG_NOCOMMENTS)
1290 && !context_getFlag (FLG_NOACCESS))
1291 {
1292 if (usymtab_existsType (tname))
1293 {
1294 typeId uid = usymtab_getTypeId (tname);
1295 uentry ue = usymtab_getTypeEntry (uid);
1296
1297 if (uentry_isAbstractDatatype (ue))
1298 {
1299 context_addFileAccessType (uid);
1300 DPRINTF (("Adding access to: %s / %d", tname, uid));
1301 }
1302 else
1303 {
1304 voptgenerror
1305 (FLG_COMMENTERROR,
1306 message
1307 ("Non-abstract type %s used in access comment",
1308 tname),
1309 loc);
1310 }
1311 }
1312 else
1313 {
1314 if (!(context_inSuppressRegion ()
1315 || context_inSuppressZone (loc)))
1316 {
1317 voptgenerror
1318 (FLG_COMMENTERROR,
1319 message
1320 ("Unrecognized type %s used in access comment",
1321 tname),
1322 loc);
1323 }
1324 }
1325 }
1326
1327 if (c != '\0')
1328 {
1329 s++;
1330 }
1331
1332 if (c != ',' && c != ' ')
1333 {
1334 break;
1335 }
1336 }
1337 }
1338 else if (mstring_equal (t, "noaccess"))
1339 {
1340 cstring tname;
1341 char lc;
1342
1343 while (TRUE)
1344 {
1345 while (((lc = *s) != '\0') && (lc == ' ' || lc == '\t' || lc == '\n'))
1346 {
1347 s++;
1348 }
1349
1350 if (lc == '\0')
1351 {
1352 break;
1353 }
1354
1355 tname = cstring_fromChars (s);
1356
1357 while ((lc = *s) != '\0' && lc != ' ' && lc != '\t'
1358 && lc != '\n' && lc != ',')
1359 {
1360 s++;
1361 }
1362
1363 *s = '\0';
1364
1365 if (!context_getFlag (FLG_NOCOMMENTS)
1366 && !context_getFlag (FLG_NOACCESS))
1367 {
1368 if (usymtab_existsType (tname))
1369 {
1370 typeId tuid = usymtab_getTypeId (tname);
1371
1372 if (context_couldHaveAccess (tuid))
1373 {
1374 DPRINTF (("Removing access: %s", tname));
1375 context_removeFileAccessType (tuid);
1376 }
1377 else
1378 {
1379 if (!(context_inSuppressRegion ()
1380 || context_inSuppressZone (loc)))
1381 {
1382 uentry ue = usymtab_getTypeEntry (tuid);
1383
1384 if (uentry_isAbstractDatatype (ue))
1385 {
1386 voptgenerror
1387 (FLG_COMMENTERROR,
1388 message
1389 ("Non-accessible abstract type %s used in noaccess comment",
1390 tname),
1391 loc);
1392 }
1393 else
1394 {
1395 voptgenerror
1396 (FLG_COMMENTERROR,
1397 message
1398 ("Non-abstract type %s used in noaccess comment",
1399 tname),
1400 loc);
1401 }
1402 }
1403 }
1404 }
1405 else
1406 {
1407 if (!(context_inSuppressRegion ()
1408 || context_inSuppressZone (loc)))
1409 {
1410 voptgenerror
1411 (FLG_COMMENTERROR,
1412 message
1413 ("Unrecognized type %s used in noaccess comment",
1414 tname),
1415 loc);
1416 }
1417 }
1418 }
1419
1420 if (lc != '\0')
1421 {
1422 s++;
1423 }
1424
1425 if (lc != ',' && lc != ' ')
1426 {
1427 break;
1428 }
1429 }
1430 }
1431 else
1432 {
1433 voptgenerror (FLG_UNRECOGCOMMENTS,
1434 message ("Semantic comment unrecognized: %s",
1435 cstring_fromChars (os)),
1436 loc);
b73d1009 1437 /*@-branchstate@*/
1438 } /* spurious (?) warning about t */
1439 /*@=branchstate@*/
16c024b5 1440
1441 sfree (t);
1442 }
1443
1444 sfree (os);
1445 fileloc_free (loc);
1446 return BADTOK;
1447}
1448
1449/*@only@*/ cstring cscannerHelp_makeIdentifier (char *s)
1450{
1451 char *c = mstring_create (strlen (s) + 1);
1452 cstring id = cstring_fromChars (c);
1453
1454 while (isalnum (*s) || (*s == '_') || (*s == '$'))
1455 {
1456 *c++ = *s++;
1457 }
1458
1459 *c = '\0';
1460 return (id);
1461}
1462
1463/*@observer@*/ /*@dependent@*/ uentry cscannerHelp_coerceId (cstring cn)
1464{
1465 if (!(usymtab_exists (cn)))
1466 {
1467 fileloc loc = fileloc_createExternal ();
1468
1469 /*
1470 ** We need to put this in a global scope, otherwise the sRef will be deallocated.
1471 */
1472
1473 uentry ce = uentry_makeUnrecognized (cn, loc);
1474
1475 if (!context_inIterEnd ())
1476 {
1477 voptgenerror
1478 (FLG_SYSTEMUNRECOG,
1479 message ("Unrecognized (possibly system) identifier: %q",
1480 uentry_getName (ce)),
1481 g_currentloc);
1482 }
1483
1484 return ce;
1485 }
1486
1487 return (usymtab_lookup (cn));
1488}
1489
1490/*
1491** like, cscannerHelp_coerceId, but doesn't supercede for iters
1492*/
1493
1494/*@observer@*/ uentry cscannerHelp_coerceIterId (cstring cn)
1495{
1496 if (!(usymtab_exists (cn)))
1497 {
1498 return uentry_undefined;
1499 }
1500
1501 return (usymtab_lookup (cn));
1502}
1503
1504/*
1505** Need to keep this in case there is a declaration that isn't processed until
1506** the scope exits. Would be good to rearrange the symbol table so this doesn't
1507** happen, and save all the cstring copying.
1508*/
1509
1510/*@observer@*/ cstring cscannerHelp_observeLastIdentifier ()
1511{
1512 cstring res = s_lastidprocessed;
1513 return res;
1514}
1515
1516static void cscanner_setLastIdentifier (/*@keep@*/ cstring id) /*@modifies s_lastidprocessed@*/
1517{
1518 if (cstring_isDefined (s_lastidprocessed))
1519 {
1520 cstring_free (s_lastidprocessed);
1521 }
1522
1523 s_lastidprocessed = id;
1524}
1525
1526int cscannerHelp_processIdentifier (cstring id)
1527{
1528 uentry le;
1529
1530 if (context_getFlag (FLG_GRAMMAR))
1531 {
1532 lldiagmsg (message ("Process identifier: %s", id));
1533 }
1534
1535 context_clearJustPopped ();
1536 cscanner_setLastIdentifier (id);
1537
1538 DPRINTF (("Context: %s", context_unparse ()));
1539
1540 if (context_inFunctionHeader ())
1541 {
1542 int tok = commentMarkerToken (id);
1543 DPRINTF (("in function decl: %s", id));
1544
1545 if (tok != BADTOK)
1546 {
1547 return tok;
1548 }
1549 else
1550 {
1551 tok = tokenMacroCode (id);
1552
1553 if (tok != BADTOK)
1554 {
1555 return tok;
1556 }
1557 else
1558 {
1559 annotationInfo ainfo;
1560
1561 if (s_expectingMetaStateName)
1562 {
1563 metaStateInfo msinfo = context_lookupMetaStateInfo (id);
1564
1565 if (metaStateInfo_isDefined (msinfo))
1566 {
1567 yylval.msinfo = msinfo;
1568 return METASTATE_NAME;
1569 }
1570 else
1571 {
1572 DPRINTF (("Not meta state name: %s", cstring_toCharsSafe (id)));
1573 }
1574 }
1575
1576 ainfo = context_lookupAnnotation (id);
1577
1578 if (annotationInfo_isDefined (ainfo))
1579 {
1580 DPRINTF (("Found annotation: %s", annotationInfo_unparse (ainfo)));
b73d1009 1581 yylval.annotation = ainfo;
16c024b5 1582 return CANNOTATION;
1583 }
1584 else
1585 {
1586 DPRINTF (("Not annotation: %s", id));
1587 }
1588 }
1589 }
1590 }
1591
1592 DPRINTF (("Here!"));
1593
1594 /* Consider handling: Defined by C99 as static const char __func__[] */
1595
1596 if (context_getFlag (FLG_GNUEXTENSIONS))
1597 {
1598 int tok = BADTOK;
1599
1600 if (cstring_equalLit (id, "__stdcall")
1601 || cstring_equalLit (id, "__cdecl")
1602 || cstring_equalLit (id, "__extension__"))
1603 {
1604 return BADTOK;
1605 }
1606 else if (cstring_equalLit (id, "__volatile__"))
1607 {
1608 tok = QVOLATILE;
1609 }
1610 else if (cstring_equalLit (id, "__signed"))
1611 {
1612 tok = QSIGNED;
1613 }
1614 else if (cstring_equalLit (id, "__unsigned"))
1615 {
1616 tok = QUNSIGNED;
1617 }
1618 else if (cstring_equalLit (id, "__const__"))
1619 {
1620 tok = QCONST;
1621 }
1622 else if (cstring_equalLit (id, "__alignof__"))
1623 {
1624 tok = CALIGNOF; /* alignof is parsed like sizeof */
1625 }
1626 else if (cstring_equalLit (id, "__typeof__"))
1627 {
1628 tok = CTYPEOF;
1629 }
1630 else if (cstring_equalLit (id, "typeof"))
1631 {
1632 tok = CTYPEOF;
1633 }
1634 else if (cstring_equalLit (id, "__FUNCTION__")
1635 || cstring_equalLit (id, "__PRETTY_FUNCTION__"))
1636 {
1637 /* These tokens hold the name of the current function as strings */
1638 /* evans 2001-12-30: changed from exprNode_stringLiteral; bug reported by Jim Zelenka. */
1639 yylval.expr = exprNode_makeConstantString (id, fileloc_copy (g_currentloc));
1640 s_tokLength = 0;
1641 s_lastWasString = TRUE;
1642 tok = CCONSTANT;
1643 return tok;
1644 }
1645 else if (cstring_equalLit (id, "__attribute__")
1646 || cstring_equalLit (id, "__asm__")
1647 || cstring_equalLit (id, "_asm")
1648 || cstring_equalLit (id, "__asm")
1649 || cstring_equalLit (id, "__declspec"))
1650 {
1651 int depth = 0;
1652 bool useparens = FALSE;
1653 bool usebraces = FALSE;
1654 bool inquote = FALSE;
1655 bool inescape = FALSE;
1656 int ic;
1657
1658 while ((ic = cscanner_input ()) != EOF)
1659 {
1660 char cc = (char) ic;
1661
1662 if (inescape)
1663 {
1664 inescape = FALSE;
1665 }
1666 else if (cc == '\\')
1667 {
1668 inescape = TRUE;
1669 }
1670 else if (cc == '\"')
1671 {
1672 inquote = !inquote;
1673 }
1674 else if (!inquote)
1675 {
1676 if (cc == '(')
1677 {
1678 if (!useparens)
1679 {
1680 if (!usebraces)
1681 {
1682 useparens = TRUE;
1683 }
1684 }
1685
1686 if (useparens)
1687 {
1688 depth++;
1689 }
1690 }
1691 else if (cc == '{')
1692 {
1693 if (!usebraces)
1694 {
1695 if (!useparens)
1696 {
1697 usebraces = TRUE;
1698 }
1699 }
1700
1701 if (usebraces)
1702 {
1703 depth++;
1704 }
1705 }
1706 else if (cc == ')' && useparens)
1707 {
1708 depth--;
1709 if (depth == 0) break;
1710 }
1711 else if (cc == '}' && usebraces)
1712 {
1713 depth--;
1714 if (depth == 0) break;
1715 }
1716 else if (cc == '}'
1717 && !usebraces && !useparens
1718 && cstring_equalLit (id, "__asm"))
1719 {
1720 /*
1721 ** We need this because some MS VC++ include files
1722 ** have __asm mov ... }
1723 ** Its a kludge, but otherwise would need to parse
1724 ** the asm code!
1725 */
1726 return TRBRACE;
1727 }
1728 else
1729 {
1730 ;
1731 }
1732 }
1733 else
1734 {
1735 ;
1736 }
1737
1738 if (cc == '\n')
1739 {
1740 context_incLineno ();
1741
1742 if (cstring_equalLit (id, "__asm")
1743 && !useparens && !usebraces)
1744 {
1745 break;
1746 }
1747 }
1748 }
1749
1750 llassert ((useparens && ic == (int) ')')
1751 || (usebraces && ic == (int) '}')
1752 || (!useparens && !usebraces));
1753
1754 return BADTOK;
1755 }
1756 else if (cstring_equalLit (id, "inline")
1757 || cstring_equalLit (id, "__inline")
1758 || cstring_equalLit (id, "_inline")
1759 || cstring_equalLit (id, "__inline__"))
1760 {
1761 tok = QINLINE;
1762 }
1763 else
1764 {
1765 ;
1766 }
1767
1768 if (tok != BADTOK)
1769 {
1770 return (cscannerHelp_returnToken (tok));
1771 }
1772 }
1773
1774 le = usymtab_lookupSafe (id);
1775
1776 /*@-dependenttrans@*/
1777
1778 if (uentry_isIter (le))
1779 {
b73d1009 1780 yylval.entry = le;
16c024b5 1781 return (ITER_NAME);
1782 }
1783 else if (uentry_isEndIter (le))
1784 {
b73d1009 1785 yylval.entry = le;
16c024b5 1786 return (ITER_ENDNAME);
1787 }
1788 else if (uentry_isUndefined (le))
1789 {
1790 yylval.cname = cstring_copy (id);
1791
1792 /* avoid parse errors for certain system built ins */
1793
1794 if (s_expectingTypeName && (cstring_firstChar (id) == '_')
1795 && (cstring_secondChar (id) == '_'))
1796 {
1797 return (TYPE_NAME_OR_ID);
1798 }
1799
1800 return (NEW_IDENTIFIER);
1801 }
1802 else if (!uentry_isDeclared (le) && !uentry_isCodeDefined (le))
1803 {
1804 if (uentry_isDatatype (le))
1805 {
1806 yylval.cname = cstring_copy (id);
1807 return (NEW_IDENTIFIER);
1808 }
1809 else
1810 {
b73d1009 1811 yylval.entry = le;
16c024b5 1812 return (IDENTIFIER);
1813 }
1814 }
1815 else if (uentry_isDatatype (le))
1816 {
1817 if (!s_expectingTypeName)
1818 {
1819 yylval.cname = cstring_copy (id);
1820
1821 return (NEW_IDENTIFIER);
1822 }
1823 else
1824 {
1825 yylval.ctyp = uentry_getAbstractType (le);
1826
1827 uentry_setUsed (le, g_currentloc);
1828 return (TYPE_NAME);
1829 }
1830 }
1831 else
1832 {
b73d1009 1833 yylval.entry = le;
16c024b5 1834 return (IDENTIFIER);
1835 }
1836
1837 /*@=dependenttrans@*/
1838}
1839
1840bool cscannerHelp_processHashIdentifier (/*@only@*/ cstring id)
1841{
1842 if (context_inMacro () || context_inIterDef () ||
1843 context_inIterEnd ())
1844 {
1845 uentry le;
1846
1847 context_clearJustPopped ();
1848
1849 le = usymtab_lookupSafe (id);
1850 cscanner_setLastIdentifier (id);
1851
1852 if (uentry_isParam (le) || uentry_isRefParam (le))
1853 {
1854 return TRUE;
1855 }
1856 else
1857 {
1858 return FALSE;
1859 }
1860 }
1861 else
1862 {
1863 /*
1864 ** Will be handled by handleLlSpecial
1865 */
1866
1867 cstring_free (id);
1868 return FALSE;
1869 }
1870}
1871
1872/*@only@*/ exprNode cscannerHelp_processString (void)
1873{
1874 exprNode res;
1875 fileloc loc;
1876 char *nl = strchr (yytext, '\n');
1877 cstring ns = cstring_fromCharsNew (yytext);
1878
1879 if (nl == NULL)
1880 {
1881 loc = fileloc_copy (g_currentloc);
1882 addColumn (size_toInt (cstring_length (ns)));
1883 }
1884 else
1885 {
1886 char *lastnl = nl;
1887
1888 loc = fileloc_copy (g_currentloc);
1889
1890 context_incLineno ();
1891
1892 while ((nl = strchr ((nl + 1), '\n')) != NULL)
1893 {
1894 context_incLineno ();
1895 lastnl = nl;
1896 }
1897 }
1898
1899
1900 res = exprNode_stringLiteral (ns, loc);
1901 return (res);
1902}
1903
1904/*
1905** process a wide character string L"...."
1906*/
1907
1908/*@only@*/ exprNode cscannerHelp_processWideString ()
1909{
1910 exprNode res;
1911 fileloc loc;
1912 char *nl = strchr (yytext, '\n');
1913 cstring ns;
1914
1915 llassert (*yytext == 'L');
1916 yytext++;
1917
1918 ns = cstring_fromCharsNew (yytext);
1919
1920 if (nl == NULL)
1921 {
1922 loc = fileloc_copy (g_currentloc);
1923 addColumn (size_toInt (cstring_length (ns)));
1924 }
1925 else
1926 {
1927 char *lastnl = nl;
1928
1929 loc = fileloc_copy (g_currentloc);
1930
1931 context_incLineno ();
1932
1933 while ((nl = strchr ((nl + 1), '\n')) != NULL)
1934 {
1935 context_incLineno ();
1936 lastnl = nl;
1937 }
1938 }
1939
1940 res = exprNode_wideStringLiteral (ns, loc);
1941 return (res);
1942}
1943
1944char cscannerHelp_processChar ()
1945{
1946 char fchar;
1947 char next;
1948
1949 llassert (*yytext != '\0');
1950 fchar = *(yytext + 1);
1951 if (fchar != '\\') return fchar;
1952
1953 next = *(yytext + 2);
1954
1955 switch (next)
1956 {
1957 case 'n': return '\n';
1958 case 't': return '\t';
1959 case '\"': return '\"';
1960 case '\'': return '\'';
1961 case '\\': return '\\';
1962 default: return '\0';
1963 }
1964}
1965
1966double cscannerHelp_processFloat ()
1967{
1968 double ret = atof (yytext);
1969
1970 return (ret);
1971}
1972
1973long cscannerHelp_processHex ()
1974{
1975 int index = 2;
1976 long val = 0;
1977
1978 llassert (yytext[0] == '0'
1979 && (yytext[1] == 'X' || yytext[1] == 'x'));
1980
1981 while (yytext[index] != '\0') {
1982 int tval;
1983 char c = yytext[index];
1984
1985 if (c >= '0' && c <= '9') {
1986 tval = (int) c - (int) '0';
1987 } else if (c >= 'A' && c <= 'F') {
1988 tval = (int) c - (int) 'A' + 10;
1989 } else if (c >= 'a' && c <= 'f') {
1990 tval = (int) c - (int) 'a' + 10;
1991 } else if (c == 'U' || c == 'L' || c == 'u' || c == 'l') {
1992 index++;
1993 while (yytext[index] != '\0') {
1994 if (c == 'U' || c == 'L' || c == 'u' || c == 'l') {
1995 ;
1996 } else {
1997 voptgenerror
1998 (FLG_SYNTAX,
1999 message ("Invalid character (%c) following specifier in hex constant: %s",
2000 c, cstring_fromChars (yytext)),
2001 g_currentloc);
2002 }
2003 index++;
2004 }
2005
2006 break;
2007 } else {
2008 voptgenerror
2009 (FLG_SYNTAX,
2010 message ("Invalid character (%c) in hex constant: %s",
2011 c, cstring_fromChars (yytext)),
2012 g_currentloc);
2013 break;
2014 }
2015
2016 val = (val * 16) + tval;
2017 index++;
2018 }
2019
2020 DPRINTF (("Hex constant: %s = %ld", yytext, val));
2021 return val;
2022}
2023
2024long cscannerHelp_processOctal ()
2025{
2026 int index = 1;
2027 long val = 0;
2028
2029 llassert (yytext[0] == '0' && yytext[1] != 'X' && yytext[1] != 'x');
2030
2031 while (yytext[index] != '\0') {
2032 int tval;
2033 char c = yytext[index];
2034
2035 if (c >= '0' && c <= '7') {
2036 tval = (int) c - (int) '0';
2037 } else if (c == 'U' || c == 'L' || c == 'u' || c == 'l') {
2038 index++;
2039 while (yytext[index] != '\0') {
2040 if (c == 'U' || c == 'L' || c == 'u' || c == 'l') {
2041 ;
2042 } else {
2043 voptgenerror
2044 (FLG_SYNTAX,
2045 message ("Invalid character (%c) following specifier in octal constant: %s",
2046 c, cstring_fromChars (yytext)),
2047 g_currentloc);
2048 }
2049 index++;
2050 }
2051
2052 break;
2053 } else {
2054 voptgenerror
2055 (FLG_SYNTAX,
2056 message ("Invalid character (%c) in octal constant: %s",
2057 c, cstring_fromChars (yytext)),
2058 g_currentloc);
2059 break;
2060 }
2061
2062 val = (val * 8) + tval;
2063 index++;
2064 }
2065
2066 DPRINTF (("Octal constant: %s = %ld", yytext, val));
2067 return val;
2068}
2069
2070long cscannerHelp_processDec ()
2071{
2072 return (atol (yytext));
2073}
2074
2075int cscannerHelp_processSpec (int tok)
2076{
2077 size_t length = strlen (yytext);
2078
2079 if (s_inSpecPart)
2080 {
2081
2082 /*drl 12/11/2002
2083 patched to fix assert failures in constraint code.
2084 Added the else if test so that splint does not treat MaxSet and MaxRead
2085 as identifies*/
2086
2087 if (s_whichSpecPart == QMODIFIES
2088 || s_whichSpecPart == QDEFINES
2089 || s_whichSpecPart == QUSES
2090 || s_whichSpecPart == QALLOCATES
2091 || s_whichSpecPart == QSETS
2092 || s_whichSpecPart == QRELEASES)
2093
2094 {
2095 DPRINTF((message("Treating specifaction keyword %s as an identifiers. (This corresponds to"
2096 " token %d and we're in the specification denoted by %d see cgrammar_tokens.h"
2097 " for an explanation of these numbers",
2098 yytext, tok, s_whichSpecPart)
2099 ));
2100
2101 ; /* Allow specificiation keywords to be used as identifiers in these contexts. */
2102 }
2103 else if ( (s_whichSpecPart == QPRECLAUSE
2104 || s_whichSpecPart == QPOSTCLAUSE
2105 || s_whichSpecPart == QINVARIANT )
2106 && (!cscannerHelp_isConstraintToken(tok) )
2107 )
2108 {
2109 DPRINTF((message("Treating specifaction keyword %s as an identifiers. (This corresponds to"
2110 " token %d and we're in the specification denoted by %d see cgrammar_tokens.h"
2111 " for an explanation of these numbers",
2112 yytext, tok, s_whichSpecPart)
2113 ));
2114
2115 /* Allow specificiation keywords to be used as identifiers in these contexts. */
2116 }
2117 else
2118 {
2119 cscannerHelp_setTokLengthT (length);
2120 return cscannerHelp_returnToken (tok);
2121 }
2122 }
2123
2124 context_saveLocation ();
2125 cscannerHelp_setTokLengthT (length);
2126 return (cscannerHelp_processIdentifier (cscannerHelp_makeIdentifier (yytext)));
2127}
2128
2129void cscannerHelp_expectingMetaStateName ()
2130{
2131 llassert (!s_expectingMetaStateName);
2132 llassert (context_inFunctionHeader ());
2133 s_expectingMetaStateName = TRUE;
2134}
2135
2136void cscannerHelp_clearExpectingMetaStateName ()
2137{
2138 llassert (s_expectingMetaStateName);
2139 s_expectingMetaStateName = FALSE;
2140}
2141
2142bool cscannerHelp_isConstraintToken (int tok)
2143 /* drl added 12/11/2002
2144 Tell whether a token has special meaning
2145 within a function constraint
2146 */
2147{
2148 return (tok == QMAXSET || tok == QMAXREAD);
2149 /* || tok == QMINREAD || tok == QMINSET */
16c024b5 2150 /* uncomment the additional if statement tests when minSet and minRead are supported */
2151}
2152
2153bool cscannerHelp_processMacro (void)
2154{
2155 uentry e2;
2156 ctype ct;
2157 int noparams = 0;
2158 cstring fname = cstring_undefined;
2159 bool res = TRUE;
2160 bool isspecfcn = FALSE;
2161 bool isiter = FALSE;
2162 bool skipparam = FALSE;
2163 bool isenditer = FALSE;
2164 bool unknownm = FALSE;
2165 bool hasParams = FALSE;
2166 bool emptyMacro = FALSE;
2167 char c = skip_whitespace ();
2168 fileloc loc = fileloc_noColumn (g_currentloc);
2169
2170 /* are both of these necessary? what do they mean? */
2171 uentryList specparams = uentryList_undefined;
2172 uentryList pn = uentryList_undefined;
2173
2174 context_resetMacroMissingParams ();
2175
2176 if (c == '\0' || c == '\n')
2177 {
2178 llcontbug (cstring_makeLiteral ("Bad macro"));
2179 fileloc_free (loc);
2180 return FALSE;
2181 }
2182
2183 fname = cstring_appendChar (fname, c);
2184
2185 while ((c = macro_nextChar ()) != '(' && c != '\0'
2186 && c != ' ' && c != '\t' && c != '\n')
2187 {
2188 fname = cstring_appendChar (fname, c);
2189 }
2190
2191 if (c == ' ' || c == '\t' || c == '\n')
2192 {
2193 char oldc = c;
2194
2195 if (c != '\n')
2196 {
2197 while (c == ' ' || c == '\t')
2198 {
2199 c = macro_nextChar ();
2200 }
2201 cscanner_unput ((int) c);
2202 }
2203
2204 if (c == '\n')
2205 {
2206 emptyMacro = TRUE;
2207 cscanner_unput ((int) c);
2208 }
2209
2210 c = oldc;
2211 }
2212
2213 hasParams = (c == '(');
2214
2215 if (usymtab_exists (fname))
2216 {
2217 e2 = usymtab_lookupExpose (fname);
2218 ct = uentry_getType (e2);
2219
2220 if (uentry_isCodeDefined (e2)
2221 && fileloc_isUser (uentry_whereDefined (e2)))
2222 {
2223 if (optgenerror
2224 (FLG_MACROREDEF,
2225 message ("Macro %s already defined", fname),
2226 loc))
2227 {
2228 uentry_showWhereDefined (e2);
2229 uentry_clearDefined (e2);
2230 }
2231
2232 if (uentry_isFunction (e2))
2233 {
2234 uentry_setType (e2, ctype_unknown);
2235 ct = ctype_unknown;
2236 unknownm = TRUE;
2237 context_enterUnknownMacro (e2);
2238 }
2239 else
2240 {
2241 context_enterConstantMacro (e2);
2242 }
2243 }
2244 else
2245 {
2246 if (uentry_isForward (e2) && uentry_isFunction (e2))
2247 {
2248 unknownm = TRUE;
2249
2250 voptgenerror
2251 (FLG_MACROFCNDECL,
2252 message
2253 ("Parameterized macro has no prototype or specification: %s ",
2254 fname),
2255 loc);
2256
2257 ct = ctype_unknown;
2258 uentry_setType (e2, ctype_unknown);
2259 uentry_setFunctionDefined (e2, loc);
2260 uentry_setUsed (e2, fileloc_undefined);
2261 context_enterUnknownMacro (e2);
2262 }
2263 else
2264 {
2265 if (uentry_isIter (e2))
2266 {
2267 isiter = TRUE;
2268 specparams = uentry_getParams (e2);
2269 noparams = uentryList_size (specparams);
2270 uentry_setDefined (e2, loc);
2271 context_enterIterDef (e2);
2272 }
2273 else if (uentry_isEndIter (e2))
2274 {
2275 isenditer = TRUE;
2276 uentry_setDefined (e2, loc);
2277 context_enterIterEnd (e2); /* don't care about it now */
2278 /* but should parse like an iter! */
2279 }
2280 else if (uentry_isConstant (e2))
2281 {
2282 if (hasParams)
2283 {
2284 voptgenerror
2285 (FLG_INCONDEFS,
2286 message ("Constant %s implemented as parameterized macro",
2287 fname),
2288 g_currentloc);
2289
2290 uentry_showWhereSpecified (e2);
2291 uentry_setType (e2, ctype_unknown);
2292 uentry_makeConstantFunction (e2);
2293 uentry_setDefined (e2, g_currentloc);
2294 uentry_setFunctionDefined (e2, g_currentloc);
2295 context_enterUnknownMacro (e2);
2296 }
2297 else
2298 {
2299 if (!uentry_isSpecified (e2))
2300 {
2301 fileloc oloc = uentry_whereDeclared (e2);
2302
2303 if (fileloc_isLib (oloc))
2304 {
2305 ;
2306 }
2307 else if (fileloc_isUndefined (oloc)
2308 || fileloc_isPreproc (oloc))
2309 {
2310 if (!emptyMacro)
2311 {
2312 voptgenerror
2313 (FLG_MACROCONSTDECL,
2314 message
2315 ("Macro constant %q not declared",
2316 uentry_getName (e2)),
2317 loc);
2318 }
2319 }
2320 else if (!fileloc_withinLines (oloc, loc, 2))
2321 { /* bogus! will give errors if there is too much whitespace */
2322 voptgenerror
2323 (FLG_SYNTAX,
2324 message
2325 ("Macro constant name %s does not match name in "
2326 "previous constant declaration. This constant "
2327 "is declared at %q", fname,
2328 fileloc_unparse (oloc)),
2329 loc);
2330 }
2331 else
2332 {
2333 /* No warning */
2334 }
2335 }
2336
2337 context_enterConstantMacro (e2);
2338 cstring_free (fname);
2339 fileloc_free (loc);
2340 return res;
2341 }
2342
2343 }
2344 else if (ctype_isFunction (ct))
2345 {
2346 isspecfcn = TRUE;
2347 specparams = ctype_argsFunction (ct);
2348 noparams = uentryList_size (specparams);
2349
2350 uentry_setFunctionDefined (e2, loc);
2351 context_enterMacro (e2);
2352 }
2353 else if (uentry_isVar (e2))
2354 {
2355 if (hasParams)
2356 {
2357 voptgenerror
2358 (FLG_INCONDEFS,
2359 message ("Variable %s implemented as parameterized macro",
2360 fname),
2361 loc);
2362
2363 uentry_showWhereSpecified (e2);
2364 uentry_setType (e2, ctype_unknown);
2365 uentry_makeVarFunction (e2);
2366 uentry_setDefined (e2, g_currentloc);
2367 uentry_setFunctionDefined (e2, g_currentloc);
2368 context_enterUnknownMacro (e2);
2369 }
2370 else
2371 {
2372 uentry ucons = uentry_makeConstant (fname,
2373 ctype_unknown,
2374 loc);
2375 if (uentry_isExpandedMacro (e2))
2376 {
2377 ; /* okay */
2378 }
2379 else
2380 {
2381 if (optgenerror
2382 (FLG_INCONDEFS,
2383 message ("Variable %s implemented by a macro",
2384 fname),
2385 loc))
2386 {
2387 uentry_showWhereSpecified (e2);
2388 }
2389 }
2390
2391 uentry_setDefined (e2, loc);
2392 uentry_setUsed (ucons, loc);
2393
2394 context_enterConstantMacro (ucons);
2395 uentry_markOwned (ucons);
2396 cstring_free (fname);
2397 return res;
2398 }
2399 }
2400 else
2401 {
2402 if (uentry_isDatatype (e2))
2403 {
2404 vgenhinterror
2405 (FLG_SYNTAX,
2406 message ("Type implemented as macro: %x",
2407 uentry_getName (e2)),
2408 message ("A type is implemented using a macro definition. A "
2409 "typedef should be used instead."),
2410 g_currentloc);
2411
2412 cscannerHelp_swallowMacro ();
2413 /* Must exit scope (not sure why a new scope was entered?) */
2414 usymtab_quietExitScope (g_currentloc);
2415 uentry_setDefined (e2, g_currentloc);
2416 res = FALSE;
2417 }
2418 else
2419 {
2420 llcontbug
2421 (message ("Unexpanded macro not function or constant: %q",
2422 uentry_unparse (e2)));
2423 uentry_setType (e2, ctype_unknown);
2424
2425 if (hasParams)
2426 {
2427 uentry_makeVarFunction (e2);
2428 uentry_setDefined (e2, g_currentloc);
2429 uentry_setFunctionDefined (e2, g_currentloc);
2430 context_enterUnknownMacro (e2);
2431 }
2432 }
2433 }
2434 }
2435 }
2436 }
2437 else
2438 {
2439 uentry ce;
2440
2441 /* evans 2001-09-09 - if it has params, assume a function */
2442 if (hasParams)
2443 {
2444 voptgenerror
2445 (FLG_MACROMATCHNAME,
2446 message ("Unexpanded macro %s does not match name of a declared "
2447 "function. The name used in the control "
2448 "comment on the previous line should match.",
2449 fname),
2450 loc);
2451
2452 ce = uentry_makeFunction (fname, ctype_unknown,
2453 typeId_invalid,
2454 globSet_undefined,
2455 sRefSet_undefined,
2456 warnClause_undefined,
2457 fileloc_undefined);
2458 uentry_setUsed (ce, loc); /* perhaps bogus? */
2459 e2 = usymtab_supEntryReturn (ce);
2460 context_enterUnknownMacro (e2);
2461 }
2462 else
2463 {
2464 voptgenerror
2465 (FLG_MACROMATCHNAME,
2466 message ("Unexpanded macro %s does not match name of a constant "
2467 "or iter declaration. The name used in the control "
2468 "comment on the previous line should match. "
2469 "(Assuming macro defines a constant.)",
2470 fname),
2471 loc);
2472
2473 ce = uentry_makeConstant (fname, ctype_unknown, fileloc_undefined);
2474 uentry_setUsed (ce, loc); /* perhaps bogus? */
2475 e2 = usymtab_supEntryReturn (ce);
2476
2477 context_enterConstantMacro (e2);
2478 cstring_free (fname);
2479 fileloc_free (loc);
2480 return res;
2481 }
2482 }
2483
2484 /* in macros, ( must follow immediatetly after name */
2485
2486 if (hasParams)
2487 {
2488 int paramno = 0;
2489
2490 c = skip_whitespace ();
2491
2492 while (c != ')' && c != '\0')
2493 {
2494 uentry param;
2495 bool suppress = context_inSuppressRegion ();
2496 cstring paramname = cstring_undefined;
2497
2498 /*
2499 ** save the parameter location
2500 */
2501
2502 decColumn ();
2503 context_saveLocation ();
2504 incColumn ();
2505
2506 while (c != ' ' && c != '\t' && c != ',' && c != '\0' && c != ')')
2507 {
2508 paramname = cstring_appendChar (paramname, c);
2509 c = macro_nextChar ();
2510 }
2511
2512 if (c == ' ' || c == '\t') c = skip_whitespace ();
2513
2514 if (c == ',')
2515 {
2516 c = macro_nextChar ();
2517 if (c == ' ' || c == '\t') c = skip_whitespace ();
2518 }
2519
2520 if (c == '\0')
2521 {
2522 llfatalerror (cstring_makeLiteral
2523 ("Bad macro syntax: uentryList"));
2524 }
2525
2526 if ((isspecfcn || isiter) && (paramno < noparams)
2527 && !uentry_isElipsisMarker (uentryList_getN
2528 (specparams, paramno)))
2529 {
2530 fileloc sloc = context_getSaveLocation ();
2531 uentry decl = uentryList_getN (specparams, paramno);
2532 sRef sr;
2533
2534 param = uentry_nameCopy (paramname, decl);
2535
2536 uentry_setParam (param);
2537 sr = sRef_makeParam (paramno, uentry_getType (param),
2538 stateInfo_makeLoc (sloc, SA_DECLARED));
2539
2540 if (sRef_getNullState (sr) == NS_ABSNULL)
2541 {
2542 ctype pt = ctype_realType (uentry_getType (param));
2543
2544 if (ctype_isUser (pt))
2545 {
2546 uentry te = usymtab_getTypeEntrySafe (ctype_typeId (pt));
2547
2548 if (uentry_isValid (te))
2549 {
2550 sRef_setStateFromUentry (sr, te);
2551 }
2552 }
2553 else
2554 {
2555 sRef_setNullState (sr, NS_UNKNOWN, sloc);
2556 }
2557 }
2558
2559 uentry_setSref (param, sr);
2560 uentry_setDeclaredForceOnly (param, sloc);
2561
2562 skipparam = isiter && uentry_isOut (uentryList_getN (specparams, paramno));
2563 }
2564 else
2565 {
2566 fileloc sloc = context_getSaveLocation ();
2567
2568 param = uentry_makeVariableSrefParam
2569 (paramname, ctype_unknown, fileloc_copy (sloc),
2570 sRef_makeParam (paramno, ctype_unknown,
2571 stateInfo_makeLoc (sloc, SA_DECLARED)));
2572 DPRINTF (("Unknown param: %s", uentry_unparseFull (param)));
2573 cstring_free (paramname);
2574
2575 sRef_setPosNull (uentry_getSref (param), sloc);
2576 uentry_setDeclaredForce (param, sloc);
2577
2578 skipparam = FALSE;
2579 fileloc_free (sloc);
2580 }
2581
2582 if (!skipparam)
2583 {
2584 llassert (!uentry_isElipsisMarker (param));
2585
2586 if (!suppress)
2587 {
2588 sRef_makeUnsafe (uentry_getSref (param));
2589 }
2590
2591 pn = uentryList_add (pn, uentry_copy (param));
2592 usymtab_supEntry (param);
2593 }
2594 else
2595 {
2596 /* don't add param */
2597 uentry_free (param);
2598 }
2599
2600 if (c == ',')
2601 {
2602 (void) macro_nextChar ();
2603 c = skip_whitespace ();
2604 }
2605
2606 paramno++;
2607 }
2608
2609 if (c == ')')
2610 {
2611 if (isspecfcn || isiter)
2612 {
2613 if (paramno != noparams && noparams >= 0)
2614 {
2615 cscannerHelp_advanceLine ();
2616
2617 voptgenerror
2618 (FLG_INCONDEFS,
2619 message ("Macro %s specified with %d args, defined with %d",
2620 fname, noparams, paramno),
2621 g_currentloc);
2622
2623 uentry_showWhereSpecified (e2);
2624 uentry_resetParams (e2, pn);
2625 }
2626 }
2627 else
2628 {
2629 uentry_resetParams (e2, pn);
2630 }
2631 }
2632 }
2633 else
2634 {
2635 /*
2636 ** the form should be:
2637 **
2638 ** # define newname oldname
2639 ** where oldname refers to a function matching the specification
2640 ** of newname.
2641 */
2642
2643 if (unknownm)
2644 {
2645 sRef_setGlobalScope ();
2646 usymtab_supGlobalEntry (uentry_makeVariableLoc (fname, ctype_unknown));
2647 sRef_clearGlobalScope ();
2648 }
2649 else
2650 {
2651 context_setMacroMissingParams ();
2652 }
2653 }
2654
2655
2656 /* context_setuentryList (pn); */
2657 usymtab_enterScope ();
2658
2659 fileloc_free (loc);
2660 cstring_free (fname);
2661
2662 return res;
2663}
2664
2665void cscannerHelp_setTokLength (int len)
2666{
2667 addColumn (len);
2668 s_tokLength = len;
2669 DPRINTF (("Set tok length: %d", len));
2670}
2671
2672void cscannerHelp_setTokLengthT (size_t len)
2673{
2674 cscannerHelp_setTokLength (size_toInt (len));
2675}
2676
2677void cscannerHelp_advanceLine (void)
2678{
2679 s_tokLength = 0;
2680 beginLine ();
2681}
2682
2683int cscannerHelp_returnToken (int t)
2684{
2685 yylval.tok = lltok_create (t, fileloc_decColumn (g_currentloc, s_tokLength));
2686 s_tokLength = 0;
2687 s_lastWasString = FALSE;
2688 return (t);
2689}
2690
2691int cscannerHelp_returnTokenLength (int t, int length)
2692{
2693 cscannerHelp_setTokLength (length);
2694 return cscannerHelp_returnToken (t);
2695}
2696
2697int cscannerHelp_returnString (cstring s)
2698{
2699 yylval.expr = exprNode_stringLiteral (s, fileloc_decColumn (g_currentloc, s_tokLength));
2700 s_tokLength = 0;
2701 s_lastWasString = TRUE;
2702 return (CCONSTANT);
2703}
2704
2705int cscannerHelp_returnInt (ctype ct, long val)
2706{
2707 ctype c = ct;
2708
2709 if (ctype_equal (ct, ctype_int))
2710 {
2711 if (val == 0)
2712 {
2713 c = context_typeofZero ();
2714 }
2715 else if (val == 1)
2716 {
2717 c = context_typeofOne ();
2718 }
2719 else
2720 {
2721 ;
2722 }
2723 }
2724
2725 yylval.expr = exprNode_numLiteral (c, cstring_fromChars (yytext),
2726 fileloc_decColumn (g_currentloc, s_tokLength),
2727 val);
2728 s_tokLength = 0;
2729 s_lastWasString = FALSE;
2730 return (CCONSTANT);
2731}
2732
2733int cscannerHelp_returnFloat (ctype ct, double f)
2734{
2735 yylval.expr = exprNode_floatLiteral (f, ct, cstring_fromChars (yytext),
2736 fileloc_decColumn (g_currentloc, s_tokLength));
2737 s_tokLength = 0;
2738 s_lastWasString = FALSE;
2739 return (CCONSTANT);
2740}
2741
2742int cscannerHelp_returnChar (char c)
2743{
2744 yylval.expr = exprNode_charLiteral (c, cstring_fromChars (yytext),
2745 fileloc_decColumn (g_currentloc, s_tokLength));
2746 s_tokLength = 0;
2747 s_lastWasString = FALSE;
2748 return (CCONSTANT);
2749}
2750
2751int cscannerHelp_returnType (int tok, ctype ct)
2752{
2753 yylval.ctyp = ct;
2754 s_tokLength = 0;
2755 s_lastWasString = FALSE;
2756 return tok;
2757}
2758
2759int cscannerHelp_returnExpr (exprNode e)
2760{
2761 yylval.expr = e;
2762 s_tokLength = 0;
2763 s_lastWasString = TRUE;
2764 return (CCONSTANT);
2765}
2766
2767void cscannerHelp_setExpectingTypeName ()
2768{
2769 s_expectingTypeName = TRUE;
2770}
2771
2772void cscannerHelp_clearExpectingTypeName ()
2773{
2774 s_expectingTypeName = FALSE;
2775}
2776
2777bool cscannerHelp_isExpectingTypeName ()
2778{
2779 return s_expectingTypeName;
2780}
2781
2782int cscannerHelp_processTextIdentifier (char *text)
2783{
2784 context_saveLocation ();
2785 cscannerHelp_setTokLength (size_toInt (mstring_length (text)));
2786 return cscannerHelp_processIdentifier (cscannerHelp_makeIdentifier (text));
2787}
2788
2789static bool s_continueLine = FALSE;
2790
2791int cscannerHelp_handleNewLine ()
2792{
2793 context_incLineno ();
2794
2795 if (s_tokLength != 0) {
2796 s_tokLength = 0;
2797 /* No error to report
2798 voptgenerror
2799 (FLG_SYNTAX,
2800 message ("Likely parse error: token spans multiple lines."),
2801 g_currentloc);
2802 */
2803 }
2804
2805 if (s_continueLine)
2806 {
2807 s_continueLine = FALSE;
2808 }
2809 else
2810 {
2811 if (context_inMacro ())
2812 {
2813 /* Don't use return cscannerHelp_returnToken */
2814 /* !!! evans 2002-03-13 */
2815 yylval.tok = lltok_create (TENDMACRO, fileloc_copy (g_currentloc));
2816 s_lastWasString = FALSE;
2817 return TENDMACRO;
2818 }
2819 }
2820
2821 return BADTOK;
2822}
2823
2824void cscannerHelp_setContinueLine ()
2825{
2826 s_continueLine = TRUE;
2827}
2828
2829void cscannerHelp_exitSpecPart ()
2830{
2831 llassert (s_inSpecPart);
2832 s_inSpecPart = FALSE;
2833 s_whichSpecPart = BADTOK;
2834}
This page took 0.462989 seconds and 5 git commands to generate.