2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2001 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 lclint: lclint-request@cs.virginia.edu
21 ** To report a bug: lclint-bug@cs.virginia.edu
22 ** For more information: http://www.splint.org
27 ** Because flex is so lame, we can't use two flex scanners at once. Instead,
28 ** we have to write a manual scanner. Should look into some real parser
29 ** generator tools one day...
32 # include "lclintMacros.nf"
34 # include "mtgrammar.h"
35 # include "mtscanner.h"
37 static inputStream scanFile; /* file to scan */
38 static mttok mtscanner_getNextToken (void);
39 static /*@only@*/ cstringTable tokenTable = cstringTable_undefined;
40 static bool isInitialized = FALSE;
42 /*@constant int MT_TOKENTABLESIZE@*/
43 # define MT_TOKENTABLESIZE 64
45 static void mtscanner_initMod (void)
47 llassert (cstringTable_isUndefined (tokenTable));
48 tokenTable = cstringTable_create (MT_TOKENTABLESIZE);
50 cstringTable_insert (tokenTable, cstring_makeLiteral ("attribute"), MT_STATE);
51 cstringTable_insert (tokenTable, cstring_makeLiteral ("global"), MT_GLOBAL);
52 cstringTable_insert (tokenTable, cstring_makeLiteral ("context"), MT_CONTEXT);
53 cstringTable_insert (tokenTable, cstring_makeLiteral ("oneof"), MT_ONEOF);
54 cstringTable_insert (tokenTable, cstring_makeLiteral ("defaults"), MT_DEFAULTS);
55 cstringTable_insert (tokenTable, cstring_makeLiteral ("default"), MT_DEFAULT);
56 cstringTable_insert (tokenTable, cstring_makeLiteral ("parameter"), MT_PARAMETER);
57 cstringTable_insert (tokenTable, cstring_makeLiteral ("result"), MT_RESULT);
58 cstringTable_insert (tokenTable, cstring_makeLiteral ("literal"), MT_LITERAL);
59 cstringTable_insert (tokenTable, cstring_makeLiteral ("null"), MT_NULL);
60 cstringTable_insert (tokenTable, cstring_makeLiteral ("reference"), MT_REFERENCE);
61 cstringTable_insert (tokenTable, cstring_makeLiteral ("clause"), MT_CLAUSE);
62 cstringTable_insert (tokenTable, cstring_makeLiteral ("annotations"), MT_ANNOTATIONS);
63 cstringTable_insert (tokenTable, cstring_makeLiteral ("merge"), MT_MERGE);
64 cstringTable_insert (tokenTable, cstring_makeLiteral ("transfers"), MT_TRANSFERS);
65 cstringTable_insert (tokenTable, cstring_makeLiteral ("preconditions"), MT_PRECONDITIONS);
66 cstringTable_insert (tokenTable, cstring_makeLiteral ("postconditions"), MT_POSTCONDITIONS);
67 cstringTable_insert (tokenTable, cstring_makeLiteral ("losereference"), MT_LOSEREFERENCE);
68 cstringTable_insert (tokenTable, cstring_makeLiteral ("error"), MT_ERROR);
69 cstringTable_insert (tokenTable, cstring_makeLiteral ("end"), MT_END);
70 cstringTable_insert (tokenTable, cstring_makeLiteral ("as"), MT_AS);
76 cstringTable_insert (tokenTable, cstring_makeLiteral ("char"), MT_CHAR);
77 cstringTable_insert (tokenTable, cstring_makeLiteral ("int"), MT_INT);
78 cstringTable_insert (tokenTable, cstring_makeLiteral ("float"), MT_FLOAT);
79 cstringTable_insert (tokenTable, cstring_makeLiteral ("double"), MT_DOUBLE);
80 cstringTable_insert (tokenTable, cstring_makeLiteral ("void"), MT_VOID);
81 cstringTable_insert (tokenTable, cstring_makeLiteral ("anytype"), MT_ANYTYPE);
82 cstringTable_insert (tokenTable, cstring_makeLiteral ("integraltype"), MT_INTEGRALTYPE);
83 cstringTable_insert (tokenTable, cstring_makeLiteral ("unsignedintegraltype"), MT_UNSIGNEDINTEGRALTYPE);
84 cstringTable_insert (tokenTable, cstring_makeLiteral ("signedintegraltype"), MT_SIGNEDINTEGRALTYPE);
85 cstringTable_insert (tokenTable, cstring_makeLiteral ("const"), MT_CONST);
86 cstringTable_insert (tokenTable, cstring_makeLiteral ("volatile"), MT_VOLATILE);
92 cstringTable_insert (tokenTable, cstring_makeLiteral ("==>"), MT_ARROW);
93 cstringTable_insert (tokenTable, cstring_makeLiteral ("+"), MT_PLUS);
94 cstringTable_insert (tokenTable, cstring_makeLiteral ("*"), MT_STAR);
95 cstringTable_insert (tokenTable, cstring_makeLiteral ("{"), MT_LBRACE);
96 cstringTable_insert (tokenTable, cstring_makeLiteral ("}"), MT_RBRACE);
97 cstringTable_insert (tokenTable, cstring_makeLiteral ("("), MT_LPAREN);
98 cstringTable_insert (tokenTable, cstring_makeLiteral (")"), MT_RPAREN);
99 cstringTable_insert (tokenTable, cstring_makeLiteral ("["), MT_LBRACKET);
100 cstringTable_insert (tokenTable, cstring_makeLiteral ("]"), MT_RBRACKET);
101 cstringTable_insert (tokenTable, cstring_makeLiteral (","), MT_COMMA);
102 cstringTable_insert (tokenTable, cstring_makeLiteral ("|"), MT_BAR);
104 isInitialized = TRUE;
107 void mtscanner_reset (inputStream sourceFile)
111 mtscanner_initMod ();
114 scanFile = sourceFile;
117 int mtlex (YYSTYPE *mtlval)
119 llassert (isInitialized);
121 /* This is important! Bison expects this */
124 mtlval->tok = mtscanner_getNextToken ();
125 DPRINTF (("Return token: %s", mttok_unparse (mtlval->tok)));
126 llassert (fileloc_isDefined (mttok_getLoc (mtlval->tok)));
127 return (mttok_getTok (mtlval->tok));
131 static void skipComments (void)
135 tchar = inputStream_peekChar (scanFile);
137 if (tchar == (int) '/' && inputStream_peekNChar (scanFile, 1) == (int) '*')
139 check ((int) '/' == inputStream_nextChar (scanFile));
140 check ((int) '*' == inputStream_nextChar (scanFile));
142 while ((tchar = inputStream_nextChar (scanFile)) != EOF)
144 if (tchar == (int) '*' && inputStream_peekChar (scanFile) == (int) '/')
146 tchar = inputStream_nextChar (scanFile);
154 (cstring_makeLiteral ("Reached end of metastate file inside comment."));
159 check ((int) '/' == tchar);
166 while (isspace (inputStream_peekChar (scanFile)))
168 tchar = inputStream_nextChar (scanFile);
176 /* If there was a comment or whitespace, need to skip again... */
181 static mttok mtscanner_getNextToken ()
190 loc = fileloc_copy (g_currentloc);
191 tchar = inputStream_nextChar (scanFile);
195 return mttok_create (EOF, cstring_undefined, loc);
198 tok = cstring_newEmpty ();
200 DPRINTF (("tchar: %c", (char) tchar));
202 if (tchar == (int) '\"')
204 bool escaped = FALSE;
207 while ((tchar = inputStream_peekChar (scanFile)) != EOF) {
210 } else if (tchar == (int) '\\') {
212 } else if (tchar == (int) '\"') {
218 tok = cstring_appendChar (tok, (char) tchar);
219 check (tchar == inputStream_nextChar (scanFile));
225 (cstring_makeLiteral ("Reached end of metastate file inside string literal."));
229 check ((int) '\"' == inputStream_nextChar (scanFile));
230 return mttok_create (MT_STRINGLIT, tok, loc);
234 tok = cstring_appendChar (tok, (char) tchar);
236 DPRINTF (("tok: %s", tok));
240 while ((tchar = inputStream_peekChar (scanFile)) != EOF) {
241 if (!isalnum (tchar) && (tchar != (int) '_') && (tchar != (int) '$')) {
245 tok = cstring_appendChar (tok, (char) tchar);
246 check (tchar == inputStream_nextChar (scanFile));
249 mtcode = cstringTable_lookup (tokenTable, tok);
251 if (mtcode == NOT_FOUND) {
252 DPRINTF (("Returning identifier: %s", tok));
253 return mttok_create (MT_IDENT, tok, loc);
258 /* Read until next space */
259 DPRINTF (("Here we are: %s", tok));
261 while ((tchar = inputStream_peekChar (scanFile)) != EOF) {
262 if (isspace (tchar) || isalnum (tchar)) {
266 tok = cstring_appendChar (tok, (char) tchar);
267 DPRINTF (("Here we are: %s", tok));
268 check (tchar == inputStream_nextChar (scanFile));
271 DPRINTF (("Here we are: [%s]", tok));
272 mtcode = cstringTable_lookup (tokenTable, tok);
274 if (mtcode == NOT_FOUND) {
279 DPRINTF (("Read %s / %d", tok, mtcode));
282 res = mttok_create (mtcode, cstring_undefined, loc);
283 DPRINTF (("Return token: %s", mttok_unparse (res)));
287 ctype mtscanner_lookupType (mttok tok)
292 llassert (mttok_isIdentifier (tok));
293 tname = mttok_observeText (tok);
295 DPRINTF (("Lookup type: %s", tname));
297 ue = usymtab_lookupSafe (tname);
299 if (uentry_isValid (ue) && uentry_isDatatype (ue))
301 DPRINTF (("Found it: %s / %s", uentry_unparse (ue),
302 ctype_unparse (uentry_getAbstractType (ue))));
304 return uentry_getAbstractType (ue);
309 ue = uentry_makeDatatype (tname, ctype_unknown, MAYBE, MAYBE, mttok_stealLoc (tok));
310 DPRINTF (("Making mts entry: %s", uentry_unparse (ue)));
311 ct = usymtab_supForwardTypeEntry (ue);
312 DPRINTF (("Type: %s", ctype_unparse (ct)));