diff options
| author | Wiimm <wiimm@wiimm.de> | 2020-11-30 16:16:56 +0100 |
|---|---|---|
| committer | Wiimm <wiimm@wiimm.de> | 2020-11-30 16:16:56 +0100 |
| commit | 9c0078c6b9c1309b48f9ece8b5cad1b9be9a75c5 (patch) | |
| tree | 0abd3b6a244076650e40a07e42adae9c2a6b2d8c /project/dclib | |
| parent | a0815499b2d9014695e6e261c909476729445360 (diff) | |
SZS v2.21a
Diffstat (limited to 'project/dclib')
| -rw-r--r-- | project/dclib/Makefile.inc | 2 | ||||
| -rw-r--r-- | project/dclib/dclib-basics.c | 78 | ||||
| -rw-r--r-- | project/dclib/dclib-basics.h | 84 | ||||
| -rw-r--r-- | project/dclib/dclib-cli.c | 357 | ||||
| -rw-r--r-- | project/dclib/dclib-file.c | 345 | ||||
| -rw-r--r-- | project/dclib/dclib-file.h | 65 | ||||
| -rw-r--r-- | project/dclib/dclib-network-linux.c | 105 | ||||
| -rw-r--r-- | project/dclib/dclib-network-linux.h | 57 | ||||
| -rw-r--r-- | project/dclib/dclib-network.h | 7 | ||||
| -rw-r--r-- | project/dclib/dclib-numeric.c | 94 | ||||
| -rw-r--r-- | project/dclib/dclib-option.h | 2 | ||||
| -rw-r--r-- | project/dclib/dclib-system.h | 49 | ||||
| -rw-r--r-- | project/dclib/dclib-types.h | 20 | ||||
| -rw-r--r-- | project/dclib/lib-bmg.c | 192 | ||||
| -rw-r--r-- | project/dclib/lib-bmg.h | 31 |
15 files changed, 1325 insertions, 163 deletions
diff --git a/project/dclib/Makefile.inc b/project/dclib/Makefile.inc index 6ab04d8..d386594 100644 --- a/project/dclib/Makefile.inc +++ b/project/dclib/Makefile.inc @@ -2,7 +2,7 @@ #------------------------------------------------------------------------------ # standard object files -DCLIB_O = dclib-basics.o dclib-color.o dclib-numeric.o \ +DCLIB_O = dclib-basics.o dclib-cli.o dclib-color.o dclib-numeric.o \ dclib-file.o dclib-option.o dclib-regex.o \ dclib-utf8.o dclib-shift-jis.o \ dclib-vector.o dclib-tables.o dclib-ui.o \ diff --git a/project/dclib/dclib-basics.c b/project/dclib/dclib-basics.c index 64ea883..8176aed 100644 --- a/project/dclib/dclib-basics.c +++ b/project/dclib/dclib-basics.c @@ -4672,12 +4672,7 @@ char * PrintKeywordList if (ret_length) *ret_length = len; - if ( buf == temp ) - { - buf = GetCircBuf(len+1); - memcpy(buf,temp,len+1); - } - return buf; + return buf == temp ? CopyCircBuf(temp,len+1) : buf; } /////////////////////////////////////////////////////////////////////////////// @@ -4874,7 +4869,7 @@ int ScanCommandList //--- scan and copy command ccp param = cmd; - while ( param < endcmd && ( isalnum(*param) || *param == '-' || *param == '_' ) ) + while ( param < endcmd && ( isalnum((int)*param) || *param == '-' || *param == '_' ) ) param++; cli->cmd_len = param - cmd; if ( cli->cmd_len > sizeof(cli->cmd)-1 ) @@ -5063,75 +5058,6 @@ int ScanCommandList // /////////////////////////////////////////////////////////////////////////////// -/////////////// global commands /////////////// -/////////////////////////////////////////////////////////////////////////////// - -enumError Command_ARGTEST ( int argc, char ** argv ) -{ - printf("ARGUMENT TEST: %u arguments:\n",argc); - - int idx; - for ( idx = 0; idx < argc; idx++ ) - printf("%4u.: |%s|\n",idx,argv[idx]); - return ERR_OK; -} - -/////////////////////////////////////////////////////////////////////////////// - -enumError Command_COLORS -( - int level, // only used, if mode==NULL - // < 0: status message (ignore mode) - // >= 1: include names - // >= 2: include alt names - // >= 3: include color names incl bold - // >= 4: include background color names - uint mode, // output mode => see PrintColorSetHelper() - uint format // output format => see PrintColorSetEx() -) -{ - if (!colout) - SetupStdMsg(); - - if ( level < 0 ) - { - printf("%s--color=%d [%s], colorize=%d [%s]\n" - "term=%s\n" - "stdout: tty=%d, mode=%d [%s], have-color=%d, n-colors=%u%s\n", - colout->status, - opt_colorize, GetColorModeName(opt_colorize,"?"), - colorize_stdout, GetColorModeName(colorize_stdout,"?"), - getenv("TERM"), isatty(fileno(stdout)), - colout->col_mode, GetColorModeName(colout->col_mode,"?"), - colout->colorize, colout->n_colors, colout->reset ); - return ERR_OK; - } - - if ( !mode && level > 0 ) - switch (level) - { - case 1: mode = 0x08; break; - case 2: mode = 0x18; break; - case 3: mode = 0x1b; break; - default: mode = 0x1f; break; - } - - if (!format) - { - const ColorMode_t col_mode = colout ? colout->col_mode : COLMD_AUTO; - PrintTextModes( stdout, 4, col_mode ); - PrintColorModes( stdout, 4, col_mode, GCM_ALT ); - #ifdef TEST - PrintColorModes( stdout, 4, col_mode, GCM_ALT|GCM_SHORT ); - #endif - } - if ( mode || format ) - PrintColorSetEx(stdout,4,colout,mode,format); - return ERR_OK; -} - -// -/////////////////////////////////////////////////////////////////////////////// /////////////// dynamic data support /////////////// /////////////////////////////////////////////////////////////////////////////// diff --git a/project/dclib/dclib-basics.h b/project/dclib/dclib-basics.h index 68eeca7..fd0b1a9 100644 --- a/project/dclib/dclib-basics.h +++ b/project/dclib/dclib-basics.h @@ -580,7 +580,7 @@ typedef struct endian_func_t { //--- info section - u8 bom[2]; // btye order mark: BE=0xfe,0xff, LE=0xff,0xfe + u8 bom[2]; // byte order mark: BE=0xfe,0xff, LE=0xff,0xfe bool is_be; // true: is big endian bool is_le; // true: is little endian dcEndian_t endian; // DC_BIG_ENDIAN or DC_LITTLE_ENDIAN @@ -609,6 +609,16 @@ typedef struct endian_func_t void (*wrf4) ( void * data_ptr, float data ); void (*wrf8) ( void * data_ptr, double data ); + //--- convert functions + + u16 (*n2hs) ( u16 data ); + u32 (*n2hl) ( u32 data ); + u64 (*n2h64) ( u64 data ); + + u16 (*h2ns) ( u16 data ); + u32 (*h2nl) ( u32 data ); + u64 (*h2n64) ( u64 data ); + } endian_func_t; extern const endian_func_t be_func; @@ -689,6 +699,8 @@ int CheckIndex1 ( int max, int index ); int CheckIndex1End ( int max, int index ); int CheckIndex2 ( int max, int * p_begin, int * p_end ); int CheckIndex2End ( int max, int * p_begin, int * p_end ); +int CheckIndexC ( int max, int * p_begin, int count ); +int CheckIndexCEnd ( int max, int * p_begin, int count ); //----------------------------------------------------------------------------- @@ -1683,6 +1695,42 @@ int ScanSplitArg // /////////////////////////////////////////////////////////////////////////////// +/////////////// arg_manager_t /////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[arg_manager_t]] + +typedef struct arg_manager_t +{ + char **argv; // list of strings + int argc; // number of used elements in 'argv' + uint size; // >0: 'argv' is alloced to store # elements + // last NULL element is not counted here +} +arg_manager_t; + +//----------------------------------------------------------------------------- + +void ResetArgManager ( arg_manager_t *am ); +void SetupArgManager ( arg_manager_t *am, int argc, char ** argv, bool clone ); +void AttachArgManager ( arg_manager_t *am, int argc, char ** argv ); +void CloneArgManager ( arg_manager_t *am, int argc, char ** argv ); + +void AddSpaceArgManager ( arg_manager_t *am, int needed_space ); + +void CopyArgManager ( arg_manager_t *dest, const arg_manager_t *src ); +void MoveArgManager ( arg_manager_t *dest, arg_manager_t *src ); + +void PrepareEditArgManager ( arg_manager_t *am, int needed_space ); + +uint AppendArgManager ( arg_manager_t *am, ccp arg1, ccp arg2, bool move_arg ); +uint InsertArgManager ( arg_manager_t *am, int pos, ccp arg1, ccp arg2, bool move_arg ); +uint ReplaceArgManager( arg_manager_t *am, int pos, ccp arg1, ccp arg2, bool move_arg ); +uint RemoveArgManager ( arg_manager_t *am, int pos, int count ); + +void DumpArgManager ( FILE *f, int indent, const arg_manager_t *am, ccp title ); + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// ContainerData_t, Container_t /////////////// /////////////////////////////////////////////////////////////////////////////// @@ -4253,7 +4301,7 @@ typedef struct DynDataList_t { DynData_t *list; // pointer to the data list uint used; // number of used data elements - uint size; // number of allocated pointer in 'list' + uint size; // number of allocated pointers in 'list' } DynDataList_t; @@ -4287,7 +4335,7 @@ typedef struct StringField_t { ccp * field; // pointer to the string field uint used; // number of used titles in the title field - uint size; // number of allocated pointer in 'field' + uint size; // number of allocated pointers in 'field' int (*func_cmp)( ccp s1, ccp s2 ); // compare function, default is strcmp() } StringField_t; @@ -4394,7 +4442,7 @@ typedef struct ParamField_t { ParamFieldItem_t * field; // pointer to the string field uint used; // number of used titles in the title field - uint size; // number of allocated pointer in 'field' + uint size; // number of allocated pointers in 'field' bool free_data; // true: unused data will be free'd // initialized with 'false' int (*func_cmp)( ccp s1, ccp s2 ); // compare function, default is strcmp() @@ -4454,7 +4502,7 @@ typedef struct MemMap_t { MemMapItem_t ** field; // pointer to the item field uint used; // number of used titles in the item field - uint size; // number of allocated pointer in 'field' + uint size; // number of allocated pointers in 'field' u64 begin; // first address } MemMap_t; @@ -4833,7 +4881,15 @@ typedef struct RestoreState_t } RestoreState_t; -//----------------------------------------------------------------------------- +/////////////////////////////////////////////////////////////////////////////// + +static inline void InitializeRestoreState ( RestoreState_t *rs ) + { DASSERT(rs); memset(rs,0,sizeof(*rs)); } + +void ResetRestoreState ( RestoreState_t *rs ); + +/////////////////////////////////////////////////////////////////////////////// +// [[RestoreStateFunc]] typedef void (*RestoreStateFunc) ( @@ -4842,6 +4898,7 @@ typedef void (*RestoreStateFunc) ); //----------------------------------------------------------------------------- +// [[RestoreStateTab_t]] typedef struct RestoreStateTab_t { @@ -4853,6 +4910,16 @@ RestoreStateTab_t; /////////////////////////////////////////////////////////////////////////////// +enumError ScanRestoreState +( + RestoreState_t *rs, // valid control + void *data, // file data, modified, terminated by NULL or LF + uint size, // size of file data + void **end_data // not NULL: store end of analysed here +); + +/////////////////////////////////////////////////////////////////////////////// + enumError RestoreState ( const RestoreStateTab_t @@ -5111,6 +5178,11 @@ __attribute__ ((packed)) SaveRestoreTab_t; #define DEF_SRT_ARRAY_AC(v) DEF_SRT_ARRAY_C(v,0,SRT_DEF_ARRAY,0) #define DEF_SRT_ARRAY_END() {0,0,0,0,SRT_DEF_ARRAY,0} +//--- global array of structs + +#define DEF_SRT_ARRAY_GN(ne) {0,sizeof(SRT_NAME),0,ne,SRT_DEF_ARRAY,0} +#define DEF_SRT_ARRAY_GA(v) {0,sizeof(*v),0,sizeof(v)/sizeof(*v),SRT_DEF_ARRAY,0} + //--- special #define DEF_SRT_SEPARATOR() {0,0,0,0,SRT__IS_LIST,0} diff --git a/project/dclib/dclib-cli.c b/project/dclib/dclib-cli.c new file mode 100644 index 0000000..24fed39 --- /dev/null +++ b/project/dclib/dclib-cli.c @@ -0,0 +1,357 @@ + +/*************************************************************************** + * * + * _____ ____ * + * | __ \ / __ \ _ _ _____ * + * | | \ \ / / \_\ | | | | _ \ * + * | | \ \| | | | | | |_| | * + * | | | || | | | | | ___/ * + * | | / /| | __ | | | | _ \ * + * | |__/ / \ \__/ / | |___| | |_| | * + * |_____/ \____/ |_____|_|_____/ * + * * + * Wiimms source code library * + * * + *************************************************************************** + * * + * Copyright (c) 2012-2020 by Dirk Clemens <wiimm@wiimm.de> * + * * + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * See file gpl-2.0.txt or http://www.gnu.org/licenses/gpl-2.0.txt * + * * + ***************************************************************************/ + +#define _GNU_SOURCE 1 + +#include <unistd.h> + +#include "dclib-basics.h" +#include "dclib-debug.h" + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// arg_manager_t /////////////// +/////////////////////////////////////////////////////////////////////////////// + +void ResetArgManager ( arg_manager_t *am ) +{ + static char *null_list[] = {0}; + + if (am) + { + if (am->size) + { + uint i; + for ( i = 0; i < am->argc; i++ ) + FreeString(am->argv[i]); + if ( am->argv != null_list ) + FREE(am->argv); + } + memset(am,0,sizeof(*am)); + + am->argv = null_list; + } +} + +/////////////////////////////////////////////////////////////////////////////// + +void SetupArgManager ( arg_manager_t *am, int argc, char ** argv, bool clone ) +{ + DASSERT(am); + memset(am,0,sizeof(*am)); + if (clone) + CloneArgManager(am,argc,argv); + else + AttachArgManager(am,argc,argv); +} + +/////////////////////////////////////////////////////////////////////////////// + +void AttachArgManager ( arg_manager_t *am, int argc, char ** argv ) +{ + DASSERT(am); + ResetArgManager(am); + am->argc = argc; + am->argv = argv; +} + +/////////////////////////////////////////////////////////////////////////////// + +void CloneArgManager ( arg_manager_t *am, int argc, char ** argv ) +{ + DASSERT(am); + AttachArgManager(am,argc,argv); + PrepareEditArgManager(am,0); +} + +/////////////////////////////////////////////////////////////////////////////// + +void CopyArgManager ( arg_manager_t *dest, const arg_manager_t *src ) +{ + DASSERT(dest); + if (!src) + ResetArgManager(dest); + else if( dest != src ) + AttachArgManager(dest,src->argc,src->argv); +} + +/////////////////////////////////////////////////////////////////////////////// + +void MoveArgManager ( arg_manager_t *dest, arg_manager_t *src ) +{ + DASSERT(dest); + ResetArgManager(dest); + if (src) + { + dest->argv = src->argv; + dest->argc = src->argc; + dest->size = src->size; + memset(src,0,sizeof(*src)); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +void PrepareEditArgManager ( arg_manager_t *am, int needed_space ) +{ + DASSERT(am); + + uint new_size = am->argc; + if ( needed_space > 0 ) + new_size += needed_space; + new_size = GetGoodAllocSize2(new_size+(new_size>>4)+10,sizeof(*am->argv)); + PRINT("PrepareEditArgManager(,%d) n=%d, size: %d -> %d\n", + needed_space, am->argc, am->size, new_size ); + + if (am->size) + am->argv = REALLOC(am->argv,sizeof(*am->argv)*new_size); + else + { + char **old = am->argv; + am->argv = MALLOC(sizeof(*am->argv)*new_size); + + uint i; + for ( i = 0; i < am->argc; i++ ) + am->argv[i] = old[i] ? STRDUP(old[i]) : 0; + } + am->size = new_size - 1; + DASSERT( am->argc <= am->size ); + am->argv[am->argc] = 0; +} + +/////////////////////////////////////////////////////////////////////////////// + +uint AppendArgManager ( arg_manager_t *am, ccp arg1, ccp arg2, bool move_arg ) +{ + DASSERT(am); + PRINT("AppendArgManager(,%s,%s,%d)\n",arg1,arg2,move_arg); + return InsertArgManager(am,am->argc,arg1,arg2,move_arg); +} + +/////////////////////////////////////////////////////////////////////////////// + +uint InsertArgManager + ( arg_manager_t *am, int pos, ccp arg1, ccp arg2, bool move_arg ) +{ + PRINT("InsertArgManager(,%d,%s,%s,%d)\n",pos,arg1,arg2,move_arg); + + pos = CheckIndex1(am->argc,pos); + const int n = (arg1!=0) + (arg2!=0); + if (n) + { + PrepareEditArgManager(am,n); + DASSERT( pos>0 && pos <= am->argc ); + char **dest = am->argv + pos; + if ( pos < am->argc ) + memmove( dest+n, dest, (u8*)(am->argv+am->argc) - (u8*)dest ); + if (arg1) + *dest++ = move_arg ? (char*)arg1 : STRDUP(arg1); + if (arg2) + *dest++ = move_arg ? (char*)arg2 : STRDUP(arg2); + am->argc += n; + am->argv[am->argc] = 0; + } + return pos+n; +} + +/////////////////////////////////////////////////////////////////////////////// + +uint ReplaceArgManager + ( arg_manager_t *am, int pos, ccp arg1, ccp arg2, bool move_arg ) +{ + PRINT("ReplaceArgManager(,%d,%s,%s,%d)\n",pos,arg1,arg2,move_arg); + + pos = CheckIndex1(am->argc,pos); + const int n = (arg1!=0) + (arg2!=0); + if (n) + { + PrepareEditArgManager(am,n); + DASSERT( pos>0 && pos <= am->argc ); + char **dest = am->argv + pos; + if (arg1) + { + if ( pos++ < am->argc ) + FreeString(*dest); + *dest++ = move_arg ? (char*)arg1 : STRDUP(arg1); + } + if (arg2) + { + if ( pos++ < am->argc ) + FreeString(*dest); + *dest++ = move_arg ? (char*)arg2 : STRDUP(arg2); + } + if ( pos > am->argc ) + { + am->argc = pos; + am->argv[am->argc] = 0; + } + } + return pos; +} + +/////////////////////////////////////////////////////////////////////////////// + +uint RemoveArgManager ( arg_manager_t *am, int pos, int count ) +{ + DASSERT(am); + + #if HAVE_PRINT + const int oldpos = pos; + #endif + const int n = CheckIndexC(am->argc,&pos,count); + PRINT("RemoveArgManager(,%d,%d) : remove n=%d: %d..%d\n", + oldpos, count, n, pos, pos+n ); + + DASSERT( pos >= 0 && pos <= am->argc ); + DASSERT( n >= 0 && pos+n <= am->argc ); + + if ( n > 0 ) + { + PrepareEditArgManager(am,0); + char **dest = am->argv + pos; + + uint i; + for ( i = 0; i <n; i++ ) + FreeString(dest[i]); + am->argc -= n; + memmove( dest, dest+n, (u8*)(am->argv+am->argc) - (u8*)dest ); + am->argv[am->argc] = 0; + } + return pos; +} + +/////////////////////////////////////////////////////////////////////////////// + +void DumpArgManager ( FILE *f, int indent, const arg_manager_t *am, ccp title ) +{ + if ( !f || !am ) + return; + + indent = NormalizeIndent(indent); + if (title) + fprintf(f,"%*s" "ArgManager[%s]: N=%d", + indent,"", title, am->argc ); + else + fprintf(f,"%*s" "ArgManager: N=%d", indent,"", am->argc ); + + if (am->size) + fprintf(f,"/%u\n",am->size); + else + fputc('\n',f); + + if (am->argc) + { + char buf[10]; + int fw = snprintf(buf,sizeof(buf),"%u",am->argc-1)+2; + + uint i; + for ( i = 0; i < am->argc; i++ ) + fprintf(f,"%*s%*u: |%s|\n", indent,"", fw,i, am->argv[i] ); + } +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// global commands /////////////// +/////////////////////////////////////////////////////////////////////////////// + +enumError Command_ARGTEST ( int argc, char ** argv ) +{ + printf("ARGUMENT TEST: %u arguments:\n",argc); + + int idx; + for ( idx = 0; idx < argc; idx++ ) + printf("%4u.: |%s|\n",idx,argv[idx]); + return ERR_OK; +} + +/////////////////////////////////////////////////////////////////////////////// + +enumError Command_COLORS +( + int level, // only used, if mode==NULL + // < 0: status message (ignore mode) + // >= 1: include names + // >= 2: include alt names + // >= 3: include color names incl bold + // >= 4: include background color names + uint mode, // output mode => see PrintColorSetHelper() + uint format // output format => see PrintColorSetEx() +) +{ + if (!colout) + SetupStdMsg(); + + if ( level < 0 ) + { + printf("%s--color=%d [%s], colorize=%d [%s]\n" + "term=%s\n" + "stdout: tty=%d, mode=%d [%s], have-color=%d, n-colors=%u%s\n", + colout->status, + opt_colorize, GetColorModeName(opt_colorize,"?"), + colorize_stdout, GetColorModeName(colorize_stdout,"?"), + getenv("TERM"), isatty(fileno(stdout)), + colout->col_mode, GetColorModeName(colout->col_mode,"?"), + colout->colorize, colout->n_colors, colout->reset ); + return ERR_OK; + } + + if ( !mode && level > 0 ) + switch (level) + { + case 1: mode = 0x08; break; + case 2: mode = 0x18; break; + case 3: mode = 0x1b; break; + default: mode = 0x1f; break; + } + + if (!format) + { + const ColorMode_t col_mode = colout ? colout->col_mode : COLMD_AUTO; + PrintTextModes( stdout, 4, col_mode ); + PrintColorModes( stdout, 4, col_mode, GCM_ALT ); + #ifdef TEST + PrintColorModes( stdout, 4, col_mode, GCM_ALT|GCM_SHORT ); + #endif + } + if ( mode || format ) + PrintColorSetEx(stdout,4,colout,mode,format); + return ERR_OK; +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// END /////////////// +/////////////////////////////////////////////////////////////////////////////// + diff --git a/project/dclib/dclib-file.c b/project/dclib/dclib-file.c index 4f02ea5..a527c5a 100644 --- a/project/dclib/dclib-file.c +++ b/project/dclib/dclib-file.c @@ -4136,6 +4136,81 @@ int ScanSections /////////////// scan configuration /////////////// /////////////////////////////////////////////////////////////////////////////// +void ResetRestoreState ( RestoreState_t *rs ) +{ + if (rs) + { + ResetParamField(&rs->param); + InitializeRestoreState(rs); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +enumError ScanRestoreState +( + RestoreState_t *rs, // valid control + void *data, // file data, modified, terminated by NULL or LF + uint size, // size of file data + void **end_data // not NULL: store end of analysed here +) +{ + DASSERT(rs); + DASSERT(data||!size); + if (!size) + return ERR_OK; + + char *ptr = data; + char *end = ptr + size; + + if (!rs->param.field) + InitializeParamField(&rs->param); + + //--- scan name=value + + while ( ptr < end ) + { + //--- skip lines and blanks + while ( ptr < end && (uchar)*ptr <= ' ' ) + ptr++; + + if ( *ptr == '[' ) + break; + + //--- scan name + ccp name = ptr; + while ( *ptr >= '!' && *ptr <= '~' && *ptr != '=' ) + ptr++; + char *name_end = ptr; + + //--- scan param + while ( *ptr == ' ' || *ptr == '\t' ) + ptr++; + if ( *ptr != '=' ) + continue; + if ( *++ptr == ' ' ) // skip max 1 space + ptr++; + + ccp value = ptr; + while ( (uchar)*ptr >= ' ' || *ptr == '\t' ) + ptr++; + + *name_end = *ptr = 0; + InsertParamField(&rs->param,name,false,0,value); + + //--- next line + while ( ptr < end && *ptr && *ptr != '\n' ) + ptr++; + } + + if (end_data) + *end_data = ptr; + + return ERR_OK; +} + +/////////////////////////////////////////////////////////////////////////////// + enumError RestoreState ( const RestoreStateTab_t @@ -4267,8 +4342,9 @@ enumError RestoreState } #endif - tab->func(&rs,tab->user_table); - if ( log_mode & RSL_UNUSED_NAMES ) + if (tab->func) + tab->func(&rs,tab->user_table); + if ( log_file && log_mode & RSL_UNUSED_NAMES ) { ParamFieldItem_t *ptr = rs.param.field, *end; for ( end = ptr + rs.param.used; ptr < end; ptr++ ) @@ -4285,7 +4361,7 @@ enumError RestoreState ptr->key, len, (ccp)ptr->data ); } } - ResetParamField(&rs.param); + ResetRestoreState(&rs); } return ERR_OK; @@ -5590,6 +5666,269 @@ ccp PrintOpenFiles ( bool count_current ) // /////////////////////////////////////////////////////////////////////////////// +/////////////// PrintScript /////////////// +/////////////////////////////////////////////////////////////////////////////// + +ccp GetNamePSFF ( PrintScriptFF fform ) +{ + switch(fform) + { + case PSFF_UNKNOWN: return "TEXT"; + case PSFF_JSON: return "JSON"; + case PSFF_BASH: return "BASH"; + case PSFF_SH: return "SH"; + case PSFF_PHP: return "PHP"; + case PSFF_MAKEDOC: return "MDOC"; + } + return "???"; +} + +/////////////////////////////////////////////////////////////////////////////// + +void PrintScriptHeader ( PrintScript_t *ps ) +{ + DASSERT(ps); + + ps->index = 0; + ps->add_index = false; + ps->sep[0] = ps->sep[1] = 0; + + if ( ps->f ) + { + switch (ps->fform) + { + case PSFF_JSON: + if (ps->create_array) + fputs("[",ps->f); + break; + + case PSFF_SH: + ps->add_index =ps->create_array; + break; + + case PSFF_PHP: + if (ps->create_array) + fprintf(ps->f,"$%s = array();\n\n",ps->varname); + break; + + case PSFF_MAKEDOC: + if (ps->create_array) + fprintf(ps->f,"%s = @LIST\n\n",ps->varname); + break; + + default: + //fputc('\n',ps->f); + break; + } + } +} + +/////////////////////////////////////////////////////////////////////////////// + +void PrintScriptFooter ( PrintScript_t *ps ) +{ + DASSERT(ps); + + if (ps->f) + { + switch (ps->fform) + { + case PSFF_JSON: + if (ps->create_array) + fputs("]\n",ps->f); + break; + + case PSFF_SH: + if (ps->create_array) + fprintf(ps->f,"%s_N=%u\n\n",ps->varname,ps->index); + break; + + case PSFF_PHP: + fputs("?>\n",ps->f); + break; + + default: + break; + } + } +} + +/////////////////////////////////////////////////////////////////////////////// + +int PutScriptVars +( + PrintScript_t *ps, // valid control struct + uint mode, // bit field: 1=open var, 2:close var + ccp text // text with line of format NAME=VALUE +) +{ + FILE * f = ps ? ps->f : 0; + if (!f) + return 0; + + + //--- begin of output + + if ( mode & 1 ) + { + if ( ps->add_index ) + snprintf( ps->prefix, sizeof(ps->prefix), + "%s_%u", ps->varname, ps->index ); + else + snprintf( ps->prefix, sizeof(ps->prefix), + "%s", ps->varname ); + + switch (ps->fform) + { + case PSFF_JSON: + fprintf(f,"%s{",ps->sep); + ps->sep[0] = ','; + break; + + case PSFF_PHP: + fputs("$d = new \\stdClass;\n",f); + break; + + case PSFF_MAKEDOC: + fprintf(f,"d = @MAP\n"); + break; + + default: + break; + } + } + + + //--- print var lines + + if (!text) + text = ""; + + uint count; + for( count = 0; ; count++ ) + { + while ( *text && (uchar)*text <= ' ' ) + text++; + + ccp ptr = text; + while ( *ptr && *ptr != '=' ) + ptr++; + if ( *ptr != '=' || ptr == text ) + break; + + ccp param = ptr++; + while ( (uchar)*ptr >= ' ' ) + ptr++; + + switch (ps->fform) + { + case PSFF_JSON: + fprintf(f, "%s\"%.*s\":%.*s", + count ? "," : "", + (int)( param - text ), text, + (int)( ptr - param - 1 ), param+1 ); + break; + + case PSFF_BASH: + if (ps->create_array) + { + fprintf(f, "%s_%.*s%s=(%.*s)\n", ps->prefix, + (int)( param - text ), text, + ps->index ? "+" : "", + (int)( ptr - param - 1 ), param+1 ); + break; + } + // fall through + + case PSFF_SH: + fprintf(f, "%s_%.*s=%.*s\n", ps->prefix, + (int)( param - text ), text, + (int)( ptr - param - 1 ), param+1 ); + break; + + case PSFF_PHP: + fprintf(f, "$d->%.*s = %.*s;\n", + (int)( param - text ), text, + (int)( ptr - param - 1 ), param+1 ); + break; + + case PSFF_MAKEDOC: + fprintf(f, "d[\"%.*s\"] = %.*s\n", + (int)( param - text ), text, + (int)( ptr - param - 1 ), param+1 ); + break; + + default: + fprintf(f, "%20.*s = %.*s\n", + (int)( param - text ), text, + (int)( ptr - param - 1 ), param+1 ); + break; + } + + text = ptr; + } + + + //--- end of output + + if ( mode & 2 ) + { + switch (ps->fform) + { + case PSFF_JSON: + fputs("}\n",f); + break; + + case PSFF_PHP: + fprintf(f, "$%s%s = $d;\n\n", + ps->prefix, ps->create_array ? "[]" : "" ); + break; + + case PSFF_MAKEDOC: + fprintf(f, "%s %s= move(d);\n\n", + ps->prefix, ps->create_array ? "#" : "" ); + break; + + default: + fputc('\n',f); + break; + } + fflush(f); + } + + ps->index++; + return count; +} + +/////////////////////////////////////////////////////////////////////////////// + +int PrintScriptVars +( + PrintScript_t *ps, // valid control struct + uint mode, // bit field: 1=open var, 2:close var + ccp format, // format of message + ... // arguments + +) +{ + DASSERT(ps); + + char buf[5000]; + if (format) + { + va_list arg; + va_start(arg,format); + vsnprintf(buf,sizeof(buf),format,arg); + va_end(arg); + } + else + *buf = 0; + + return PutScriptVars(ps,mode,buf); +} + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// END /////////////// /////////////////////////////////////////////////////////////////////////////// diff --git a/project/dclib/dclib-file.h b/project/dclib/dclib-file.h index 6f6aee9..bce66b1 100644 --- a/project/dclib/dclib-file.h +++ b/project/dclib/dclib-file.h @@ -183,7 +183,6 @@ static inline int CompareTimeSpecVal static inline int CompareTimeSpecTime ( const struct timespec *a, const time_t tim ) { DASSERT(a); - DASSERT(b); return a->tv_sec < tim ? -1 : a->tv_sec > tim ? 1 : a->tv_nsec > 0; @@ -1330,6 +1329,70 @@ ccp PrintOpenFiles ( bool count_current ); // print to circ buffer // /////////////////////////////////////////////////////////////////////////////// +/////////////// PrintScript /////////////// +/////////////////////////////////////////////////////////////////////////////// +// [[PrintScriptFF]] // FF = File Format + +typedef enum PrintScriptFF +{ + PSFF_UNKNOWN, // always 0 + PSFF_JSON, + PSFF_BASH, + PSFF_SH, + PSFF_PHP, + PSFF_MAKEDOC, +} +PrintScriptFF; + +ccp GetNamePSFF ( PrintScriptFF fform ); + +//----------------------------------------------------------------------------- +// [[PrintScript_t]] + +typedef struct PrintScript_t +{ + FILE *f; // valid output file + PrintScriptFF fform; // output: file format + ccp varname; // valid ponter to var name + bool create_array; // true: create ar arrays + bool add_index; // true: add index to varname + uint index; // index for array operations + char sep[2]; // separator for JSON + char prefix[100]; // varname prefix +} +PrintScript_t; + +//----------------------------------------------------------------------------- + +static inline void InitializePrintScript ( PrintScript_t *ps ) + { DASSERT(ps); memset(ps,0,sizeof(*ps)); } + +static inline void ResetPrintScript ( PrintScript_t *ps ) + { DASSERT(ps); memset(ps,0,sizeof(*ps)); } + +/////////////////////////////////////////////////////////////////////////////// + +void PrintScriptHeader ( PrintScript_t *ps ); +void PrintScriptFooter ( PrintScript_t *ps ); + +int PutScriptVars +( + PrintScript_t *ps, // valid control struct + uint mode, // bit field: 1=open var, 2:close var + ccp text // text with line of format NAME=VALUE +); + +int PrintScriptVars +( + PrintScript_t *ps, // valid control struct + uint mode, // bit field: 1=open var, 2:close var + ccp format, // format of message + ... // arguments +) +__attribute__ ((__format__(__printf__,3,4))); + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// E N D /////////////// /////////////////////////////////////////////////////////////////////////////// diff --git a/project/dclib/dclib-network-linux.c b/project/dclib/dclib-network-linux.c index 900714e..b913aa4 100644 --- a/project/dclib/dclib-network-linux.c +++ b/project/dclib/dclib-network-linux.c @@ -49,6 +49,111 @@ // /////////////////////////////////////////////////////////////////////////////// +/////////////// IP/UDP /////////////// +/////////////////////////////////////////////////////////////////////////////// + +ssize_t ReceiveUDPv4 +( + int sock, // valid socket + void *buf, // buffer tostore incoming data + size_t buf_size, // size of buffer + int flags, // flags for recffrom() or recvmsg() + struct sockaddr_in *src_addr, // not NULL: store source address + in_addr_t *dest_addr // not NULL: store destination IPv4 (NBO) +) +{ + DASSERT(buf); + + if (!dest_addr) + { + socklen_t src_len = sizeof(*src_addr); + return recvfrom( sock, buf, buf_size, flags, + (struct sockaddr*)src_addr, &src_len ); + } + + struct sockaddr_in sa_temp; + if (!src_addr) + src_addr = &sa_temp; + + *dest_addr = 0; + u8 control[CMSG_SPACE(sizeof(struct in_pktinfo))]; + + struct iovec iov; + iov.iov_base = buf; + iov.iov_len = buf_size; + + struct msghdr msg = {0}; + msg.msg_name = src_addr; + msg.msg_namelen = sizeof(*src_addr); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = control; + msg.msg_controllen = sizeof(control); + + ssize_t stat = recvmsg(sock,&msg,flags); + if ( stat < 0 ) + return stat; + + struct cmsghdr *cp; + for ( cp = CMSG_FIRSTHDR(&msg); cp; cp = CMSG_NXTHDR(&msg,cp)) + { + if ( cp->cmsg_level == IPPROTO_IP && cp->cmsg_type == IP_PKTINFO ) + { + struct in_pktinfo *pktinfo = (struct in_pktinfo*) CMSG_DATA(cp); + *dest_addr = pktinfo->ipi_spec_dst.s_addr; + break; + } + } + + return stat; +} + +/////////////////////////////////////////////////////////////////////////////// + +ssize_t SendUDPv4 +( + int sock, // valid socket + const void *data, // data to send + size_t data_size, // size of data + int flags, // flags for sendto() or sendmsg() + struct sockaddr_in *dest_addr, // destination address (NULL possible) + in_addr_t src_addr // not 0: source IPv4 (NBO) +) +{ + DASSERT(data); + DASSERT(dest_addr); + + if (!src_addr) + return sendto(sock,data,data_size,flags,dest_addr,sizeof(*dest_addr)); + + u8 control[CMSG_SPACE(sizeof(struct in_pktinfo))]; + + struct iovec iov; + iov.iov_base = (void*)data; + iov.iov_len = data_size; + + struct msghdr msg = {0}; + msg.msg_name = dest_addr; + msg.msg_namelen = sizeof(*dest_addr); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = control; + msg.msg_controllen = sizeof(control); + + struct cmsghdr *cp = CMSG_FIRSTHDR(&msg); + cp->cmsg_level = IPPROTO_IP; + cp->cmsg_type = IP_PKTINFO; + cp->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); + + struct in_pktinfo *pki = (struct in_pktinfo*) CMSG_DATA(cp); + pki->ipi_ifindex = 0; + pki->ipi_spec_dst.s_addr = src_addr; + + return sendmsg(sock,&msg,flags); +} + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// SendRawUDP() /////////////// /////////////////////////////////////////////////////////////////////////////// diff --git a/project/dclib/dclib-network-linux.h b/project/dclib/dclib-network-linux.h index fc09ed8..bd3cb79 100644 --- a/project/dclib/dclib-network-linux.h +++ b/project/dclib/dclib-network-linux.h @@ -41,7 +41,62 @@ // /////////////////////////////////////////////////////////////////////////////// -/////////////// IP interface /////////////// +/////////////// IP/UDP /////////////// +/////////////////////////////////////////////////////////////////////////////// + +ssize_t ReceiveUDPv4 +( + int sock, // valid socket + void *buf, // buffer tostore incoming data + size_t buf_size, // size of buffer + int flags, // flags for recffrom() or recvmsg() + struct sockaddr_in *src_addr, // not NULL: stire source address + in_addr_t *dest_addr // not NULL: store destination IPv4 (NBO) +); + +/////////////////////////////////////////////////////////////////////////////// + +ssize_t SendUDPv4 +( + int sock, // valid socket + const void *data, // data to send + size_t data_size, // size of data + int flags, // flags for sendto() or sendmsg() + struct sockaddr_in *dest_addr, // destination address (NULL possible) + in_addr_t src_addr // not 0: source IPv4 (NBO) +); + +/////////////////////////////////////////////////////////////////////////////// + +ssize_t recvfrom2 +( + int sock, + void *buf, + size_t buf_size, + int flags, + struct sockaddr *src_addr, + socklen_t *src_addrlen, + struct sockaddr *dest_addr, + socklen_t *dest_addrlen +); + +//----------------------------------------------------------------------------- + +ssize_t sendto2 +( + int sock, + const void *buf, + size_t buf_size, + int flags, + struct sockaddr *dest_addr, + socklen_t dest_addrlen, + struct sockaddr_in *src_addr, + socklen_t src_addrlen +); + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// SendRawUDP() /////////////// /////////////////////////////////////////////////////////////////////////////// enumError SendRawUDP diff --git a/project/dclib/dclib-network.h b/project/dclib/dclib-network.h index 4cf099f..58076c9 100644 --- a/project/dclib/dclib-network.h +++ b/project/dclib/dclib-network.h @@ -42,6 +42,13 @@ // /////////////////////////////////////////////////////////////////////////////// +/////////////// definitions /////////////// +/////////////////////////////////////////////////////////////////////////////// + +#define GOOD_SOCKADR_SIZE sizeof(struct sockaddr_un) + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// host name support /////////////// /////////////////////////////////////////////////////////////////////////////// // [[NetworkHost_t]] diff --git a/project/dclib/dclib-numeric.c b/project/dclib/dclib-numeric.c index 138053d..d39567b 100644 --- a/project/dclib/dclib-numeric.c +++ b/project/dclib/dclib-numeric.c @@ -711,13 +711,29 @@ void write_lef4n ( float32 * dest, const float32 * src, int n ) /////////////////////////////////////////////////////////////////////////////// +static inline u16 ident16 ( u16 data ) { return data; } +static inline u32 ident32 ( u32 data ) { return data; } +static inline u64 ident64 ( u64 data ) { return data; } + +static inline u16 reverse16 ( u16 data ) { return swap16(&data); } +static inline u32 reverse32 ( u32 data ) { return swap32(&data); } +static inline u64 reverse64 ( u64 data ) { return swap64(&data); } + const endian_func_t be_func = { {0xfe,0xff}, true, false, DC_BIG_ENDIAN, be16, be24, be32, be40, be48, be56, be64, bef4, bef8, write_be16, write_be24, write_be32, write_be40, write_be48, write_be56, write_be64, - write_bef4, write_bef8 + write_bef4, write_bef8, + + #if IS_BIG_ENDIAN + ident16, ident32, ident64, + ident16, ident32, ident64, + #else + reverse16, reverse32, reverse64, + reverse16, reverse32, reverse64, + #endif }; const endian_func_t le_func = @@ -726,7 +742,15 @@ const endian_func_t le_func = le16, le24, le32, le40, le48, le56, le64, lef4, lef8, write_le16, write_le24, write_le32, write_le40, write_le48, write_le56, write_le64, - write_lef4, write_lef8 + write_lef4, write_lef8, + + #if IS_LITTLE_ENDIAN + ident16, ident32, ident64, + ident16, ident32, ident64, + #else + reverse16, reverse32, reverse64, + reverse16, reverse32, reverse64, + #endif }; const endian_func_t * GetEndianFunc ( const void * byte_order_mark ) @@ -854,6 +878,72 @@ int CheckIndex2End ( int max, int * p_begin, int * p_end ) return end - begin; } +/////////////////////////////////////////////////////////////////////////////// + +int CheckIndexC ( int max, int * p_begin, int count ) +{ + DASSERT( max >= 0 ); + DASSERT(p_begin); + + int begin = *p_begin, end = begin + count; + if ( begin < 0 ) + { + begin += max; + end = begin + count; + if ( begin < 0 ) + begin = 0; + } + else if ( begin > max ) + begin = max; + + if ( end < 0 ) + end = 0; + else if ( end > max ) + end = max; + + if ( end < begin ) + { + *p_begin = end; + return begin-end; + } + + *p_begin = begin; + return end - begin; +} + +/////////////////////////////////////////////////////////////////////////////// + +int CheckIndexCEnd ( int max, int * p_begin, int count ) +{ + DASSERT( max >= 0 ); + DASSERT(p_begin); + + int begin = *p_begin, end = begin + count; + if ( begin <= 0 ) + { + begin += max; + end = begin + count; + if ( begin < 0 ) + begin = 0; + } + else if ( begin > max ) + begin = max; + + if ( end < 0 ) + end = 0; + else if ( end > max ) + end = max; + + if ( end < begin ) + { + *p_begin = end; + return begin-end; + } + + *p_begin = begin; + return end - begin; +} + // /////////////////////////////////////////////////////////////////////////////// /////////////// encoding/decoding /////////////// diff --git a/project/dclib/dclib-option.h b/project/dclib/dclib-option.h index f1bf8f0..d293b9e 100644 --- a/project/dclib/dclib-option.h +++ b/project/dclib/dclib-option.h @@ -269,7 +269,7 @@ typedef struct GOptions_t //--- parameters int argc; // number of parameters - char **argv; // paramters without options + char **argv; // parameters without options //--- named options diff --git a/project/dclib/dclib-system.h b/project/dclib/dclib-system.h index e5a7380..e1f8264 100644 --- a/project/dclib/dclib-system.h +++ b/project/dclib/dclib-system.h @@ -44,10 +44,11 @@ typedef enum enumSystemID SYSID_UNKNOWN = 0x00000000, SYSID_I386 = 0x01000000, SYSID_X86_64 = 0x02000000, - SYSID_CYGWIN = 0x03000000, - SYSID_APPLE = 0x04000000, - SYSID_LINUX = 0x05000000, - SYSID_UNIX = 0x06000000, + SYSID_CYGWIN32 = 0x03000000, + SYSID_CYGWIN64 = 0x04000000, + SYSID_APPLE = 0x05000000, + SYSID_LINUX = 0x06000000, + SYSID_UNIX = 0x07000000, } enumSystemID; @@ -56,29 +57,39 @@ typedef enum enumSystemID #undef SYSTEM_LINUX #ifdef __CYGWIN__ - #define SYSTEM "cygwin" - #define SYSTEMID SYSID_CYGWIN + #define SYSTEM "cygwin" + #ifdef __x86_64 + #define SYSTEM2 "cygwin64" + #define SYSTEMID SYSID_CYGWIN64 + #else + #define SYSTEM2 "cygwin32" + #define SYSTEMID SYSID_CYGWIN32 + #endif #elif __APPLE__ - #define SYSTEM "mac" - #define SYSTEMID SYSID_APPLE + #define SYSTEM "mac" + #define SYSTEMID SYSID_APPLE #elif __linux__ #define SYSTEM_LINUX 1 #ifdef __i386__ - #define SYSTEM "i386" - #define SYSTEMID SYSID_I386 + #define SYSTEM "i386" + #define SYSTEMID SYSID_I386 #elif __x86_64__ - #define SYSTEM "x86_64" - #define SYSTEMID SYSID_X86_64 + #define SYSTEM "x86_64" + #define SYSTEMID SYSID_X86_64 #else - #define SYSTEM "linux" - #define SYSTEMID SYSID_LINUX + #define SYSTEM "linux" + #define SYSTEMID SYSID_LINUX #endif #elif __unix__ - #define SYSTEM "unix" - #define SYSTEMID SYSID_UNIX + #define SYSTEM "unix" + #define SYSTEMID SYSID_UNIX #else - #define SYSTEM "unknown" - #define SYSTEMID SYSID_UNKNOWN + #define SYSTEM "unknown" + #define SYSTEMID SYSID_UNKNOWN +#endif + +#ifndef SYSTEM2 + #define SYSTEM2 SYSTEM #endif /////////////////////////////////////////////////////////////////////////////// @@ -87,11 +98,13 @@ static inline void dclibPrintSystem ( FILE * f ) { fprintf(f, "SYSTEM\t\t:= %s\n" + "SYSTEM2\t\t:= %s\n" "SYSTEMID\t:= 0x%x\n" #ifdef SYSTEM_LINUX "SYSTEM_LINUX\t:= 1\n" #endif ,SYSTEM + ,SYSTEM2 ,SYSTEMID ); } diff --git a/project/dclib/dclib-types.h b/project/dclib/dclib-types.h index 8631d9a..360c026 100644 --- a/project/dclib/dclib-types.h +++ b/project/dclib/dclib-types.h @@ -51,6 +51,22 @@ /////////////////////////////////////////////////////////////////////////////// /////////////// endian /////////////// /////////////////////////////////////////////////////////////////////////////// + +#undef IS_BIG_ENDIAN +#undef IS_LITTLE_ENDIAN + +#if __BYTE_ORDER == __BIG_ENDIAN + #define IS_BIG_ENDIAN 1 + #define IS_LITTLE_ENDIAN 0 +#elif __BYTE_ORDER == __LITTLE_ENDIAN + #define IS_BIG_ENDIAN 0 + #define IS_LITTLE_ENDIAN 1 +#else + #define IS_BIG_ENDIAN 0 + #define IS_LITTLE_ENDIAN 0 +#endif + +//----------------------------------------------------------------------------- // [[dcEndian_t]] typedef enum dcEndian_t @@ -63,7 +79,7 @@ typedef enum dcEndian_t //--- define local & reverse endian, if possible - #if __BYTE_ORDER == __LITTLE_ENDIAN || __BYTE_ORDER == __BIG_ENDIAN + #if IS_BIG_ENDIAN || IS_LITTLE_ENDIAN DC_LOCAL_ENDIAN = DC_DEFAULT_ENDIAN, DC_REVERSE_ENDIAN = DC_SECOND_ENDIAN, @@ -73,7 +89,7 @@ typedef enum dcEndian_t //--- define aliases for little & big endian - #if __BYTE_ORDER == __BIG_ENDIAN + #if IS_BIG_ENDIAN DC_BIG_ENDIAN = DC_DEFAULT_ENDIAN, DC_LITTLE_ENDIAN = DC_SECOND_ENDIAN, diff --git a/project/dclib/lib-bmg.c b/project/dclib/lib-bmg.c index 639d940..599c2dc 100644 --- a/project/dclib/lib-bmg.c +++ b/project/dclib/lib-bmg.c @@ -89,6 +89,7 @@ bool opt_bmg_use_raw_sections= 0; // true: use raw sections //----------------------------------------------------------------------------- +int opt_bmg_endian = BMG_AUTO_ENDIAN; int opt_bmg_encoding = BMG_ENC__UNDEFINED; uint opt_bmg_inf_size = 0; OffOn_t opt_bmg_mid = OFFON_AUTO; @@ -150,6 +151,42 @@ const KeywordTab_t PatchKeysBMG[] = // /////////////////////////////////////////////////////////////////////////////// +/////////////// endian helpers /////////////// +/////////////////////////////////////////////////////////////////////////////// + +static const endian_func_t * get_bmg_endian ( const bmg_t * bmg ) +{ + return opt_bmg_endian == BMG_LITTLE_ENDIAN + ? &le_func + : opt_bmg_endian == BMG_BIG_ENDIAN || !bmg + ? &be_func + : bmg->endian; +} + +//----------------------------------------------------------------------------- + +static const endian_func_t * get_endian_by_bh ( const bmg_header_t * bh, uint size ) +{ + DASSERT(bh); + if ( be_func.n2hl(bh->size) <= size + && be_func.n2hl(bh->n_sections) <= BMG_MAX_SECTIONS + ) + { + return &be_func; + } + + if ( le_func.n2hl(bh->size) <= size + && le_func.n2hl(bh->n_sections) <= BMG_MAX_SECTIONS + ) + { + return &le_func; + } + + return 0; +} + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// print & scan string16 /////////////// /////////////////////////////////////////////////////////////////////////////// @@ -1069,18 +1106,27 @@ static u16 * ScanRange16U32 /////////////// ScanSectionsBMG() /////////////// /////////////////////////////////////////////////////////////////////////////// -bmg_sect_list_t * ScanSectionsBMG ( cvp data, uint size ) +bmg_sect_list_t * ScanSectionsBMG + ( cvp data, uint size, const endian_func_t *endian ) { //--- initialize if ( !data || size < sizeof(bmg_header_t) || memcmp(data,BMG_MAGIC,8) ) return 0; - bmg_sect_list_t sl; - memset(&sl,0,sizeof(sl)); - sl.header = (bmg_header_t*)data; - sl.source_size = ntohl(sl.header->size); - sl.n_sections = ntohl(sl.header->n_sections); + bmg_sect_list_t sl = {0}; + sl.header = (bmg_header_t*)data; + + if (!endian) + { + endian = get_endian_by_bh(sl.header,size); + if (!endian) + return 0; + } + + sl.endian = endian; + sl.source_size = endian->n2hl(sl.header->size); + sl.n_sections = endian->n2hl(sl.header->n_sections); FastBuf_t fb; InitializeFastBufAlloc(&fb,10*sizeof(bmg_sect_info_t)); @@ -1099,7 +1145,7 @@ bmg_sect_list_t * ScanSectionsBMG ( cvp data, uint size ) memset(&si,0,sizeof(si)); si.offset = (u8*)sect - (u8*)data; - si.sect_size = si.real_size = ntohl(sect->size); + si.sect_size = si.real_size = endian->n2hl(sect->size); if ( (u8*)sect + si.real_size > data_end ) si.real_size = data_end - (u8*)sect; @@ -1110,8 +1156,8 @@ bmg_sect_list_t * ScanSectionsBMG ( cvp data, uint size ) { sl.pinf = (bmg_inf_t*)sect; si.head_size = sizeof(bmg_inf_t); - si.elem_size = ntohs(sl.pinf->inf_size); - si.n_elem_head = ntohs(sl.pinf->n_msg); + si.elem_size = endian->n2hs(sl.pinf->inf_size); + si.n_elem_head = endian->n2hs(sl.pinf->n_msg); si.known = true; si.supported = true; si.info = "offset & attributes"; @@ -1137,7 +1183,7 @@ bmg_sect_list_t * ScanSectionsBMG ( cvp data, uint size ) sl.pmid = (bmg_mid_t*)sect; si.head_size = sizeof(bmg_mid_t); si.elem_size = sizeof(u32); - si.n_elem_head = ntohs(sl.pinf->n_msg); + si.n_elem_head = endian->n2hs(sl.pinf->n_msg); si.known = true; si.supported = true; si.info = "message ids"; @@ -1821,6 +1867,32 @@ int (*GetArenaIndexBMG) ( uint idx, int result_on_invalid ) = GetArenaIndexBMG0; // /////////////////////////////////////////////////////////////////////////////// +/////////////// bmg endian support /////////////// +/////////////////////////////////////////////////////////////////////////////// + +const KeywordTab_t TabEndianBMG[] = +{ + { BMG_AUTO_ENDIAN, "AUTO", "UNDEFINED", 0 }, + { BMG_BIG_ENDIAN, "BIG", "BE", 0 }, + { BMG_LITTLE_ENDIAN, "LITTLE", "LE", 0 }, + { 0,0,0,0 } +}; + +//----------------------------------------------------------------------------- + +ccp GetEndianNameBMG ( int endian, ccp return_if_invalid ) +{ + switch (endian) + { + case BMG_AUTO_ENDIAN: return "AUTO"; + case BMG_BIG_ENDIAN: return "BIG"; + case BMG_LITTLE_ENDIAN: return "LITTLE"; + } + return return_if_invalid; +} + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// bmg encoding support /////////////// /////////////////////////////////////////////////////////////////////////////// @@ -1922,6 +1994,8 @@ void InitializeBMG ( bmg_t * bmg ) DASSERT(bmg); memset(bmg,0,sizeof(*bmg)); + + bmg->endian = &be_func; bmg->have_mid = 1; bmg->encoding = BMG_ENC__DEFAULT; bmg->use_slots = opt_bmg_use_slots; @@ -2168,11 +2242,12 @@ enumError ScanRawBMG ( bmg_t * bmg ) { DASSERT(bmg); DASSERT(bmg->data); + DASSERT(bmg->endian); const bmg_header_t * bh = (bmg_header_t*)bmg->data; DASSERT(!memcmp(bh->magic,BMG_MAGIC,sizeof(bh->magic))); - u32 data_size = ntohl(bh->size); + u32 data_size = bmg->endian->n2hl(bh->size); bmg->encoding = bh->encoding; if ( !bmg->encoding && data_size*BMG_LEGACY_BLOCK_SIZE <= bmg->data_size ) { @@ -2189,7 +2264,7 @@ enumError ScanRawBMG ( bmg_t * bmg ) data_size = bmg->data_size; } - const bmg_sect_list_t *sl = ScanSectionsBMG(bmg->data,data_size); + const bmg_sect_list_t *sl = ScanSectionsBMG(bmg->data,data_size,bmg->endian); if ( !sl || !sl->header ) return ERROR0(ERR_INVALID_DATA,"Invalid BMG data: %s",bmg->fname); @@ -2251,33 +2326,33 @@ enumError ScanRawBMG ( bmg_t * bmg ) if ( !sl->pinf || !sl->pdat ) return ERROR0(ERR_INVALID_DATA,"Corrupted BMG file: %s\n",bmg->fname); - bmg->unknown_inf_0c = ntohl(pinf->unknown_0c); + bmg->unknown_inf_0c = bmg->endian->n2hl(pinf->unknown_0c); uint max_item; bmg->have_mid = pmid != 0; if (bmg->have_mid) { - bmg->unknown_mid_0a = ntohs(pmid->unknown_0a); - bmg->unknown_mid_0c = ntohl(pmid->unknown_0c); + bmg->unknown_mid_0a = bmg->endian->n2hs(pmid->unknown_0a); + bmg->unknown_mid_0c = bmg->endian->n2hl(pmid->unknown_0c); - max_item = ( ntohl(pmid->size) - sizeof(*pmid) ) / sizeof(*pmid->mid); - if ( max_item > ntohs(pmid->n_msg) ) - max_item = ntohs(pmid->n_msg); + max_item = ( bmg->endian->n2hl(pmid->size) - sizeof(*pmid) ) / sizeof(*pmid->mid); + if ( max_item > bmg->endian->n2hs(pmid->n_msg) ) + max_item = bmg->endian->n2hs(pmid->n_msg); PRINT("BMG with MID1: N=%u [inf=%u,mid=%u], %s\n", - max_item, ntohs(pinf->n_msg), ntohs(pmid->n_msg), bmg->fname ); + max_item, bmg->endian->n2hs(pinf->n_msg), bmg->endian->n2hs(pmid->n_msg), bmg->fname ); } else { - max_item = ntohs(pinf->n_msg); + max_item = bmg->endian->n2hs(pinf->n_msg); PRINT("BMG without MID1: N=%u, %s\n",max_item,bmg->fname); } - const uint max_offset = ( ntohl(pdat->size) - sizeof(*pdat) ) + const uint max_offset = ( bmg->endian->n2hl(pdat->size) - sizeof(*pdat) ) / sizeof(*pdat->text_pool); const u8 *text_end = pdat->text_pool + max_offset; const u8 *raw_inf = (u8*)pinf->list; - const uint src_inf_size = ntohs(pinf->inf_size); + const uint src_inf_size = bmg->endian->n2hs(pinf->inf_size); AssignInfSizeBMG(bmg,src_inf_size); @@ -2289,7 +2364,7 @@ enumError ScanRawBMG ( bmg_t * bmg ) for ( idx = 0; idx < bmg->attrib_used; idx += 4 ) { const u32 major = FindMajority32(raw_inf+idx+4,max_item,src_inf_size); - noPRINT("-> IDX: %2u -> %8x\n",idx,ntohl(major)); + noPRINT("-> IDX: %2u -> %8x\n",idx,bmg->endian->n2hl(major)); memcpy(bmg->attrib+idx,&major,4); } //HexDump16(stderr,8,0x10,bmg->attrib,bmg->attrib_used); @@ -2309,9 +2384,9 @@ enumError ScanRawBMG ( bmg_t * bmg ) for ( slot = 0; slot < max_item; slot++, raw_inf += src_inf_size ) { bmg_inf_item_t *item = (bmg_inf_item_t*)raw_inf; - const u32 offset = ntohl(item->offset); + const u32 offset = bmg->endian->n2hl(item->offset); - u32 mid = pmid ? ntohl(pmid->mid[slot]) : slot; + u32 mid = pmid ? bmg->endian->n2hl(pmid->mid[slot]) : slot; if ( mid == 0xffff && !offset ) ffff_count++; if ( mid < prev_mid ) @@ -2677,7 +2752,9 @@ enumError ScanTextBMG ( bmg_t * bmg ) continue; noPRINT("PARAM: %s = |%.*s|\n",namebuf,(int)(ptr-start),start); - if (!strcmp(namebuf,"LEGACY")) + if (!strcmp(namebuf,"ENDIAN")) + bmg->endian = str2l(start,0,10) > 0 ? &le_func : &be_func; + else if (!strcmp(namebuf,"LEGACY")) bmg->legacy = str2l(start,0,10) > 0; else if (!strcmp(namebuf,"ENCODING")) AssignEncodingBMG(bmg,str2l(start,0,10)); @@ -2975,9 +3052,13 @@ enumError ScanBMG bmg->fname = STRDUP(fname); const bmg_header_t * bh = (bmg_header_t*)bmg->data; - if ( !memcmp(bh->magic,BMG_MAGIC,sizeof(bh->magic)) - && ntohl(bh->size) <= bmg->data_size ) - return ScanRawBMG(bmg); + + if (!memcmp(bh->magic,BMG_MAGIC,sizeof(bh->magic))) + { + bmg->endian = get_endian_by_bh(bh,bmg->data_size); + if (bmg->endian) + return ScanRawBMG(bmg); + } ccp ptr = (ccp)bmg->data + GetTextBOMLen(bmg->data,bmg->data_size); if ( !memcmp(ptr,BMG_TEXT_MAGIC,4) ) @@ -3072,6 +3153,7 @@ void InitializeCreateBMG ( bmg_create_t *bc, bmg_t *bmg ) memset(bc,0,sizeof(*bc)); bc->bmg = bmg; + bc->endian = get_bmg_endian(bmg); bc->have_mid = opt_bmg_mid == OFFON_AUTO ? bmg->have_mid : opt_bmg_mid >= OFFON_ON; @@ -3157,6 +3239,7 @@ bmg_item_t * GetNextBI ( bmg_create_t *bc ) { DASSERT(bc); DASSERT(bc->bmg); + DASSERT(bc->bmg->endian); bmg_t *bmg = bc->bmg; @@ -3191,14 +3274,14 @@ bmg_item_t * GetNextBI ( bmg_create_t *bc ) u32 *pmid = (u32*)WriteFastBuf( &bc->mid, bc->slot*sizeof(u32), 0, sizeof(u32) ); DASSERT(pmid); - *pmid = htonl(bi->mid); + *pmid = bc->endian->h2nl(bi->mid); const uint inf_size = bmg->inf_size; bmg_inf_item_t *ii = (bmg_inf_item_t*)WriteFastBuf ( &bc->inf, bc->slot * inf_size, 0, inf_size ); DASSERT(ii); if ( !isSpecialEntryBMG(bi->text) ) - ii->offset = htonl(GetFastBufLen(&bc->dat)); + ii->offset = bc->endian->h2nl(GetFastBufLen(&bc->dat)); memcpy(ii->attrib,bi->attrib,bmg->attrib_used); if ( bc->n_msg <= bc->slot ) @@ -3366,11 +3449,13 @@ enumError CreateRawBMG ) { DASSERT(bmg); + DASSERT(bmg->endian); TRACE("CreateRawBMG()\n"); //--- setup bmg_create_t +// [[opt-endian]] bmg_create_t bc; InitializeCreateBMG(&bc,bmg); PRINT("fb:inf: %s\n", GetFastBufStatus(&bc.inf) ); @@ -3457,8 +3542,8 @@ enumError CreateRawBMG //---- setup bmg header bmg_header_t *bh = (bmg_header_t*)bmg->raw_data; - bh->size = htonl( bmg->legacy ? total_size/BMG_LEGACY_BLOCK_SIZE: total_size ); - bh->n_sections = htonl( ( bc.have_mid ? 3 : 2 ) + raw_count ); + bh->size = bc.endian->h2nl( bmg->legacy ? total_size/BMG_LEGACY_BLOCK_SIZE: total_size ); + bh->n_sections = bc.endian->h2nl( ( bc.have_mid ? 3 : 2 ) + raw_count ); bh->encoding = bmg->legacy ? 0 : encoding; memcpy(bh->magic,BMG_MAGIC,sizeof(bh->magic)); @@ -3469,10 +3554,10 @@ enumError CreateRawBMG //---- setup inf section bmg_inf_t *pinf = (bmg_inf_t*)dest; - pinf->size = htonl(inf_size); - pinf->n_msg = htons(bc.n_msg); - pinf->inf_size = htons(bmg->inf_size); - pinf->unknown_0c = htonl(bmg->unknown_inf_0c); + pinf->size = bc.endian->h2nl(inf_size); + pinf->n_msg = bc.endian->h2ns(bc.n_msg); + pinf->inf_size = bc.endian->h2ns(bmg->inf_size); + pinf->unknown_0c = bc.endian->h2nl(bmg->unknown_inf_0c); memcpy(pinf->magic,BMG_INF_MAGIC,sizeof(pinf->magic)); memcpy(pinf->list,inf.ptr,inf.len); @@ -3483,7 +3568,7 @@ enumError CreateRawBMG //---- setup dat section bmg_dat_t * pdat = (bmg_dat_t*)dest; - pdat->size = htonl(dat_size); + pdat->size = bc.endian->h2nl(dat_size); memcpy(pdat->magic,BMG_DAT_MAGIC,sizeof(pdat->magic)); memcpy(pdat->text_pool,dat.ptr,dat.len); @@ -3496,10 +3581,10 @@ enumError CreateRawBMG if (bc.have_mid) { bmg_mid_t *pmid = (bmg_mid_t*)dest; - pmid->size = htonl(mid_size); - pmid->n_msg = htons(bc.n_msg); - pmid->unknown_0a = htons(bmg->unknown_mid_0a); - pmid->unknown_0c = htonl(bmg->unknown_mid_0c); + pmid->size = bc.endian->h2nl(mid_size); + pmid->n_msg = bc.endian->h2ns(bc.n_msg); + pmid->unknown_0a = bc.endian->h2ns(bmg->unknown_mid_0a); + pmid->unknown_0c = bc.endian->h2nl(bmg->unknown_mid_0c); memcpy(pmid->magic,BMG_MID_MAGIC,sizeof(pmid->magic)); memcpy(pmid->mid,mid.ptr,mid.len); @@ -3522,7 +3607,7 @@ enumError CreateRawBMG bmg_section_t *sect = (bmg_section_t*)dest; memcpy(sect->magic,raw->magic,sizeof(sect->magic)); - sect->size = htonl(raw->total_size); + sect->size = bc.endian->h2nl(raw->total_size); const mem_t mem = GetFastBufMem(&raw->data); memcpy(sect->data,mem.ptr,mem.len); @@ -3840,6 +3925,10 @@ enumError SaveTextBMG { "%s" "\r\n" + "# The endianness of binary files: 0=big endian (default), 1=little endian.\r\n" + "# Little endian is only tested for encoding UTF-8 (need examples of analysis).\r\n" + "@ENDIAN = %u\r\n" + "\r\n" "# If 1, then enable legacy (GameCube) mode for old binary BMG files.\r\n" "# If enabled, ENCODING is always CP1252.\r\n" "@LEGACY = %u\r\n" @@ -3847,7 +3936,7 @@ enumError SaveTextBMG "# Define encoding of BMG: 1=CP1252, 2=UTF-16/be, 3=Shift-JIS, 4=UTF-8\r\n" "@ENCODING = %u\r\n" "\r\n" - "# Create »MID1« section: 0:off, 1=on\r\n" + "# Create »MID1« section: 0=off, 1=on\r\n" "@BMG-MID = %u\r\n" "\r\n" "# Size of each element of section 'INF1' (MKW=8).\r\n" @@ -3871,7 +3960,7 @@ enumError SaveTextBMG { "%s" "\r\n" - "# This part define values for unknown parameters of section headers.\r\n" + "# This part defines values for unknown parameters of section headers.\r\n" "@UNKNOWN-INF32-0C = %#10x # 32 bit value of section INF1 offset 0x0c\r\n" "@UNKNOWN-MID16-0A = %#10x # 16 bit value of section MID1 offset 0x0a\r\n" "@UNKNOWN-MID32-0C = %#10x # 32 bit value of section MID1 offset 0x0c\r\n" @@ -3897,12 +3986,14 @@ enumError SaveTextBMG HavePredifinedSlots(bmg); bmg->legacy = bmg->legacy != 0; + const endian_func_t *endian = get_bmg_endian(bmg); const int encoding = bmg->legacy ? BMG_ENC_CP1252 : CheckEncodingBMG(opt_bmg_encoding,bmg->encoding); const bool print_settings // print only, if unusual - = encoding != BMG_ENC__DEFAULT + = endian->is_le + || encoding != BMG_ENC__DEFAULT || bmg->attrib_used != 4 || be32(bmg->attrib) != BMG_INF_STD_ATTRIB || !bmg->have_mid @@ -3917,12 +4008,14 @@ enumError SaveTextBMG { fprintf(F.f,text_param, param_announce, - bmg->legacy, encoding, bmg->have_mid, bmg->inf_size, abuf, + endian->is_le, bmg->legacy, + encoding, bmg->have_mid, bmg->inf_size, abuf, bmg->use_color_names, bmg->use_mkw_messages ); param_announce = ""; } else if ( brief_count < BRIEF_NO_MAGIC ) - fprintf(F.f,"@LEGACY = %u\r\n" + fprintf(F.f,"@ENDIAN = %u\r\n" + "@LEGACY = %u\r\n" "@ENCODING = %u\r\n" "@BMG-MID = %u\r\n" "@INF-SIZE = 0x%02x\r\n" @@ -3930,7 +4023,8 @@ enumError SaveTextBMG "@COLOR-NAMES = %u\r\n" "@MKW-MESSAGES = %u\r\n" "\r\n", - bmg->legacy, encoding, bmg->have_mid, bmg->inf_size, abuf, + endian->is_le, bmg->legacy, + encoding, bmg->have_mid, bmg->inf_size, abuf, bmg->use_color_names, bmg->use_mkw_messages ); } diff --git a/project/dclib/lib-bmg.h b/project/dclib/lib-bmg.h index 590d93b..561348e 100644 --- a/project/dclib/lib-bmg.h +++ b/project/dclib/lib-bmg.h @@ -49,6 +49,7 @@ #define BMG_INF_MAX_SIZE (4+BMG_ATTRIB_SIZE) // max supported inf size #define BMG_INF_LIMIT 1000 // max allowed inf size #define BMG_LEGACY_BLOCK_SIZE 32 // block size for legacy files +#define BMG_MAX_SECTIONS 100 // max supported sections (sanity check) // [[xbuf]] #define BMG_MSG_BUF_SIZE 20050 // good buf size for messages @@ -69,6 +70,7 @@ typedef u16 bmg_slot_t; // type of slot typedef struct bmg_t bmg_t; + // /////////////////////////////////////////////////////////////////////////////// /////////////// MKW specific consts /////////////// @@ -240,6 +242,7 @@ extern bool opt_bmg_use_raw_sections;// true: use raw sections //----------------------------------------------------------------------------- +extern int opt_bmg_endian; extern int opt_bmg_encoding; extern uint opt_bmg_inf_size; extern OffOn_t opt_bmg_mid; @@ -400,6 +403,22 @@ typedef struct bmg_section_t __attribute__ ((packed)) bmg_section_t; //----------------------------------------------------------------------------- +// [[bmg_endian_t]] + +typedef enum bmg_endian_t +{ + BMG_AUTO_ENDIAN, + BMG_BIG_ENDIAN, // used in MKWii + BMG_LITTLE_ENDIAN, + + BMG_DEFAULT_ENDIAN = BMG_BIG_ENDIAN, +} +__attribute__ ((packed)) bmg_endian_t; + +extern const KeywordTab_t TabEndianBMG[]; +ccp GetEndianNameBMG ( int endian, ccp return_if_invalid ); + +//----------------------------------------------------------------------------- // [[bmg_encoding_t]] typedef enum bmg_encoding_t @@ -583,11 +602,11 @@ bmg_sect_info_t; typedef struct bmg_sect_list_t { - // all pointers point into raw source data - uint source_size; // valid source size uint this_size; // total size of this including info[] + const endian_func_t *endian; // endian functions, never NULL + // all following pointers point into raw source data bmg_header_t *header; // NULL or pointer to BMG file header bmg_inf_t *pinf; // NULL or pointer to INF1 header bmg_dat_t *pdat; // NULL or pointer to DAT1 header @@ -606,7 +625,8 @@ bmg_sect_list_t; //----------------------------------------------------------------------------- // result is alloced => FREE(result) -bmg_sect_list_t * ScanSectionsBMG ( cvp data, uint size ); +bmg_sect_list_t * ScanSectionsBMG + ( cvp data, uint size, const endian_func_t *endian ); // endian==0: auto detect const bmg_sect_info_t * SearchSectionBMG ( @@ -729,6 +749,7 @@ typedef struct bmg_t ccp fname; // alloced filename of loaded file FileAttrib_t fatt; // file attribute bool is_text_src; // true: source was text + const endian_func_t * endian; // endian functions, never NULL //--- container, used by SZS tools @@ -897,6 +918,10 @@ enumError SaveTextBMG typedef struct bmg_create_t { bmg_t *bmg; // current bmg + const endian_func_t // endian functions, never NULL + *endian; // init by bmg->endian, overridden by opt_bmg_endian + + FastBuf_t inf; // INF1 data FastBuf_t dat; // DAT1 data FastBuf_t mid; // MID1 data |
