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
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 "splintMacros.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
);
87 cstringTable_insert (tokenTable
, cstring_makeLiteral ("restrict"), MT_RESTRICT
);
93 cstringTable_insert (tokenTable
, cstring_makeLiteral ("==>"), MT_ARROW
);
94 cstringTable_insert (tokenTable
, cstring_makeLiteral ("+"), MT_PLUS
);
95 cstringTable_insert (tokenTable
, cstring_makeLiteral ("*"), MT_STAR
);
96 cstringTable_insert (tokenTable
, cstring_makeLiteral ("{"), MT_LBRACE
);
97 cstringTable_insert (tokenTable
, cstring_makeLiteral ("}"), MT_RBRACE
);
98 cstringTable_insert (tokenTable
, cstring_makeLiteral ("("), MT_LPAREN
);
99 cstringTable_insert (tokenTable
, cstring_makeLiteral (")"), MT_RPAREN
);
100 cstringTable_insert (tokenTable
, cstring_makeLiteral ("["), MT_LBRACKET
);
101 cstringTable_insert (tokenTable
, cstring_makeLiteral ("]"), MT_RBRACKET
);
102 cstringTable_insert (tokenTable
, cstring_makeLiteral (","), MT_COMMA
);
103 cstringTable_insert (tokenTable
, cstring_makeLiteral ("|"), MT_BAR
);
105 isInitialized
= TRUE
;
108 void mtscanner_reset (inputStream sourceFile
)
112 mtscanner_initMod ();
115 scanFile
= sourceFile
;
118 int mtlex (MTSTYPE
*mtlval
)
120 llassert (isInitialized
);
122 /* This is important! Bison expects this */
125 mtlval
->tok
= mtscanner_getNextToken ();
126 DPRINTF (("Return token: %s", mttok_unparse (mtlval
->tok
)));
127 llassert (fileloc_isDefined (mttok_getLoc (mtlval
->tok
)));
128 return (mttok_getTok (mtlval
->tok
));
132 static void skipComments (void)
136 tchar
= inputStream_peekChar (scanFile
);
138 if (tchar
== (int) '/' && inputStream_peekNChar (scanFile
, 1) == (int) '*')
140 check ((int) '/' == inputStream_nextChar (scanFile
));
141 check ((int) '*' == inputStream_nextChar (scanFile
));
143 while ((tchar
= inputStream_nextChar (scanFile
)) != EOF
)
145 if (tchar
== (int) '*' && inputStream_peekChar (scanFile
) == (int) '/')
147 tchar
= inputStream_nextChar (scanFile
);
155 (cstring_makeLiteral ("Reached end of metastate file inside comment."));
160 check ((int) '/' == tchar
);
167 while (isspace (inputStream_peekChar (scanFile
)))
169 tchar
= inputStream_nextChar (scanFile
);
177 /* If there was a comment or whitespace, need to skip again... */
182 static mttok
mtscanner_getNextToken (void)
191 loc
= fileloc_copy (g_currentloc
);
192 tchar
= inputStream_nextChar (scanFile
);
196 return mttok_create (EOF
, cstring_undefined
, loc
);
199 tok
= cstring_newEmpty ();
201 DPRINTF (("tchar: %c", (char) tchar
));
203 if (tchar
== (int) '\"')
205 bool escaped
= FALSE
;
208 while ((tchar
= inputStream_peekChar (scanFile
)) != EOF
) {
211 } else if (tchar
== (int) '\\') {
213 } else if (tchar
== (int) '\"') {
219 tok
= cstring_appendChar (tok
, (char) tchar
);
220 check (tchar
== inputStream_nextChar (scanFile
));
226 (cstring_makeLiteral ("Reached end of metastate file inside string literal."));
230 check ((int) '\"' == inputStream_nextChar (scanFile
));
231 return mttok_create (MT_STRINGLIT
, tok
, loc
);
235 tok
= cstring_appendChar (tok
, (char) tchar
);
237 DPRINTF (("tok: %s", tok
));
241 while ((tchar
= inputStream_peekChar (scanFile
)) != EOF
) {
242 if (!isalnum (tchar
) && (tchar
!= (int) '_') && (tchar
!= (int) '$')) {
246 tok
= cstring_appendChar (tok
, (char) tchar
);
247 check (tchar
== inputStream_nextChar (scanFile
));
250 mtcode
= cstringTable_lookup (tokenTable
, tok
);
252 if (mtcode
== NOT_FOUND
) {
253 DPRINTF (("Returning identifier: %s", tok
));
254 return mttok_create (MT_IDENT
, tok
, loc
);
259 /* Read until next space */
260 DPRINTF (("Here we are: %s", tok
));
262 while ((tchar
= inputStream_peekChar (scanFile
)) != EOF
) {
263 if (isspace (tchar
) || isalnum (tchar
)) {
267 tok
= cstring_appendChar (tok
, (char) tchar
);
268 DPRINTF (("Here we are: %s", tok
));
269 check (tchar
== inputStream_nextChar (scanFile
));
272 DPRINTF (("Here we are: [%s]", tok
));
273 mtcode
= cstringTable_lookup (tokenTable
, tok
);
275 if (mtcode
== NOT_FOUND
) {
280 DPRINTF (("Read %s / %d", tok
, mtcode
));
283 res
= mttok_create (mtcode
, cstring_undefined
, loc
);
284 DPRINTF (("Return token: %s", mttok_unparse (res
)));
288 ctype
mtscanner_lookupType (mttok tok
)
293 llassert (mttok_isIdentifier (tok
));
294 tname
= mttok_observeText (tok
);
296 DPRINTF (("Lookup type: %s", tname
));
298 ue
= usymtab_lookupSafe (tname
);
300 if (uentry_isValid (ue
) && uentry_isDatatype (ue
))
302 DPRINTF (("Found it: %s / %s", uentry_unparse (ue
),
303 ctype_unparse (uentry_getAbstractType (ue
))));
305 return uentry_getAbstractType (ue
);
310 ue
= uentry_makeDatatype (tname
, ctype_unknown
, MAYBE
, qual_createUnknown(),
311 mttok_stealLoc (tok
));
312 DPRINTF (("Making mts entry: %s", uentry_unparse (ue
)));
313 ct
= usymtab_supForwardTypeEntry (ue
);
314 DPRINTF (("Type: %s", ctype_unparse (ct
)));