|
|
// Copyright (c) 1993-1999 Microsoft Corporation
/*
** helper functions for Gerd Immeyer's grammar ** */
/****************************************************************************
* include files ***************************************************************************/
#pragma warning ( disable : 4514 4710 )
#include "nulldefs.h"
extern "C" { #include <stdio.h>
#include <io.h>
#include <process.h>
#include <string.h>
#include <stdlib.h>
}
#include "common.hxx"
#include "errors.hxx"
#include "midlnode.hxx"
#include "listhndl.hxx"
#include "filehndl.hxx"
#include "lextable.hxx"
#include "lexutils.hxx"
#include "grammar.h"
#include "gramutil.hxx"
#include "cmdana.hxx"
#include "control.hxx"
#include "tlgen.hxx"
#include <float.h>
extern "C" { #include "lex.h"
}
/****************************************************************************
* local definitions and macros ***************************************************************************/
#define warning(p) /* temp defintion to get rid of compiler probs */
#define MAX_ID_LENGTH (31)
#define MAX_DECIMAL_LENGTH (10)
#define MAX_HEX_LENGTH (8)
#define MAX_OCTAL_LENGTH (25)
/***************************************************************************
* local data ***************************************************************************/
/***************************************************************************
* local procedures ***************************************************************************/ long convert(char *, short, short); token_t cnv_int(void); token_t cnv_hex(void); token_t cnv_octal(void); token_t cnv_float(void); inline token_t GetNextToken() {return yylex();} inline void UngetToken(token_t token) {yyunlex(token);} token_t name(void); token_t map_token(token_t token); void lex_error(int number);
/***************************************************************************
* global data ***************************************************************************/
// token_t TokenMap[LASTTOKEN];
short handle_import; short inside_rpc; lextype_t yylval; token_t toktyp_G; /* token type */ short toklen_G; /* len of token string */ char *tokptr_G; /* pointer to token string */ short curr_line_G; /* current line in file */ char *curr_file_G; /* current file name */ long tokval_G; /* value of constant token */ FILE *hFile_G; /* current file */ BOOL fAbandonNumberLengthLimits;
/***************************************************************************
* external data ***************************************************************************/ extern short DebugLine; extern NFA_INFO *pImportCntrl; extern LexTable * pMidlLexTable; extern short CompileMode; extern SymTable * pBaseSymTbl; extern CMD_ARG * pCommand; extern ccontrol * pCompiler; extern char LastLexChar;
/***************************************************************************
* external procedures ***************************************************************************/
token_t is_keyword( char *, short);
/***************************************************************************/
const extern short st[ 13 ][ 16 ]; const extern short ct[256];
// Used to disable identifier to keyword mapping for declspec parsing.
BOOL IdToKeywordMapping = TRUE;
#define __isdigit(c) (((c) >= '0' && (c) <= '9'))
token_t cnv_int(void) { LastLexChar = NewCCGetch(); int chBeyond = NewCCGetch(); NewCCputbackc((char)chBeyond);
if( LastLexChar == '.' && chBeyond!= '.') { STATUS_T Status = STATUS_OK; short LengthCollected = (short)strlen(tokptr_G); char * ptr = &tokptr_G[LengthCollected];
char ch = LastLexChar;
*ptr++ = ch; *ptr++ = ch = NewCCGetch(); if (__isdigit(ch)) { *ptr++ = ch = NewCCGetch(); while (__isdigit(ch)) { *ptr++ = ch = NewCCGetch(); } if (ch == 'e' || ch == 'E') { *ptr++ = ch = NewCCGetch(); if (ch == '-' || ch == '+') { *ptr++ = ch = NewCCGetch(); if (__isdigit(ch)) { *ptr++ = ch = NewCCGetch(); while (__isdigit(ch)) { *ptr++ = ch = NewCCGetch(); } } else { Status = ERROR_PARSING_NUMERICAL; } } else if (__isdigit(ch)) { *ptr++ = ch = NewCCGetch(); while (__isdigit(ch)) { *ptr++ = ch = NewCCGetch(); } } } } else { Status = ERROR_PARSING_NUMERICAL; }
if (Status != STATUS_OK) { ParseError( Status, (char *)0 ); exit( Status ); }
*ptr = 0; token_t tokenType = DOUBLECONSTANT; double d = atof(tokptr_G);
if (ch != 'l' && ch != 'L') { NewCCputbackc(ch); *(ptr-1) = 0; tokenType = unsigned short( (d < FLT_MAX || d > FLT_MIN) ? FLOATCONSTANT : DOUBLECONSTANT ); } else { NewCCputbackc(NewCCGetch()); } if ( tokenType == DOUBLECONSTANT ) { yylval.yy_numeric.dVal = d; } else { yylval.yy_numeric.fVal = (float) d; }
yylval.yy_numeric.pValStr = pMidlLexTable->LexInsert(tokptr_G); return tokenType; } else { token_t Tok = NUMERICCONSTANT; yylval.yy_numeric.pValStr = pMidlLexTable->LexInsert(tokptr_G); yylval.yy_numeric.Val = tokval_G = convert(tokptr_G, 10, MAX_DECIMAL_LENGTH );
if( (LastLexChar == 'L') || (LastLexChar == 'l')) { Tok = NUMERICLONGCONSTANT; } else { if( (LastLexChar == 'U') || (LastLexChar == 'u')) { Tok = NUMERICULONGCONSTANT; if( ((LastLexChar = NewCCGetch()) != 'L') && (LastLexChar != 'l')) { NewCCputbackc(LastLexChar); Tok = NUMERICUCONSTANT; } } else { NewCCputbackc( LastLexChar ); return NUMERICCONSTANT; } } return Tok; } }
token_t cnv_hex(void) { token_t Tok = HEXCONSTANT; unsigned long Val;
yylval.yy_numeric.pValStr = pMidlLexTable->LexInsert(tokptr_G); tokptr_G += 2; /* skip 0x */ Val = yylval.yy_numeric.Val = tokval_G = convert(tokptr_G, 16, MAX_HEX_LENGTH); tokptr_G -= 2;
LastLexChar = NewCCGetch();
if( (LastLexChar == 'L') || (LastLexChar == 'l')) { Tok = HEXLONGCONSTANT; } else { // LastLexChar = NewCCGetch();
if( (LastLexChar == 'U') || (LastLexChar == 'u')) { Tok = HEXULONGCONSTANT; if( ((LastLexChar = NewCCGetch()) != 'L') && (LastLexChar != 'l')) { NewCCputbackc(LastLexChar); Tok = HEXUCONSTANT; } } else { NewCCputbackc(LastLexChar); return HEXCONSTANT; } } return Tok; }
token_t cnv_octal(void) { token_t Tok = OCTALCONSTANT; unsigned long Val;
yylval.yy_numeric.pValStr = pMidlLexTable->LexInsert(tokptr_G); Val = yylval.yy_numeric.Val = tokval_G = convert(tokptr_G, 8, MAX_OCTAL_LENGTH);
LastLexChar = NewCCGetch();
if( (LastLexChar == 'L') || (LastLexChar == 'l')) { Tok = OCTALLONGCONSTANT; } else { // LastLexChar = NewCCGetch();
if( (LastLexChar == 'U') || (LastLexChar == 'u')) { Tok = OCTALULONGCONSTANT; if( ((LastLexChar = NewCCGetch()) != 'L') && (LastLexChar != 'l')) { NewCCputbackc(LastLexChar); Tok = OCTALUCONSTANT; } } else { NewCCputbackc(LastLexChar); return OCTALCONSTANT; } }
return Tok; }
token_t cnv_float(void) { warning("floating point constants not allowed"); yylval.yy_numeric.Val = tokval_G = 0; lex_error(101); yylval.yy_numeric.pValStr = pMidlLexTable->LexInsert(tokptr_G); return NUMERICCONSTANT; }
long convert(char *ptr, short base, short MaxSize) { REG long answer = 0; REG char ch; BOOL fZeroIsNotALeadingZeroAnymore = FALSE; short count = 0;
while ((ch = *ptr++) != 0) { if ((ch & 0x5f) >= 'A') answer = answer * base + (ch & 0x5f) - 'A'+ 10; else answer = answer * base + ch - '0';
if( ch == '0') { if( fZeroIsNotALeadingZeroAnymore ) count++; } else { fZeroIsNotALeadingZeroAnymore = TRUE; count++; } }
if( ( count > MaxSize ) && !fAbandonNumberLengthLimits ) { ParseError( CONSTANT_TOO_BIG, (char *)NULL ); }
return answer; }
void SkipToToken(token_t token) { token_t NextToken; do { NextToken = GetNextToken(); } while( ( token != NextToken) && (EOI != NextToken) ); }
MODIFIER_SET ParseUnknownDeclSpecItem(char *pIdentifier) {
INITIALIZED_MODIFIER_SET ModifierSet; unsigned long Level = 0;
char AppendTxt[512]; unsigned int CurChar = 0;
memset( AppendTxt, '\0', sizeof(AppendTxt) );
const unsigned int MaxCurChar = 512 - 1 - sizeof(')') - sizeof(' ') - sizeof('\0');
char ch; short ci; for(;;) // skip white space
{ ci = ct[ (unsigned char)(ch = NewCCGetch()) ]; if (0 == st[ 0 ][ ci & 0x00ff ]) { AppendTxt[CurChar++] = ch; if ( CurChar >= MaxCurChar ) { ParseError(SYNTAX_ERROR, "Invalid _declspec"); return ModifierSet; } } else break; } if ('(' == ch) { // identifier(...) form
Level++; AppendTxt[CurChar++] = '(';
do { ch = NewCCGetch(); switch(ch) { case 0: //end of file
goto Exit; case '(': Level++; break; case ')': Level--; break; }
AppendTxt[CurChar++] = ch; if ( CurChar >= MaxCurChar ) { ParseError(SYNTAX_ERROR, "Invalid _declspec"); return ModifierSet; }
} while ( Level );
}
else { NewCCputbackc(ch); } Exit: AppendTxt[CurChar++] = ')'; AppendTxt[CurChar++] = ' '; size_t StringLength = sizeof("__declspec(") + strlen(pIdentifier) + CurChar + sizeof('\0'); char *UnknownDeclspec = new char[StringLength]; strcpy( UnknownDeclspec, "__declspec("); strcat( UnknownDeclspec, pIdentifier ); strcat( UnknownDeclspec, AppendTxt); ModifierSet.SetDeclspecUnknown( UnknownDeclspec ); delete[] UnknownDeclspec;
return ModifierSet; }
#pragma warning(push)
#pragma warning( disable : 4244 ) // disable long to short conversion warning
MODIFIER_SET ParseDeclSpecAlign() {
unsigned short AlignmentValue = 8; toktyp_G = GetNextToken();
if (toktyp_G != '(') { ParseError( BENIGN_SYNTAX_ERROR, "( expected after _declspec( align"); UngetToken(toktyp_G); goto exit; }
toktyp_G = GetNextToken();
switch(toktyp_G) { case NUMERICCONSTANT: case NUMERICLONGCONSTANT: case HEXCONSTANT: case HEXLONGCONSTANT: case OCTALCONSTANT: case OCTALLONGCONSTANT: case NUMERICUCONSTANT: case NUMERICULONGCONSTANT: case HEXUCONSTANT: case HEXULONGCONSTANT: case OCTALUCONSTANT: case OCTALULONGCONSTANT: break; //valid case
default: ParseError( MSCDECL_INVALID_ALIGN, NULL); SkipToToken(')'); goto exit; }
//Check if value is nonzero power of 2 <= 8192
switch((long)tokval_G) { case 1: case 2: case 4: case 8: case 16: case 32: case 64: case 128: case 256: case 512: case 1024: case 2048: case 4096: case 8192: AlignmentValue = (unsigned short)tokval_G; break; //valid case
default: ParseError( MSCDECL_INVALID_ALIGN, NULL); AlignmentValue = 8; break; }
toktyp_G = GetNextToken();
if (toktyp_G != ')') { ParseError( BENIGN_SYNTAX_ERROR, ") expected to follow _declspec(align(N \n"); SkipToToken(')'); }
exit: INITIALIZED_MODIFIER_SET ModifierSet; ModifierSet.SetDeclspecAlign(AlignmentValue); ParseError( BENIGN_SYNTAX_ERROR, "_declspec(align()) is not supported." ); return ModifierSet; }
#pragma warning(pop)
token_t ParseDeclSpec() { /* Parses the MS_VC declspec() syntax.
syntax: _declspec(declspeclist ) declspeclist: declspecitemlist declspecitem | declspecitem | nothing declspecitem: identifier | identifier(...) */ token_t LParen = GetNextToken(); if ('(' != LParen) { ParseError( BENIGN_SYNTAX_ERROR, "( expected after _declspec"); return LParen; }
// Disable ID to keyword mapping.
BOOL OldIdToKeywordMapping = IdToKeywordMapping; IdToKeywordMapping = FALSE;
INITIALIZED_MODIFIER_SET ModifierSet;
for(;;) { // VC skips comma, so we skip commas.
while(',' == (toktyp_G = GetNextToken())); if (')' == toktyp_G) { break; }
if (IDENTIFIER == toktyp_G || TYPENAME == toktyp_G || LIBNAME == toktyp_G) { if (strcmp( tokptr_G, "dllimport") == 0) { ModifierSet.SetModifier(ATTR_DLLIMPORT); } else if (strcmp( tokptr_G, "dllexport") == 0) { ModifierSet.SetModifier(ATTR_DLLEXPORT); } else if (strcmp( tokptr_G, "align") == 0) { ModifierSet.Merge(ParseDeclSpecAlign()); } else { ModifierSet.Merge(ParseUnknownDeclSpecItem(tokptr_G)); } } else { ParseError( BENIGN_SYNTAX_ERROR, "Invalid _declspec" ); SkipToToken(')'); break; } }
IdToKeywordMapping = OldIdToKeywordMapping;
yylval.yy_modifiers = ModifierSet; return (toktyp_G = KWMSCDECLSPEC); }
const extern short ct[256]; const extern short st[13][16];
token_t name(void) { /* have received a name from the input file, first we */ /* check to see if it is a keyword. */
short InBracket = short( inside_rpc ? INBRACKET : 0 );
if ( IdToKeywordMapping ) toktyp_G = is_keyword(tokptr_G, InBracket); else toktyp_G = IDENTIFIER;
if (KWMSCDECLSPEC == toktyp_G) { return ParseDeclSpec(); }
if( KWSAFEARRAY == toktyp_G) { /* SAFEARRAY is a special case
* In order to correctly parse the ODL SAFEARRAY syntax: * SAFEARRAY ( FOO * ) BAR; * we look ahead at the next non white space character * to see if it's an open parenthasis. If it is then we eat * the character and return KWSAFEARRAY, otherwise we * put the character back into the stream and return the * string "SAFEARRAY" as an IDENTIFIER. */ char ch; short ci; do ci = ct[ (unsigned char)(ch = NewCCGetch()) ]; while (0 == st[ 0 ][ ci & 0x00ff ]); /* skip white space */ if ('(' != ch) { NewCCputbackc(ch); toktyp_G = IDENTIFIER; } }
if (toktyp_G == IDENTIFIER) { if( strlen( tokptr_G ) > MAX_ID_LENGTH ) { ParseError( ID_TRUNCATED, tokptr_G ); // tokptr_G[ MAX_ID_LENGTH ] = '\0'; // dont truncate
}
/* We need to know if the identifier is followed by a period.
* If it is, it may be a library name and so we need to check * the libary name table to see if we should return LIBNAME * instead of TYPENAME or IDENTIFIER. * We look ahead to the next non white space character as above; * the difference being that we do not consume the non whitespace * character as we would for "SAFEARRAY(". */ char ch; short ci; do ci = ct[ (unsigned char)(ch = NewCCGetch()) ]; while (0 == st[ 0 ][ ci & 0x00ff ]); /* skip white space */ NewCCputbackc(ch); if( '.' == ch ) { // we need to check to see if the identifier is a library name
if (FIsLibraryName(tokptr_G)) { toktyp_G = LIBNAME; yylval.yy_pSymName = new char [toklen_G + 1]; strcpy(yylval.yy_pSymName, tokptr_G); return toktyp_G; } } /* Check the symbol table to see if the identifier
* is a TYPENAME. */ #ifdef unique_lextable
// all names go in the lex table -- this is important for the symtable search
yylval.yy_pSymName = pMidlLexTable->LexInsert(tokptr_G);
// see if the name corresponds to a base level typedef
SymKey SKey( yylval.yy_pSymName, NAME_DEF );
if( pBaseSymTbl->SymSearch( SKey ) ) { toktyp_G = TYPENAME; } } #else // unique_lextable
// see if the name corresponds to a base level typedef
SymKey SKey( tokptr_G, NAME_DEF ); named_node * pNode;
if ( ( pNode = pBaseSymTbl->SymSearch( SKey ) ) != 0 ) { char * szTemp = new char[toklen_G + 1]; strcpy(szTemp, tokptr_G); pNode->SetCurrentSpelling(szTemp); toktyp_G = TYPENAME; yylval.yy_graph = pNode; } else { yylval.yy_pSymName = pMidlLexTable->LexInsert(tokptr_G); }
} #endif // unique_lextable
return toktyp_G; }
void lex_error(int number) { printf("lex error : %d\n", number); }
|