]> andersk Git - splint.git/blob - src/mtscanner.c
*** empty log message ***
[splint.git] / src / mtscanner.c
1 /*
2 ** LCLint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2001 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 lclint: lclint-request@cs.virginia.edu
21 ** To report a bug: lclint-bug@cs.virginia.edu
22 ** For more information: http://lclint.cs.virginia.edu
23 */
24 /*
25 ** mtscanner.c
26 **
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...
30 */
31
32 # include "lclintMacros.nf"
33 # include "llbasic.h"
34 # include "mtgrammar.h"
35 # include "mtscanner.h"
36
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;
41
42 /*@constant int MT_TOKENTABLESIZE@*/
43 # define MT_TOKENTABLESIZE 64
44
45 static void mtscanner_initMod (void)
46 {
47   llassert (cstringTable_isUndefined (tokenTable));
48   tokenTable = cstringTable_create (MT_TOKENTABLESIZE);
49
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);
71
72   /*
73   ** C Types
74   */
75
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
88   /*
89   ** Punctuation
90   */
91
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);
103
104   isInitialized = TRUE;
105 }
106
107 void mtscanner_reset (inputStream sourceFile)
108 {
109   if (!isInitialized) 
110     {
111       mtscanner_initMod ();
112     }
113
114   scanFile = sourceFile;
115 }
116
117 int mtlex (YYSTYPE *mtlval)
118 {
119   llassert (isInitialized);
120
121   /* This is important!  Bison expects this */
122
123   /*@ignore@*/
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));
128   /*@end@*/
129 }
130
131 static void skipComments (void)
132 {
133   int tchar;
134   bool gotone = FALSE;
135   tchar = inputStream_peekChar (scanFile);
136
137   if (tchar == (int) '/' && inputStream_peekNChar (scanFile, 1) == (int) '*') 
138     {
139       check ((int) '/' == inputStream_nextChar (scanFile));
140       check ((int) '*' == inputStream_nextChar (scanFile));
141       
142       while ((tchar = inputStream_nextChar (scanFile)) != EOF) 
143         {
144           if (tchar == (int) '*' && inputStream_peekChar (scanFile) == (int) '/')
145             {
146               tchar = inputStream_nextChar (scanFile);
147               break;
148             }
149         }
150
151       if (tchar == EOF)
152         {
153           llfatalerror 
154             (cstring_makeLiteral ("Reached end of metastate file inside comment."));
155           BADBRANCH;
156         }
157       else
158         {
159           check ((int) '/' == tchar);
160           gotone = TRUE;
161         }
162     }
163
164   if (isspace (tchar)) 
165     {
166       while (isspace (inputStream_peekChar (scanFile)))
167         {
168           tchar = inputStream_nextChar (scanFile);
169         }
170
171       gotone = TRUE;
172     }
173
174   if (gotone)
175     {
176       /* If there was a comment or whitespace, need to skip again... */
177       skipComments ();
178     }
179 }
180
181 static mttok mtscanner_getNextToken ()
182 {
183   int tchar;
184   int mtcode;
185   cstring tok;
186   mttok res;
187   fileloc loc;
188
189   skipComments ();
190   loc = fileloc_copy (g_currentloc);
191   tchar = inputStream_nextChar (scanFile);
192
193   if (tchar == EOF) 
194     {
195       return mttok_create (EOF, cstring_undefined, loc);
196     }
197
198   tok = cstring_newEmpty ();
199
200   DPRINTF (("tchar: %c", (char) tchar));
201
202   if (tchar == (int) '\"') 
203     {
204       bool escaped = FALSE;
205
206       /* String literal */
207       while ((tchar = inputStream_peekChar (scanFile)) != EOF) {
208         if (escaped) {
209           escaped = FALSE;
210         } else if (tchar == (int) '\\') {
211           escaped = TRUE;
212         } else if (tchar == (int) '\"') {
213           break;
214         } else {
215           ;
216         }
217
218         tok = cstring_appendChar (tok, (char) tchar);
219         check (tchar == inputStream_nextChar (scanFile));
220       }
221
222       if (tchar == EOF)
223         {
224           llfatalerror 
225             (cstring_makeLiteral ("Reached end of metastate file inside string literal."));
226         }
227       else
228         {
229           check ((int) '\"' == inputStream_nextChar (scanFile));
230           return mttok_create (MT_STRINGLIT, tok, loc);
231         }
232     }
233   
234   tok = cstring_appendChar (tok, (char) tchar);
235
236   DPRINTF (("tok: %s", tok));
237
238   if (isalpha (tchar)) 
239     {
240       while ((tchar = inputStream_peekChar (scanFile)) != EOF) {
241         if (!isalnum (tchar) && (tchar != (int) '_') && (tchar != (int) '$')) {
242           break;
243         }
244         
245         tok = cstring_appendChar (tok, (char) tchar);
246         check (tchar == inputStream_nextChar (scanFile));
247       }
248
249       mtcode = cstringTable_lookup (tokenTable, tok);
250
251       if (mtcode == NOT_FOUND) {
252         DPRINTF (("Returning identifier: %s", tok));
253         return mttok_create (MT_IDENT, tok, loc);
254       }
255     } 
256   else 
257     {
258       /* Read until next space */
259       DPRINTF (("Here we are: %s", tok));
260
261       while ((tchar = inputStream_peekChar (scanFile)) != EOF) {
262         if (isspace (tchar) || isalnum (tchar)) {
263           break;
264         }
265         
266         tok = cstring_appendChar (tok, (char) tchar);
267         DPRINTF (("Here we are: %s", tok));
268         check (tchar == inputStream_nextChar (scanFile));
269       }
270
271       DPRINTF (("Here we are: [%s]", tok));
272       mtcode = cstringTable_lookup (tokenTable, tok);
273       
274       if (mtcode == NOT_FOUND) {
275         mtcode = MT_BADTOK;
276       }
277     }
278   
279   DPRINTF (("Read %s / %d", tok, mtcode));
280   cstring_free (tok);
281
282   res = mttok_create (mtcode, cstring_undefined, loc);
283   DPRINTF (("Return token: %s", mttok_unparse (res)));
284   return res;
285 }
286
287 ctype mtscanner_lookupType (mttok tok)
288 {
289   cstring tname;
290   uentry ue;
291
292   llassert (mttok_isIdentifier (tok));
293   tname = mttok_observeText (tok);
294
295   DPRINTF (("Lookup type:  %s", tname));
296
297   ue = usymtab_lookupSafe (tname);
298
299   if (uentry_isValid (ue) && uentry_isDatatype (ue))
300     {
301       DPRINTF (("Found it: %s / %s", uentry_unparse (ue),
302                 ctype_unparse (uentry_getAbstractType (ue))));
303     
304       return uentry_getAbstractType (ue);
305     }
306   else
307     {
308       ctype ct;
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)));
313       return ct;
314     }
315 }
This page took 0.058179 seconds and 5 git commands to generate.