aboutsummaryrefslogtreecommitdiff
path: root/project/src/lib-lecode.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--project/src/lib-lecode.c2042
1 files changed, 4 insertions, 2038 deletions
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 <wiimm@wiimm.de> *
+ * Copyright (c) 2011-2021 by Dirk Clemens <wiimm@wiimm.de> *
* *
***************************************************************************
* *
@@ -41,7 +41,6 @@
#include "lib-mkw.h"
#include "lib-szs.h"
#include "lpar.inc"
-#include "lex.inc"
#include <stddef.h>
@@ -72,43 +71,6 @@ 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;
@@ -2703,2005 +2668,6 @@ enumError ScanTextLPAR_CHAT
//
///////////////////////////////////////////////////////////////////////////////
-/////////////// 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 ///////////////
///////////////////////////////////////////////////////////////////////////////