/*
** Splint - annotation-assisted static program checker
** Copyright (C) 1994-2003 University of Virginia,
** Massachusetts Institute of Technology
**
** This program is free software; you can redistribute it and/or modify it
** under the terms of the GNU General Public License as published by the
** Free Software Foundation; either version 2 of the License, or (at your
** option) any later version.
**
** This program is distributed in the hope that it will be useful, but
** WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** General Public License for more details.
**
** The GNU General Public License is available from http://www.gnu.org/ or
** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
** MA 02111-1307, USA.
**
** For information on splint: info@splint.org
** To report a bug: splint-bug@splint.org
** For more information: http://www.splint.org
*/
/*
** mtscanner.c
**
** Because flex is so lame, we can't use two flex scanners at once. Instead,
** we have to write a manual scanner. Should look into some real parser
** generator tools one day...
*/
# include "splintMacros.nf"
# include "basic.h"
# include "mtgrammar.h"
# include "mtscanner.h"
static inputStream scanFile; /* file to scan */
static mttok mtscanner_getNextToken (void);
static /*@only@*/ cstringTable tokenTable = cstringTable_undefined;
static bool isInitialized = FALSE;
/*@constant int MT_TOKENTABLESIZE@*/
# define MT_TOKENTABLESIZE 64
static void mtscanner_initMod (void)
{
llassert (cstringTable_isUndefined (tokenTable));
tokenTable = cstringTable_create (MT_TOKENTABLESIZE);
cstringTable_insert (tokenTable, cstring_makeLiteral ("attribute"), MT_STATE);
cstringTable_insert (tokenTable, cstring_makeLiteral ("global"), MT_GLOBAL);
cstringTable_insert (tokenTable, cstring_makeLiteral ("context"), MT_CONTEXT);
cstringTable_insert (tokenTable, cstring_makeLiteral ("oneof"), MT_ONEOF);
cstringTable_insert (tokenTable, cstring_makeLiteral ("defaults"), MT_DEFAULTS);
cstringTable_insert (tokenTable, cstring_makeLiteral ("default"), MT_DEFAULT);
cstringTable_insert (tokenTable, cstring_makeLiteral ("parameter"), MT_PARAMETER);
cstringTable_insert (tokenTable, cstring_makeLiteral ("result"), MT_RESULT);
cstringTable_insert (tokenTable, cstring_makeLiteral ("literal"), MT_LITERAL);
cstringTable_insert (tokenTable, cstring_makeLiteral ("null"), MT_NULL);
cstringTable_insert (tokenTable, cstring_makeLiteral ("reference"), MT_REFERENCE);
cstringTable_insert (tokenTable, cstring_makeLiteral ("clause"), MT_CLAUSE);
cstringTable_insert (tokenTable, cstring_makeLiteral ("annotations"), MT_ANNOTATIONS);
cstringTable_insert (tokenTable, cstring_makeLiteral ("merge"), MT_MERGE);
cstringTable_insert (tokenTable, cstring_makeLiteral ("transfers"), MT_TRANSFERS);
cstringTable_insert (tokenTable, cstring_makeLiteral ("preconditions"), MT_PRECONDITIONS);
cstringTable_insert (tokenTable, cstring_makeLiteral ("postconditions"), MT_POSTCONDITIONS);
cstringTable_insert (tokenTable, cstring_makeLiteral ("losereference"), MT_LOSEREFERENCE);
cstringTable_insert (tokenTable, cstring_makeLiteral ("error"), MT_ERROR);
cstringTable_insert (tokenTable, cstring_makeLiteral ("end"), MT_END);
cstringTable_insert (tokenTable, cstring_makeLiteral ("as"), MT_AS);
/*
** C Types
*/
cstringTable_insert (tokenTable, cstring_makeLiteral ("char"), MT_CHAR);
cstringTable_insert (tokenTable, cstring_makeLiteral ("int"), MT_INT);
cstringTable_insert (tokenTable, cstring_makeLiteral ("float"), MT_FLOAT);
cstringTable_insert (tokenTable, cstring_makeLiteral ("double"), MT_DOUBLE);
cstringTable_insert (tokenTable, cstring_makeLiteral ("void"), MT_VOID);
cstringTable_insert (tokenTable, cstring_makeLiteral ("anytype"), MT_ANYTYPE);
cstringTable_insert (tokenTable, cstring_makeLiteral ("integraltype"), MT_INTEGRALTYPE);
cstringTable_insert (tokenTable, cstring_makeLiteral ("unsignedintegraltype"), MT_UNSIGNEDINTEGRALTYPE);
cstringTable_insert (tokenTable, cstring_makeLiteral ("signedintegraltype"), MT_SIGNEDINTEGRALTYPE);
cstringTable_insert (tokenTable, cstring_makeLiteral ("const"), MT_CONST);
cstringTable_insert (tokenTable, cstring_makeLiteral ("volatile"), MT_VOLATILE);
cstringTable_insert (tokenTable, cstring_makeLiteral ("restrict"), MT_RESTRICT);
/*
** Punctuation
*/
cstringTable_insert (tokenTable, cstring_makeLiteral ("==>"), MT_ARROW);
cstringTable_insert (tokenTable, cstring_makeLiteral ("+"), MT_PLUS);
cstringTable_insert (tokenTable, cstring_makeLiteral ("*"), MT_STAR);
cstringTable_insert (tokenTable, cstring_makeLiteral ("{"), MT_LBRACE);
cstringTable_insert (tokenTable, cstring_makeLiteral ("}"), MT_RBRACE);
cstringTable_insert (tokenTable, cstring_makeLiteral ("("), MT_LPAREN);
cstringTable_insert (tokenTable, cstring_makeLiteral (")"), MT_RPAREN);
cstringTable_insert (tokenTable, cstring_makeLiteral ("["), MT_LBRACKET);
cstringTable_insert (tokenTable, cstring_makeLiteral ("]"), MT_RBRACKET);
cstringTable_insert (tokenTable, cstring_makeLiteral (","), MT_COMMA);
cstringTable_insert (tokenTable, cstring_makeLiteral ("|"), MT_BAR);
isInitialized = TRUE;
}
void mtscanner_reset (inputStream sourceFile)
{
if (!isInitialized)
{
mtscanner_initMod ();
}
scanFile = sourceFile;
}
int mtlex (YYSTYPE *mtlval)
{
llassert (isInitialized);
/* This is important! Bison expects this */
/*@ignore@*/
mtlval->tok = mtscanner_getNextToken ();
DPRINTF (("Return token: %s", mttok_unparse (mtlval->tok)));
llassert (fileloc_isDefined (mttok_getLoc (mtlval->tok)));
return (mttok_getTok (mtlval->tok));
/*@end@*/
}
static void skipComments (void)
{
int tchar;
bool gotone = FALSE;
tchar = inputStream_peekChar (scanFile);
if (tchar == (int) '/' && inputStream_peekNChar (scanFile, 1) == (int) '*')
{
check ((int) '/' == inputStream_nextChar (scanFile));
check ((int) '*' == inputStream_nextChar (scanFile));
while ((tchar = inputStream_nextChar (scanFile)) != EOF)
{
if (tchar == (int) '*' && inputStream_peekChar (scanFile) == (int) '/')
{
tchar = inputStream_nextChar (scanFile);
break;
}
}
if (tchar == EOF)
{
llfatalerror
(cstring_makeLiteral ("Reached end of metastate file inside comment."));
BADBRANCH;
}
else
{
check ((int) '/' == tchar);
gotone = TRUE;
}
}
if (isspace (tchar))
{
while (isspace (inputStream_peekChar (scanFile)))
{
tchar = inputStream_nextChar (scanFile);
}
gotone = TRUE;
}
if (gotone)
{
/* If there was a comment or whitespace, need to skip again... */
skipComments ();
}
}
static mttok mtscanner_getNextToken ()
{
int tchar;
int mtcode;
cstring tok;
mttok res;
fileloc loc;
skipComments ();
loc = fileloc_copy (g_currentloc);
tchar = inputStream_nextChar (scanFile);
if (tchar == EOF)
{
return mttok_create (EOF, cstring_undefined, loc);
}
tok = cstring_newEmpty ();
DPRINTF (("tchar: %c", (char) tchar));
if (tchar == (int) '\"')
{
bool escaped = FALSE;
/* String literal */
while ((tchar = inputStream_peekChar (scanFile)) != EOF) {
if (escaped) {
escaped = FALSE;
} else if (tchar == (int) '\\') {
escaped = TRUE;
} else if (tchar == (int) '\"') {
break;
} else {
;
}
tok = cstring_appendChar (tok, (char) tchar);
check (tchar == inputStream_nextChar (scanFile));
}
if (tchar == EOF)
{
llfatalerror
(cstring_makeLiteral ("Reached end of metastate file inside string literal."));
}
else
{
check ((int) '\"' == inputStream_nextChar (scanFile));
return mttok_create (MT_STRINGLIT, tok, loc);
}
}
tok = cstring_appendChar (tok, (char) tchar);
DPRINTF (("tok: %s", tok));
if (isalpha (tchar))
{
while ((tchar = inputStream_peekChar (scanFile)) != EOF) {
if (!isalnum (tchar) && (tchar != (int) '_') && (tchar != (int) '$')) {
break;
}
tok = cstring_appendChar (tok, (char) tchar);
check (tchar == inputStream_nextChar (scanFile));
}
mtcode = cstringTable_lookup (tokenTable, tok);
if (mtcode == NOT_FOUND) {
DPRINTF (("Returning identifier: %s", tok));
return mttok_create (MT_IDENT, tok, loc);
}
}
else
{
/* Read until next space */
DPRINTF (("Here we are: %s", tok));
while ((tchar = inputStream_peekChar (scanFile)) != EOF) {
if (isspace (tchar) || isalnum (tchar)) {
break;
}
tok = cstring_appendChar (tok, (char) tchar);
DPRINTF (("Here we are: %s", tok));
check (tchar == inputStream_nextChar (scanFile));
}
DPRINTF (("Here we are: [%s]", tok));
mtcode = cstringTable_lookup (tokenTable, tok);
if (mtcode == NOT_FOUND) {
mtcode = MT_BADTOK;
}
}
DPRINTF (("Read %s / %d", tok, mtcode));
cstring_free (tok);
res = mttok_create (mtcode, cstring_undefined, loc);
DPRINTF (("Return token: %s", mttok_unparse (res)));
return res;
}
ctype mtscanner_lookupType (mttok tok)
{
cstring tname;
uentry ue;
llassert (mttok_isIdentifier (tok));
tname = mttok_observeText (tok);
DPRINTF (("Lookup type: %s", tname));
ue = usymtab_lookupSafe (tname);
if (uentry_isValid (ue) && uentry_isDatatype (ue))
{
DPRINTF (("Found it: %s / %s", uentry_unparse (ue),
ctype_unparse (uentry_getAbstractType (ue))));
return uentry_getAbstractType (ue);
}
else
{
ctype ct;
ue = uentry_makeDatatype (tname, ctype_unknown, MAYBE, qual_createUnknown(),
mttok_stealLoc (tok));
DPRINTF (("Making mts entry: %s", uentry_unparse (ue)));
ct = usymtab_supForwardTypeEntry (ue);
DPRINTF (("Type: %s", ctype_unparse (ct)));
return ct;
}
}
syntax highlighted by Code2HTML, v. 0.9.1