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