aboutsummaryrefslogtreecommitdiff
path: root/project/dclib
diff options
context:
space:
mode:
authorWiimm <wiimm@wiimm.de>2020-11-30 16:16:56 +0100
committerWiimm <wiimm@wiimm.de>2020-11-30 16:16:56 +0100
commit9c0078c6b9c1309b48f9ece8b5cad1b9be9a75c5 (patch)
tree0abd3b6a244076650e40a07e42adae9c2a6b2d8c /project/dclib
parenta0815499b2d9014695e6e261c909476729445360 (diff)
SZS v2.21a
Diffstat (limited to '')
-rw-r--r--project/dclib/Makefile.inc2
-rw-r--r--project/dclib/dclib-basics.c78
-rw-r--r--project/dclib/dclib-basics.h84
-rw-r--r--project/dclib/dclib-cli.c357
-rw-r--r--project/dclib/dclib-file.c345
-rw-r--r--project/dclib/dclib-file.h65
-rw-r--r--project/dclib/dclib-network-linux.c105
-rw-r--r--project/dclib/dclib-network-linux.h57
-rw-r--r--project/dclib/dclib-network.h7
-rw-r--r--project/dclib/dclib-numeric.c94
-rw-r--r--project/dclib/dclib-option.h2
-rw-r--r--project/dclib/dclib-system.h49
-rw-r--r--project/dclib/dclib-types.h20
-rw-r--r--project/dclib/lib-bmg.c192
-rw-r--r--project/dclib/lib-bmg.h31
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