mirror of
https://bitbucket.org/seefoe/dockerized-swg-src.git
synced 2026-01-15 23:04:57 -05:00
1004 lines
30 KiB
Plaintext
1004 lines
30 KiB
Plaintext
%expect 1
|
|
%{
|
|
/*-----------------------------------------------------------------------------**
|
|
** FILE: parser.yac **
|
|
** (c) 1998 - Bootprint GTInteractive **
|
|
** **
|
|
** DESCRIPTION: parser for mIFF **
|
|
** **
|
|
** AUTHOR: Hideki Ikeda **
|
|
** HISTORY: **
|
|
** **
|
|
** Notes: companion to parser.lex **
|
|
**-----------------------------------------------------------------------------*/
|
|
|
|
/*---------------**
|
|
** C declaration **
|
|
**---------------*/
|
|
#pragma warning (disable: 4005) /* macro redefinition - bision.simple redefines alloca() */
|
|
#pragma warning (disable: 4127) /* conditional expression is constant - in bison.simple */
|
|
#pragma warning (disable: 4131) /* uses old-style declarator - mostly in bison.simple */
|
|
#pragma warning (disable: 4244) /* possible loss of data due to conversion from one type to another - bision.simple */
|
|
#pragma warning (disable: 4701) /* local variable ('yyval' in first case) may be used without having been initialed */
|
|
// #pragma warning (disable: 6311) /* compiler malloc.h: see previous definition of alloca() */
|
|
|
|
/* include files */
|
|
#include <math.h> /* for pow() and stuff */
|
|
#include <string.h>
|
|
#include <stdlib.h> /* for toupper() */
|
|
#include <wchar.h> /* for wide character (16bit) strings */
|
|
#include <ctype.h> /* for strtoupper and strtolower */
|
|
#include <stdio.h>
|
|
|
|
/*----------------------------------------------------------------**
|
|
** debug options, turn these on to TEST ONLY! don't leave these **
|
|
** switch on, it's annoying as hell in console mode! **
|
|
** NOTE: if you turn YYERROR_VERBOSE on, you MUST have YYDEBUG! **
|
|
** IMHO, it's better off using primitive printf() method to debug **
|
|
**----------------------------------------------------------------*/
|
|
#define YYERROR_VERBOSE 1
|
|
#define YYDEBUG 1
|
|
|
|
#undef YYERROR_VERBOSE
|
|
#undef YYDEBUG
|
|
|
|
/* external prototype declaration */
|
|
extern void MIFFMessage(char *message); /* found in mIFF.CPP */
|
|
extern char * MIFFallocString(int sizeOfString);
|
|
extern void MIFFfreeString(char * pointer);
|
|
extern int validateTargetFilename(char *fname, int fnameSize); /* found mIFF.CPP */
|
|
extern void yyerror(char *);
|
|
extern int yylex(void);
|
|
extern void setCurrentLineNumber(int lineNum, char * fileName, int mysteryNum);
|
|
extern void MIFFSetIFFName(const char *newFileName);
|
|
extern void MIFFinsertForm(const char *formName);
|
|
extern void MIFFinsertChunk(const char *chunkName);
|
|
extern void MIFFinsertChunkData(void * buffer, unsigned bufferSize);
|
|
extern int MIFFloadRawData(char *fname, void * buffer, unsigned maxBufferSize);
|
|
extern void MIFFexitChunk(void);
|
|
extern void MIFFexitForm(void);
|
|
extern unsigned long MIFFgetLabelHash(char *inputStream);
|
|
|
|
/* local prototype declaration */
|
|
void initGlobalVars(void);
|
|
void checkArgs(void);
|
|
void checkPragmas(void);
|
|
|
|
void includeBinary(char *fname);
|
|
|
|
void write32(long i32);
|
|
void write16(short i16);
|
|
void write8(char i8);
|
|
void writeU32(unsigned long ui32);
|
|
void writeU16(unsigned short ui16);
|
|
void writeU8(unsigned char u8);
|
|
void writeDouble(double d);
|
|
void writeFloat(float f);
|
|
void writeString(char *s);
|
|
void writeString16(char *s);
|
|
void writeLabelHash(char *s);
|
|
void writeTag(char *tag);
|
|
void writeSize(unsigned long size);
|
|
void writeData(void *dataPtr, unsigned dataSize);
|
|
|
|
void initSymTable(void);
|
|
long searchEnumSymbolTable(char *symString);
|
|
long getEnumValue(long index);
|
|
void addEnumSymbol(char *symString, long value);
|
|
void parseESCstring(char *str, char *targetBuffer, int sizeOfTarget);
|
|
|
|
/*----------------------------------------------**
|
|
** Global vars used by all functions and parser **
|
|
**----------------------------------------------*/
|
|
char err_msg[256];
|
|
int errorFlag;
|
|
|
|
/*-----------------------------------------------------------------------------**
|
|
** NOTE: this symbol table is ONLY used to construct symbols for enum table!!! **
|
|
**-----------------------------------------------------------------------------*/
|
|
#define MAX_SYMBOLS (1024) /* total number of symbols it can grow to... */
|
|
#define MAX_SYMCHARS (128) /* I label thee insane if you have more the 128 char for your variable! */
|
|
struct structEnumSymTableType
|
|
{
|
|
char symbol[MAX_SYMCHARS];
|
|
long value;
|
|
};
|
|
|
|
struct structEnumSymTableType symbolEnumTable[MAX_SYMBOLS];
|
|
unsigned currSymIndex = 0;
|
|
long lastValue = -1;
|
|
char id[MAX_SYMCHARS];
|
|
|
|
/* vars set by pragmas */
|
|
#define MAX_BUFFER_SIZE (16 * 1024 * 1024)
|
|
#define MAX_STRING_SIZE (512)
|
|
char drive[8];
|
|
char directory[MAX_STRING_SIZE/2];
|
|
char filename[MAX_STRING_SIZE/2];
|
|
char extension[8];
|
|
char outFileName[MAX_STRING_SIZE];
|
|
int usePragmas;
|
|
|
|
/*------------------------------------------------------------------------**
|
|
** The IRONY of these so-called temp-data's that are GLOBAL is **
|
|
** that they aren't temp if functions called within are also using it **
|
|
** This really gives me the creeps and goosbumps! DOWN with GLOBAL VARS! **
|
|
**------------------------------------------------------------------------*/
|
|
int iTemp, jTemp;
|
|
char byteTemp;
|
|
short wordTemp;
|
|
char tempStr[MAX_STRING_SIZE];
|
|
|
|
%}
|
|
|
|
/*--------------------**
|
|
** Bison declarations **
|
|
**--------------------*/
|
|
%union {
|
|
long ltype;
|
|
double dtype;
|
|
char *stype;
|
|
char chtype;
|
|
|
|
int tokentype;
|
|
}
|
|
|
|
/*------------------------------------------------**
|
|
** define tokens defined in lex file **
|
|
** NOTE: all LITERALs are treated as signed long **
|
|
** all FLOAT_LITERALs are treated as double **
|
|
**------------------------------------------------*/
|
|
%token <chtype> CHAR_LIT
|
|
%token <stype> STR_LIT
|
|
%token <stype> IDENTIFIER
|
|
%token <ltype> LIT
|
|
%token <dtype> FLOAT_LIT
|
|
|
|
/* all command tokens are <tokentype> type */
|
|
%token <tokentype> INT32
|
|
%token <tokentype> INT16
|
|
%token <tokentype> INT8
|
|
%token <tokentype> UINT32
|
|
%token <tokentype> UINT16
|
|
%token <tokentype> UINT8
|
|
%token <tokentype> FLOAT
|
|
%token <tokentype> DOUBLE
|
|
%token <tokentype> STRING
|
|
%token <tokentype> WSTRING
|
|
%token <tokentype> LABELHASH
|
|
|
|
%token <tokentype> FORM
|
|
%token <tokentype> CHUNK
|
|
%token <tokentype> PRAGMA
|
|
%token <tokentype> PRAGMA_DRIVE PRAGMA_DIR PRAGMA_FNAME PRAGMA_EXT
|
|
%token <tokentype> ENUMSTRUCT
|
|
%token <tokentype> INCLUDESOURCE
|
|
%token <tokentype> INCLUDEBIN
|
|
%token <tokentype> INCLUDEIFF
|
|
%token <tokentype> SIN
|
|
%token <tokentype> COS
|
|
%token <tokentype> TAN
|
|
%token <tokentype> ACOS
|
|
%token <tokentype> ASIN
|
|
%token <tokentype> ATAN
|
|
%token <tokentype> POUND
|
|
%token <tokentype> SHIFTRIGHT
|
|
%token <tokentype> SHIFTLEFT
|
|
%token <tokentype> RAISEDPOWER
|
|
|
|
%%
|
|
|
|
/*------------------------------------------------------------------------**
|
|
** Begin Grammar rules **
|
|
** **
|
|
** Note: if possible, always try to use left recurrsion rather then right **
|
|
** to save stack depth... **
|
|
**------------------------------------------------------------------------*/
|
|
mIFFSource:
|
|
{
|
|
/* initialize some global varibles before we start */
|
|
initGlobalVars();
|
|
checkArgs();
|
|
}
|
|
preprocessor
|
|
{
|
|
/* take care of any mIFF related preprocessors that we might encounter */
|
|
checkPragmas();
|
|
}
|
|
body
|
|
;
|
|
|
|
/*----------------------**
|
|
** Preprocessor handler **
|
|
**----------------------*/
|
|
preprocessor: { /* we don't really have to have preprocessor */}
|
|
| preprocessor pragma
|
|
| preprocessor debugInfo /* we have to have debugInfo or else pragma gets confused when it finds a # line */
|
|
;
|
|
|
|
pragma: PRAGMA PRAGMA_DRIVE STR_LIT {
|
|
if (usePragmas)
|
|
{
|
|
strcpy(drive, $<stype>3);
|
|
if (strlen(drive) > 2)
|
|
{
|
|
sprintf(err_msg, "Drive [%s] is not a valid drive [must be in C: format]", drive);
|
|
yyerror(err_msg);
|
|
}
|
|
drive[1] = ':';
|
|
drive[2] = 0;
|
|
}
|
|
MIFFfreeString($<stype>3);
|
|
}
|
|
| PRAGMA PRAGMA_DIR STR_LIT {
|
|
if (usePragmas)
|
|
{
|
|
strcpy(directory, $<stype>3);
|
|
if (directory[strlen(directory)] != '\\')
|
|
directory[strlen(directory)] = '\\';
|
|
directory[strlen(directory) + 1] = 0;
|
|
}
|
|
MIFFfreeString($<stype>3);
|
|
}
|
|
| PRAGMA PRAGMA_FNAME STR_LIT {
|
|
if (usePragmas)
|
|
strcpy(filename, $<stype>3);
|
|
MIFFfreeString($<stype>3);
|
|
}
|
|
| PRAGMA PRAGMA_EXT STR_LIT {
|
|
if (usePragmas)
|
|
strcpy(extension, $<stype>3);
|
|
MIFFfreeString($<stype>3);
|
|
}
|
|
| PRAGMA IDENTIFIER STR_LIT {
|
|
sprintf(err_msg, "Unknown PRAGMA identifier [%s]", $<stype>2);
|
|
yyerror(err_msg);
|
|
MIFFfreeString($<stype>2);
|
|
MIFFfreeString($<stype>3);
|
|
}
|
|
;
|
|
|
|
/*-------------------------------------------------------**
|
|
** This is the #line pragmas in a format of: **
|
|
** # lineNum "FileName" mysteryNumber **
|
|
** We call setCurrentLineNumber so when an error occurs, **
|
|
** it will be sync'd to correct filename and linenumber **
|
|
**-------------------------------------------------------*/
|
|
debugInfo: POUND LIT STR_LIT { setCurrentLineNumber($<ltype>2, $<stype>3, 0); MIFFfreeString($<stype>3);}
|
|
| POUND LIT STR_LIT LIT { setCurrentLineNumber($<ltype>2, $<stype>3, $<ltype>4); MIFFfreeString($<stype>3);}
|
|
;
|
|
|
|
/*-----------------------**
|
|
** The main body section **
|
|
**-----------------------*/
|
|
body: /* body can be empty */
|
|
| body form formbody
|
|
| body chunk chunkbody
|
|
| body enumSection
|
|
| body includesource { /* do nothing... should not exist if went thru the preprocessor */ }
|
|
| body includeIFF
|
|
| body debugInfo
|
|
;
|
|
|
|
/*------------------------**
|
|
** Enumeration definition **
|
|
**------------------------*/
|
|
enumSection: ENUMSTRUCT enumDeclare '{' enumBody '}' enumType ';' { /* enumSection */ }
|
|
;
|
|
|
|
enumDeclare: { /* could have no declaration */ lastValue = -1; }
|
|
| IDENTIFIER { /* enumDeclare: ID */ lastValue = -1; MIFFfreeString($<stype>1);}
|
|
;
|
|
|
|
enumBody: { /* enumBody: can be empty list */ }
|
|
| enumAssign { /* enumAssign */ }
|
|
| enumBody ',' enumAssign { /* enumAssign, enumBody */ }
|
|
;
|
|
|
|
enumAssign: IDENTIFIER '=' exprL {
|
|
addEnumSymbol($<stype>1, $<ltype>3);
|
|
MIFFfreeString($<stype>1);
|
|
}
|
|
| IDENTIFIER { /* in this case, inc 1 from last count */
|
|
addEnumSymbol($<stype>1, ++lastValue);
|
|
MIFFfreeString($<stype>1);
|
|
}
|
|
;
|
|
|
|
enumType: /* type declaration can be empty */
|
|
| enumList
|
|
;
|
|
|
|
enumList: IDENTIFIER { /* enumList: just ID */ MIFFfreeString($<stype>1);}
|
|
| enumList ',' IDENTIFIER { /* enumList: ID, enumList */ MIFFfreeString($<stype>3);}
|
|
;
|
|
|
|
/*----------------------------**
|
|
** different types of include **
|
|
**----------------------------*/
|
|
includesource: INCLUDESOURCE STR_LIT { /* do nothing... because CCCP/preprocessor takes care of this*/ MIFFfreeString($<stype>2);}
|
|
;
|
|
|
|
includebin: INCLUDEBIN STR_LIT { includeBinary($<stype>2); MIFFfreeString($<stype>2);}
|
|
;
|
|
|
|
includeIFF: INCLUDEIFF STR_LIT { includeBinary($<stype>2); MIFFfreeString($<stype>2);}
|
|
;
|
|
|
|
/*------------------**
|
|
** the FORM section **
|
|
**------------------*/
|
|
form: FORM STR_LIT {
|
|
/* first make sure we have 4 char for FORM name */
|
|
if (strlen($<stype>2) > 4)
|
|
{
|
|
sprintf(err_msg, "FORM name %s greater then 4 char", $<stype>2);
|
|
yyerror(err_msg);
|
|
}
|
|
else if (!errorFlag)
|
|
{
|
|
/* pack the string with ' ' (spaces) if less then 4 chars */
|
|
strcpy(tempStr, $<stype>2);
|
|
if (strlen(tempStr) < 4)
|
|
{
|
|
/* pack the string */
|
|
for (iTemp = strlen(tempStr);iTemp < 4; iTemp++)
|
|
{
|
|
tempStr[iTemp] = ' '; /* pack it with space */
|
|
}
|
|
}
|
|
|
|
/* let's make sure we don't have a smart ass who wants to do form "FORM" */
|
|
if ((toupper(tempStr[0]) == 'F') &&
|
|
(toupper(tempStr[1]) == 'O') &&
|
|
(toupper(tempStr[2]) == 'R') &&
|
|
(toupper(tempStr[3]) == 'M'))
|
|
{
|
|
yyerror("FORM name CANNOT BE 'FORM'... nice try bozo!");
|
|
}
|
|
|
|
/* FORM <size> <tagname> */
|
|
MIFFinsertForm(tempStr);
|
|
}
|
|
MIFFfreeString($<stype>2);
|
|
}
|
|
;
|
|
|
|
formbody: '{' formelements '}' { if (!errorFlag) MIFFexitForm(); };
|
|
|
|
formelements: body { /* recursion of multiple depth in form is allowed */ }
|
|
| INCLUDEBIN STR_LIT {
|
|
yyerror("Found attempt to include binary file inside FORM\nBinary file inclusion ONLY allowed inside a CHUNK!\nError");
|
|
MIFFfreeString($<stype>2);
|
|
}
|
|
;
|
|
|
|
/*-------------------**
|
|
** the CHUNK section **
|
|
**-------------------*/
|
|
chunk: CHUNK STR_LIT {
|
|
/* first make sure we have 4 char for CHUNK name */
|
|
if (strlen($<stype>2) > 4)
|
|
{
|
|
sprintf(err_msg, "CHUNK name %s greater then 4 char", $<stype>2);
|
|
yyerror(err_msg);
|
|
}
|
|
else if (!errorFlag)
|
|
{
|
|
/* pack the string with ' ' (spaces) if less then 4 chars */
|
|
strcpy(tempStr, $<stype>2);
|
|
if (strlen(tempStr) < 4)
|
|
{
|
|
/* pack the string */
|
|
for (iTemp = strlen(tempStr);iTemp < 4; iTemp++)
|
|
{
|
|
tempStr[iTemp] = ' '; /* pack it with space */
|
|
}
|
|
}
|
|
|
|
/* let's make sure we don't have a smart ass who wants to do chunk "FORM" */
|
|
if ((toupper(tempStr[0]) == 'F') &&
|
|
(toupper(tempStr[1]) == 'O') &&
|
|
(toupper(tempStr[2]) == 'R') &&
|
|
(toupper(tempStr[3]) == 'M'))
|
|
{
|
|
yyerror("CHUNK name CANNOT BE 'FORM'... nice try bozo!");
|
|
}
|
|
|
|
MIFFinsertChunk(tempStr);
|
|
}
|
|
MIFFfreeString($<stype>2);
|
|
}
|
|
;
|
|
|
|
chunkbody: '{' chunkelements '}' { if (!errorFlag) MIFFexitChunk(); };
|
|
|
|
chunkelements: /* can be empty */
|
|
| chunkelements memalloc
|
|
| chunkelements includebin
|
|
| chunkelements debugInfo
|
|
| chunkelements includeIFF { yyerror("Found attempt to include IFF (binary) file inside CHUNK\nIFF inclusion ONLY allowed outside a CHUNK!\nError"); }
|
|
;
|
|
|
|
memalloc: INT32 l32AllocExpr { }
|
|
| INT16 l16AllocExpr { }
|
|
| INT8 l8AllocExpr { }
|
|
| UINT32 lU32AllocExpr { }
|
|
| UINT16 lU16AllocExpr { }
|
|
| UINT8 lU8AllocExpr { }
|
|
| FLOAT fAllocExpr { }
|
|
| DOUBLE dAllocExpr { }
|
|
| LABELHASH STR_LIT {
|
|
writeLabelHash($<stype>2);
|
|
}
|
|
| STRING STR_LIT { writeString($<stype>2);
|
|
/* now, add a NULL termination for this string */
|
|
byteTemp = 0; write8(byteTemp);
|
|
MIFFfreeString($<stype>2);
|
|
}
|
|
| WSTRING STR_LIT { writeString16($<stype>2);
|
|
/* now, add a NULL termination for this string */
|
|
wordTemp = 0; write16(wordTemp);
|
|
MIFFfreeString($<stype>2);
|
|
}
|
|
;
|
|
|
|
l32AllocExpr: exprL { write32($<ltype>1); }
|
|
| l32AllocExpr ',' exprL { write32($<ltype>3); }
|
|
;
|
|
|
|
l16AllocExpr: exprL { write16((short) $<ltype>1); }
|
|
| l16AllocExpr ',' exprL { write16((short) $<ltype>3); }
|
|
;
|
|
|
|
l8AllocExpr: exprL { write8((char) $<ltype>1); }
|
|
| l8AllocExpr ',' exprL { write8((char) $<ltype>3); }
|
|
;
|
|
|
|
lU32AllocExpr: exprL { writeU32($<ltype>1); }
|
|
| lU32AllocExpr ',' exprL { writeU32($<ltype>3); }
|
|
;
|
|
|
|
lU16AllocExpr: exprL { writeU16((unsigned short) $<ltype>1); }
|
|
| lU16AllocExpr ',' exprL { writeU16((unsigned short) $<ltype>3); }
|
|
;
|
|
|
|
lU8AllocExpr: exprL { writeU8((unsigned char) $<ltype>1); }
|
|
| lU8AllocExpr ',' exprL { writeU8((unsigned char) $<ltype>3); }
|
|
;
|
|
|
|
fAllocExpr: exprD { writeFloat((float) $<dtype>1); }
|
|
| fAllocExpr ',' exprD { writeFloat((float) $<dtype>3); }
|
|
;
|
|
|
|
dAllocExpr: exprD { writeDouble($<dtype>1); }
|
|
| dAllocExpr ',' exprD { writeDouble($<dtype>3); }
|
|
;
|
|
|
|
|
|
/*-------------------------**
|
|
** expression for integers **
|
|
**-------------------------*/
|
|
exprL: exprL '+' factorL { $<ltype>$ = $<ltype>1 + $<ltype>3; }
|
|
| exprL '-' factorL { $<ltype>$ = $<ltype>1 - $<ltype>3; }
|
|
| exprL SHIFTLEFT factorL { $<ltype>$ = $<ltype>1 << $<ltype>3; }
|
|
| exprL SHIFTRIGHT factorL { $<ltype>$ = $<ltype>1 >> $<ltype>3; }
|
|
| exprL '&' factorL { $<ltype>$ = $<ltype>1 & $<ltype>3; }
|
|
| exprL '|' factorL { $<ltype>$ = $<ltype>1 | $<ltype>3; }
|
|
| exprL '^' factorL { $<ltype>$ = $<ltype>1 ^ $<ltype>3; }
|
|
| factorL { $<ltype>$ = ($<ltype>1); }
|
|
;
|
|
|
|
factorL: factorL '*' termL { $<ltype>$ = $<ltype>1 * $<ltype>3; }
|
|
| factorL '/' termL { $<ltype>$ = $<ltype>1 / $<ltype>3; }
|
|
| factorL '%' termL { $<ltype>$ = $<ltype>1 % $<ltype>3; }
|
|
| termL { $<ltype>$ = ($<ltype>1); }
|
|
;
|
|
|
|
termL: LIT { $<ltype>$ = $<ltype>1; }
|
|
| '~' termL { $<ltype>$ = ~$<ltype>2; } /* bitwise NOT */
|
|
| '-' termL { $<ltype>$ = -$<ltype>2; } /* Unary minus */
|
|
| '+' termL { $<ltype>$ = $<ltype>2; } /* Unary plus */
|
|
| '(' exprL ')' { $<ltype>$ = ($<ltype>2); }
|
|
| IDENTIFIER { /* assume it's enum symbol */
|
|
$<ltype>$ = (signed long) getEnumValue(searchEnumSymbolTable($<stype>1));
|
|
MIFFfreeString($<stype>1);
|
|
}
|
|
;
|
|
|
|
/*-----------------------**
|
|
** expression for floats **
|
|
**-----------------------*/
|
|
exprD: exprD '+' factorD { $<dtype>$ = $<dtype>1 + $<dtype>3; }
|
|
| exprD '-' factorD { $<dtype>$ = $<dtype>1 - $<dtype>3; }
|
|
| exprD RAISEDPOWER factorD { $<dtype>$ = pow($<dtype>1, $<dtype>3);} /* exponentiation */
|
|
| factorD { $<dtype>$ = ($<dtype>1); }
|
|
;
|
|
|
|
factorD: factorD '*' termD { $<dtype>$ = $<dtype>1 * $<dtype>3; }
|
|
| factorD '/' termD { $<dtype>$ = $<dtype>1 / $<dtype>3; }
|
|
| termD { $<dtype>$ = ($<dtype>1); }
|
|
;
|
|
|
|
termD: FLOAT_LIT { $<dtype>$ = $<dtype>1; }
|
|
| LIT { $<dtype>$ = (double) $<ltype>1; } /* we should be able to handle values that are integer and treat it as float */
|
|
| '-' termD { $<dtype>$ = -$<dtype>2; } /* Unary minus */
|
|
| '+' termD { $<dtype>$ = $<dtype>2; } /* Unary plus */
|
|
| '(' exprD ')' { $<dtype>$ = ($<dtype>2); }
|
|
| SIN '(' exprD ')' { $<dtype>$ = sin( $<dtype>3 ); }
|
|
| COS '(' exprD ')' { $<dtype>$ = cos( $<dtype>3 ); }
|
|
| TAN '(' exprD ')' { $<dtype>$ = tan( $<dtype>3 ); }
|
|
| ACOS '(' exprD ')' { $<dtype>$ = acos( $<dtype>3 ); }
|
|
| ASIN '(' exprD ')' { $<dtype>$ = asin( $<dtype>3 ); }
|
|
| ATAN '(' exprD ')' { $<dtype>$ = atan( $<dtype>3 ); }
|
|
| IDENTIFIER { /* assume it's enum symbol */
|
|
$<dtype>$ = (signed long) getEnumValue(searchEnumSymbolTable($<stype>1));
|
|
MIFFfreeString($<stype>1);
|
|
}
|
|
;
|
|
|
|
%%
|
|
|
|
/*-------------------------------------------**
|
|
** and now... the supporting C functions... **
|
|
**-------------------------------------------*/
|
|
void initGlobalVars(void)
|
|
{
|
|
/* assign defaults */
|
|
drive[0] = 0;
|
|
directory[0] = 0;
|
|
filename[0] = 0;
|
|
extension[0] = 0;
|
|
err_msg[0] = 0;
|
|
usePragmas = 1; /* default to #pragmas enabled because as a stand-alone .YAC, we have no knowledge of outFileName */
|
|
|
|
errorFlag = 0;
|
|
|
|
initSymTable();
|
|
}
|
|
|
|
void checkPragmas(void)
|
|
{
|
|
int indexOriginal, indexDest;
|
|
char _tempStr[512];
|
|
|
|
if (usePragmas)
|
|
{
|
|
/* check after pre processor if output target is still NULL */
|
|
if (!drive[0] && !errorFlag)
|
|
{
|
|
yyerror("Drive pragma not defined");
|
|
errorFlag = 1;
|
|
}
|
|
if (!directory[0] && !errorFlag)
|
|
{
|
|
yyerror("Directory pragma not defined");
|
|
errorFlag = 1;
|
|
}
|
|
if (!filename[0] && !errorFlag)
|
|
{
|
|
yyerror("Filename pragma not defined");
|
|
errorFlag = 1;
|
|
}
|
|
if (!extension[0] && !errorFlag)
|
|
{
|
|
yyerror("Extension pragma not defined");
|
|
errorFlag = 1;
|
|
}
|
|
|
|
if (!errorFlag)
|
|
{
|
|
/* create an output file */
|
|
strcpy(_tempStr, directory); /* copy directory to _tempStr because we'll be messing with directory */
|
|
for (indexOriginal = 0, indexDest = 0; indexOriginal < (int) strlen(_tempStr); indexOriginal++)
|
|
{
|
|
/* search for double-slashes and convert it to single slash */
|
|
if ((_tempStr[indexOriginal] == '\\') && (_tempStr[indexOriginal+1] == '\\'))
|
|
{
|
|
directory[indexDest] = '\\';
|
|
indexOriginal++;
|
|
}
|
|
else
|
|
directory[indexDest] = _tempStr[indexOriginal]; /* copy current position of _tempStr to directory */
|
|
indexDest++;
|
|
directory[indexDest] = 0; /* force NULL termination */
|
|
}
|
|
sprintf(outFileName, "%s%s%s%s", drive, directory, filename, extension);
|
|
}
|
|
} /* if usePragmas */
|
|
|
|
MIFFSetIFFName(outFileName); /* tell mIFF we want to use this filename instead of whatever it has! */
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------------------**
|
|
** This function is called early in the process to find out if usePragma flag was set **
|
|
** in the command line or not. If it was, mIFF already has the outfile and will stuff **
|
|
** it into the outFileName data pool. Even if mIFF had an idea of what the output file **
|
|
** name is, if usePragma flag returned said it is true, then #pragas in the mIFF source **
|
|
** is used instead and overrides whatever file name it has returned. **
|
|
** see usePragmas() for more details. **
|
|
**--------------------------------------------------------------------------------------*/
|
|
void checkArgs(void)
|
|
{
|
|
/* request an external function (found in either mIFF.CPP or mIFFView.CPP) to see if pragmas and filename was set... */
|
|
usePragmas = validateTargetFilename(outFileName, sizeof(outFileName));
|
|
}
|
|
|
|
/*----------------------------**
|
|
** Write to FILE functions... **
|
|
**----------------------------*/
|
|
void write32(long i32)
|
|
{
|
|
MIFFinsertChunkData(&i32, sizeof(long));
|
|
}
|
|
|
|
void write16(short i16)
|
|
{
|
|
MIFFinsertChunkData(&i16, sizeof(short));
|
|
}
|
|
|
|
void write8(char i8)
|
|
{
|
|
MIFFinsertChunkData(&i8, sizeof(char));
|
|
}
|
|
|
|
void writeU32(unsigned long ui32)
|
|
{
|
|
MIFFinsertChunkData(&ui32, sizeof(long));
|
|
}
|
|
|
|
void writeU16(unsigned short ui16)
|
|
{
|
|
MIFFinsertChunkData(&ui16, sizeof(short));
|
|
}
|
|
|
|
void writeU8(unsigned char ui8)
|
|
{
|
|
MIFFinsertChunkData(&ui8, sizeof(char));
|
|
}
|
|
|
|
void writeDouble(double d)
|
|
{
|
|
MIFFinsertChunkData(&d, sizeof(double));
|
|
}
|
|
|
|
void writeFloat(float f)
|
|
{
|
|
MIFFinsertChunkData(&f, sizeof(float));
|
|
}
|
|
|
|
void writeString(char *s)
|
|
{
|
|
char tempS[MAX_STRING_SIZE];
|
|
parseESCstring(s, tempS, MAX_STRING_SIZE);
|
|
|
|
MIFFinsertChunkData(tempS, strlen(tempS));
|
|
}
|
|
|
|
void writeString16(char *s)
|
|
{
|
|
char tempS[MAX_STRING_SIZE];
|
|
int charCount = 0;
|
|
wchar_t wtempStr[512]; /* just to be on the safe side, allocating huge array... */
|
|
|
|
parseESCstring(s, tempS, MAX_STRING_SIZE);
|
|
|
|
/* make sure string length is less then the allocated wchar size */
|
|
if ((strlen(tempS) * sizeof(wchar_t)) > (512* sizeof(wchar_t)))
|
|
yyerror("wstring: 16bit string too long to handle in buffer!\n");
|
|
else
|
|
{
|
|
/* call MultiByteString to WideCharString function */
|
|
charCount = mbstowcs(wtempStr, tempS, strlen(tempS));
|
|
writeData(wtempStr, charCount * sizeof(wchar_t));
|
|
}
|
|
}
|
|
|
|
void writeLabelHash(char *s)
|
|
{
|
|
writeU32(MIFFgetLabelHash(s));
|
|
}
|
|
|
|
/* search from escape string such as \n and convert it to actual byte */
|
|
void parseESCstring(char *str, char *targetBuffer, int sizeOfTarget)
|
|
{
|
|
char *sPtr = str;
|
|
int strIndex = 0;
|
|
char numString[32]; /* hopefully, never go over 3 char i.e. \x0FF */
|
|
int numIndex = 0;
|
|
int tempNum = 0;
|
|
int exitParser = 0;
|
|
int loopFlag = 0;
|
|
|
|
/* memory hog but cute way to convert ascii hex to number */
|
|
int hexTable[256];
|
|
memset(hexTable, 0xFF, 256);
|
|
hexTable['0'] = 0x00;
|
|
hexTable['1'] = 0x01;
|
|
hexTable['2'] = 0x02;
|
|
hexTable['3'] = 0x03;
|
|
hexTable['4'] = 0x04;
|
|
hexTable['5'] = 0x05;
|
|
hexTable['6'] = 0x06;
|
|
hexTable['7'] = 0x07;
|
|
hexTable['8'] = 0x08;
|
|
hexTable['9'] = 0x09;
|
|
hexTable['A'] = 0x0A; hexTable['a'] = 0x0A;
|
|
hexTable['B'] = 0x0B; hexTable['b'] = 0x0B;
|
|
hexTable['C'] = 0x0C; hexTable['c'] = 0x0C;
|
|
hexTable['D'] = 0x0D; hexTable['d'] = 0x0D;
|
|
hexTable['E'] = 0x0E; hexTable['e'] = 0x0E;
|
|
hexTable['F'] = 0x0F; hexTable['f'] = 0x0F;
|
|
|
|
memset(targetBuffer, 0, sizeOfTarget);
|
|
while ((*sPtr) && !exitParser) /* assume we can go until NULL termination */
|
|
{
|
|
/* check for escape sequences */
|
|
if (*sPtr == '\\')
|
|
{
|
|
sPtr++; /* check out next character */
|
|
switch (tolower(*sPtr))
|
|
{
|
|
case 'a': /* BELL */
|
|
{
|
|
targetBuffer[strIndex++] = '\a';
|
|
break;
|
|
}
|
|
|
|
case 'b': /* BACKSPACE */
|
|
{
|
|
targetBuffer[strIndex++] = '\b';
|
|
break;
|
|
}
|
|
|
|
case 'f': /* FORMFEED */
|
|
{
|
|
targetBuffer[strIndex++] = '\a';
|
|
break;
|
|
}
|
|
|
|
case 'n': /* NEWLINE */
|
|
{
|
|
targetBuffer[strIndex++] = '\n';
|
|
break;
|
|
}
|
|
|
|
case 'r': /* CARRIAGE RETURN */
|
|
{
|
|
targetBuffer[strIndex++] = '\r';
|
|
break;
|
|
}
|
|
|
|
case 't': /* TAB */
|
|
{
|
|
targetBuffer[strIndex++] = '\t';
|
|
break;
|
|
}
|
|
|
|
case 'v': /* VERTICAL TAB */
|
|
{
|
|
targetBuffer[strIndex++] = '\v';
|
|
break;
|
|
}
|
|
|
|
case '\'': /* SINGLE QUOTE */
|
|
{
|
|
targetBuffer[strIndex++] = '\'';
|
|
break;
|
|
}
|
|
|
|
case '\"': /* DOUBLE QUOTE */
|
|
{
|
|
targetBuffer[strIndex++] = '\"';
|
|
break;
|
|
}
|
|
|
|
case '\\': /* BACKSLASH */
|
|
{
|
|
targetBuffer[strIndex++] = '\\';
|
|
break;
|
|
}
|
|
|
|
case '?': /* LITERAL QUESTION MARK */
|
|
{
|
|
targetBuffer[strIndex++] = '\?';
|
|
break;
|
|
}
|
|
|
|
case '0': /* ASCII octal */
|
|
case '1': /* ASCII octal */
|
|
case '2': /* ASCII octal */
|
|
case '3': /* ASCII octal */
|
|
case '4': /* ASCII octal */
|
|
case '5': /* ASCII octal */
|
|
case '6': /* ASCII octal */
|
|
case '7': /* ASCII octal */
|
|
{
|
|
/* read until non-digit encountered - if octal value is greater then \377 (400 or more) it is bigger the 255! */
|
|
numIndex = 0;
|
|
|
|
while ((*sPtr >= '0') && (*sPtr <= '7') && (*sPtr))
|
|
{
|
|
numString[numIndex++] = *sPtr;
|
|
sPtr++;
|
|
if (numIndex > 3)
|
|
{
|
|
sprintf(err_msg, "Escape sequence Octal numbers greater then\noctal o400 (256 decimal)! [more then 3 digits]");
|
|
yyerror(err_msg);
|
|
exitParser = 1;
|
|
}
|
|
}
|
|
|
|
/* now we should have string of octal number in numString */
|
|
if (!exitParser)
|
|
{
|
|
if (numIndex == 3)
|
|
tempNum = (hexTable[numString[0]] * 64) + (hexTable[numString[1]] * 8) + hexTable[numString[2]];
|
|
else if (numIndex == 2)
|
|
tempNum = (hexTable[numString[0]] * 8) + hexTable[numString[1]];
|
|
else
|
|
tempNum = hexTable[numString[0]];
|
|
|
|
if (tempNum > 255)
|
|
{
|
|
sprintf(err_msg, "Escape sequence Octal numbers greater then\noctal o400 (256 decimal)!");
|
|
yyerror(err_msg);
|
|
exitParser = 1;
|
|
}
|
|
|
|
if (!exitParser)
|
|
targetBuffer[strIndex++] = tempNum;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case 'x': /* ASCII hex */
|
|
{
|
|
/* we have to make sure the hex value is less then 256! */
|
|
numIndex = 0;
|
|
loopFlag = 1;
|
|
sPtr++; /* skip the 'x' */
|
|
|
|
while ((0xFF != hexTable[*sPtr]) && (*sPtr))
|
|
{
|
|
numString[numIndex++] = *sPtr;
|
|
sPtr++;
|
|
if (numIndex > 3)
|
|
{
|
|
sprintf(err_msg, "Escape sequence HEX numbers greater then 0x100\n(256 decimal)! [more then 3 digits]");
|
|
yyerror(err_msg);
|
|
exitParser = 1;
|
|
}
|
|
}
|
|
|
|
if (!exitParser)
|
|
{
|
|
if (numIndex == 3)
|
|
tempNum = (hexTable[numString[0]] * 0x100) + (hexTable[numString[1]] * 0x10) + hexTable[numString[2]];
|
|
else if (numIndex == 2)
|
|
tempNum = (hexTable[numString[0]] * 0x10) + hexTable[numString[1]];
|
|
else
|
|
tempNum = hexTable[numString[0]];
|
|
}
|
|
|
|
if (tempNum > 255)
|
|
{
|
|
sprintf(err_msg, "Escape sequence HEX numbers greater then 0x100\n(256 decimal)!");
|
|
yyerror(err_msg);
|
|
exitParser = 1;
|
|
}
|
|
|
|
if (!exitParser)
|
|
targetBuffer[strIndex++] = tempNum;
|
|
|
|
break;
|
|
}
|
|
|
|
case '8':
|
|
case '9':
|
|
{
|
|
/* they tried to do octal mode, but 8 and 9 is not in the definition of octal */
|
|
yyerror("Attempted to enter escape sequence with non-octal value");
|
|
exitParser = 1;
|
|
break;
|
|
}
|
|
|
|
default:
|
|
sprintf(err_msg, "Unknown ESCape sequence \\%c found in string.\n", *sPtr);
|
|
yyerror(err_msg);
|
|
exitParser = 1;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
targetBuffer[strIndex++] = *sPtr;
|
|
sPtr++;
|
|
}
|
|
}
|
|
|
|
|
|
void writeData(void *dataPtr, unsigned dataSize)
|
|
{
|
|
MIFFinsertChunkData(dataPtr, dataSize);
|
|
}
|
|
|
|
|
|
/* NOTE: includeBinary modifies fsize for the caller to access for adjusting the chunk size */
|
|
void includeBinary(char *fname)
|
|
{
|
|
char buffer[MAX_BUFFER_SIZE+1];
|
|
int fsize = 0;
|
|
|
|
fsize = MIFFloadRawData(fname, buffer, MAX_BUFFER_SIZE);
|
|
MIFFinsertChunkData(buffer, fsize);
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------------**
|
|
** Following functions below are all used for constructing, adding, and searching **
|
|
** the symbol table created by enum keyword. It is at this moment, set in a way **
|
|
** that if two identical symbols are added to the list, it will use the first **
|
|
** symbol added to the list and ignores the rest (because of forward search) **
|
|
**--------------------------------------------------------------------------------*/
|
|
void initSymTable(void)
|
|
{
|
|
memset(symbolEnumTable, 0, sizeof(struct structEnumSymTableType) * MAX_SYMBOLS);
|
|
currSymIndex = 0;
|
|
lastValue = -1;
|
|
}
|
|
|
|
/* Searches thru the symbol table and returns the index */
|
|
long searchEnumSymbolTable(char *symString)
|
|
{
|
|
long index = 0;
|
|
int found = 0;
|
|
while ((0 != symbolEnumTable[index].symbol[0]) && !found)
|
|
{
|
|
|
|
if (0 == strcmp(symbolEnumTable[index].symbol, symString))
|
|
{
|
|
found = 1;
|
|
break;
|
|
}
|
|
else
|
|
index++;
|
|
}
|
|
|
|
if (!found)
|
|
{
|
|
index = -1;
|
|
sprintf(err_msg, "Undefined symbol %s", symString);
|
|
yyerror(err_msg);
|
|
}
|
|
|
|
return(index);
|
|
}
|
|
|
|
long getEnumValue(long index)
|
|
{
|
|
if (index >= 0)
|
|
return(symbolEnumTable[index].value);
|
|
return(-1);
|
|
}
|
|
|
|
void addEnumSymbol(char *symString, long value)
|
|
{
|
|
if (MAX_SYMCHARS < strlen(symString))
|
|
{
|
|
/* somebody insane decided to use variable longer then max size! */
|
|
sprintf(err_msg, "%s is longer then %d characters! [value: %ld]", symString, MAX_SYMCHARS, value);
|
|
yyerror(err_msg);
|
|
}
|
|
else
|
|
{
|
|
strcpy(symbolEnumTable[currSymIndex].symbol, symString);
|
|
symbolEnumTable[currSymIndex].value = value;
|
|
lastValue = value;
|
|
currSymIndex++;
|
|
if (MAX_SYMBOLS < currSymIndex)
|
|
{
|
|
sprintf(err_msg, "Symbol table reached maximum size of %d", MAX_SYMBOLS);
|
|
yyerror(err_msg);
|
|
}
|
|
}
|
|
}
|