2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 University of Virginia,
4 ** Massachusetts Institute of Technology
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.
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.
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.
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
25 ** cscannerHelp.c - procedures for scanning C
27 ** Most of this code was in cscanner.l, but moved here to separate it
28 ** from the flex-generated code.
31 # include "splintMacros.nf"
33 # include "cscannerHelp.h"
34 # include "cscanner.h"
35 # include "cgrammar_tokens.h"
38 static int lminput (void);
39 static int s_tokLength = 0;
41 static /*@owned@*/ cstring s_lastidprocessed = cstring_undefined;
42 static bool s_inSpecPart = FALSE;
43 static int s_whichSpecPart;
44 static char s_savechar = '\0';
45 static bool s_expectingMetaStateName = FALSE;
46 static bool s_lastWasString = FALSE;
47 static bool s_expectingTypeName = TRUE;
51 /*@null@*/ /*@observer@*/ char *name;
56 ** These tokens are followed by syntax that is parsed by the
60 static struct skeyword s_parsetable[] = {
61 { "modifies", QMODIFIES } ,
62 { "globals", QGLOBALS } ,
65 { "constant", QCONSTANT } ,
66 { "function", QFUNCTION } ,
68 { "defines", QDEFINES } ,
70 { "allocates", QALLOCATES } ,
72 { "releases", QRELEASES } ,
73 { "pre", QPRECLAUSE } ,
74 { "post", QPOSTCLAUSE } ,
75 { "setBufferSize", QSETBUFFERSIZE},
76 { "setStringLength", QSETSTRINGLENGTH},
77 { "testinRange", QTESTINRANGE},
78 { "requires", QPRECLAUSE } ,
79 { "ensures", QPOSTCLAUSE } ,
80 { "invariant", QINVARIANT} ,
85 ** These tokens are either stand-alone tokens, or followed by
86 ** token-specific text.
89 static struct skeyword s_keytable[] = {
90 { "anytype", QANYTYPE } ,
91 { "integraltype", QINTEGRALTYPE } ,
92 { "unsignedintegraltype", QUNSIGNEDINTEGRALTYPE } ,
93 { "signedintegraltype", QSIGNEDINTEGRALTYPE } ,
98 { "dependent", QDEPENDENT } ,
99 { "partial", QPARTIAL } ,
100 { "special", QSPECIAL } ,
101 { "truenull", QTRUENULL } ,
102 { "falsenull", QFALSENULL } ,
103 { "nullwhentrue", QTRUENULL } ,
104 { "falsewhennull", QFALSENULL } ,
107 { "notnull", QNOTNULL } ,
108 { "abstract", QABSTRACT } ,
109 { "numabstract", QNUMABSTRACT } ,
110 { "concrete", QCONCRETE } ,
111 { "mutable", QMUTABLE } ,
112 { "immutable", QIMMUTABLE } ,
113 { "unused", QUNUSED } ,
114 { "external", QEXTERNAL } ,
116 { "unique", QUNIQUE } ,
117 { "returned", QRETURNED } ,
118 { "exposed", QEXPOSED } ,
119 { "refcounted", QREFCOUNTED } ,
121 { "newref", QNEWREF } ,
122 { "tempref", QTEMPREF } ,
123 { "killref", QKILLREF } ,
125 { "relnull", QRELNULL } ,
126 { "nullterminated", QNULLTERMINATED },
127 { "setBufferSize", QSETBUFFERSIZE },
128 { "testInRange", QTESTINRANGE},
129 { "isnull", QISNULL },
130 { "MaxSet", QMAXSET},
131 { "MaxRead", QMAXREAD},
132 { "maxSet", QMAXSET},
133 { "maxRead", QMAXREAD},
134 { "reldef", QRELDEF } ,
135 { "observer", QOBSERVER } ,
136 { "exits", QEXITS } ,
137 { "noreturn", QEXITS } ,
138 { "mayexit", QMAYEXIT } ,
139 { "maynotreturn", QMAYEXIT } ,
140 { "trueexit", QTRUEEXIT } ,
141 { "falseexit", QFALSEEXIT } ,
142 { "noreturnwhentrue", QTRUEEXIT } ,
143 { "noreturnwhenfalse", QFALSEEXIT } ,
144 { "neverexit", QNEVEREXIT } ,
145 { "alwaysreturns", QNEVEREXIT } ,
147 { "shared", QSHARED } ,
149 { "unchecked", QUNCHECKED } ,
150 { "checked", QCHECKED } ,
151 { "checkmod", QCHECKMOD } ,
152 { "checkedstrict", QCHECKEDSTRICT } ,
153 { "innercontinue", QINNERCONTINUE } ,
154 { "innerbreak", QINNERBREAK } ,
155 { "loopbreak", QLOOPBREAK } ,
156 { "switchbreak", QSWITCHBREAK } ,
157 { "safebreak", QSAFEBREAK } ,
158 { "fallthrough", QFALLTHROUGH } ,
159 { "l_fallthrou", QLINTFALLTHROUGH } ,
160 { "l_fallth", QLINTFALLTHRU } ,
161 { "notreached", QNOTREACHED } ,
162 { "l_notreach", QLINTNOTREACHED } ,
163 { "printflike", QPRINTFLIKE } ,
164 { "l_printfli", QLINTPRINTFLIKE } ,
165 { "scanflike", QSCANFLIKE } ,
166 { "messagelike", QMESSAGELIKE } ,
167 { "l_argsus", QARGSUSED } ,
172 ** would be better if these weren't hard coded...
175 static bool isArtificial (cstring s)
177 return (cstring_equalLit (s, "modifies")
178 || cstring_equalLit (s, "globals")
179 || cstring_equalLit (s, "warn")
180 || cstring_equalLit (s, "alt"));
183 void cscannerHelp_swallowMacro (void)
186 bool skipnext = FALSE;
188 while ((i = lminput ()) != EOF)
204 reader_checkUngetc (i, yyin);
216 reader_checkUngetc (i, yyin);
220 static int commentMarkerToken (cstring s)
224 while (s_parsetable[i].name != NULL)
226 DPRINTF (("Try :%s:%s:", s, s_parsetable[i].name));
228 if (cstring_equalLit (s, s_parsetable[i].name))
230 return s_parsetable[i].token;
239 static int tokenMacroCode (cstring s)
243 while (s_keytable[i].name != NULL)
245 if (cstring_equalLit (s, s_keytable[i].name))
247 if (s_keytable[i].token == QLINTFALLTHROUGH)
250 (FLG_WARNLINTCOMMENTS,
252 ("Traditional lint comment /*FALLTHROUGH*/ used. "
253 "Splint interprets this in the same way as most Unix lints, but it is "
254 "preferable to replace it with the /*@fallthrough@*/ "
259 else if (s_keytable[i].token == QLINTFALLTHRU)
262 (FLG_WARNLINTCOMMENTS,
264 ("Traditional lint comment /*FALLTHRU*/ used. "
265 "Splint interprets this in the same way as most Unix lints, but it is "
266 "preferable to replace it with the /*@fallthrough@*/ "
271 else if (s_keytable[i].token == QLINTNOTREACHED)
274 (FLG_WARNLINTCOMMENTS,
276 ("Traditional lint comment /*NOTREACHED*/ used. "
277 "Splint interprets this in the same way as most Unix lints, but it is "
278 "preferable to replace it with the /*@notreached@*/ "
279 "semantic comment."),
284 else if (s_keytable[i].token == QPRINTFLIKE)
286 setSpecialFunction (qual_createPrintfLike ());
289 else if (s_keytable[i].token == QLINTPRINTFLIKE)
292 (FLG_WARNLINTCOMMENTS,
294 ("Traditional lint comment /*PRINTFLIKE*/ used. "
295 "Splint interprets this in the same way as most Unix lints, but it is "
296 "preferable to replace it with either /*@printflike@*/, "
297 "/*@scanflike@*/ or /*@messagelike@*/."),
300 setSpecialFunction (qual_createPrintfLike ());
303 else if (s_keytable[i].token == QSCANFLIKE)
305 setSpecialFunction (qual_createScanfLike ());
308 else if (s_keytable[i].token == QMESSAGELIKE)
310 setSpecialFunction (qual_createMessageLike ());
313 else if (s_keytable[i].token == QARGSUSED)
316 (FLG_WARNLINTCOMMENTS,
318 ("Traditional lint comment /*ARGSUSED*/ used. "
319 "Splint interprets this in the same way as most Unix lints, but it is "
320 "preferable to use /*@unused@*/ annotations on "
321 "the unused parameters."),
329 return s_keytable[i].token;
339 static int lminput ()
341 if (s_savechar == '\0')
344 return (cscanner_input ());
348 int save = (int) s_savechar;
354 static void lmsavechar (char c)
356 if (s_savechar == '\0')
362 llbuglit ("lmsavechar: override");
366 int cscannerHelp_ninput ()
370 if (c != EOF && ((char)c == '\n'))
372 context_incLineno ();
378 static char macro_nextChar (void)
380 static bool in_quote = FALSE, in_escape = FALSE, in_char = FALSE;
385 c = char_fromInt (ic);
387 if (!in_quote && !in_char && (c == '\\' || c == BEFORE_COMMENT_MARKER[0]))
391 while ((c = char_fromInt (lminput ())) != '\0' && c != '\n')
393 ; /* skip to newline */
396 context_incLineno ();
400 return macro_nextChar ();
407 else /* if (c == '@') */
411 if (cscannerHelp_handleLlSpecial () != BADTOK)
413 llerrorlit (FLG_SYNTAX, "Macro cannot use special syntax");
416 return macro_nextChar ();
419 else if (!in_escape && c == '\"')
421 in_quote = !in_quote;
423 else if (!in_escape && c == '\'')
427 else if ((in_quote || in_char) && c == '\\')
429 in_escape = !in_escape;
431 else if ((in_quote || in_char) && in_escape)
435 else if (!in_quote && c == '/')
439 if ((c2 = char_fromInt (lminput ())) == '*')
443 while ((c2 = char_fromInt (lminput ())) != '\0'
444 && c2 != '\n' && c2 != '*')
451 while ((c2 = char_fromInt (lminput ())) != '\0'
464 llfatalerror (cstring_makeLiteral ("Macro: bad comment!"));
468 return macro_nextChar ();
472 /*** putchar does not work! why? puts to stdio...??! ***/
485 ** keeps semantic comments
488 static char macro_nextCharC (void)
490 static bool in_quote = FALSE, in_escape = FALSE, in_char = FALSE;
493 c = char_fromInt (lminput ());
495 if (!in_quote && !in_char && c == '\\')
497 while ((c = char_fromInt (lminput ())) != '\0' && c != '\n')
499 ; /* skip to newline */
502 context_incLineno ();
506 return macro_nextCharC ();
513 else if (!in_escape && c == '\"')
515 in_quote = !in_quote;
517 else if (!in_escape && c == '\'')
521 else if ((in_quote || in_char) && c == '\\')
523 in_escape = !in_escape;
525 else if ((in_quote || in_char) && in_escape)
529 else if (!in_quote && c == '/')
533 if ((c2 = char_fromInt (lminput ())) == '*')
537 while ((c2 = char_fromInt (lminput ())) != '\0'
538 && c2 != '\n' && c2 != '*')
545 while ((c2 = char_fromInt (lminput ())) != '\0'
558 llfatalerror (cstring_makeLiteral ("Macro: bad comment!"));
562 return macro_nextCharC ();
569 else /* normal character */
578 ** skips whitespace (handles line continuations)
579 ** returns first non-whitespace character
582 static char skip_whitespace (void)
586 while ((c = macro_nextChar ()) == ' ' || c == '\t')
594 void cscannerHelp_handleMacro ()
596 cstring mac = cstring_undefined;
600 while (currentColumn () > 2)
602 mac = cstring_appendChar (mac, ' ');
603 cscannerHelp_setTokLength (-1);
606 c = macro_nextCharC ();
608 if (c >= '0' && c <= '9')
612 for (i = 0; i < (((int) (c - '0')) + 1); i++)
614 mac = cstring_appendChar (mac, ' ');
622 while (((c = macro_nextCharC ()) != '\0') && (c != '\n'))
624 mac = cstring_appendChar (mac, c);
628 macrocode = tokenMacroCode (mac);
630 if (macrocode == BADTOK && !isArtificial (mac))
632 context_addMacroCache (mac);
641 context_incLineno ();
645 bool cscannerHelp_handleSpecial (char *yyt)
647 char *l; /* !! = mstring_create (MAX_NAME_LENGTH); */
654 len_yyt = strlen (yyt +1) ;
656 l = mstring_copy (yyt + 1);
658 while ((c = char_fromInt (lminput ())) != '\n' && c != '\0')
660 l = mstring_append(l, c);
663 /* Need to safe original l for deallocating. */
668 olc = cstring_fromChars (ol);
670 if (cstring_equalPrefixLit (olc, "pragma"))
672 char *pname = mstring_create (size_fromInt (MAX_PRAGMA_LEN));
673 char *opname = pname;
674 char *ptr = ol + 6; /* pragma is six characters, plus space */
678 /* skip whitespace */
679 while (((c = *ptr) != '\0') && isspace (c))
685 while (((c = *ptr) != '\0') && !isspace (c))
689 if (len > MAX_PRAGMA_LEN)
700 if (len == PRAGMA_LEN_EXPAND
701 && mstring_equal (opname, PRAGMA_EXPAND))
703 cstring exname = cstring_undefined;
707 while (((c = *ptr) != '\0') && !isspace (c))
709 exname = cstring_appendChar (exname, c);
714 ue = usymtab_lookupExposeGlob (exname);
716 if (uentry_isExpandedMacro (ue))
718 if (fileloc_isPreproc (uentry_whereDefined (ue)))
720 fileloc_setColumn (g_currentloc, 1);
721 uentry_setDefined (ue, g_currentloc);
725 cstring_free (exname);
728 else if (cstring_equalPrefixLit (olc, "ident"))
730 /* Some pre-processors will leave these in the code. Ignore rest of line */
733 ** Yuk...Win32 filenames can have spaces in them...we need to read
734 ** to the matching end quote.
736 else if ((sscanf (ol, "line %d \"", &lineno) == 1)
737 || (sscanf (ol, " %d \"", &lineno) == 1))
744 while (*tmp != '\"' && *tmp != '\0')
749 llassert (*tmp == '\"');
755 while (*tmp != '\"' && *tmp != '\0')
760 llassert (*tmp == '\"');
764 # if defined(OS2) || defined(MSDOS) || defined(WIN32)
767 ** DOS-like path delimiters get delivered in pairs, something like
768 ** \"..\\\\file.h\", so we have to make it normal again. We do NOT
769 ** remove the pre dirs yet as we usually specify tmp paths relative
770 ** to the current directory, so tmp files would not get found in
771 ** the hash table. If this method fails we try it again later.
778 ** Skip past the drive marker.
781 if (strchr (stmp, ':') != NULL)
783 stmp = strchr (stmp, ':') + 1;
786 while ((stmp = strchr (stmp, CONNECTCHAR)) != NULL )
788 if (*(stmp+1) == CONNECTCHAR)
790 memmove (stmp, stmp+1, strlen (stmp));
796 fid = fileTable_lookupBase (context_fileTable (), fname);
797 if (!(fileId_isValid (fid)))
799 fname = removePreDirs (fname);
800 fid = fileTable_lookupBase (context_fileTable (), fname);
803 # else /* !defined(OS2) && !defined(MSDOS) */
804 fname = removePreDirs (fname);
805 fid = fileTable_lookupBase (context_fileTable (), fname);
806 # endif /* !defined(OS2) && !defined(MSDOS) */
808 if (!(fileId_isValid (fid)))
810 if (context_inXHFile ())
812 fid = fileTable_addXHFile (context_fileTable (), fname);
814 else if (isHeaderFile (fname))
816 fid = fileTable_addHeaderFile (context_fileTable (), fname);
820 fid = fileTable_addFile (context_fileTable (), fname);
824 setFileLine (fid, lineno);
825 /*@noaccess cstring@*/
827 else if ((sscanf (ol, "line %d", &lineno) == 1)
828 || (sscanf (ol, " %d", &lineno) == 1))
830 setLine (lineno); /* next line is <cr> */
834 if (mstring_equal (ol, "")) {
835 DPRINTF (("Empty pp command!"));
837 ** evs 2000-05-16: This is a horrible kludge, to get around a bug (well, difficulty) in the pre-processor.
838 ** We handle a plain # in the input file, by echoing it, and ignoring it in the post-pp-file.
844 (FLG_UNRECOGDIRECTIVE,
845 message ("Unrecognized pre-processor directive: #%s",
846 cstring_fromChars (ol)),
851 return FALSE; /* evans 2001-12-30: was: TRUE; */
858 int cscannerHelp_handleLlSpecial (void)
863 char *s = mstring_createEmpty ();
869 loc = fileloc_copy (g_currentloc);
870 DPRINTF (("Handle special: %s", fileloc_unparse (loc)));
872 while (((ic = cscannerHelp_ninput ()) != 0) && isalpha (ic))
875 s = mstring_append (s, c);
879 DPRINTF (("Read: %s / %s", s, fileloc_unparse (g_currentloc)));
882 if (charsread == 0 && ic == (int) AFTER_COMMENT_MARKER[0])
884 ic = cscannerHelp_ninput ();
886 llassert (ic == (int) AFTER_COMMENT_MARKER[1]);
892 return QNOMODS; /* special token no modifications token */
896 DPRINTF (("Coment marker: %s", os));
897 tok = commentMarkerToken (cstring_fromChars (os));
901 s_tokLength = charsread;
904 s_whichSpecPart = tok;
909 DPRINTF (("Not a comment marker..."));
910 /* Add rest of the comment */
912 if (ic != 0 && ic != EOF)
916 s = mstring_append (s, c);
919 while (((ic = cscannerHelp_ninput ()) != 0) && (ic != EOF)
920 && (ic != (int) AFTER_COMMENT_MARKER[0]))
924 /* evans 2001-09-01 added to prevent assertion failures for uncloses syntactic comments */
927 hasnl = TRUE; /* This prevents tokLength from being set later. */
932 message ("Likely parse error: syntactic comment token spans multiple lines: %s",
933 cstring_fromChars (s)),
937 s = mstring_append (s, c);
941 } /* spurious (?) warnings about s */
944 DPRINTF (("Read: %s / %s", s, fileloc_unparse (g_currentloc)));
946 if (ic == (int) AFTER_COMMENT_MARKER[0])
948 int nc = cscannerHelp_ninput ();
949 llassert ((char) nc == AFTER_COMMENT_MARKER[1]);
955 while (*s == ' ' || *s == '\t' || *s == '\n')
960 if (*s == '-' || *s == '+' || *s == '=') /* setting flags */
964 while (c == '-' || c == '+' || c == '=')
966 ynm set = ynm_fromCodeChar (c);
971 thisflag = cstring_fromChars (s);
973 while ((c = *s) != '\0' && (c != '-') && (c != '=')
974 && (c != '+') && (c != ' ') && (c != '\t') && (c != '\n'))
981 if (!context_getFlag (FLG_NOCOMMENTS))
983 cstring flagname = thisflag;
984 flagcode fflag = flags_identifyFlag (flagname);
986 if (flagcode_isSkip (fflag))
990 else if (flagcode_isModeName (fflag))
992 if (ynm_isMaybe (set))
997 ("Semantic comment attempts to restore flag %s. "
998 "A mode flag cannot be restored.",
1003 context_setMode (flagname);
1006 else if (flagcode_isInvalid (fflag))
1009 (FLG_UNRECOGFLAGCOMMENTS,
1010 message ("Unrecognized option in semantic comment: %s",
1014 else if (flagcode_isGlobalFlag (fflag))
1019 ("Semantic comment attempts to set global flag %s. "
1020 "A global flag cannot be set locally.",
1026 context_fileSetFlag (fflag, set, loc);
1028 if (flagcode_hasArgument (fflag))
1030 if (ynm_isMaybe (set))
1035 ("Semantic comment attempts to restore flag %s. "
1036 "A flag for setting a value cannot be restored.",
1041 { /* cut-and-pastied from llmain...blecch */
1042 cstring extra = cstring_undefined;
1048 rest = mstring_copy (s);
1052 while ((rchar = *rest) != '\0'
1053 && (isspace (rchar)))
1059 while ((rchar = *rest) != '\0'
1060 && !isspace (rchar))
1062 extra = cstring_appendChar (extra, rchar);
1066 s--; /* evans 2002-07-12: this was previously only in the else branch.
1067 Leads to an invalid read on the true branch.
1072 if (cstring_isUndefined (extra))
1077 ("Flag %s (in semantic comment) must be followed by an argument",
1078 flagcode_unparse (fflag)));
1080 cstring_free (extra);
1084 if (flagcode_hasNumber (fflag))
1086 flags_setValueFlag (fflag, extra);
1088 else if (flagcode_hasChar (fflag))
1090 flags_setValueFlag (fflag, extra);
1092 else if (flagcode_hasString (fflag))
1094 flags_setStringFlag (fflag, extra);
1098 cstring_free (extra);
1112 while ((c == ' ') || (c == '\t') || (c == '\n'))
1118 if (context_inHeader () && !isArtificial (cstring_fromChars (os)))
1120 DPRINTF (("Here adding comment: %s", os));
1121 context_addComment (cstring_fromCharsNew (os), loc);
1133 annotationInfo ainfo;
1135 while (*s != '\0' && *s != ' ' && *s != '\t' && *s != '\n')
1147 t = cstring_toCharsSafe (cstring_downcase (cstring_fromChars (t)));
1148 macrocode = tokenMacroCode (cstring_fromChars (t));
1150 if (macrocode != BADTOK)
1152 s_tokLength = hasnl ? 0 : size_toInt (mstring_length (t));
1158 if (macrocode == SKIPTOK)
1166 ainfo = context_lookupAnnotation (cstring_fromChars (os));
1168 if (annotationInfo_isDefined (ainfo)) {
1169 DPRINTF (("Found annotation: %s", annotationInfo_unparse (ainfo)));
1170 yylval.annotation = ainfo;
1178 if (context_inHeader ())
1185 if ((context_inMacro () || context_inGlobalContext ())
1186 && macrocode != SKIPTOK
1187 && !isArtificial (cstring_fromChars (os)))
1189 if (context_processingMacros ())
1191 /* evans 2002-02-24: don't add comments when procssing macros */
1195 context_addComment (cstring_fromCharsNew (os), loc);
1209 if (mstring_equal (t, "ignore"))
1211 if (!context_getFlag (FLG_NOCOMMENTS))
1213 context_enterSuppressRegion (loc);
1216 else if ((*t == 'i' || *t == 't')
1217 && (*(t + 1) == '\0'))
1219 if (!context_getFlag (FLG_NOCOMMENTS)
1220 && (*t == 'i' || context_getFlag (FLG_TMPCOMMENTS)))
1222 context_enterSuppressLine (-1, loc); /* infinite suppression */
1225 else if (((*t == 'i') || (*t == 't'))
1226 && ((*(t + 1) >= '0' && *(t + 1) <= '9')))
1228 bool tmpcomment = (*t == 't');
1230 char *tt = t; /* don't mangle t, since it is free'd */
1233 if (lc >= '0' && lc <= '9')
1235 val = (int)(lc - '0');
1238 while (lc >= '0' && lc <= '9')
1241 val += (int) (lc - '0');
1246 if (!context_getFlag (FLG_NOCOMMENTS)
1247 && (!tmpcomment || context_getFlag (FLG_TMPCOMMENTS)))
1249 DPRINTF (("Here: enter suppress: %s", fileloc_unparse (loc)));
1250 context_enterSuppressLine (val, loc);
1253 else if (mstring_equal (t, "end"))
1255 if (!context_getFlag (FLG_NOCOMMENTS))
1257 context_exitSuppressRegion (loc);
1260 else if (mstring_equal (t, "notfunction"))
1262 ; /* handled by pcpp */
1264 else if (mstring_equal (t, "access"))
1270 while (((c = *s) != '\0') && (c == ' ' || c == '\t' || c == '\n'))
1280 tname = cstring_fromChars (s);
1282 while ((c = *s) != '\0' && c != ' '
1283 && c != '\t' && c != '\n' && c != ',')
1290 DPRINTF (("Access %s", tname));
1292 if (!context_getFlag (FLG_NOCOMMENTS)
1293 && !context_getFlag (FLG_NOACCESS))
1295 if (usymtab_existsType (tname))
1297 typeId uid = usymtab_getTypeId (tname);
1298 uentry ue = usymtab_getTypeEntry (uid);
1300 if (uentry_isAbstractDatatype (ue))
1302 context_addFileAccessType (uid);
1303 DPRINTF (("Adding access to: %s / %d", tname, uid));
1310 ("Non-abstract type %s used in access comment",
1317 if (!(context_inSuppressRegion ()
1318 || context_inSuppressZone (loc)))
1323 ("Unrecognized type %s used in access comment",
1335 if (c != ',' && c != ' ')
1341 else if (mstring_equal (t, "noaccess"))
1348 while (((lc = *s) != '\0') && (lc == ' ' || lc == '\t' || lc == '\n'))
1358 tname = cstring_fromChars (s);
1360 while ((lc = *s) != '\0' && lc != ' ' && lc != '\t'
1361 && lc != '\n' && lc != ',')
1368 if (!context_getFlag (FLG_NOCOMMENTS)
1369 && !context_getFlag (FLG_NOACCESS))
1371 if (usymtab_existsType (tname))
1373 typeId tuid = usymtab_getTypeId (tname);
1375 if (context_couldHaveAccess (tuid))
1377 DPRINTF (("Removing access: %s", tname));
1378 context_removeFileAccessType (tuid);
1382 if (!(context_inSuppressRegion ()
1383 || context_inSuppressZone (loc)))
1385 uentry ue = usymtab_getTypeEntry (tuid);
1387 if (uentry_isAbstractDatatype (ue))
1392 ("Non-accessible abstract type %s used in noaccess comment",
1401 ("Non-abstract type %s used in noaccess comment",
1410 if (!(context_inSuppressRegion ()
1411 || context_inSuppressZone (loc)))
1416 ("Unrecognized type %s used in noaccess comment",
1428 if (lc != ',' && lc != ' ')
1436 voptgenerror (FLG_UNRECOGCOMMENTS,
1437 message ("Semantic comment unrecognized: %s",
1438 cstring_fromChars (os)),
1441 } /* spurious (?) warning about t */
1452 /*@only@*/ cstring cscannerHelp_makeIdentifier (char *s)
1454 char *c = mstring_create (strlen (s) + 1);
1455 cstring id = cstring_fromChars (c);
1457 while (isalnum (*s) || (*s == '_') || (*s == '$'))
1466 /*@observer@*/ /*@dependent@*/ uentry cscannerHelp_coerceId (cstring cn)
1468 if (!(usymtab_exists (cn)))
1470 fileloc loc = fileloc_createExternal ();
1473 ** We need to put this in a global scope, otherwise the sRef will be deallocated.
1476 uentry ce = uentry_makeUnrecognized (cn, loc);
1478 if (!context_inIterEnd ())
1482 message ("Unrecognized (possibly system) identifier: %q",
1483 uentry_getName (ce)),
1490 return (usymtab_lookup (cn));
1494 ** like, cscannerHelp_coerceId, but doesn't supercede for iters
1497 /*@observer@*/ uentry cscannerHelp_coerceIterId (cstring cn)
1499 if (!(usymtab_exists (cn)))
1501 return uentry_undefined;
1504 return (usymtab_lookup (cn));
1508 ** Need to keep this in case there is a declaration that isn't processed until
1509 ** the scope exits. Would be good to rearrange the symbol table so this doesn't
1510 ** happen, and save all the cstring copying.
1513 /*@observer@*/ cstring cscannerHelp_observeLastIdentifier ()
1515 cstring res = s_lastidprocessed;
1519 static void cscanner_setLastIdentifier (/*@keep@*/ cstring id) /*@modifies s_lastidprocessed@*/
1521 if (cstring_isDefined (s_lastidprocessed))
1523 cstring_free (s_lastidprocessed);
1526 s_lastidprocessed = id;
1529 int cscannerHelp_processIdentifier (cstring id)
1533 if (context_getFlag (FLG_GRAMMAR))
1535 lldiagmsg (message ("Process identifier: %s", id));
1538 context_clearJustPopped ();
1539 cscanner_setLastIdentifier (id);
1541 DPRINTF (("Context: %s", context_unparse ()));
1543 if (context_inFunctionHeader ())
1545 int tok = commentMarkerToken (id);
1546 DPRINTF (("in function decl: %s", id));
1554 tok = tokenMacroCode (id);
1562 annotationInfo ainfo;
1564 if (s_expectingMetaStateName)
1566 metaStateInfo msinfo = context_lookupMetaStateInfo (id);
1568 if (metaStateInfo_isDefined (msinfo))
1570 yylval.msinfo = msinfo;
1571 return METASTATE_NAME;
1575 DPRINTF (("Not meta state name: %s", cstring_toCharsSafe (id)));
1579 ainfo = context_lookupAnnotation (id);
1581 if (annotationInfo_isDefined (ainfo))
1583 DPRINTF (("Found annotation: %s", annotationInfo_unparse (ainfo)));
1584 yylval.annotation = ainfo;
1589 DPRINTF (("Not annotation: %s", id));
1595 DPRINTF (("Here!"));
1597 /* Consider handling: Defined by C99 as static const char __func__[] */
1599 if (context_getFlag (FLG_GNUEXTENSIONS))
1603 if (cstring_equalLit (id, "__stdcall")
1604 || cstring_equalLit (id, "__cdecl")
1605 || cstring_equalLit (id, "__extension__"))
1609 else if (cstring_equalLit (id, "__volatile__"))
1613 else if (cstring_equalLit (id, "__signed"))
1617 else if (cstring_equalLit (id, "__unsigned"))
1621 else if (cstring_equalLit (id, "__const__"))
1625 else if (cstring_equalLit (id, "__alignof__"))
1627 tok = CALIGNOF; /* alignof is parsed like sizeof */
1629 else if (cstring_equalLit (id, "__typeof__"))
1633 else if (cstring_equalLit (id, "typeof"))
1637 else if (cstring_equalLit (id, "__FUNCTION__")
1638 || cstring_equalLit (id, "__PRETTY_FUNCTION__"))
1640 /* These tokens hold the name of the current function as strings */
1641 /* evans 2001-12-30: changed from exprNode_stringLiteral; bug reported by Jim Zelenka. */
1642 yylval.expr = exprNode_makeConstantString (id, fileloc_copy (g_currentloc));
1644 s_lastWasString = TRUE;
1648 else if (cstring_equalLit (id, "__attribute__")
1649 || cstring_equalLit (id, "__asm__")
1650 || cstring_equalLit (id, "_asm")
1651 || cstring_equalLit (id, "__asm")
1652 || cstring_equalLit (id, "__declspec"))
1655 bool useparens = FALSE;
1656 bool usebraces = FALSE;
1657 bool inquote = FALSE;
1658 bool inescape = FALSE;
1661 while ((ic = cscanner_input ()) != EOF)
1663 char cc = (char) ic;
1669 else if (cc == '\\')
1673 else if (cc == '\"')
1709 else if (cc == ')' && useparens)
1712 if (depth == 0) break;
1714 else if (cc == '}' && usebraces)
1717 if (depth == 0) break;
1720 && !usebraces && !useparens
1721 && cstring_equalLit (id, "__asm"))
1724 ** We need this because some MS VC++ include files
1725 ** have __asm mov ... }
1726 ** Its a kludge, but otherwise would need to parse
1743 context_incLineno ();
1745 if (cstring_equalLit (id, "__asm")
1746 && !useparens && !usebraces)
1753 llassert ((useparens && ic == (int) ')')
1754 || (usebraces && ic == (int) '}')
1755 || (!useparens && !usebraces));
1759 else if (cstring_equalLit (id, "inline")
1760 || cstring_equalLit (id, "__inline")
1761 || cstring_equalLit (id, "_inline")
1762 || cstring_equalLit (id, "__inline__"))
1773 return (cscannerHelp_returnToken (tok));
1777 le = usymtab_lookupSafe (id);
1779 /*@-dependenttrans@*/
1781 if (uentry_isIter (le))
1786 else if (uentry_isEndIter (le))
1789 return (ITER_ENDNAME);
1791 else if (uentry_isUndefined (le))
1793 yylval.cname = cstring_copy (id);
1795 /* avoid parse errors for certain system built ins */
1797 if (s_expectingTypeName && (cstring_firstChar (id) == '_')
1798 && (cstring_secondChar (id) == '_'))
1800 return (TYPE_NAME_OR_ID);
1803 return (NEW_IDENTIFIER);
1805 else if (!uentry_isDeclared (le) && !uentry_isCodeDefined (le))
1807 if (uentry_isDatatype (le))
1809 yylval.cname = cstring_copy (id);
1810 return (NEW_IDENTIFIER);
1815 return (IDENTIFIER);
1818 else if (uentry_isDatatype (le))
1820 if (!s_expectingTypeName)
1822 yylval.cname = cstring_copy (id);
1824 return (NEW_IDENTIFIER);
1828 yylval.ctyp = uentry_getAbstractType (le);
1830 uentry_setUsed (le, g_currentloc);
1837 return (IDENTIFIER);
1840 /*@=dependenttrans@*/
1843 bool cscannerHelp_processHashIdentifier (/*@only@*/ cstring id)
1845 if (context_inMacro () || context_inIterDef () ||
1846 context_inIterEnd ())
1850 context_clearJustPopped ();
1852 le = usymtab_lookupSafe (id);
1853 cscanner_setLastIdentifier (id);
1855 if (uentry_isParam (le) || uentry_isRefParam (le))
1867 ** Will be handled by handleLlSpecial
1875 /*@only@*/ exprNode cscannerHelp_processString (void)
1879 char *nl = strchr (yytext, '\n');
1880 cstring ns = cstring_fromCharsNew (yytext);
1884 loc = fileloc_copy (g_currentloc);
1885 addColumn (size_toInt (cstring_length (ns)));
1891 loc = fileloc_copy (g_currentloc);
1893 context_incLineno ();
1895 while ((nl = strchr ((nl + 1), '\n')) != NULL)
1897 context_incLineno ();
1903 res = exprNode_stringLiteral (ns, loc);
1908 ** process a wide character string L"...."
1911 /*@only@*/ exprNode cscannerHelp_processWideString ()
1915 char *nl = strchr (yytext, '\n');
1918 llassert (*yytext == 'L');
1921 ns = cstring_fromCharsNew (yytext);
1925 loc = fileloc_copy (g_currentloc);
1926 addColumn (size_toInt (cstring_length (ns)));
1932 loc = fileloc_copy (g_currentloc);
1934 context_incLineno ();
1936 while ((nl = strchr ((nl + 1), '\n')) != NULL)
1938 context_incLineno ();
1943 res = exprNode_wideStringLiteral (ns, loc);
1947 char cscannerHelp_processChar ()
1952 llassert (*yytext != '\0');
1953 fchar = *(yytext + 1);
1954 if (fchar != '\\') return fchar;
1956 next = *(yytext + 2);
1960 case 'n': return '\n';
1961 case 't': return '\t';
1962 case '\"': return '\"';
1963 case '\'': return '\'';
1964 case '\\': return '\\';
1965 default: return '\0';
1969 double cscannerHelp_processFloat ()
1971 double ret = atof (yytext);
1976 long cscannerHelp_processHex ()
1981 llassert (yytext[0] == '0'
1982 && (yytext[1] == 'X' || yytext[1] == 'x'));
1984 while (yytext[index] != '\0') {
1986 char c = yytext[index];
1988 if (c >= '0' && c <= '9') {
1989 tval = (int) c - (int) '0';
1990 } else if (c >= 'A' && c <= 'F') {
1991 tval = (int) c - (int) 'A' + 10;
1992 } else if (c >= 'a' && c <= 'f') {
1993 tval = (int) c - (int) 'a' + 10;
1994 } else if (c == 'U' || c == 'L' || c == 'u' || c == 'l') {
1996 while (yytext[index] != '\0') {
1997 if (c == 'U' || c == 'L' || c == 'u' || c == 'l') {
2002 message ("Invalid character (%c) following specifier in hex constant: %s",
2003 c, cstring_fromChars (yytext)),
2013 message ("Invalid character (%c) in hex constant: %s",
2014 c, cstring_fromChars (yytext)),
2019 val = (val * 16) + tval;
2023 DPRINTF (("Hex constant: %s = %ld", yytext, val));
2027 long cscannerHelp_processOctal ()
2032 llassert (yytext[0] == '0' && yytext[1] != 'X' && yytext[1] != 'x');
2034 while (yytext[index] != '\0') {
2036 char c = yytext[index];
2038 if (c >= '0' && c <= '7') {
2039 tval = (int) c - (int) '0';
2040 } else if (c == 'U' || c == 'L' || c == 'u' || c == 'l') {
2042 while (yytext[index] != '\0') {
2043 if (c == 'U' || c == 'L' || c == 'u' || c == 'l') {
2048 message ("Invalid character (%c) following specifier in octal constant: %s",
2049 c, cstring_fromChars (yytext)),
2059 message ("Invalid character (%c) in octal constant: %s",
2060 c, cstring_fromChars (yytext)),
2065 val = (val * 8) + tval;
2069 DPRINTF (("Octal constant: %s = %ld", yytext, val));
2073 long cscannerHelp_processDec ()
2075 return (atol (yytext));
2078 int cscannerHelp_processSpec (int tok)
2080 size_t length = strlen (yytext);
2086 patched to fix assert failures in constraint code.
2087 Added the else if test so that splint does not treat MaxSet and MaxRead
2090 if (s_whichSpecPart == QMODIFIES
2091 || s_whichSpecPart == QDEFINES
2092 || s_whichSpecPart == QUSES
2093 || s_whichSpecPart == QALLOCATES
2094 || s_whichSpecPart == QSETS
2095 || s_whichSpecPart == QRELEASES)
2098 DPRINTF((message("Treating specifaction keyword %s as an identifiers. (This corresponds to"
2099 " token %d and we're in the specification denoted by %d see cgrammar_tokens.h"
2100 " for an explanation of these numbers",
2101 yytext, tok, s_whichSpecPart)
2104 ; /* Allow specificiation keywords to be used as identifiers in these contexts. */
2106 else if ( (s_whichSpecPart == QPRECLAUSE
2107 || s_whichSpecPart == QPOSTCLAUSE
2108 || s_whichSpecPart == QINVARIANT )
2109 && (!cscannerHelp_isConstraintToken(tok) )
2112 DPRINTF((message("Treating specifaction keyword %s as an identifiers. (This corresponds to"
2113 " token %d and we're in the specification denoted by %d see cgrammar_tokens.h"
2114 " for an explanation of these numbers",
2115 yytext, tok, s_whichSpecPart)
2118 /* Allow specificiation keywords to be used as identifiers in these contexts. */
2122 cscannerHelp_setTokLengthT (length);
2123 return cscannerHelp_returnToken (tok);
2127 context_saveLocation ();
2128 cscannerHelp_setTokLengthT (length);
2129 return (cscannerHelp_processIdentifier (cscannerHelp_makeIdentifier (yytext)));
2132 void cscannerHelp_expectingMetaStateName ()
2134 llassert (!s_expectingMetaStateName);
2135 llassert (context_inFunctionHeader ());
2136 s_expectingMetaStateName = TRUE;
2139 void cscannerHelp_clearExpectingMetaStateName ()
2141 llassert (s_expectingMetaStateName);
2142 s_expectingMetaStateName = FALSE;
2145 bool cscannerHelp_isConstraintToken (int tok)
2146 /* drl added 12/11/2002
2147 Tell whether a token has special meaning
2148 within a function constraint
2151 return (tok == QMAXSET || tok == QMAXREAD);
2152 /* || tok == QMINREAD || tok == QMINSET */
2153 /* uncomment the additional if statement tests when minSet and minRead are supported */
2156 bool cscannerHelp_processMacro (void)
2161 cstring fname = cstring_undefined;
2163 bool isspecfcn = FALSE;
2164 bool isiter = FALSE;
2165 bool skipparam = FALSE;
2166 bool isenditer = FALSE;
2167 bool unknownm = FALSE;
2168 bool hasParams = FALSE;
2169 bool emptyMacro = FALSE;
2170 char c = skip_whitespace ();
2171 fileloc loc = fileloc_noColumn (g_currentloc);
2173 /* are both of these necessary? what do they mean? */
2174 uentryList specparams = uentryList_undefined;
2175 uentryList pn = uentryList_undefined;
2177 context_resetMacroMissingParams ();
2179 if (c == '\0' || c == '\n')
2181 llcontbug (cstring_makeLiteral ("Bad macro"));
2186 fname = cstring_appendChar (fname, c);
2188 while ((c = macro_nextChar ()) != '(' && c != '\0'
2189 && c != ' ' && c != '\t' && c != '\n')
2191 fname = cstring_appendChar (fname, c);
2194 if (c == ' ' || c == '\t' || c == '\n')
2200 while (c == ' ' || c == '\t')
2202 c = macro_nextChar ();
2204 cscanner_unput ((int) c);
2210 cscanner_unput ((int) c);
2216 hasParams = (c == '(');
2218 if (usymtab_exists (fname))
2220 e2 = usymtab_lookupExpose (fname);
2221 ct = uentry_getType (e2);
2223 if (uentry_isCodeDefined (e2)
2224 && fileloc_isUser (uentry_whereDefined (e2)))
2228 message ("Macro %s already defined", fname),
2231 uentry_showWhereDefined (e2);
2232 uentry_clearDefined (e2);
2235 if (uentry_isFunction (e2))
2237 uentry_setType (e2, ctype_unknown);
2240 context_enterUnknownMacro (e2);
2244 context_enterConstantMacro (e2);
2249 if (uentry_isForward (e2) && uentry_isFunction (e2))
2256 ("Parameterized macro has no prototype or specification: %s ",
2261 uentry_setType (e2, ctype_unknown);
2262 uentry_setFunctionDefined (e2, loc);
2263 uentry_setUsed (e2, fileloc_undefined);
2264 context_enterUnknownMacro (e2);
2268 if (uentry_isIter (e2))
2271 specparams = uentry_getParams (e2);
2272 noparams = uentryList_size (specparams);
2273 uentry_setDefined (e2, loc);
2274 context_enterIterDef (e2);
2276 else if (uentry_isEndIter (e2))
2279 uentry_setDefined (e2, loc);
2280 context_enterIterEnd (e2); /* don't care about it now */
2281 /* but should parse like an iter! */
2283 else if (uentry_isConstant (e2))
2289 message ("Constant %s implemented as parameterized macro",
2293 uentry_showWhereSpecified (e2);
2294 uentry_setType (e2, ctype_unknown);
2295 uentry_makeConstantFunction (e2);
2296 uentry_setDefined (e2, g_currentloc);
2297 uentry_setFunctionDefined (e2, g_currentloc);
2298 context_enterUnknownMacro (e2);
2302 if (!uentry_isSpecified (e2))
2304 fileloc oloc = uentry_whereDeclared (e2);
2306 if (fileloc_isLib (oloc))
2310 else if (fileloc_isUndefined (oloc)
2311 || fileloc_isPreproc (oloc))
2316 (FLG_MACROCONSTDECL,
2318 ("Macro constant %q not declared",
2319 uentry_getName (e2)),
2323 else if (!fileloc_withinLines (oloc, loc, 2))
2324 { /* bogus! will give errors if there is too much whitespace */
2328 ("Macro constant name %s does not match name in "
2329 "previous constant declaration. This constant "
2330 "is declared at %q", fname,
2331 fileloc_unparse (oloc)),
2340 context_enterConstantMacro (e2);
2341 cstring_free (fname);
2347 else if (ctype_isFunction (ct))
2350 specparams = ctype_argsFunction (ct);
2351 noparams = uentryList_size (specparams);
2353 uentry_setFunctionDefined (e2, loc);
2354 context_enterMacro (e2);
2356 else if (uentry_isVar (e2))
2362 message ("Variable %s implemented as parameterized macro",
2366 uentry_showWhereSpecified (e2);
2367 uentry_setType (e2, ctype_unknown);
2368 uentry_makeVarFunction (e2);
2369 uentry_setDefined (e2, g_currentloc);
2370 uentry_setFunctionDefined (e2, g_currentloc);
2371 context_enterUnknownMacro (e2);
2375 uentry ucons = uentry_makeConstant (fname,
2378 if (uentry_isExpandedMacro (e2))
2386 message ("Variable %s implemented by a macro",
2390 uentry_showWhereSpecified (e2);
2394 uentry_setDefined (e2, loc);
2395 uentry_setUsed (ucons, loc);
2397 context_enterConstantMacro (ucons);
2398 uentry_markOwned (ucons);
2399 cstring_free (fname);
2405 if (uentry_isDatatype (e2))
2409 message ("Type implemented as macro: %x",
2410 uentry_getName (e2)),
2411 message ("A type is implemented using a macro definition. A "
2412 "typedef should be used instead."),
2415 cscannerHelp_swallowMacro ();
2416 /* Must exit scope (not sure why a new scope was entered?) */
2417 usymtab_quietExitScope (g_currentloc);
2418 uentry_setDefined (e2, g_currentloc);
2424 (message ("Unexpanded macro not function or constant: %q",
2425 uentry_unparse (e2)));
2426 uentry_setType (e2, ctype_unknown);
2430 uentry_makeVarFunction (e2);
2431 uentry_setDefined (e2, g_currentloc);
2432 uentry_setFunctionDefined (e2, g_currentloc);
2433 context_enterUnknownMacro (e2);
2444 /* evans 2001-09-09 - if it has params, assume a function */
2448 (FLG_MACROMATCHNAME,
2449 message ("Unexpanded macro %s does not match name of a declared "
2450 "function. The name used in the control "
2451 "comment on the previous line should match.",
2455 ce = uentry_makeFunction (fname, ctype_unknown,
2459 warnClause_undefined,
2461 uentry_setUsed (ce, loc); /* perhaps bogus? */
2462 e2 = usymtab_supEntryReturn (ce);
2463 context_enterUnknownMacro (e2);
2468 (FLG_MACROMATCHNAME,
2469 message ("Unexpanded macro %s does not match name of a constant "
2470 "or iter declaration. The name used in the control "
2471 "comment on the previous line should match. "
2472 "(Assuming macro defines a constant.)",
2476 ce = uentry_makeConstant (fname, ctype_unknown, fileloc_undefined);
2477 uentry_setUsed (ce, loc); /* perhaps bogus? */
2478 e2 = usymtab_supEntryReturn (ce);
2480 context_enterConstantMacro (e2);
2481 cstring_free (fname);
2487 /* in macros, ( must follow immediatetly after name */
2493 c = skip_whitespace ();
2495 while (c != ')' && c != '\0')
2498 bool suppress = context_inSuppressRegion ();
2499 cstring paramname = cstring_undefined;
2502 ** save the parameter location
2506 context_saveLocation ();
2509 while (c != ' ' && c != '\t' && c != ',' && c != '\0' && c != ')')
2511 paramname = cstring_appendChar (paramname, c);
2512 c = macro_nextChar ();
2515 if (c == ' ' || c == '\t') c = skip_whitespace ();
2519 c = macro_nextChar ();
2520 if (c == ' ' || c == '\t') c = skip_whitespace ();
2525 llfatalerror (cstring_makeLiteral
2526 ("Bad macro syntax: uentryList"));
2529 if ((isspecfcn || isiter) && (paramno < noparams)
2530 && !uentry_isElipsisMarker (uentryList_getN
2531 (specparams, paramno)))
2533 fileloc sloc = context_getSaveLocation ();
2534 uentry decl = uentryList_getN (specparams, paramno);
2537 param = uentry_nameCopy (paramname, decl);
2539 uentry_setParam (param);
2540 sr = sRef_makeParam (paramno, uentry_getType (param),
2541 stateInfo_makeLoc (sloc, SA_DECLARED));
2543 if (sRef_getNullState (sr) == NS_ABSNULL)
2545 ctype pt = ctype_realType (uentry_getType (param));
2547 if (ctype_isUser (pt))
2549 uentry te = usymtab_getTypeEntrySafe (ctype_typeId (pt));
2551 if (uentry_isValid (te))
2553 sRef_setStateFromUentry (sr, te);
2558 sRef_setNullState (sr, NS_UNKNOWN, sloc);
2562 uentry_setSref (param, sr);
2563 uentry_setDeclaredForceOnly (param, sloc);
2565 skipparam = isiter && uentry_isOut (uentryList_getN (specparams, paramno));
2569 fileloc sloc = context_getSaveLocation ();
2571 param = uentry_makeVariableSrefParam
2572 (paramname, ctype_unknown, fileloc_copy (sloc),
2573 sRef_makeParam (paramno, ctype_unknown,
2574 stateInfo_makeLoc (sloc, SA_DECLARED)));
2575 DPRINTF (("Unknown param: %s", uentry_unparseFull (param)));
2576 cstring_free (paramname);
2578 sRef_setPosNull (uentry_getSref (param), sloc);
2579 uentry_setDeclaredForce (param, sloc);
2582 fileloc_free (sloc);
2587 llassert (!uentry_isElipsisMarker (param));
2591 sRef_makeUnsafe (uentry_getSref (param));
2594 pn = uentryList_add (pn, uentry_copy (param));
2595 usymtab_supEntry (param);
2599 /* don't add param */
2600 uentry_free (param);
2605 (void) macro_nextChar ();
2606 c = skip_whitespace ();
2614 if (isspecfcn || isiter)
2616 if (paramno != noparams && noparams >= 0)
2618 cscannerHelp_advanceLine ();
2622 message ("Macro %s specified with %d args, defined with %d",
2623 fname, noparams, paramno),
2626 uentry_showWhereSpecified (e2);
2627 uentry_resetParams (e2, pn);
2632 uentry_resetParams (e2, pn);
2639 ** the form should be:
2641 ** # define newname oldname
2642 ** where oldname refers to a function matching the specification
2648 sRef_setGlobalScope ();
2649 usymtab_supGlobalEntry (uentry_makeVariableLoc (fname, ctype_unknown));
2650 sRef_clearGlobalScope ();
2654 context_setMacroMissingParams ();
2659 /* context_setuentryList (pn); */
2660 usymtab_enterScope ();
2663 cstring_free (fname);
2668 void cscannerHelp_setTokLength (int len)
2672 DPRINTF (("Set tok length: %d", len));
2675 void cscannerHelp_setTokLengthT (size_t len)
2677 cscannerHelp_setTokLength (size_toInt (len));
2680 void cscannerHelp_advanceLine (void)
2686 int cscannerHelp_returnToken (int t)
2688 yylval.tok = lltok_create (t, fileloc_decColumn (g_currentloc, s_tokLength));
2690 s_lastWasString = FALSE;
2694 int cscannerHelp_returnTokenLength (int t, int length)
2696 cscannerHelp_setTokLength (length);
2697 return cscannerHelp_returnToken (t);
2700 int cscannerHelp_returnString (cstring s)
2702 yylval.expr = exprNode_stringLiteral (s, fileloc_decColumn (g_currentloc, s_tokLength));
2704 s_lastWasString = TRUE;
2708 int cscannerHelp_returnInt (ctype ct, long val)
2712 if (ctype_equal (ct, ctype_int))
2716 c = context_typeofZero ();
2720 c = context_typeofOne ();
2728 yylval.expr = exprNode_numLiteral (c, cstring_fromChars (yytext),
2729 fileloc_decColumn (g_currentloc, s_tokLength),
2732 s_lastWasString = FALSE;
2736 int cscannerHelp_returnFloat (ctype ct, double f)
2738 yylval.expr = exprNode_floatLiteral (f, ct, cstring_fromChars (yytext),
2739 fileloc_decColumn (g_currentloc, s_tokLength));
2741 s_lastWasString = FALSE;
2745 int cscannerHelp_returnChar (char c)
2747 yylval.expr = exprNode_charLiteral (c, cstring_fromChars (yytext),
2748 fileloc_decColumn (g_currentloc, s_tokLength));
2750 s_lastWasString = FALSE;
2754 int cscannerHelp_returnType (int tok, ctype ct)
2758 s_lastWasString = FALSE;
2762 int cscannerHelp_returnExpr (exprNode e)
2766 s_lastWasString = TRUE;
2770 void cscannerHelp_setExpectingTypeName ()
2772 s_expectingTypeName = TRUE;
2775 void cscannerHelp_clearExpectingTypeName ()
2777 s_expectingTypeName = FALSE;
2780 bool cscannerHelp_isExpectingTypeName ()
2782 return s_expectingTypeName;
2785 int cscannerHelp_processTextIdentifier (char *text)
2787 context_saveLocation ();
2788 cscannerHelp_setTokLength (size_toInt (mstring_length (text)));
2789 return cscannerHelp_processIdentifier (cscannerHelp_makeIdentifier (text));
2792 static bool s_continueLine = FALSE;
2794 int cscannerHelp_handleNewLine ()
2796 context_incLineno ();
2798 if (s_tokLength != 0) {
2800 /* No error to report
2803 message ("Likely parse error: token spans multiple lines."),
2810 s_continueLine = FALSE;
2814 if (context_inMacro ())
2816 /* Don't use return cscannerHelp_returnToken */
2817 /* !!! evans 2002-03-13 */
2818 yylval.tok = lltok_create (TENDMACRO, fileloc_copy (g_currentloc));
2819 s_lastWasString = FALSE;
2827 void cscannerHelp_setContinueLine ()
2829 s_continueLine = TRUE;
2832 void cscannerHelp_exitSpecPart ()
2834 llassert (s_inSpecPart);
2835 s_inSpecPart = FALSE;
2836 s_whichSpecPart = BADTOK;