Converted data config file to text, added new parser stuff.

This commit is contained in:
n-a-c-h
2005-06-01 00:00:58 +00:00
parent 7956fc55da
commit 7cc94adb76
5 changed files with 1348 additions and 14 deletions

View File

@@ -18,6 +18,8 @@
#along with this program; if not, write to the Free Software
#Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
PSR=parsegen
CHIPDIR=chips
CPUDIR=cpu
DOSDIR=dos
@@ -73,11 +75,11 @@ ZIPOBJ=${ZIPDIR}/unzip.o ${ZIPDIR}/zpng.o
EFFECTSOBJ=${EFFECTSDIR}/burn.o ${EFFECTSDIR}/water.o ${EFFECTSDIR}/smoke.o
MAINOBJ=cfgload.o endmem.o init.o initc.o uic.o patch.o ui.o vcache.o version.o\
zmovie.o zstate.o debug.o zloader.o
zmovie.o zstate.o debug.o zloader.o cfgparse.o
OBJS=${CHIPSOBJ} ${CPUOBJ} ${WINOBJ} ${WINDOSOBJ} ${GUIOBJ} ${VIDEOBJ} ${MAINOBJ} ${NETOBJ} ${ZIPOBJ} ${EFFECTSOBJ} ${JMAOBJ}
.SUFFIXES: .cpp .c .asm
.SUFFIXES: .cpp .c .asm .psr
%.o: %.cpp
@CXX@ @CFLAGS@ -o $@ -c $<
@@ -88,9 +90,12 @@ OBJS=${CHIPSOBJ} ${CPUOBJ} ${WINOBJ} ${WINDOSOBJ} ${GUIOBJ} ${VIDEOBJ} ${MAINOBJ
%.o: %.asm
@NASMPATH@ @NFLAGS@ -o $@ $<
%.c: %.psr
${PSR} -D__LINUX__ $@ $<
ALL: @ZSNESEXE@
@ZSNESEXE@: ${OBJS}
@ZSNESEXE@: ${PSR} ${OBJS}
@CXX@ -o @ZSNESEXE@ ${OBJS} @CFLAGS@ @LDFLAGS@
${ZIPDIR}/zpng.o: ${ZIPDIR}/zpng.c ${ZIPDIR}/zpng.h
@@ -210,6 +215,10 @@ ${DOSDIR}/zsipx.o: ${DOSDIR}/zsipx.asm
${CHIPDIR}/sa1proc.o: ${CHIPDIR}/sa1proc.asm macros.mac
endmem.o: endmem.asm macros.mac
${PSR}: $<
cfgparse.c: $< ${PSR}
cfgparse${OE}: $<
${JMADIR}/7zlzma.o: ${JMADIR}/7zlzma.cpp ${JMADIR}/7z.h ${JMADIR}/iiostrm.h
${JMADIR}/crc32.o: ${JMADIR}/crc32.cpp ${JMADIR}/crc32.h
${JMADIR}/iiostrm.o: ${JMADIR}/iiostrm.cpp ${JMADIR}/iiostrm.h ${JMADIR}/crc32.h

356
zsnes/src/cfgparse.psr Normal file
View File

@@ -0,0 +1,356 @@
GUIRAdd db 15
GUIGAdd db 10
GUIBAdd db 31
mousewrap db 0 ; 0 = mouse boundries, 1 = mouse wrap
mouseshad db 1 ; 0 = no mouse shadow, 1 = mouse shadow
lastcursres db 0 ; 0 = go to load, 1 = go to previous menu, 2 = no menu
resetposn db 1 ; 0 = no window reset, 1 = window reset
NEWSYM GUIClick, db 0 ; 1 = mouse click enters/exits gui
GUIwinposx2 dd 0,5 ,60 ,30 ,55 ,50 ,65 ,5 ,30 ,20 ,10 ,80 ,65 ,20 ,70 ,50 ,3 ,0
GUIwinposy2 dd 0,20 ,70 ,30 ,20 ,22 ,36 ,20 ,30 ,20 ,40 ,70 ,60 ,30 ,65 ,50 ,22,0
; Default keys
; Sound Channels 0 .. 7, Save/Select/Load States, Fast Forward
; Exit, Load, Reset, BG Disables, Reset, Windowing, New Gfx, OffsetMode
; State Selection 0 .. 9
NEWSYM KeyDisableSC0, dd 63
NEWSYM KeyDisableSC1, dd 64
NEWSYM KeyDisableSC2, dd 65
NEWSYM KeyDisableSC3, dd 66
NEWSYM KeyDisableSC4, dd 67
NEWSYM KeyDisableSC5, dd 68
NEWSYM KeyDisableSC6, dd 87
NEWSYM KeyDisableSC7, dd 88
NEWSYM KeySaveState, dd 60
NEWSYM KeyStateSelct, dd 61
NEWSYM KeyLoadState, dd 62
NEWSYM KeyFastFrwrd, dd 41
NEWSYM KeyQuickExit, dd 0
NEWSYM KeyQuickLoad, dd 0
NEWSYM KeyQuickRst, dd 0
NEWSYM KeyBGDisble0, dd 2
NEWSYM KeyBGDisble1, dd 3
NEWSYM KeyBGDisble2, dd 4
NEWSYM KeyBGDisble3, dd 5
NEWSYM KeySprDisble, dd 6
NEWSYM KeyResetAll, dd 7
NEWSYM KeyExtraEnab, dd 8
NEWSYM KeyNewGfxSwt, dd 9
NEWSYM KeyWinDisble, dd 10
NEWSYM KeyOffsetMSw, dd 11
NEWSYM KeyStateSlc0, dd 0
NEWSYM KeyStateSlc1, dd 0
NEWSYM KeyStateSlc2, dd 0
NEWSYM KeyStateSlc3, dd 0
NEWSYM KeyStateSlc4, dd 0
NEWSYM KeyStateSlc5, dd 0
NEWSYM KeyStateSlc6, dd 0
NEWSYM KeyStateSlc7, dd 0
NEWSYM KeyStateSlc8, dd 0
NEWSYM KeyStateSlc9, dd 0
GUIshowallext db 0
GUIloadfntype db 0
NEWSYM pl3selk, dd 0 ; 3SELECT = SHIFT
NEWSYM pl3startk, dd 0 ; 3START = ENTER
NEWSYM pl3upk, dd 0 ; 3UP = up
NEWSYM pl3downk, dd 0 ; 3DOWN = down
NEWSYM pl3leftk, dd 0 ; 3LEFT = left
NEWSYM pl3rightk, dd 0 ; 3RIGHT = right
NEWSYM pl3Xk, dd 0 ; 3X = INS
NEWSYM pl3Ak, dd 0 ; 3A = HOME
NEWSYM pl3Lk, dd 0 ; 3L = PAGE UP
NEWSYM pl3Yk, dd 0 ; 3Y = DELETE
NEWSYM pl3Bk, dd 0 ; 3B = END
NEWSYM pl3Rk, dd 0 ; 3R = PAGE DOWN
NEWSYM pl4selk, dd 0 ; 4SELECT = SHIFT
NEWSYM pl4startk, dd 0 ; 4START = ENTER
NEWSYM pl4upk, dd 0 ; 4UP = up
NEWSYM pl4downk, dd 0 ; 4DOWN = down
NEWSYM pl4leftk, dd 0 ; 4LEFT = left
NEWSYM pl4rightk, dd 0 ; 4RIGHT = right
NEWSYM pl4Xk, dd 0 ; 4X = INS
NEWSYM pl4Ak, dd 0 ; 4A = HOME
NEWSYM pl4Lk, dd 0 ; 4L = PAGE UP
NEWSYM pl4Yk, dd 0 ; 4Y = DELETE
NEWSYM pl4Bk, dd 0 ; 4B = END
NEWSYM pl4Rk, dd 0 ; 4R = PAGE DOWN
NEWSYM TimeChecker, db 0 ; Future Reserved
GUISoundBuffer db 1 ; Sound Buffer Disabled
prevloadnames times 16*10 db 32
prevloaddname times 128*10 db 0
prevloadfname times 16*10 db 32
prevlfreeze db 0
GUIsmallscreenon db 0
GUIScreenScale db 0
NEWSYM pl3contrl, db 0
NEWSYM pl4contrl, db 0
NEWSYM pl1p209b, db 0
NEWSYM pl2p209b, db 0
NEWSYM pl3p209b, db 0
NEWSYM pl4p209b, db 0
JoyPad1Move db 0
NEWSYM FirstTimeData, db 0
NEWSYM PrevSWFix, db 0
NEWSYM CalibXmin, dd 0
NEWSYM CalibYmin, dd 0
NEWSYM CalibXmax, dd 0
NEWSYM CalibYmax, dd 0
NEWSYM CalibXmin209, dd 0
NEWSYM CalibYmin209, dd 0
NEWSYM CalibXmax209, dd 0
NEWSYM CalibYmax209, dd 0
NEWSYM maxskip, db 9
NEWSYM FPSAtStart, db 0
NEWSYM SidewinderFix, db 0
GUIInitSt1 db 'ATZ'
GUIInitSt2 db 'AT S0=0'
GUIDialSt db 'ATDT ',0
NEWSYM ComNum, db 2
NEWSYM ComIRQ, db 3
NEWSYM BaudRate, dd 3
NEWSYM pl1Atk, dd 0 ; Turbo A
NEWSYM pl1Btk, dd 0 ; Turbo B
NEWSYM pl1Xtk, dd 0 ; Turbo X
NEWSYM pl1Ytk, dd 0 ; Turbo Y
NEWSYM pl2Atk, dd 0 ; Turbo A
NEWSYM pl2Btk, dd 0 ; Turbo B
NEWSYM pl2Xtk, dd 0 ; Turbo X
NEWSYM pl2Ytk, dd 0 ; Turbo Y
NEWSYM pl3Atk, dd 0 ; Turbo A
NEWSYM pl3Btk, dd 0 ; Turbo B
NEWSYM pl3Xtk, dd 0 ; Turbo X
NEWSYM pl3Ytk, dd 0 ; Turbo Y
NEWSYM pl4Atk, dd 0 ; Turbo A
NEWSYM pl4Btk, dd 0 ; Turbo B
NEWSYM pl4Xtk, dd 0 ; Turbo X
NEWSYM pl4Ytk, dd 0 ; Turbo Y
NEWSYM Turbo30hz, db 0 ; Turbo at 30hz instead of 60hz
NEWSYM KeyVolUp, dd 0
NEWSYM KeyVolDown, dd 0
NEWSYM KeyFRateUp, dd 0
NEWSYM KeyFRateDown, dd 0
NEWSYM KeyQuickChat, dd 20
NEWSYM FossilUse, db 0
NEWSYM TimerEnable, db 0
NEWSYM Surround, db 0
NEWSYM InterSound, db 1
NEWSYM FastFwdToggle, db 0
NEWSYM En2xSaI, db 0
NEWSYM AutoLoadCht, db 0
NEWSYM KeyQuickSnapShot, dd 0
CheatSrcByteSize db 0
CheatSrcByteBase db 0
CheatSrcSearchType db 0
CheatUpperByteOnly db 0
NEWSYM SRAMSave5Sec, db 0
NEWSYM ReInitSoundC, db 0
NEWSYM OldGfxMode2 , db 0
NEWSYM PitchModEn , db 0
NEWSYM LatestSave , db 0
NEWSYM AutoState , db 0
NEWSYM OldVolume , db 1
NEWSYM BlankVar , db 1
NEWSYM pl1ULk, dd 0
NEWSYM pl1URk, dd 0
NEWSYM pl1DLk, dd 0
NEWSYM pl1DRk, dd 0
NEWSYM pl2ULk, dd 0
NEWSYM pl2URk, dd 0
NEWSYM pl2DLk, dd 0
NEWSYM pl2DRk, dd 0
NEWSYM pl3ULk, dd 0
NEWSYM pl3URk, dd 0
NEWSYM pl3DLk, dd 0
NEWSYM pl3DRk, dd 0
NEWSYM pl4ULk, dd 0
NEWSYM pl4URk, dd 0
NEWSYM pl4DLk, dd 0
NEWSYM pl4DRk, dd 0
NEWSYM LowPassFilterType, db 0
NEWSYM DontSavePath, db 0
NEWSYM ReCalib, db 1
NEWSYM GUIComboGameSpec, db 0
NEWSYM SoundNoiseDis, db 0 ; Disable Noise
NEWSYM Triplebufen, db 0
NEWSYM SoundBufEn, db 0
NEWSYM SPCDisable, db 0
NEWSYM RaisePitch, db 0
prevloadl db 0
prevloaddnamel times 512*10 db 0
prevloadfnamel times 512*10 db 0
%ifdef __WIN32__
NEWSYM PrevWinMode, db 2
NEWSYM PrevFSMode, db 6
%elifdef __LINUX__
NEWSYM PrevWinMode, db 2
NEWSYM PrevFSMode, db 3
%elifdef __MSDOS__
NEWSYM PrevWinMode, db 0
NEWSYM PrevFSMode, db 0
%endif
; Window position index
; GAME 1 > Load
; 2 > Pick state
; 12 > Reset
; 14 > Save/Open state
; CONFIG 3 > Inputs
; 4 > Options
; 5 > Video
; 6 > Sound
; 17 > Add-ons
; 18 > Chip cfg
; 19 > Paths
; 20 > Saves
; 21 > Speed
; CHEAT 7 > Add/Browse
; 13 > Search
;(NETPLAY 8 > Internet)
; MISC 9 > Misc keys
; 10 > GUI opns
; 11 > About
; 15 > Movie opn
; 16 > Key comb.
;# 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
OldWinPos db 0
GUIwinposx dd 0, 5,60,30,55,50,65, 5,30,20,10,80,65,20,70,50, 3,50,50, 5,10,20
GUIwinposxexp times 30 dd 0
GUIwinposy dd 0,20,70,30,20,22,36,20,30,20,30,20,60,30,65,50,22,60,20,20,20,20
GUIwinposyexp times 30 dd 0
NEWSYM GUIEffect, db 0
NEWSYM pl5selk, dd 0 ; 4SELECT = SHIFT
NEWSYM pl5startk, dd 0 ; 4START = ENTER
NEWSYM pl5upk, dd 0 ; 4UP = up
NEWSYM pl5downk, dd 0 ; 4DOWN = down
NEWSYM pl5leftk, dd 0 ; 4LEFT = left
NEWSYM pl5rightk, dd 0 ; 4RIGHT = right
NEWSYM pl5Xk, dd 0 ; 4X = INS
NEWSYM pl5Ak, dd 0 ; 4A = HOME
NEWSYM pl5Lk, dd 0 ; 4L = PAGE UP
NEWSYM pl5Yk, dd 0 ; 4Y = DELETE
NEWSYM pl5Bk, dd 0 ; 4B = END
NEWSYM pl5Rk, dd 0 ; 4R = PAGE DOWN
NEWSYM pl5ULk, dd 0
NEWSYM pl5URk, dd 0
NEWSYM pl5DLk, dd 0
NEWSYM pl5DRk, dd 0
NEWSYM pl5Atk, dd 0 ; Turbo A
NEWSYM pl5Btk, dd 0 ; Turbo B
NEWSYM pl5Xtk, dd 0 ; Turbo X
NEWSYM pl5Ytk, dd 0 ; Turbo Y
NEWSYM pl5contrl, db 0
NEWSYM pl1p209, db 0
NEWSYM pl2p209, db 0
NEWSYM pl3p209, db 0
NEWSYM pl4p209, db 0
NEWSYM pl5p209, db 0
NEWSYM GUIEnableTransp, db 0
NEWSYM Mode7HiRes16b, dd 0
NEWSYM NewEngEnForce, db 1
NEWSYM KeyRewind, dd 0
NEWSYM ChatNick, times 16 db 0
NEWSYM KeySlowDown, dd 0
NEWSYM UseCubicSpline, db 1
NEWSYM LargeSoundBuf, db 0
NEWSYM HighPriority, db 0
NEWSYM AlwaysOnTop, db 0
NEWSYM SaveMainWindowPos, db 1
NEWSYM MainWindowX, dw -1
NEWSYM MainWindowY, dw -1
NEWSYM ScreenShotFormat, db 0
NEWSYM pl1Ltk, dd 0 ; Turbo L
NEWSYM pl1Rtk, dd 0 ; Turbo R
NEWSYM pl2Ltk, dd 0 ; Turbo L
NEWSYM pl2Rtk, dd 0 ; Turbo R
NEWSYM pl3Ltk, dd 0 ; Turbo L
NEWSYM pl3Rtk, dd 0 ; Turbo R
NEWSYM pl4Ltk, dd 0 ; Turbo L
NEWSYM pl4Rtk, dd 0 ; Turbo R
NEWSYM pl5Ltk, dd 0 ; Turbo L
NEWSYM pl5Rtk, dd 0 ; Turbo R
NEWSYM GUITRAdd, db 0
NEWSYM GUITGAdd, db 10
NEWSYM GUITBAdd, db 31
NEWSYM GUIWRAdd, db 8
NEWSYM GUIWGAdd, db 8
NEWSYM GUIWBAdd, db 25
NEWSYM GrayscaleMode, db 0
NEWSYM MouseWheel, db 1
NEWSYM SmallMsgText, db 0
NEWSYM AllowMultipleInst, db 0
NEWSYM FilteredGUI, db 1
NEWSYM BilinearFilter, db 0
NEWSYM TripleBufferWin, db 0
NEWSYM ExclusiveSound, db 0
NEWSYM DisableScreenSaver, db 0
NEWSYM MMXSupport, db 1
NEWSYM TrapMouseCursor, db 1
NEWSYM KeyQuickClock, dd 0
NEWSYM KeyQuickSaveSPC, dd 0
NEWSYM AutoIncSaveSlot, db 0
NEWSYM TCPIPAddress, times 29 db 0
NEWSYM SoundInterpType, db 1
NEWSYM KeyDisplayFPS, dd 0
NEWSYM KeyIncStateSlot, dd 0
NEWSYM KeyDecStateSlot, dd 0
NEWSYM KeyUsePlayer1234, dd 0
NEWSYM hqFilter, db 0
NEWSYM reserved, db 0 ;old
NEWSYM scale2xFilter, db 0
NEWSYM st010difficulty, db 0 ;old
NEWSYM SnapPath, times 1024 db ""
NEWSYM SPCPath, times 1024 db ""
NEWSYM BSXPath, times 1024 db ""
NEWSYM STPath, times 1024 db ""
NEWSYM GNextPath, times 1024 db ""
NEWSYM SGPath, times 1024 db ""
NEWSYM FEOEZPath, times 1024 db ""
NEWSYM SJNSPath, times 1024 db ""
NEWSYM MDHPath, times 1024 db ""
NEWSYM SPL4Path, times 1024 db ""
NEWSYM AutoPatch, db 1
NEWSYM RomInfo, db 1
NEWSYM SRAMState, db 0
NEWSYM RewindStates, db 16
NEWSYM PrimaryBuffer, db 0
NEWSYM RewindFrames, db 15
NEWSYM KeyInsrtChap, dd 0
NEWSYM KeyNextChap, dd 0
NEWSYM KeyPrevChap, dd 0
NEWSYM MovieDisplayFrame, db 0
NEWSYM MovieStartMethod, db 0
NEWSYM EMUPauseKey, dd 0
NEWSYM INCRFrameKey, dd 0
NEWSYM PauseLoad, db 0
NEWSYM PauseRewind, db 0
NEWSYM KeyResetSpeed, dd 0
NEWSYM EmuSpeed, db 29 ; 29 = 1x, 0 = /30 and 58 = 30x
NEWSYM FFRatio, db 9 ; 0 = 2x, 28 = 30x
NEWSYM SDRatio, db 0 ; 0 = /2, 28 = /30
NEWSYM KeyEmuSpeedUp, dd 0
NEWSYM KeyEmuSpeedDown, dd 0
NEWSYM AllowUDLR, db 0

View File

@@ -63,13 +63,10 @@ unsigned char CalcCfgChecksum()
void GUIRestoreVars()
{
unsigned char read_cfg_vars(const char *);
FILE *cfg_fp;
if ((cfg_fp = fopen(GUIFName, "rb")))
{
fread(&GUIRAdd, 1, PHnumGUIsave, cfg_fp);
fclose(cfg_fp);
}
read_cfg_vars(GUIFName);
smallscreenon = (unsigned int)GUIsmallscreenon;
ScreenScale = GUIScreenScale;
@@ -106,14 +103,14 @@ void GUIRestoreVars()
void ExecGUISaveVars()
{
unsigned char write_cfg_vars(const char *);
FILE *cfg_fp;
if (ShowTimer == 1) { TimeChecker = CalcCfgChecksum(); }
if (!cfgdontsave && (cfg_fp = fopen(GUIFName, "wb")))
if (!cfgdontsave)
{
fwrite(&GUIRAdd, 1, PHnumGUIsave, cfg_fp);
fclose(cfg_fp);
write_cfg_vars(GUIFName);
}
if (NumComboGlob && (cfg_fp = fopen(GUICName, "wb")))

View File

@@ -50,6 +50,7 @@ JMADIR=jma
DELETECOMMAND=rm -f
TRUTH=;true
SLASH=/
PSR=parsegen
ASM=nasm
ASMOPT=-O1
ASMFLAGSORIG=
@@ -110,6 +111,7 @@ ifeq (${CROSS},no)
TRUTH=
DELETECOMMAND=del
SLASH=\${BLAHBLAHBLAH}
PSR=parsegen.exe
endif
ifeq (${OS},__MSDOS__)
@@ -183,7 +185,7 @@ JMAOBJ=${JMADIR}/7zlzma${OE} ${JMADIR}/crc32${OE} ${JMADIR}/iiostrm${OE}\
${JMADIR}/winout${OE} ${JMADIR}/zsnesjma${OE}
MAINOBJ=cfgload${OE} endmem${OE} init${OE} initc${OE} uic${OE} patch${OE}\
ui${OE} vcache${OE} version${OE} zmovie${OE} zstate${OE} zloader${OE}
ui${OE} vcache${OE} version${OE} zmovie${OE} zstate${OE} zloader${OE} cfgparse${OE}
DOSOBJORIG=${DOSDIR}/debug${OE} ${DOSDIR}/joy${OE} ${DOSDIR}/vesa2${OE}\
${DOSDIR}/initvid${OE} ${DOSDIR}/sw${OE} ${DOSDIR}/gppro${OE} ${DOSDIR}/vesa12${OE}
@@ -203,7 +205,7 @@ DELETEOBJS=${OBJS}
endif
.SUFFIXES: .c .cpp .asm
.SUFFIXES: .c .cpp .asm .psr
ifneq (${ENV},msvc)
%${OE}: %.c
@@ -228,10 +230,13 @@ else
${ASM} ${ASMOPT} -f win32 -D__WIN32__ -o $@ $<
endif
%.c: %.psr
${PSR} -D${OS} $@ $<
ALL: zsnes
${DELETECOMMAND} version${OE}
zsnes: ${OBJFIX} ${OBJS}
zsnes: ${PSR} ${OBJFIX} ${OBJS}
ifneq (${ENV},msvc)
${CPPC} ${STRIP} -o ${EXE} ${OBJS} ${LIBS}
else
@@ -362,6 +367,9 @@ ${WINDIR}/winlink${OE}: ${WINDIR}/winlink.cpp ${WINDIR}/resource.h
${OBJFIX}: $<
gcc -O3 -o $@ objfix.c
endif
${PSR}: $<
cfgparse.c: $< ${PSR}
cfgparse${OE}: $<
clean:

964
zsnes/src/parsegen.cpp Normal file
View File

@@ -0,0 +1,964 @@
/*
Config file handler creator by Nach (C) 2005
*/
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <sstream>
#include <set>
#include <stack>
using namespace std;
#include <errno.h>
#if defined(__MSDOS__) || defined(__WIN32__)
#define SLASH_STR "\\"
#else
#define SLASH_STR "/"
#endif
#define LINE_LENGTH 2048*10
char line[LINE_LENGTH];
set<string> defines;
stack<bool> ifs;
typedef vector<string> str_array;
str_array memsets;
enum cfg_value_type { single_value, quoted_value, parameterized_value };
struct cfg_var_struct
{
string name;
string object;
cfg_value_type type;
size_t size;
};
typedef vector<cfg_var_struct> cfg_var_array;
cfg_var_array cfg_vars;
size_t current_line_number = 0;
size_t current_column_number = 0;
void show_error_loc(const char *str)
{
cerr << "Error: parse problem occured at " << current_line_number << ":" << current_column_number << ". " << str << "." << endl;
}
void check_existing_var(string& str)
{
for (cfg_var_array::iterator i = cfg_vars.begin(); i != cfg_vars.end(); i++)
{
if (i->name == str)
{
cerr << "Duplicate definition of \"" << i->name << "\" found on line " << current_line_number << "." << endl;
break;
}
}
}
void add_config_var(string& name, const char *object, cfg_value_type val, size_t size)
{
check_existing_var(name);
cfg_var_struct cfg_var = {name, object, val, size};
cfg_vars.push_back(cfg_var);
//cout << "Name: " << name << "; Value Type: " << val << "; Size: " << size << endl;
}
//Find next matching character which is not escaped
char *find_next_match(char *str, char match_char)
{
char *pos = 0;
while (*str)
{
if (*str == match_char)
{
pos = str;
}
if (*str == '\\')
{
if (str[1])
{
str++;
}
else
{
break;
}
}
str++;
}
return(pos);
}
//This is like strtok(), except this understands quoted characters and updates error locations
char *get_token(char *str, char *delim)
{
static char *pos = 0;
char *token = 0;
if (str) //Start a new string?
{
pos = str;
}
if (pos)
{
//Skip delimiters
while (*pos && strchr(delim, *pos))
{
pos++;
}
if (*pos)
{
token = pos;
//Skip non-delimiters
while (*pos && !strchr(delim, *pos))
{
//Skip quoted characters
if ((*pos == '\"') || (*pos == '\''))
{
char *match_pos = 0;
if ((match_pos = find_next_match(pos+1, *pos)))
{
pos = match_pos;
}
}
pos++;
}
if (*pos)
{
*pos++ = '\0';
}
}
}
if (token) { current_column_number = token - line; }
return(token);
}
//Like strchr() but understands quoted characters
char *find_chr(char *str, char match_char)
{
char *pos = 0;
while (*str)
{
if (*str == match_char)
{
pos = str;
break;
}
//Skip quoted characters
if ((*str == '\"') || (*str == '\''))
{
char *match_pos = 0;
if ((match_pos = find_next_match(str+1, *str)))
{
str = match_pos;
}
}
str++;
}
return(pos);
}
//Convert $AB12 and 0AB12h style hex to 0xAB12 hex
string hex_convert(string str)
{
size_t dollar_pos;
while ((dollar_pos = str.find("$")) != string::npos)
{
str.replace(dollar_pos, 1, "0x");
}
while (tolower(str[0]) == 'h')
{
str.erase(0, 1);
}
size_t h_pos;
while ((h_pos = str.find_first_of("hH")) != string::npos)
{
size_t h_len = 1;
while ((h_pos-h_len) && isxdigit(str[h_pos-h_len]))
{
h_len++;
}
str.erase(h_pos, 1);
str.insert(h_pos-h_len+1, "0x");
}
return(str);
}
//Ascii numbers to integer, with support for mathematics in the string
ssize_t enhanced_atoi(const char *str)
{
ssize_t num = 0;
//Make sure result file doesn't exist
if (remove("eatio.res") && (errno != ENOENT))
{
cerr << "Error: Can not get accurate value information (eatio.res)." << endl;
}
//Biggest cheat of all time
ofstream out_stream("eatio.c");
if (out_stream)
{
out_stream << "#include <stdio.h>\n"
<< "int main()\n"
<< "{\n"
<< " FILE *fp = fopen(\"eatio.res\", \"w\");\n"
<< " if (fp)\n"
<< " {\n"
<< " fprintf(fp, \"%d\", " << hex_convert(str) << ");\n"
<< " fclose(fp);\n"
<< " }\n"
<< " return(0);\n"
<< "}\n\n";
out_stream.close();
#ifdef MSC_VER
system("cl /Foeatio.exe eatio.c");
#else
system("gcc -o eatio.exe eatio.c -s");
#endif
system("."SLASH_STR"eatio.exe");
remove("eatio.c");
remove("eatio.exe");
ifstream in_stream("eatio.res");
if (in_stream)
{
in_stream >> num;
in_stream.close();
}
else
{
cerr << "Error: Can not get accurate value information (eatio.res)." << endl;
}
remove("eatio.res");
}
return(num);
}
//Standard atoi(), but shows error if string isn't all a number
ssize_t safe_atoi(string& str)
{
if (!str.length()) { str = "X"; } //Force error
const char *p = str.c_str();
for (p = ((*p == '-') ? p+1 : p); *p; p++)
{
if (!isdigit(*p))
{
show_error_loc("Not a number");
}
}
return(atoi(str.c_str()));
}
#define var_type_is_char(var_type) !strcmp(var_type+strlen(var_type)-strlen("char"), "char")
#define var_type_is_short(var_type) !strcmp(var_type+strlen(var_type)-strlen("short"), "short")
#define var_type_is_int(var_type) !strcmp(var_type+strlen(var_type)-strlen("int"), "int")
#define short_scale "*sizeof(short)"
#define int_scale "*sizeof(int)"
//Return the comment from global line variable
char *get_comment()
{
char *comment = find_chr(line, ';');
if (comment)
{
*comment = 0;
comment++;
if (isspace(comment[strlen(comment)-1]))
{
comment[strlen(comment)-1] = 0;
}
}
return(comment);
}
void output_comment(ostream& c_stream, const char *comment)
{
if (comment)
{
c_stream << " //" << comment;
}
c_stream << "\n";
}
bool all_spaces(const char *str)
{
while (*str)
{
if (!isspace(*str)) { return(false); }
str++;
}
return(true);
}
//Convert asm types to C types
char *convert_asm_type(const char *str, bool unsigned_var = true)
{
char *var_type = 0;
if (!strcasecmp(str, "dd"))
{
var_type = "unsigned int";
}
else if (!strcasecmp(str, "dw"))
{
var_type = "unsigned short";
}
else if (!strcasecmp(str, "db"))
{
var_type = "unsigned char";
}
else
{
show_error_loc("Not a valid type");
}
if (var_type && !unsigned_var)
{
var_type += strlen("unsigned ");
}
return(var_type);
}
void output_parser_start(ostream& c_stream)
{
c_stream << "/*\n"
<< "Config file handler generated by Nach's Config file handler creator.\n"
<< "*/\n"
<< "\n"
<< "#include <stdio.h>\n"
<< "#include <stdlib.h>\n"
<< "#include <ctype.h>\n"
<< "#include <string.h>\n"
<< "\n"
<< "\n"
<< "#define LINE_LENGTH " << LINE_LENGTH << "\n"
<< "static char line[LINE_LENGTH];\n"
<< "\n"
<< "\n"
<< "static char *encode_string(const char *str)\n"
<< "{\n"
<< " size_t i = 0;\n"
<< " line[i++] = '\\\"';\n"
<< " while (*str)\n"
<< " {\n"
<< " if ((*str == '\\\\') ||\n"
<< " (*str == '\\\"') ||\n"
<< " (*str == '\\\'') ||\n"
<< " (*str == '\\n') ||\n"
<< " (*str == '\\t'))\n"
<< " {\n"
<< " line[i++] = '\\\\';\n"
<< " }\n"
<< " line[i++] = *str++;\n"
<< " }\n"
<< " line[i++] = '\\\"';\n"
<< " line[i] = 0;\n"
<< " return(line);\n"
<< "}\n"
<< "\n"
<< "static char *decode_string(char *str)\n"
<< "{\n"
<< " size_t str_len = strlen(str), i = 0;\n"
<< " char *dest = str;\n"
<< " \n"
<< " if ((str_len > 1) && (*str == '\\\"') && (str[str_len-1] == '\\\"'))\n"
<< " {\n"
<< " memmove(str, str+1, str_len-2);\n"
<< " str[str_len-2] = 0;\n"
<< "\n"
<< " while (*str)\n"
<< " {\n"
<< " if (*str == '\\\\')\n"
<< " {\n"
<< " str++;\n"
<< " }\n"
<< " dest[i++] = *str++;\n"
<< " }\n"
<< " }\n"
<< " dest[i] = 0;\n"
<< " return(dest);\n"
<< "}\n"
<< "\n"
<< "static char *find_next_match(char *str, char match_char)\n"
<< "{\n"
<< " char *pos = 0;\n"
<< "\n"
<< " while (*str)\n"
<< " {\n"
<< " if (*str == match_char)\n"
<< " {\n"
<< " pos = str;\n"
<< " }\n"
<< " if (*str == '\\\\')\n"
<< " {\n"
<< " if (str[1])\n"
<< " {\n"
<< " str++;\n"
<< " }\n"
<< " else\n"
<< " {\n"
<< " break;\n"
<< " }\n"
<< " }\n"
<< " str++;\n"
<< " }\n"
<< " return(pos);\n"
<< "}\n"
<< "\n"
<< "static char *find_str(char *str, char *match_str)\n"
<< "{\n"
<< " char *pos = 0;\n"
<< "\n"
<< " while (*str)\n"
<< " {\n"
<< " if (strchr(match_str, *str))\n"
<< " {\n"
<< " pos = str;\n"
<< " break;\n"
<< " }\n"
<< " if ((*str == '\\\"') || (*str == '\\\''))\n"
<< " {\n"
<< " char *match_pos = 0;\n"
<< " if ((match_pos = find_next_match(str+1, *str)))\n"
<< " {\n"
<< " str = match_pos;\n"
<< " }\n"
<< " }\n"
<< " str++;\n"
<< " }\n"
<< " return(pos); \n"
<< "}\n"
<< "\n"
<< "\n";
}
void output_init_var(ostream& c_stream)
{
c_stream << "\n"
<< "static void init_cfg_vars()\n"
<< "{\n"
<< " static unsigned char init_done = 0;\n"
<< " if (!init_done)\n"
<< " {\n"
<< " init_done = 1;\n"
<< "\n";
for (str_array::iterator i = memsets.begin(); i != memsets.end(); i++)
{
c_stream << " " << *i << "\n";
}
c_stream << " }\n"
<< "}\n";
}
void output_array_write(ostream& c_stream, const char *type)
{
c_stream << "\n"
<< "static void write_" << type << "_array(FILE *fp, const char *var_name, " << type << " *var, size_t size)\n"
<< "{\n"
<< " size_t i;\n"
<< " fprintf(fp, \"%s=%d\", var_name, (int)*var);\n"
<< " for (i = 1; i < size; i++)\n"
<< " {\n"
<< " fprintf(fp, \",%d\", (int)(var[i]));\n"
<< " }\n"
<< " fprintf(fp, \"\\n\");\n"
<< "}\n";
}
void output_write_var(ostream& c_stream)
{
output_array_write(c_stream, "char");
output_array_write(c_stream, "short");
output_array_write(c_stream, "int");
c_stream << "\n"
<< "unsigned char write_cfg_vars(const char *file)\n"
<< "{\n"
<< " FILE *fp = 0;\n"
<< "\n"
<< " init_cfg_vars();\n"
<< "\n"
<< " if ((fp = fopen(file, \"w\")))\n"
<< " {\n";
for (cfg_var_array::iterator i = cfg_vars.begin(); i != cfg_vars.end(); i++)
{
if (i->type == parameterized_value)
{
c_stream << " write_" << convert_asm_type(i->object.c_str(), false)
<< "_array(fp, \"" << i->name << "\", " << i->name << ", " << i->size << ");\n";
}
else
{
c_stream << " fprintf(fp, \"" << i->name << "=";
if (i->type == single_value)
{
c_stream << "%d\\n\", " << i->name;
}
else
{
c_stream << "%s\\n\", encode_string(" << i->name << ")";
}
c_stream << ");\n";
}
}
c_stream << " fclose(fp);\n"
<< "\n"
<< " return(1);\n"
<< " }\n"
<< " return(0);\n"
<< "}\n";
}
void output_array_read(ostream& c_stream, const char *type)
{
c_stream << "\n"
<< "static void read_" << type << "_array(char *line, " << type << " *var, size_t size)\n"
<< "{\n"
<< " size_t i;\n"
<< " char *token;\n"
<< " *var = atoi(strtok(line, \", \\t\\r\\n\"));\n"
<< " for (i = 1; (i < size) && (token = strtok(0, \", \\t\\r\\n\")); i++)\n"
<< " {\n"
<< " var[i] = atoi(token);\n"
<< " }\n"
<< "}\n";
}
void output_read_var(ostream& c_stream)
{
output_array_read(c_stream, "char");
output_array_read(c_stream, "short");
output_array_read(c_stream, "int");
c_stream << "\n"
<< "unsigned char read_cfg_vars(const char *file)\n"
<< "{\n"
<< " FILE *fp = 0;\n"
<< "\n"
<< " init_cfg_vars();\n"
<< "\n"
<< " if (!(fp = fopen(file, \"r\")))\n"
<< " {\n"
<< " write_cfg_vars(file);\n"
<< " return(0);\n"
<< " }\n"
<< "\n"
<< " while (!feof(fp))\n"
<< " {\n"
<< " char *p, *var, *value;\n"
<< "\n"
<< " fgets(line, LINE_LENGTH, fp);\n"
<< " if ((p = find_str(line, \";\"))) { *p = 0; }\n"
<< " if ((p = strchr(line, '=')))\n"
<< " {\n"
<< " *p = 0;\n"
<< " var = line;\n"
<< " value = p+1;\n"
<< " while (isspace(*var)) { var++; }\n"
<< " while (isspace(*value)) { value++; }\n"
<< " if ((p = find_str(var, \" \\t\\r\\n\"))) { *p = 0; }\n"
<< " if ((p = find_str(value, \" \\t\\r\\n\"))) { *p = 0; }\n"
<< " if (!*var || !*value) { continue; }\n"
<< " }\n"
<< " else\n"
<< " {\n"
<< " continue;\n"
<< " }\n"
<< "\n";
for (cfg_var_array::iterator i = cfg_vars.begin(); i != cfg_vars.end(); i++)
{
c_stream << " if (!strcmp(var, \"" + i->name + "\")) { ";
if (i->type == single_value)
{
c_stream << i->name << " = atoi(value);";
}
else if (i->type == parameterized_value)
{
c_stream << "read_" << convert_asm_type(i->object.c_str(), false)
<< "_array(value, " << i->name << ", " << i->size << ");";
}
else
{
c_stream << "*" << i->name << " = 0; "
<< "strncat(" << i->name << ", decode_string(value), sizeof(" << i->name << ")-1);";
}
c_stream << " }\n";
}
c_stream << " }\n"
<< "\n"
<< " fclose(fp);\n"
<< " write_cfg_vars(file);\n"
<< " return(1);\n"
<< "}\n";
}
void handle_directive(char *instruction, char *label)
{
if (!strcasecmp(instruction, "define"))
{
if (label)
{
defines.insert(label);
}
else
{
show_error_loc("Could not get define label");
}
}
else if (!strcasecmp(instruction, "undef"))
{
if (label)
{
defines.erase(label);
}
else
{
show_error_loc("Could not get undefine label");
}
}
else if (!strcasecmp(instruction, "ifdef"))
{
if (label)
{
if (defines.find(label) != defines.end())
{
ifs.push(true);
}
else
{
ifs.push(false);
}
}
else
{
show_error_loc("Could not get ifdef label");
}
}
else if (!strcasecmp(instruction, "else"))
{
if (label)
{
show_error_loc("Processor directive else does not accept labels");
}
else
{
if (ifs.empty())
{
show_error_loc("Processor directive else without ifdef");
}
else
{
bool process = !ifs.top();
ifs.pop();
ifs.push(process);
}
}
}
else if (!strcasecmp(instruction, "elifdef") || !strcasecmp(instruction, "elseifdef"))
{
if (label)
{
if (ifs.top())
{
ifs.pop();
ifs.push(false);
}
else if (defines.find(label) != defines.end())
{
ifs.pop();
ifs.push(true);
}
}
else
{
show_error_loc("Could not get elseifdef label");
}
}
else if (!strcasecmp(instruction, "endif"))
{
if (label)
{
show_error_loc("Processor directive endif does not accept labels");
}
else
{
if (ifs.empty())
{
show_error_loc("Processor directive endif without ifdef");
}
else
{
ifs.pop();
}
}
}
else
{
show_error_loc("Unknown processor directive");
}
}
void parser_generate(istream& psr_stream, ostream& c_stream)
{
output_parser_start(c_stream);
while (!psr_stream.eof())
{
char *token;
char *comment;
psr_stream.getline(line, LINE_LENGTH);
current_line_number++;
comment = get_comment();
if (all_spaces(line))
{
output_comment(c_stream, comment);
continue;
}
if ((token = get_token(line, " ")) &&
(strcasecmp(token, "NEWSYM") || (token = get_token(0, " ,"))))
{
if ((*token == '#') || (*token == '%'))
{
handle_directive(token+1, get_token(0, " "));
continue;
}
if (!ifs.empty() && !ifs.top())
{
continue;
}
string varname = token;
if ((token = get_token(0, " ,")))
{
size_t array = 0;
if (strcasecmp(token, "times") ||
((token = get_token(0, " ")) && (array = enhanced_atoi(token)) && (token = get_token(0, " "))))
{
char *asm_type = token;
char *var_type = convert_asm_type(asm_type);
if (var_type)
{
string initial_value = get_token(0, " ,\n");
if (((initial_value[0] == '\"') && (initial_value[initial_value.length()-1] == '\"')) ||
((initial_value[0] == '\'') && (initial_value[initial_value.length()-1] == '\'')))
{
//Make sure it's double quoted
initial_value[0] = '\"';
initial_value[initial_value.length()-1] = '\"';
if (!array)
{
array = initial_value.length()-1; //Size minus quotes plus null
}
c_stream << "char " << varname << "[" << array << "];";
ostringstream memset_line;
if (initial_value.length()-2 < array)
{
memset_line << "strcpy(" << varname << ", " << initial_value << ");";
}
else
{
memset_line << "strncpy(" << varname << ", " << initial_value << ", " << (array-1) << "); "
<< varname << "[" << array << "] = 0;";
}
memsets.push_back(memset_line.str());
add_config_var(varname, asm_type, quoted_value, 0);
}
else
{
ssize_t init_value_num = safe_atoi(initial_value);
if (init_value_num < 0)
{
var_type += strlen("unsigned ");
}
c_stream << var_type << " " << varname;
if (array)
{
if (var_type_is_char(var_type) || !init_value_num)
{
c_stream << "[" << array << "]";
ostringstream memset_line;
memset_line << "memset(" << varname << ", " << init_value_num << ", " << array;
if (var_type_is_short(var_type))
{
memset_line << short_scale;
}
else if (var_type_is_int(var_type))
{
memset_line << int_scale;
}
memset_line << ");";
memsets.push_back(memset_line.str());
}
else
{
c_stream << "[" << array << "] = {";
for (size_t i = array; i > 1; i--)
{
c_stream << init_value_num << ",";
}
c_stream << init_value_num << "%d}";
}
add_config_var(varname, asm_type, parameterized_value, array);
}
else
{
if ((token = get_token(0, " ,\n")))
{
array = 1;
c_stream << "[] = {" << init_value_num;
do
{
c_stream << "," << atoi(token);
array++;
} while((token = get_token(0, " ,\n")));
c_stream << "}";
add_config_var(varname, asm_type, parameterized_value, array);
}
else
{
c_stream << " = " << init_value_num;
add_config_var(varname, asm_type, single_value, 0);
}
}
c_stream << ";";
}
}
//Else already handled
}
else
{
show_error_loc("Could not get array size");
}
}
else
{
show_error_loc("Could not get type");
}
}
else
{
show_error_loc("Could not get variable name");
}
output_comment(c_stream, comment);
}
output_init_var(c_stream);
output_write_var(c_stream);
output_read_var(c_stream);
c_stream << "\n";
if (!ifs.empty())
{
cerr << "Error: " << ifs.size() << " ifdef segments have no endif." << endl;
}
}
int main(size_t argc, const char **argv)
{
size_t param_pos = 1;
for (; param_pos < argc; param_pos++)
{
if (!strncmp(argv[param_pos], "-D", 2))
{
defines.insert(argv[param_pos]+2);
}
else
{
break;
}
}
if ((argc-param_pos) != 2)
{
cout << "Config file handler creator by Nach (C) 2005\n"
<< "\n"
<< "Usage:\n"
<< "parsegen [-Ddefine] <output> <input>\n"
<< "\n"
<< " -Ddefine Define a processor director. Example: -D__LINUX__\n"
<< " Can specify multiple defines.\n"
<< endl;
return(1);
}
const char *psr_file = argv[param_pos+1], *c_file = argv[param_pos];
int ret_val = 0;
ifstream psr_stream(psr_file);
if (psr_stream)
{
ofstream c_stream(c_file);
if (c_stream)
{
parser_generate(psr_stream, c_stream);
c_stream.close();
}
else
{
cerr << "Error opening " << c_file << " for writing." << endl;
ret_val |= 2;
}
psr_stream.close();
}
else
{
cerr << "Error opening " << psr_file << " for reading." << endl;
ret_val |= 4;
}
return(0);
}