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