From 69894f75254cd630e2e4fe1422044c6b7d6adb5f Mon Sep 17 00:00:00 2001 From: Wiimm Date: Wed, 3 Feb 2021 16:42:38 +0100 Subject: SZS 2.23a --- project/src/lib-lecode.c | 2042 +--------------------------------------------- 1 file changed, 4 insertions(+), 2038 deletions(-) (limited to 'project/src/lib-lecode.c') diff --git a/project/src/lib-lecode.c b/project/src/lib-lecode.c index 5e7aa32..0222315 100644 --- a/project/src/lib-lecode.c +++ b/project/src/lib-lecode.c @@ -17,7 +17,7 @@ * This file is part of the SZS project. * * Visit https://szs.wiimm.de/ for project details and sources. * * * - * Copyright (c) 2011-2020 by Dirk Clemens * + * Copyright (c) 2011-2021 by Dirk Clemens * * * *************************************************************************** * * @@ -41,7 +41,6 @@ #include "lib-mkw.h" #include "lib-szs.h" #include "lpar.inc" -#include "lex.inc" #include @@ -70,43 +69,6 @@ int opt_reserved_1bb = -1; bool opt_complete = false; -// -/////////////////////////////////////////////////////////////////////////////// -/////////////// LEX action log /////////////// -/////////////////////////////////////////////////////////////////////////////// - -bool LEX_ACTION_LOG ( bool is_patch, const char * format, ... ) -{ - #if HAVE_PRINT - { - char buf[200]; - snprintf(buf,sizeof(buf),">>>[LEX]<<< %s",format); - va_list arg; - va_start(arg,format); - PRINT_ARG_FUNC(buf,arg); - va_end(arg); - } - #endif - -// if ( verbose > 2 || KMP_MODE & KMPMD_LOG || is_patch && ~KMP_MODE & KMPMD_SILENT ) - if ( verbose > 2 || is_patch ) - { - fflush(stdout); - fprintf(stdlog," %s>[LEX]%s ", - colset->heading, - is_patch ? colset->highlight : colset->info ); - va_list arg; - va_start(arg,format); - vfprintf(stdlog,format,arg); - va_end(arg); - fputs(colset->reset,stdlog); - fflush(stdlog); - return true; - } - - return false; -} - // /////////////////////////////////////////////////////////////////////////////// /////////////// helpers /////////////// @@ -2152,6 +2114,9 @@ enumError ApplyCTCODE ( le_analyse_t * ana, const ctcode_t * ctcode ) //--- setup + if (ctcode->lpar) + ana->lpar = *ctcode->lpar; + ana->n_cup_track = 0; ana->n_cup_arena = 0; ana->n_slot = 0; @@ -2701,2005 +2666,6 @@ enumError ScanTextLPAR_CHAT return ERR_OK; } -// -/////////////////////////////////////////////////////////////////////////////// -/////////////// lecode extension LEX /////////////// -/////////////////////////////////////////////////////////////////////////////// - -enumError ScanLexFile - ( cvp data, uint data_size, lex_stream_func func, - cvp user_ptr, int user_int ) -{ - if ( !data || data_size < sizeof(lex_header_t) ) - return ERR_INVALID_DATA; - - const lex_header_t *hd = (lex_header_t*)data; - if (memcmp(hd->magic,LEX_BIN_MAGIC,4)) - return ERR_INVALID_DATA; - - if ( ntohs(hd->major_version) != LEX_MAJOR_VERSION ) - return ERR_INVALID_VERSION; - - const uint size = ntohl(hd->size); - const uint off = ntohl(hd->element_off); - if ( (size&3) || size > data_size || (off&3) || off + 4 > size ) - return ERR_INVALID_DATA; - - return ScanLexElements((u8*)data+off,size-off,func,user_ptr,user_int); -} - -/////////////////////////////////////////////////////////////////////////////// - -enumError ScanLexElements - ( cvp data, uint data_size, lex_stream_func func, - cvp user_ptr, int user_int ) -{ - if ( !data || !data_size || (data_size&3) ) - return ERR_INVALID_DATA; - - enumError max_err = ERR_OK; - - uint off = 0; - while ( off < data_size ) - { - const lex_element_t *s = (lex_element_t*)( (u8*)data + off ); - - const u32 magic = ntohl(s->magic); - if (!magic) - break; - - const uint size = ntohl(s->size); - off += sizeof(lex_element_t) + size; - if ( (size&3) || off > data_size ) - return ERR_INVALID_DATA; - - PRINT("LEX SECTION: %.4s, size:%x\n",PrintID(&s->magic,4,0),size); - if (func) - { - const int err = func(magic,s->data,size,user_ptr,user_int); - if (err<0) - return -err; - if ( max_err < err ) - max_err = err; - } - } - - return max_err; -} - -/////////////////////////////////////////////////////////////////////////////// - -lex_element_t * FindLexElement ( lex_header_t *head, uint data_size, u32 magic ) -{ - if ( !head || data_size <= sizeof(lex_header_t) || (data_size&3) ) - return 0; - - uint file_size = ntohl(head->size); - if ( file_size > data_size ) - return 0; - file_size -= sizeof(lex_element_t); - - uint offset = ntohl(head->element_off); - if ( offset > file_size ) - return 0; - - magic = htonl(magic); - for(;;) - { - lex_element_t *elem = (lex_element_t*)((u8*)head + offset); - offset += 8 + ntohl(elem->size); - if ( offset > file_size ) - return 0; - if ( elem->magic == magic ) - return elem; - } -} - -// -/////////////////////////////////////////////////////////////////////////////// -/////////////// fix lex items /////////////// -/////////////////////////////////////////////////////////////////////////////// - -typedef void (*FixElementFunc) ( lex_t * lex, lex_item_t * item ); - -/////////////////////////////////////////////////////////////////////////////// - -static void FixLEXElement_SET1 ( lex_set1_t *set1 ) -{ - DASSERT(set1); - - uint i; - for ( i = 0; i < 3; i++ ) - { - float f = bef4(set1->item_factor.v+i); - if ( !isnormal(f) || f < 1.0 ) - write_bef4(set1->item_factor.v+i,1.0); - } -} - -//----------------------------------------------------------------------------- - -static void FixLEXItem_SET1 -( - lex_t * lex, // LEX data structure - lex_item_t * item // item to fix -) -{ - DASSERT(lex); - DASSERT(item); - DASSERT( ntohl(item->elem.size) >= sizeof(lex_set1_t) ); - - lex_set1_t *set1 = (lex_set1_t*)item->elem.data; - FixLEXElement_SET1(set1); -} - -// -/////////////////////////////////////////////////////////////////////////////// -/////////////// lex_t helpers /////////////// -/////////////////////////////////////////////////////////////////////////////// - -static lex_item_t * FindElementLEX -( - const lex_t * lex, // LEX data structure - u32 magic // magic -) -{ - magic = htonl(magic); - - uint i; - lex_item_t **ss; - for ( i = 0, ss = lex->item; i < lex->item_used; i++, ss++ ) - if ( (*ss)->elem.magic == magic ) - return *ss; - return 0; -} - -/////////////////////////////////////////////////////////////////////////////// - -static uint GetLexSortOrder ( u32 magic ) -{ - switch(magic) - { - case LEXS_SET1: return 1; - case LEXS_TEST: return 9; - default: return 2; - } -} - -/////////////////////////////////////////////////////////////////////////////// - -static void UpdateHaveLex ( lex_t *lex ) -{ - DASSERT(lex); - uint have_lex = 0; - - uint i; - lex_item_t **ss; - for ( i = 0, ss = lex->item; i < lex->item_used; i++, ss++ ) - { - const u32 magic = ntohl((*ss)->elem.magic); - const uint size = ntohl((*ss)->elem.size); - uint j; - for ( j = 0; j < HAVELEX__N; j++ ) - if ( magic == have_lex_info[j].magic && size >= have_lex_info[j].min_size ) - { - have_lex |= 1 << j; - break; - } - } - - lex->have_lex = have_lex; -} - -/////////////////////////////////////////////////////////////////////////////// - -static lex_item_t * AppendElementLEX -( - lex_t * lex, // LEX data structure - u32 magic, // magic - const void * data, // data of section - uint size, // size of 'data' - bool overwrite // false: abort if exists and return 0 - // true: overwrite -) -{ - DASSERT(lex); - DASSERT( data || !size ); - - - //--- add have_lex - - uint i; - for ( i = 0; i < HAVELEX__N; i++ ) - if ( magic == have_lex_info[i].magic && size >= have_lex_info[i].min_size ) - { - lex->have_lex |= 1 << i; - break; - } - - - //--- check if already exists - - lex_item_t **ss; - const u32 be_magic = htonl(magic); - for ( i = 0, ss = lex->item; i < lex->item_used; i++, ss++ ) - if ( (*ss)->elem.magic == be_magic ) - { - if (!overwrite) - return 0; - break; - } - - - //--- grow item list if necessary - - if ( i == lex->item_size ) - { - lex->item_size = lex->item_size + 30; - lex->item = REALLOC( lex->item, lex->item_size * sizeof(*lex->item) ); - // 'ss' becomes invalid! - ss = lex->item + i; - } - - if ( i < lex->item_used ) - FREE(*ss); - else - lex->item_used++; - - - //--- fix item size - - uint size4 = ALIGN32(size,4); - FixElementFunc fix_func = 0; - - switch(magic) - { - case LEXS_SET1: - fix_func = FixLEXItem_SET1; - if ( size4 < sizeof(lex_set1_t) ) - size4 = ALIGN32(sizeof(lex_set1_t),4); - break; - - case LEXS_TEST: - if ( size4 < sizeof(lex_test_t) ) - size4 = ALIGN32(sizeof(lex_test_t),4); - break; - } - - - //--- setup item - - lex_item_t *s = MALLOC(sizeof(lex_item_t)+size4); - *ss = s; - s->sort_order = GetLexSortOrder(magic); - s->insert_order = i; - s->elem.magic = be_magic; - s->elem.size = htonl(size4); - memcpy(s->elem.data,data,size); - if ( size < size4 ) - memset(s->elem.data+size,0,size4-size); - - if (fix_func) - fix_func(lex,s); - - return s; -} - -/////////////////////////////////////////////////////////////////////////////// - -static bool RemoveElementLEX -( - lex_t *lex, // LEX data structure - const lex_item_t *li // element to remove (robust) -) -{ - if ( !li || !li->elem.magic ) - return 0; - - uint i; - lex_item_t **ss; - for ( i = 0, ss = lex->item; i < lex->item_used; i++, ss++ ) - if ( *ss == li ) - { - memmove(ss,ss+1,lex->item_used-i); - lex->item_used--; - FREE((lex_item_t*)li); - UpdateHaveLex(lex); - return true; - } - return false; -} - -//----------------------------------------------------------------------------- - -static uint RemoveElementByMagicLEX -( - lex_t *lex, // LEX data structure - u32 magic // magic -) -{ - if (!magic) - return 0; - - uint count = 0; - for(;;) - { - lex_item_t *li = FindElementLEX(lex,magic); - if (!li) - return count; - count += RemoveElementLEX(lex,li); - } -} - -/////////////////////////////////////////////////////////////////////////////// - -static int cmp_lex_item ( const lex_item_t ** pa, const lex_item_t ** pb ) -{ - const lex_item_t *a = *pa; - const lex_item_t *b = *pb; - noPRINT(">> SORT: %u.%u : %u.%u\n", - a->sort_order, a->insert_order, - b->sort_order, b->insert_order ); - - int res = (int)a->sort_order - (int)b->sort_order; - return res ? res : (int)a->insert_order - (int)b->insert_order; -} - -//----------------------------------------------------------------------------- - -static void SortItemsLEX -( - lex_t * lex // LEX data structure -) -{ - if ( lex->item_used > 1 ) - qsort( lex->item, lex->item_used, sizeof(*lex->item), - (qsort_func)cmp_lex_item ); -} - -// -/////////////////////////////////////////////////////////////////////////////// -/////////////// have lex support /////////////// -/////////////////////////////////////////////////////////////////////////////// -// order is important, compare have_lex_t and ct.wiimm.de - -const have_lex_info_t have_lex_info[HAVELEX__N] = -{ - { LEXS_SET1, "set1", 1 }, - { LEXS_CANN, "cannon", 0 }, - { LEXS_TEST, "test", 1 }, - { LEXS_HIPT, "hidepos", sizeof(lex_hipt_rule_t) }, - //--- add new sections here (order is important) -}; - -/////////////////////////////////////////////////////////////////////////////// - -ccp CreateSectionInfoLEX - ( have_lex_t special, bool add_value, ccp return_if_empty ) -{ - static char buf[500]; - char *dest = buf; - - if (add_value) - dest = snprintfE( dest, buf+sizeof(buf), "%u=" , special ); - - uint i, mask; - ccp sep = ""; - for ( i = 0, mask = 1; i < HAVELEX__N; i++, mask <<= 1 ) - if ( special & mask ) - { - dest = StringCat2E(dest,buf+sizeof(buf),sep,have_lex_info[i].name); - sep = ","; - } - - return dest == buf ? return_if_empty : CopyCircBuf0(buf,dest-buf); -} - -// -/////////////////////////////////////////////////////////////////////////////// -/////////////// LEX setup /////////////// -/////////////////////////////////////////////////////////////////////////////// - -void InitializeLEX ( lex_t * lex ) -{ - DASSERT(lex); - memset(lex,0,sizeof(*lex)); - - lex->fname = EmptyString; -} - -/////////////////////////////////////////////////////////////////////////////// - -void ResetLEX ( lex_t * lex ) -{ - if (lex) - { - FreeString(lex->fname); - if (lex->raw_data) - FREE(lex->raw_data); - - if (lex->item) - { - uint i; - for ( i = 0; i < lex->item_used; i++ ) - if (lex->item[i]) - FREE(lex->item[i]); - FREE(lex->item); - } - InitializeLEX(lex); - } -} - -/////////////////////////////////////////////////////////////////////////////// - -void UpdateLEX ( lex_t * lex, bool add_missing, bool add_test ) -{ - DASSERT(lex); - - if ( add_missing && lex->develop ) - { - } - - if (add_missing) - { - //--- SET1 - AppendSet1LEX(lex,false); - - //--- CANN - AppendCannLEX(lex,false); - - //--- HIPT - AppendHiptLEX(lex,false); - } - - if (add_test) //--- TEST - AppendTestLEX(lex,false); - - SortItemsLEX(lex); -} - -//----------------------------------------------------------------------------- - -lex_item_t * AppendSet1LEX ( lex_t * lex, bool overwrite ) -{ - lex_set1_t set1; - memset(&set1,0,sizeof(set1)); - // AppendElementLE() does call FixLEXItem_SET1() - return AppendElementLEX(lex,LEXS_SET1,&set1,sizeof(set1),false); -} - -//----------------------------------------------------------------------------- - -lex_item_t * AppendCannLEX ( lex_t * lex, bool overwrite ) -{ - return AppendElementLEX( lex, LEXS_CANN, CannonDataLEX, - sizeof(CannonDataLEX), overwrite); -} - -//----------------------------------------------------------------------------- - -lex_item_t * AppendHiptLEX ( lex_t * lex, bool overwrite ) -{ - return AppendElementLEX( lex, LEXS_HIPT, 0, 0, overwrite); -} - -//----------------------------------------------------------------------------- - -lex_item_t * AppendTestLEX ( lex_t * lex, bool overwrite ) -{ - return AppendElementLEX( lex, LEXS_TEST, TestDataLEX, - sizeof(TestDataLEX), overwrite); -} - -/////////////////////////////////////////////////////////////////////////////// - -void DumpElementsLEX ( FILE *f, lex_t *lex, bool hexdump ) -{ - DASSERT(f); - DASSERT(lex); - - fprintf(f,"LEX SECTIONS: %u/%u\n",lex->item_used,lex->item_size); - - uint i; - for ( i = 0; i < lex->item_used; i++ ) - { - lex_item_t *s = lex->item[i]; - const uint size = ntohl(s->elem.size); - fprintf(f," %-4.4s %08x, size: %5u = 0x%04x\n", - PrintID(&s->elem.magic,4,0), s->elem.magic, size, size ); - if ( size && hexdump ) - HexDump16(f,8,0,s->elem.data,size); - } -} - -// -/////////////////////////////////////////////////////////////////////////////// -/////////////// lex parser functions /////////////// -/////////////////////////////////////////////////////////////////////////////// - -static enumError F_isLEX -( - struct Var_t * res, // store result here - struct Var_t * param, // parameters, modified - uint n_param, // number of parameters - struct ScanInfo_t * si, // not NULL: use for error messages - const FuncParam_t * fpar // pointer to user parameter -) -{ - DASSERT(res); - DASSERT(param); - - uint result = 0; - if ( si && si->lex ) - { - result = 1; - - if (si->lex->fname) - { - ccp fname = strrchr(si->lex->fname,'/'); - if (fname) - fname++; - else - fname = si->lex->fname; - - if ( !strcasecmp(fname,"course.lex") - || !strcasecmp(fname,"course.txt") - || !strcasecmp(fname,"course.txt.lex") ) - { - result = 2; - } - } - } - - res->i = result; - res->mode = VAR_INT; - return ERR_OK; -} - -/////////////////////////////////////////////////////////////////////////////// - -static const struct FuncTable_t lex_func_tab[] = -{ - { 0, 0, "ISLEX", F_isLEX, 0, // replace only function call - "int", "isLEX()", 0 }, // but not info - - {0,0,0,0,0,0,0,0} -}; - -// -/////////////////////////////////////////////////////////////////////////////// -/////////////// setup lex parser /////////////// -/////////////////////////////////////////////////////////////////////////////// - -const VarMap_t * SetupVarsLEX() -{ - static VarMap_t vm = {0}; - if (!vm.used) - { - DefineMkwVars(&vm); - DefineParserFuncTab(lex_func_tab,FF_LEX); - DefineParserVars(&vm); - } - - return &vm; -} - -// -/////////////////////////////////////////////////////////////////////////////// -/////////////// ScanRawLEX() /////////////// -/////////////////////////////////////////////////////////////////////////////// - -enumError DumpLEXFunc - ( u32 magic, const u8 *data, uint size, cvp user_ptr, int user_int ) -{ - u32 m = htonl(magic); - printf(" %s 0x%08x, %5u = 0x%04x bytes\n", - PrintID(&m,4,0), magic, size, size ); - if ( user_int < 0 || user_int >= 0x10 ) - { - if ( user_int > 0 && size > user_int ) - size = user_int; - HexDump16(stdout,5,0,data,size); - putchar('\n'); - } - return ERR_OK; -} - -//----------------------------------------------------------------------------- - -enumError ScanLEXFunc - ( u32 magic, const u8 *data, uint size, cvp user_ptr, int user_int ) -{ - #if HAVE_PRINT - u32 m = htonl(magic); - PRINT(">>>>> %-4.4s %08x : size: %u = 0x%x\n", - PrintID(&m,4,0), magic, size, size ); - #endif - - lex_t *lex = (lex_t*)user_ptr; - DASSERT(lex); - - switch (magic) - { - case LEXS_TERMINATE: - case LEXS_IGNORE: - // ignore - break; - - default: - AppendElementLEX(lex,magic,data,size,true); - #if HAVE_PRINT0 - if (logging>1) - DumpElementsLEX(stdout,lex,logging>2); - #endif - } - return ERR_OK; -} - -//----------------------------------------------------------------------------- - -enumError ScanRawLEX -( - lex_t * lex, // LEX data structure - bool init_lex, // true: initialize 'lex' first - const void * data, // data to scan - uint data_size, // size of 'data' - uint dump_mode // 0: add element to lex->item - // 1: dump scanned elements - // >=0x10: add hexdump of max # bytes -) -{ - DASSERT(lex); - if (init_lex) - InitializeLEX(lex); - - if ( IsValidLEX(data,data_size,data_size,lex->fname) >= VALID_ERROR ) - { - return ERROR0(ERR_INVALID_DATA, - "Invalid LEX file: %s\n" - "Add option --lex=force or --force to ignore some validity checks.", - lex->fname ? lex->fname : "?" ); - } - - lex->fform = FF_LEX; - enumError err = ScanLexFile( data, data_size, - dump_mode ? DumpLEXFunc : ScanLEXFunc, lex, dump_mode ); - if (err) - ERROR0(err,"Scanning of LEX file failed: %s\n",lex->fname); - else - UpdateLEX(lex,opt_complete,false); - - if (logging>0) - DumpElementsLEX(stdout,lex,logging>2); - return err; -} - -// -/////////////////////////////////////////////////////////////////////////////// -/////////////// ScanTextLEX() /////////////// -/////////////////////////////////////////////////////////////////////////////// -// [[lex_section_id]] - -typedef enum lex_section_id -{ - LID_UNKNOWN, - LID_IGNORE, - LID_SETUP, - LID_HEXDUMP, - - LID_SETTINGS1, - LID_CANNON, - LID_HIDE_PT, - LID_TEST, -} -lex_section_id; - -/////////////////////////////////////////////////////////////////////////////// - -static const KeywordTab_t lex_section_name[] = -{ - //------------------------------------------------------------------------ - // ID NAME INFO unused - //------------------------------------------------------------------------ - - { LID_IGNORE, "END", "--", 0 }, - { LID_SETUP, "SETUP", "Setup", 0 }, - { LID_HEXDUMP, "HEXDUMP", "Hexdump of unknown section", 0 }, - - { LID_SETTINGS1, "SET1", "Basic settings", 0 }, - { LID_CANNON, "CANN", "Cannon settings", 0 }, - { LID_HIDE_PT, "HIPT", "Hide position tracker", 0 }, - { LID_TEST, "TEST", "Test case", 0 }, - - { 0,0,0,0 } -}; - -/////////////////////////////////////////////////////////////////////////////// - -static const KeywordTab_t lex_offline_online[] = -{ - { LEX_OO_AUTO, "AUTO", "0", 0 }, - { LEX_OO_OFFLINE, "OFFLINE", "1", 0 }, - { LEX_OO_OFFLINE, "NEVER", 0, 0 }, - { LEX_OO_ONLINE, "ONLINE", "2", 0 }, - { LEX_OO_ONLINE, "ALWAYS", 0, 0 }, - { -9, "OFF", "-1", -1 }, - { 0,0,0,0 } -}; - -/////////////////////////////////////////////////////////////////////////////// - -static const KeywordTab_t lex_game_mode[] = -{ - { LEX_GMODE_AUTO, "AUTO", "0", -1 }, - { LEX_GMODE_STD, "STANDARD", "1", KMP_GMODE_STD }, - { LEX_GMODE_STD, "STD", 0, KMP_GMODE_STD }, - { LEX_GMODE_BALLOON, "BALLOON", "2", KMP_GMODE_BALLOON }, - { LEX_GMODE_COIN, "COIN", "3", KMP_GMODE_COIN }, - { LEX_GMODE_VERSUS, "VERSUS", "4", KMP_GMODE_VERSUS }, - { LEX_GMODE_ITEMRAIN, "ITEMRAIN", "5", KMP_GMODE_ITEMRAIN }, - { -1, "OFF", "-1", -1 }, - { 0,0,0,0 } -}; - -/////////////////////////////////////////////////////////////////////////////// - -static const KeywordTab_t lex_engine[] = -{ - { LEX_ENGINE_AUTO, "AUTO", "0", -1 }, - { LEX_ENGINE_BATTLE, "BATTLE", 0, ENGINE_BATTLE }, - { LEX_ENGINE_50, "50CC", 0, ENGINE_50 }, - { LEX_ENGINE_100, "100CC", 0, ENGINE_100 }, - { LEX_ENGINE_150, "150CC", 0, ENGINE_150 }, - { LEX_ENGINE_200, "200CC", 0, ENGINE_200 }, - { LEX_ENGINE_150M, "150M", "150MIRROR", ENGINE_150M }, - { LEX_ENGINE_200M, "200M", "200MIRROR", ENGINE_200M }, - { -1, "OFF", "-1", -1 }, - { 0,0,0,0 } -}; - -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// - -static enumError ScanLEXElementHexdump -( - lex_t * lex, // KMP data structure - ScanInfo_t * si // valid data -) -{ - DASSERT(lex); - DASSERT(si); - TRACE("ScanLEXElementHexdump()\n"); - - - //--- setup data - - u32 magic = LEXS_IGNORE; - ScanParam_t ptab[] = - { - { "MAGIC", SPM_U32, &magic, }, - {0} - }; - - char fb_buf[1000]; - FastBuf_t *fb = InitializeFastBuf(fb_buf,sizeof(fb_buf)); - - - //--- main loop - - for(;;) - { - char ch = NextCharSI(si,true); - if ( !ch || ch == '[' ) - break; - - if ( ch == '@' ) - ScanParamSI(si,ptab); - else - ScanHexlineSI(si,fb,true); - } - CheckLevelSI(si); - - if ( magic != LEXS_IGNORE || magic != LEXS_TERMINATE ) - AppendElementLEX(lex,magic,fb->buf,fb->ptr-fb->buf,true); - - ResetFastBuf(fb); - return ERR_OK; -} - -/////////////////////////////////////////////////////////////////////////////// - -static enumError ScanLEXElement_SET1 -( - lex_t * lex, // KMP data structure - ScanInfo_t * si // valid data -) -{ - DASSERT(lex); - DASSERT(si); - TRACE("ScanLEXElement_SET1()\n"); - - - //--- setup data - - lex_set1_t set1 = {0}; - - const ScanParam_t ptab[] = - { - { "ITEM-POS-FACTOR", SPM_FLOAT3_BE, &set1.item_factor }, - { "TEST1", SPM_U8, set1.test+0 }, - { "TEST2", SPM_U8, set1.test+1 }, - { "TEST3", SPM_U8, set1.test+2 }, - { "TEST4", SPM_U8, set1.test+3 }, - {0} - }; - - char fb_buf[1000]; - FastBuf_t *fb = InitializeFastBuf(fb_buf,sizeof(fb_buf)); - AppendFastBuf(fb,&set1,sizeof(set1)); - - - //--- main loop - - for(;;) - { - char ch = NextCharSI(si,true); - if ( !ch || ch == '[' ) - break; - - if ( ch == '@' ) - ScanParamSI(si,ptab); - else - ScanHexlineSI(si,fb,true); - } - CheckLevelSI(si); - - memcpy(fb->buf,&set1,sizeof(set1)); - HEXDUMP16(0,0,fb->buf,fb->ptr-fb->buf); - AppendElementLEX(lex,LEXS_SET1,fb->buf,fb->ptr-fb->buf,true); - - ResetFastBuf(fb); - return ERR_OK; -} - -/////////////////////////////////////////////////////////////////////////////// - -static enumError ScanLEXElement_CANN -( - lex_t * lex, // KMP data structure - ScanInfo_t * si // valid data -) -{ - DASSERT(lex); - DASSERT(si); - TRACE("ScanLEXElement_CANN()\n"); - - - //--- setup data - - ScanParam_t ptab[] = - { - {0} - }; - - char fb_buf[1000]; - FastBuf_t *fb = InitializeFastBuf(fb_buf,sizeof(fb_buf)); - AppendFastBuf(fb,EmptyString,4); - - - //--- main loop - - uint n_cannon = 0; - for(;;) - { - char ch = NextCharSI(si,true); - if ( !ch || ch == '[' ) - break; - - if ( ch == '@' ) - { - ScanParamSI(si,ptab); - continue; - } - - enumError err; - ScanIndexSI(si,&err,n_cannon,0,2); - if (err) - break; - - float f[4]; - ScanFloatSI(si,f,4); - - uint i; - u32 *fp = (u32*)f; - for ( i = 0; i < 4; i++, fp++ ) - *fp = htonl(*fp); - AppendFastBuf(fb,f,sizeof(f)); - n_cannon++; - CheckEolSI(si); - } - - if ( n_cannon > 0 ) - { - write_be32(fb->buf,n_cannon); - //HexDump16(stdout,0,0,fb->buf,fb->ptr-fb->buf); - AppendElementLEX(lex,LEXS_CANN,fb->buf,fb->ptr-fb->buf,true); - } - - ResetFastBuf(fb); - return ERR_OK; -} - -/////////////////////////////////////////////////////////////////////////////// - -static enumError ScanLEXElement_HIPT -( - lex_t * lex, // KMP data structure - ScanInfo_t * si // valid data -) -{ - DASSERT(lex); - DASSERT(si); - TRACE("ScanLEXElement_HIPT()\n"); - - - //--- setup data - - ScanParam_t ptab[] = - { - {0} - }; - - char fb_buf[1000]; - FastBuf_t *fb = InitializeFastBuf(fb_buf,sizeof(fb_buf)); - - - //--- main loop - - for(;;) - { - char ch = NextCharSI(si,true); - if ( !ch || ch == '[' ) - break; - - if ( ch == '@' ) - { - ScanParamSI(si,ptab); - continue; - } - - u8 num[sizeof(lex_hipt_rule_t)]; - ScanU8SI(si,num,sizeof(num),false); - AppendFastBuf(fb,num,sizeof(num)); - CheckEolSI(si); - } - - AppendElementLEX(lex,LEXS_HIPT,fb->buf,fb->ptr-fb->buf,true); - ResetFastBuf(fb); - - return ERR_OK; -} - -/////////////////////////////////////////////////////////////////////////////// - -static enumError ScanLEXElement_TEST -( - lex_t * lex, // KMP data structure - ScanInfo_t * si // valid data -) -{ - DASSERT(lex); - DASSERT(si); - TRACE("ScanLEXElement_TEST()\n"); - - - //--- setup data - - lex_test_t test; - memcpy(&test,TestDataLEX,sizeof(test)); - - const ScanParam_t ptab[] = - { - { "OFFLINE-ONLINE", SPM_U8, &test.offline_online }, - { "N-OFFLINE", SPM_U8, &test.n_offline }, - { "N-ONLINE", SPM_U8, &test.n_online }, - { "COND-BIT", SPM_S8, &test.cond_bit }, - { "GAME-MODE", SPM_U8, &test.game_mode }, - { "ENGINE", SPM_U8, &test.engine }, - { "RANDOM", SPM_U8, &test.random }, - {0} - }; - - char fb_buf[1000]; - FastBuf_t *fb = InitializeFastBuf(fb_buf,sizeof(fb_buf)); - AppendFastBuf(fb,&test,sizeof(test)); - - - //--- main loop - - for(;;) - { - char ch = NextCharSI(si,true); - if ( !ch || ch == '[' ) - break; - - if ( ch == '@' ) - ScanParamSI(si,ptab); - else - ScanHexlineSI(si,fb,true); - } - CheckLevelSI(si); - - memcpy(fb->buf,&test,sizeof(test)); - HEXDUMP16(0,0,fb->buf,fb->ptr-fb->buf); - AppendElementLEX(lex,LEXS_TEST,fb->buf,fb->ptr-fb->buf,true); - - ResetFastBuf(fb); - return ERR_OK; -} - -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// - -enumError ScanTextLEX -( - lex_t * lex, // LEX data structure - bool init_lex, // true: initialize 'lex' first - const void * data, // data to scan - uint data_size // size of 'data' -) -{ - PRINT("ScanTextLEX(init=%d)\n",init_lex); - - DASSERT(lex); - if (init_lex) - InitializeLEX(lex); - - ScanInfo_t si; - InitializeSI(&si,data,data_size,lex->fname,lex->revision); - si.predef = SetupVarsLEX(); - - enumError max_err = ERR_OK; - lex->is_pass2 = false; - - for(;;) - { - PRINT("----- SCAN LEX SECTIONS, PASS%u ...\n",lex->is_pass2+1); - - max_err = ERR_OK; - si.lex = lex; - si.no_warn = !lex->is_pass2; - si.total_err = 0; - DefineIntVar(&si.gvar, "$PASS", lex->is_pass2+1 ); - - for(;;) - { - char ch = NextCharSI(&si,true); - if (!ch) - break; - - if ( ch != '[' ) - { - NextLineSI(&si,true,false); - continue; - } - ResetLocalVarsSI(&si,lex->revision); - - si.cur_file->ptr++; - char sect_name[20]; - ScanNameSI(&si,sect_name,sizeof(sect_name),true,true,0); - PRINT0("--> pass=%u: #%04u: %s\n",lex->is_pass2+1,si.cur_file->line,sect_name); - - int abbrev_count; - const KeywordTab_t *cmd = ScanKeyword(&abbrev_count,sect_name,lex_section_name); - if ( !cmd || abbrev_count ) - continue; - NextLineSI(&si,false,false); - PRINT0("--> %-6s #%-4u |%.3s|\n",cmd->name1,si.cur_file->line,si.cur_file->ptr); - - enumError err = ERR_OK; - switch (cmd->id) - { - case LID_IGNORE: - // ignore it without warning - break; - - case LID_SETUP: - // nothing to do at the moment - break; - - case LID_HEXDUMP: - err = ScanLEXElementHexdump(lex,&si); - break; - - case LID_SETTINGS1: - err = ScanLEXElement_SET1(lex,&si); - break; - - case LID_CANNON: - err = ScanLEXElement_CANN(lex,&si); - break; - - case LID_HIDE_PT: - err = ScanLEXElement_HIPT(lex,&si); - break; - - case LID_TEST: - err = ScanLEXElement_TEST(lex,&si); - break; - - default: - err = ERROR0(ERR_WARNING,"Unknown section (ignored): %s\n",sect_name); - break; - } - - if ( max_err < err ) - max_err = err; - } - - if (lex->is_pass2) - break; - - lex->is_pass2 = true; - RestartSI(&si); - } - - ResetSI(&si); - - UpdateLEX(lex,opt_complete,false); - return max_err; -} - -// -/////////////////////////////////////////////////////////////////////////////// -/////////////// LEX: scan and load /////////////// -/////////////////////////////////////////////////////////////////////////////// - -enumError ScanLEX -( - lex_t * lex, // LEX data structure - bool init_lex, // true: initialize 'lex' first - const void * data, // data to scan - uint data_size // size of 'data' -) -{ - DASSERT(lex); - PRINT("ScanLEX() size=%u\n",data_size); - HEXDUMP16(0,0,data,16); - - enumError err; -// [[analyse-magic]] - switch (GetByMagicFF(data,data_size,data_size)) - { - case FF_LEX: - lex->fform = FF_LEX; - err = ScanRawLEX(lex,init_lex,data,data_size,0); - break; - - case FF_LEX_TXT: - lex->fform = FF_LEX_TXT; - err = ScanTextLEX(lex,init_lex,data,data_size); - break; - - default: - if (init_lex) - InitializeLEX(lex); - return ERROR0(ERR_INVALID_DATA, - "No LEX file: %s\n", lex->fname ? lex->fname : "?"); - } - - PatchLEX(lex); - return err; -} - -/////////////////////////////////////////////////////////////////////////////// - -enumError ScanRawDataLEX -( - lex_t * lex, // LEX data structure - bool init_lex, // true: initialize 'lex' first - struct raw_data_t * raw // valid raw data -) -{ - DASSERT(lex); - DASSERT(raw); - if (init_lex) - InitializeLEX(lex); - else - ResetLEX(lex); - - lex->fatt = raw->fatt; - lex->fname = raw->fname; - raw->fname = 0; - - return raw->is_0 ? ERR_OK : ScanLEX(lex,false,raw->data,raw->data_size); -} - -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// - -enumError LoadLEX -( - lex_t * lex, // LEX data structure - bool init_lex, // true: initialize 'lex' first - ccp fname, // valid pointer to filenname - bool ignore_no_file // ignore if file does not exists - // and return warning ERR_NOT_EXISTS -) -{ - DASSERT(lex); - DASSERT(fname); - if (init_lex) - InitializeLEX(lex); - else - ResetLEX(lex); - - //--- load and scan data - - raw_data_t raw; - enumError err = LoadRawData(&raw,true,fname,0,ignore_no_file,0); - if (!err) - { - lex->fname = raw.fname; - raw.fname = 0; - err = ScanLEX(lex,false,raw.data,raw.data_size); - } - - ResetRawData(&raw); - return err; -} - -// -/////////////////////////////////////////////////////////////////////////////// -/////////////// CreateRawLEX() /////////////// -/////////////////////////////////////////////////////////////////////////////// - -enumError CreateRawLEX -( - lex_t * lex // pointer to valid LEX -) -{ - DASSERT(lex); - if (lex->raw_data) - FREE(lex->raw_data); - - uint total_size = sizeof(lex_header_t) + sizeof(lex_element_t); // final term! - - uint i; - for ( i = 0; i < lex->item_used; i++ ) - { - lex_item_t *s = lex->item[i]; - total_size += sizeof(lex_element_t) + ntohl(s->elem.size); - } - - lex->raw_data = MALLOC(total_size); - lex->raw_data_size = total_size; - - lex_header_t *hd = (lex_header_t*)lex->raw_data; - memcpy(hd->magic,LEX_BIN_MAGIC,sizeof(hd->magic)); - hd->major_version = htons(LEX_MAJOR_VERSION); - hd->minor_version = htons(LEX_MINOR_VERSION); - hd->size = htonl(total_size); - hd->element_off = htonl(sizeof(lex_header_t)); - - u8 *dest = lex->raw_data + sizeof(lex_header_t); - for ( i = 0; i < lex->item_used; i++ ) - { - lex_item_t *s = lex->item[i]; - const uint size = sizeof(lex_element_t) + ntohl(s->elem.size); - ASSERT ( dest + size < lex->raw_data + lex->raw_data_size ); - memcpy(dest,&s->elem,size); - dest += size; - } - ASSERT ( dest + sizeof(lex_element_t) == lex->raw_data + lex->raw_data_size ); - memset(dest,0,sizeof(lex_element_t)); - - return ERR_OK; -} - -// -/////////////////////////////////////////////////////////////////////////////// -/////////////// SaveRawLEX() /////////////// -/////////////////////////////////////////////////////////////////////////////// - -enumError SaveRawLEX -( - lex_t * lex, // pointer to valid LEX - ccp fname, // filename of destination - bool set_time // true: set time stamps -) -{ - DASSERT(lex); - DASSERT(fname); - PRINT("SaveRawLEX(%s,%d)\n",fname,set_time); - - //--- create raw data - - enumError err = CreateRawLEX(lex); - if (err) - return err; - DASSERT(lex->raw_data); - DASSERT(lex->raw_data_size); - - - //--- write to file - - File_t F; - err = CreateFileOpt(&F,true,fname,testmode,lex->fname); - if ( err > ERR_WARNING || !F.f ) - return err; - SetFileAttrib(&F.fatt,&lex->fatt,0); - - if ( fwrite(lex->raw_data,1,lex->raw_data_size,F.f) != lex->raw_data_size ) - FILEERROR1(&F,ERR_WRITE_FAILED,"Write failed: %s\n",fname); - return ResetFile(&F,set_time); -} - -// -/////////////////////////////////////////////////////////////////////////////// -/////////////// SaveTextLEX() /////////////// -/////////////////////////////////////////////////////////////////////////////// - -static enumError SaveTextLEX_SET1 -( - FILE * f, // file to write - const lex_t * lex, // pointer to valid LEX - lex_item_t * item // item to save -) -{ - DASSERT(f); - DASSERT(lex); - DASSERT(item); - - const uint size = ntohl(item->elem.size); - noPRINT("SaveTextLEX_SET1(), size=%u\n",size); - DASSERT( size >= sizeof(lex_set1_t) ); - if ( size < sizeof(lex_set1_t)) - return ERR_OK; - - const u8 *data = item->elem.data; - const lex_set1_t *set1 = (lex_set1_t*)data; - - fprintf(f,text_lex_elem_set1_cr - ,item->sort_order - ,bef4(&set1->item_factor.x) - ,bef4(&set1->item_factor.y) - ,bef4(&set1->item_factor.z) - ); - - if (*(u32*)set1->test) - fprintf(f,text_lex_elem_set1_develop_cr - ,set1->test[0],set1->test[1],set1->test[2],set1->test[3] - ); - - if ( size > sizeof(lex_set1_t) ) - { - fputs("\n# Hex dump for unknown settings:\n",f); - HexDump(f,0,sizeof(lex_set1_t),5,16, - item->elem.data + sizeof(lex_set1_t), - size - sizeof(lex_set1_t) ); - } - - return ERR_OK; -} - -/////////////////////////////////////////////////////////////////////////////// - -static enumError SaveTextLEX_CANN -( - FILE * f, // file to write - const lex_t * lex, // pointer to valid LEX - lex_item_t * item // item to save -) -{ - DASSERT(f); - DASSERT(lex); - DASSERT(item); - - fprintf(f,text_lex_elem_cann_cr,item->sort_order); - if ( item->elem.size < 4 + 16 ) - return ERR_OK; - - const u8 *data = item->elem.data; - uint n = be32(data); - uint max = ( ntohl(item->elem.size) - 4 ) / 16; - if ( n > max ) - n = max; - - uint i, off = 4; - for ( i = 0; i < n; i++, off += 16 ) - fprintf(f,"%4u %10.3f %10.3f %10.3f %10.3f\r\n", - i, bef4(data+off), bef4(data+off+4), - bef4(data+off+8), bef4(data+off+12) ); - - return ERR_OK; -} - -/////////////////////////////////////////////////////////////////////////////// - -static enumError SaveTextLEX_HIPT -( - FILE * f, // file to write - const lex_t * lex, // pointer to valid LEX - lex_item_t * item // item to save -) -{ - DASSERT(f); - DASSERT(lex); - DASSERT(item); - - fprintf(f,text_lex_elem_hipt_cr,item->sort_order); - if ( item->elem.size < 4 + 16 ) - return ERR_OK; - - const lex_hipt_rule_t *rule = (lex_hipt_rule_t*)item->elem.data; - int n = ntohl(item->elem.size) / sizeof(*rule) ; - - int i, last_lap = 1000; - for ( i = 0; i < n; i++, rule++ ) - { - if ( last_lap != rule->lap ) - { - last_lap = rule->lap; - fputs("\r\n",f); - } - - fprintf(f,"%5u %4d %4u %4u %4u\r\n", - rule->cond, rule->lap, rule->from, rule->to, rule->mode ); - } - - return ERR_OK; -} - -/////////////////////////////////////////////////////////////////////////////// - -static enumError SaveTextLEX_TEST -( - FILE * f, // file to write - const lex_t * lex, // pointer to valid LEX - lex_item_t * item // item to save -) -{ - DASSERT(f); - DASSERT(lex); - DASSERT(item); - - const uint size = ntohl(item->elem.size); - PRINT("SaveTextLEX_TEST(), size=%u\n",size); - DASSERT( size >= sizeof(lex_test_t) ); - if ( size < sizeof(lex_test_t)) - return ERR_OK; - - const u8 *data = item->elem.data; - const lex_test_t *test = (lex_test_t*)data; - - const KeywordTab_t *off_on; - for ( off_on = lex_offline_online; off_on->name1; off_on++ ) - if ( off_on->id == test->offline_online && off_on->opt >= 0 ) - break; - - const KeywordTab_t *gmode; - for ( gmode = lex_game_mode; gmode->name1; gmode++ ) - if ( gmode->id == test->game_mode && gmode->opt >= 0 ) - break; - - const KeywordTab_t *engine; - for ( engine = lex_engine; engine->name1; engine++ ) - if ( engine->id == test->engine && engine->opt >= 0 ) - break; - - fprintf(f,text_lex_elem_test_cr - ,item->sort_order - ,off_on->name1 ? off_on->name1 : "AUTO" - ,test->n_offline - ,test->n_online - ,test->cond_bit - ,gmode->name1 ? gmode->name1 : "AUTO" - ,engine->name1 ? engine->name1 : "AUTO" - ,test->random - ); - - if ( size > sizeof(lex_test_t) ) - { - fputs("\n# Hex dump for unknown settings:\n",f); - HexDump(f,0,sizeof(lex_test_t),5,16, - item->elem.data + sizeof(lex_test_t), - size - sizeof(lex_test_t) ); - } - - return ERR_OK; -} - -/////////////////////////////////////////////////////////////////////////////// - -enumError SaveTextLEX -( - const lex_t * lex, // pointer to valid LEX - ccp fname, // filename of destination - bool set_time // true: set time stamps -) -{ - // use DOS/Windows line format -> unix can handle it ;) - - DASSERT(lex); - DASSERT(fname); - PRINT("SaveTextLEX(%s,%d)\n",fname,set_time); - - - //--- open file - - File_t F; - enumError err = CreateFileOpt(&F,true,fname,testmode,lex->fname); - if ( err > ERR_WARNING || !F.f ) - return err; - SetFileAttrib(&F.fatt,&lex->fatt,0); - - - //--- print header + syntax info - - if ( print_header && !brief_count && !export_count ) - fprintf(F.f,text_lex_head_cr); - else - fprintf(F.f, - "%s\r\n" - "# LEX syntax & semantics: https://szs.wiimm.de/info/lex-syntax.html\r\n" - ,LEX_TEXT_MAGIC); - - - //--- print info section & section counter alphabetically - - if ( brief_count || export_count ) - { - fprintf(F.f, - "%s[SETUP]\r\n\r\n" - "TOOL = %s\r\n" - "SYSTEM2 = %s\r\n" - "VERSION = %s\r\n" - "REVISION = %u\r\n" - "DATE = %s\r\n" - "\r\n", - section_sep, - tool_name, SYSTEM2, VERSION, REVISION_NUM, DATE ); - } - else - { - fprintf(F.f, text_lex_setup_cr, - tool_name, SYSTEM2, VERSION, REVISION_NUM, DATE ); - - uint i; - for ( i = 0; i < lex->item_used; i++ ) - { - lex_item_t *s = lex->item[i]; - const uint size = ntohl(s->elem.size); - fprintf(F.f,"# %-4.4s %08x, 0x%04x bytes\r\n", - PrintID(&s->elem.magic,4,0), s->elem.magic, size ); - } - } - - enumError max_err = ERR_OK; - - uint i; - for ( i = 0; i < lex->item_used; i++ ) - { - lex_item_t *s = lex->item[i]; - const uint size = ntohl(s->elem.size); - const u32 magic = ntohl(s->elem.magic); - enumError err = ERR_OK; - switch(magic) - { - case LEXS_SET1: - err = SaveTextLEX_SET1(F.f,lex,s); - break; - - case LEXS_CANN: - err = SaveTextLEX_CANN(F.f,lex,s); - break; - - case LEXS_HIPT: - err = SaveTextLEX_HIPT(F.f,lex,s); - break; - - case LEXS_TEST: - err = SaveTextLEX_TEST(F.f,lex,s); - break; - - default: - hexdump_eol = "\r\n"; - fprintf(F.f,text_lex_hexdump_cr, - s->sort_order, magic, PrintID(&s->elem.magic,4,0) ); - HexDump(F.f,0,0,5,16,s->elem.data,size); - break; - } - - if ( max_err < err ) - max_err = err; - } - - fputs(section_end,F.f); - ResetFile(&F,set_time); - return max_err; -} - -// -/////////////////////////////////////////////////////////////////////////////// -/////////////// LEX options /////////////// -/////////////////////////////////////////////////////////////////////////////// - -bool opt_lex_purge = false; -bool force_lex_test = false; -bool opt_lt_clear = false; -int opt_lt_online = -9; -int opt_lt_n_offline = -9; -int opt_lt_n_online = -9; -int opt_lt_cond_bit = -9; -int opt_lt_game_mode = -9; -int opt_lt_engine = -9; -int opt_lt_random = -9; - -//----------------------------------------------------------------------------- - -int ScanOptLtOnline ( ccp arg ) -{ - if ( !arg || !*arg ) - opt_lt_online = -9; - else - { - int abbrev; - const KeywordTab_t *key = ScanKeyword(&abbrev,arg,lex_offline_online); - if (!key) - { - PrintKeywordError(lex_offline_online,arg,abbrev,0, - "keyword for option --lt-online"); - return 1; - } - opt_lt_online = key->id; - } - return 0; -} - -//----------------------------------------------------------------------------- - -int ScanOptLtNPlayers ( ccp arg ) -{ - if ( !arg || !*arg ) - opt_lt_n_offline = opt_lt_n_online = -9; - else - { - ccp comma = strchr(arg,','); - if (comma) - { - opt_lt_n_offline = str2l(arg,0,10); - opt_lt_n_online = str2l(comma+1,0,10); - } - else - { - int n = str2l(arg,0,10); - if ( n > 4 ) - { - opt_lt_n_offline = -9; - opt_lt_n_online = n; - } - else - { - opt_lt_n_offline = n; - opt_lt_n_online = -9; - } - } - - if ( opt_lt_n_offline < 0 ) - opt_lt_n_offline = -9; - else if ( opt_lt_n_offline > 4 ) - opt_lt_n_offline = 4; - - if ( opt_lt_n_online < 0 ) - opt_lt_n_online = -9; - else if ( opt_lt_n_online > 99 ) - opt_lt_n_online = 99; - } - - return 0; -} - -//----------------------------------------------------------------------------- - -int ScanOptLtCondBit ( ccp arg ) -{ - if ( !arg || !*arg ) - opt_lt_cond_bit = -9; - else - { - int n = str2l(arg,0,10); - opt_lt_cond_bit = n < -1 || n >= 16 ? -9 : n; - } - return 0; -} - -//----------------------------------------------------------------------------- - -int ScanOptLtGameMode ( ccp arg ) -{ - if ( !arg || !*arg ) - opt_lt_game_mode = -1; - else - { - int abbrev; - const KeywordTab_t *key = ScanKeyword(&abbrev,arg,lex_game_mode); - if (!key) - { - PrintKeywordError(lex_game_mode,arg,abbrev,0, - "keyword for option --lt-game-mode"); - return 1; - } - opt_lt_game_mode = key->id; - } - return 0; -} - -//----------------------------------------------------------------------------- - -int ScanOptLtEngine ( ccp arg ) -{ - if ( !arg || !*arg ) - opt_lt_engine = -1; - else - { - int abbrev; - const KeywordTab_t *key = ScanKeyword(&abbrev,arg,lex_engine); - if (!key) - { - PrintKeywordError(lex_engine,arg,abbrev,0, - "keyword for option --lt-engine"); - return 1; - } - opt_lt_engine = key->id; - } - return 0; -} - -//----------------------------------------------------------------------------- - -int ScanOptLtRandom ( ccp arg ) -{ - if ( !arg || !*arg ) - opt_lt_random = -1; - else - { - int n = str2l(arg,0,10); - opt_lt_random = n < 0 || n > 6 ? -9 : n; - } - return 0; -} - -// -/////////////////////////////////////////////////////////////////////////////// -/////////////// lex_info_t /////////////// -/////////////////////////////////////////////////////////////////////////////// - -void SetupLexInfo ( lex_info_t *info, const lex_t *lex ) -{ - DASSERT(info); - InitializeLexInfo(info); - - if (lex) - { - info->lex_found = true; - lex_item_t *item; - - item = FindElementLEX(lex,LEXS_SET1); - if (item) - { - info->set1_found = true; - memcpy(&info->set1,item->elem.data,sizeof(info->set1)); - bef4n(info->set1.item_factor.v,info->set1.item_factor.v,3); - } - - item = FindElementLEX(lex,LEXS_TEST); - if (item) - { - info->test_found = true; - memcpy(&info->test,item->elem.data,sizeof(info->test)); - } - } -} - -/////////////////////////////////////////////////////////////////////////////// - -enumError SetupLexInfoByData ( lex_info_t *info, cvp data, uint data_size ) -{ - lex_t lex; - const enumError err = ScanLEX(&lex,true,data,data_size); - if (!err) - SetupLexInfo(info,&lex); - else - InitializeLexInfo(info); - ResetLEX(&lex); - return err; -} - -// -/////////////////////////////////////////////////////////////////////////////// -/////////////// LEX patching /////////////// -/////////////////////////////////////////////////////////////////////////////// - -// return TRUE if any option set -bool HavePatchTestLEX() -{ - return force_lex_test - || opt_lt_clear - || opt_lt_online >= 0 - || opt_lt_n_offline >= 0 - || opt_lt_n_online >= 0 - || opt_lt_game_mode >= 0 - || opt_lt_engine >= 0 - || opt_lt_random >= 0; -} - - -//----------------------------------------------------------------------------- - -// return TRUE if any option set and not default -bool HaveActivePatchTestLEX() -{ - return force_lex_test - || opt_lt_online > 0 - || opt_lt_n_offline > 0 - || opt_lt_n_online > 0 - || opt_lt_game_mode > LEX_GMODE_AUTO - || opt_lt_engine > LEX_ENGINE_AUTO - || opt_lt_random >= 0; -} - -//----------------------------------------------------------------------------- - -// return TRUE if modified / set optional 'empty' to true, if test section is empty -bool PatchTestLEX ( lex_test_t *lt, bool *empty ) -{ - DASSERT(lt); - PRINT0("--lt-*: clear=%d, online=%d, n=%d,%d, gm=%d, en=%d, rnd=%d\n", - opt_lt_clear, opt_lt_online, opt_lt_n_offline, opt_lt_n_online, - opt_lt_game_mode, opt_lt_engine, opt_lt_random ); - - lex_test_t temp; - memcpy( &temp, opt_lt_clear ? (lex_test_t*)&TestDataLEX : lt, sizeof(temp) ); - - if ( opt_lt_online >= LEX_OO_AUTO && opt_lt_online <= LEX_OO_ONLINE ) - temp.offline_online = opt_lt_online; - - if ( opt_lt_n_offline >= 0 ) - temp.n_offline = opt_lt_n_offline > 4 ? 4 : opt_lt_n_offline; - - if ( opt_lt_n_online >= 0 ) - temp.n_online = opt_lt_n_online > 99 ? 99 : opt_lt_n_online; - - if ( opt_lt_cond_bit >= -1 && opt_lt_cond_bit < 16 ) - temp.cond_bit = opt_lt_cond_bit; - - if ( opt_lt_game_mode >= 0 ) - temp.game_mode = opt_lt_game_mode; - - if ( opt_lt_engine >= 0 ) - temp.engine = opt_lt_engine; - - if ( opt_lt_random >= 0 ) - temp.random = opt_lt_random; - - if (empty) - *empty = !memcmp(&temp,&TestDataLEX,sizeof(temp)); - if (memcmp(lt,&temp,sizeof(*lt))) - { - memcpy(lt,&temp,sizeof(*lt)); - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- - -bool PatchLEX ( lex_t * lex ) -{ - DASSERT(lex); - - bool modified = false; - if (HavePatchTestLEX()) - { - lex_item_t *li = FindElementLEX(lex,LEXS_TEST); - const bool had_test = li != 0; - if (!had_test) - { - if (!HaveActivePatchTestLEX()) - return 0; - li = AppendTestLEX(lex,false); - } - DASSERT(li); - lex_test_t orig; - memcpy(&orig,li->elem.data,sizeof(orig)); - - bool empty; - modified = PatchTestLEX((lex_test_t*)li->elem.data,&empty); - PRINT("PATCH+ LEX/TEST: had=%d, empty=%d, modified=%d => have_lex:%x\n", - had_test, empty, modified, lex->have_lex ); - if ( empty && !force_lex_test ) - { - if ( RemoveElementLEX(lex,li) && had_test ) - modified = true; - } - else if (!had_test) - modified = true; - - PRINT("PATCH- LEX/TEST: had=%d, empty=%d, modified=%d => have_lex:%x\n", - had_test, empty, modified, lex->have_lex ); - - if (modified) - lex->modified = true; - } - - if (opt_lex_purge) - modified |= PurgeLEX(lex); - - return modified; -} - -// -/////////////////////////////////////////////////////////////////////////////// -/////////////// LEX purging /////////////// -/////////////////////////////////////////////////////////////////////////////// - -bool PurgeLEX ( lex_t * lex ) -{ - DASSERT(lex); - - bool modified = false; - - uint i = 0; - while ( i < lex->item_used ) - { - lex_item_t **ss = lex->item+i; - const uint size = ntohl((*ss)->elem.size); - const u8 *data = (*ss)->elem.data; - - bool remove = false; - switch(ntohl((*ss)->elem.magic)) - { - case LEXS_SET1: - { - lex_set1_t set1; - memset(&set1,0,sizeof(set1)); - FixLEXElement_SET1(&set1); - remove = !memcmp(data,&set1,sizeof(set1)); - } - break; - - case LEXS_CANN: - remove = size <= sizeof(CannonDataLEX) - && !memcmp(data,&CannonDataLEX,size); - break; - - case LEXS_HIPT: - remove = size < sizeof(lex_hipt_rule_t); - break; - - case LEXS_TEST: - remove = !memcmp(data,TestDataLEX,sizeof(TestDataLEX)); - break; - - default: - remove = true; - break; - } - - if (remove) - modified |= RemoveElementLEX(lex,*ss); - else - i++; - } - - if (modified) - UpdateHaveLex(lex); - - return modified; -} - // /////////////////////////////////////////////////////////////////////////////// /////////////// END /////////////// -- cgit v1.3.1