aboutsummaryrefslogtreecommitdiff
path: root/project/src/wbmgt.c
diff options
context:
space:
mode:
authorroot <root@dc13.lemmi>2020-07-21 10:00:46 +0200
committerroot <root@dc13.lemmi>2020-07-21 10:00:46 +0200
commit1192c4575ea7afdf38e3fa0df4587a08620af11e (patch)
tree6910a62487c282d0840d2e668aa7eb40b7c8a3fd /project/src/wbmgt.c
parent76de8a89f7c1d1b4522eb66e8f89d248e8c1781f (diff)
SZS v2.18a
Diffstat (limited to '')
-rw-r--r--project/src/wbmgt.c984
1 files changed, 984 insertions, 0 deletions
diff --git a/project/src/wbmgt.c b/project/src/wbmgt.c
new file mode 100644
index 0000000..3750bce
--- /dev/null
+++ b/project/src/wbmgt.c
@@ -0,0 +1,984 @@
+
+/***************************************************************************
+ * _______ _______ _______ *
+ * | ___ |____ | ___ | *
+ * | | |_| / /| | |_| *
+ * | |_____ / / | |_____ *
+ * |_____ | / / |_____ | *
+ * _ | | / / _ | | *
+ * | |___| |/ /____| |___| | *
+ * |_______|_______|_______| *
+ * *
+ * Wiimms SZS Tools *
+ * https://szs.wiimm.de/ *
+ * *
+ ***************************************************************************
+ * *
+ * This file is part of the SZS project. *
+ * Visit https://szs.wiimm.de/ for project details and sources. *
+ * *
+ * Copyright (c) 2011-2020 by Dirk Clemens <wiimm@wiimm.de> *
+ * *
+ ***************************************************************************
+ * *
+ * 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 *
+ * *
+ ***************************************************************************/
+
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "lib-xbmg.h"
+#include "lib-szs.h"
+#include "lib-mkw.h"
+#include "dclib-utf8.h"
+#include "dclib-regex.h"
+#include "ui.h" // [[dclib]] wrapper
+#include "ui-wbmgt.c"
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// functions not neded by wbmgt ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+#if !SZS_WRAPPER
+ bool DefineIntVar ( VarMap_t * vm, ccp varname, int value ) { return false; }
+#endif
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// definitions ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+#define TITLE WBMGT_SHORT ": " WBMGT_LONG " v" VERSION " r" REVISION \
+ " " SYSTEM " - " AUTHOR " - " DATE
+
+//
+///////////////////////////////////////////////////////////////////////////////
+
+static void help_exit ( bool xmode )
+{
+ fputs( TITLE "\n", stdout );
+
+ if (xmode)
+ {
+ int cmd;
+ for ( cmd = 0; cmd < CMD__N; cmd++ )
+ PrintHelpCmd(&InfoUI_wbmgt,stdout,0,cmd,0,0,URI_HOME);
+ }
+ else
+ PrintHelpCmd(&InfoUI_wbmgt,stdout,0,0,"HELP",0,URI_HOME);
+
+ exit(ERR_OK);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static void print_version_section ( bool print_sect_header )
+{
+ if (print_sect_header)
+ fputs("[version]\n",stdout);
+
+ const u32 base = 0x04030201;
+ const u8 * e = (u8*)&base;
+ const u32 endian = be32(e);
+
+ printf( "prog=" WBMGT_SHORT "\n"
+ "name=" WBMGT_LONG "\n"
+ "version=" VERSION "\n"
+ "beta=%d\n"
+ "revision=" REVISION "\n"
+ "system=" SYSTEM "\n"
+ "endian=%u%u%u%u %s\n"
+ "author=" AUTHOR "\n"
+ "date=" DATE "\n"
+ "url=" URI_HOME WBMGT_SHORT "\n"
+ "\n"
+ , BETA_VERSION
+ , e[0], e[1], e[2], e[3]
+ , endian == 0x01020304 ? "little"
+ : endian == 0x04030201 ? "big" : "mixed" );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static void version_exit()
+{
+ if ( brief_count > 1 )
+ fputs( VERSION "\n", stdout );
+ else if (brief_count)
+ fputs( VERSION " r" REVISION " " SYSTEM "\n", stdout );
+ else if (print_sections)
+ print_version_section(true);
+ else if (long_count)
+ print_version_section(false);
+ else
+ fputs( TITLE "\n", stdout );
+
+ exit(ERR_OK);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static void print_title ( FILE * f )
+{
+ static bool done = false;
+ if (!done)
+ {
+ done = true;
+ if (print_sections)
+ print_version_section(true);
+ else if ( verbose >= 1 && f == stdout )
+ fprintf(f,"\n%s\n\n",TITLE);
+ else
+ fprintf(f,"***** %s *****\n",TITLE);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static const KeywordTab_t * current_command = 0;
+
+static void hint_exit ( enumError stat )
+{
+ if ( current_command )
+ fprintf(stderr,
+ "-> Type '%s help %s' (pipe it to a pager like 'less') for more help.\n\n",
+ progname, CommandInfo[current_command->id].name1 );
+ else
+ fprintf(stderr,
+ "-> Type '%s -h' or '%s help' (pipe it to a pager like 'less') for more help.\n\n",
+ progname, progname );
+ exit(stat);
+}
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// command test ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+static enumError cmd_test_options()
+{
+ printf("\nOptions (compatibility: %s; format: hex=dec):\n",PrintOptCompatible());
+
+ printf(" old/new: %16x = %12d\n",opt_new,opt_new);
+ printf(" test: %16x = %12d\n",testmode,testmode);
+ printf(" verbose: %16x = %12d\n",verbose,verbose);
+ printf(" width: %16x = %12d\n",opt_width,opt_width);
+ printf(" escape-char: %16x = %12d\n",escape_char,escape_char);
+
+ printf(" inf-size: %16x = %12d\n",opt_bmg_inf_size,opt_bmg_inf_size);
+ printf(" bmg-mid: %16d = %12s\n",opt_bmg_mid,GetKeywordOffAutoOn(opt_bmg_mid));
+
+ char attrib[BMG_ATTRIB_BUF_SIZE];
+ if (opt_bmg_force_attrib)
+ {
+ PrintAttribBMG(attrib,sizeof(attrib),bmg_force_attrib,BMG_ATTRIB_SIZE,0,true);
+ printf(" force-attrib: %s\n",attrib);
+ }
+ if (opt_bmg_def_attrib)
+ {
+ PrintAttribBMG(attrib,sizeof(attrib),bmg_def_attrib,BMG_ATTRIB_SIZE,0,true);
+ printf(" def-attrib: %s\n",attrib);
+ }
+
+ printf(" no-attrib: %16x = %12d\n",opt_bmg_no_attrib,opt_bmg_no_attrib);
+ printf(" x-escapes: %16x = %12d\n",opt_bmg_x_escapes,opt_bmg_x_escapes);
+ printf(" old-escapes: %16x = %12d\n",opt_bmg_old_escapes,opt_bmg_old_escapes);
+ printf(" bmg-color: %16x = %12d\n",opt_bmg_colors,opt_bmg_colors);
+ printf(" bmg-inline: %16x = %12d\n",opt_bmg_inline_attrib,opt_bmg_inline_attrib);
+
+ ListPatchingListBMG(stdout,2,"patch-bmg list");
+
+ if (opt_tracks)
+ DumpTrackList(0,0,0);
+ if (opt_arenas)
+ DumpArenaList(0,0,0);
+
+ return ERR_OK;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static enumError cmd_test()
+{
+ #if 1 || !defined(TEST) // test options
+
+ return cmd_test_options();
+
+ #elif 0
+
+ ParamList_t *param;
+ for ( param = first_param; param; param = param->next )
+ {
+ //NORMALIZE_FILENAME_PARAM(param);
+ }
+ return ERR_OK;
+
+ #endif
+}
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// command points ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+static enumError cmd_points()
+{
+ if (n_param)
+ {
+ ERROR0(ERR_WARNING,
+ "%u parameter%s ignored.\n",
+ n_param, n_param == 1 ? "" : "s" );
+ n_param = 0;
+ }
+
+ const MkwPointInfo_t *mpi = GetMkwPointInfo(MkwPointsTab);
+ printf("\nVersus points [%s]:\n",mpi->info);
+ PrintMkwPoints( stdout, 2, MkwPointsTab, brief_count ? 2 : 1, 0, long_count );
+ return ERR_OK;
+}
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// command regexp ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+static enumError cmd_regexp()
+{
+ if ( n_param < 2 )
+ return ERROR0(ERR_SYNTAX,"At least 2 parameters needed: REGEX STRING...\n");
+
+ Regex_t re;
+ enumError err = ScanRegex(&re,true,first_param->arg);
+ if ( err || !re.valid )
+ return ERROR0(err,"Invalid regex: %s\n",first_param->arg);
+
+ struct { FastBuf_t b; char space[500]; } res;
+ InitializeFastBuf(&res,sizeof(res));
+
+ ParamList_t *param;
+ for ( param = first_param->next; param; param = param->next )
+ {
+ int stat = ReplaceRegex( &re, &res.b, param->arg, -1 );
+ printf("\n%s\n -> [%d] %s\n",
+ param->arg, stat, GetFastBufString(&res.b) );
+ }
+
+ putchar('\n');
+ ResetFastBuf(&res.b);
+ ResetRegex(&re);
+ return ERR_OK;
+}
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// command extract ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+static enumError cmd_extract()
+{
+ if ( n_param != 2 )
+ return ERROR0(ERR_SYNTAX,"Excat 2 parameters expected:"
+ " Section name and file\n");
+
+ ccp sname = first_param->arg;
+ const uint slen = strlen(sname);
+ if ( slen < 1 || slen > 4 )
+ return ERROR0(ERR_SYNTAX,
+ "Section name must consist of 1 to 4 characters: %s",sname);
+
+ ParamList_t *param = first_param->next;
+ NORMALIZE_FILENAME_PARAM(param);
+
+ raw_data_t raw;
+ enumError err = LoadRawData(&raw,true,param->arg,0,opt_ignore>0,0);
+ if (err)
+ return err;
+
+ if ( raw.fform != FF_BMG )
+ return ERROR0(ERR_SYNTAX,"Not a binary BMG file: %s",raw.fname);
+
+
+ //--- search sections
+
+ const bmg_sect_list_t *sl = ScanSectionsBMG(raw.data,raw.data_size);
+ #if 0
+ {
+ const bmg_sect_info_t *si;
+
+ si = SearchSectionBMG(sl,sname,false,false);
+ fprintf(stderr,"SEARCH »%s« : %s\n",
+ sname, si ? PrintID(si->sect->magic,4,0) : "-" );
+
+ si = SearchSectionBMG(sl,sname,true,false);
+ fprintf(stderr,"SEARCH abbrev »%s« : %s\n",
+ sname, si ? PrintID(si->sect->magic,4,0) : "-" );
+
+ si = SearchSectionBMG(sl,sname,false,true);
+ fprintf(stderr,"SEARCH icase »%s« : %s\n",
+ sname, si ? PrintID(si->sect->magic,4,0) : "-" );
+
+ si = SearchSectionBMG(sl,sname,true,true);
+ fprintf(stderr,"SEARCH abbrev icase »%s« : %s\n",
+ sname, si ? PrintID(si->sect->magic,4,0) : "-" );
+ }
+ #endif
+
+ err = ERR_NOT_EXISTS;
+ const bmg_sect_info_t *si = SearchSectionBMG(sl,sname,true,true);
+
+ if (si)
+ {
+ const u8 *data = raw.data + si->offset;
+ uint size = si->real_size;
+
+ if (!print_header)
+ {
+ const uint head_size = si->head_size
+ ? si->head_size : sizeof(bmg_section_t);
+ if ( size >= head_size )
+ {
+ data += head_size;
+ size -= head_size;
+ }
+ }
+
+ PRINT("FOUND: %.4s, off: %u 0x%x, size: %u 0x%x [h=%d]\n",
+ si->sect->magic, si->offset, si->offset,
+ size, size, print_header );
+
+ fwrite(data,1,size,stdout);
+ err = ERR_OK;
+ }
+
+ FREE((void*)sl);
+ return err;
+}
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// command sections ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+static enumError cmd_sections()
+{
+ raw_data_t raw;
+ InitializeRawData(&raw);
+
+ enumError max_err = ERR_OK;
+
+ ParamList_t *param;
+ for ( param = first_param; param; param = param->next )
+ {
+ NORMALIZE_FILENAME_PARAM(param);
+
+ enumError err = LoadRawData(&raw,false,param->arg,0,opt_ignore>0,0);
+ if (err)
+ return err;
+
+ if ( raw.fform != FF_BMG )
+ {
+ ERROR0(ERR_SYNTAX,"Not a binary BMG file: %s",raw.fname);
+ if ( max_err < ERR_SYNTAX )
+ max_err = ERR_SYNTAX;
+ continue;
+ }
+
+ const bmg_sect_list_t *sl = ScanSectionsBMG(raw.data,raw.data_size);
+ if (!sl)
+ {
+ ERROR0(ERR_INVALID_DATA,"Can't scan binary BMG file: %s",raw.fname);
+ if ( max_err < ERR_INVALID_DATA )
+ max_err = ERR_INVALID_DATA;
+ continue;
+ }
+
+ uint max_info_len = 4;
+ const bmg_sect_info_t *si;
+ for ( si = sl->info; si->sect; si++ )
+ {
+ if (si->info)
+ {
+ const uint ilen = strlen(si->info);
+ if ( max_info_len < ilen )
+ max_info_len = ilen;
+ }
+ }
+
+ const uint seplen = 3*(56+max_info_len);
+ printf( "\n"
+ "%sFile: %s\n"
+ "%sSize: 0x%x = %u bytes, %u sections, encoding #%u (%s)\n"
+ "%s%.*s\n"
+ "%s offset size sect cut head n(elem) n(e)\n"
+ "%s hex hex size size magic size *size cut info\n"
+ "%s%.*s%s\n"
+ ,
+ colout->heading, param->arg,
+ colout->heading, sl->source_size, sl->source_size, sl->n_sections,
+ sl->header->encoding,
+ GetEncodingNameBMG(sl->header->encoding,"?"),
+ colout->heading, seplen, ThinLine300_3,
+ colout->heading,
+ colout->heading,
+ colout->heading, seplen, ThinLine300_3,
+ colout->reset );
+
+ for ( si = sl->info; si->sect; si++ )
+ {
+ printf("%8x %7x %7u",
+ si->offset, si->real_size, si->real_size );
+
+ if ( si->real_size < si->sect_size )
+ printf(" %s%3u%s ", colout->warn,
+ si->sect_size - si->real_size, colout->reset );
+ else
+ fputs(" - ",stdout);
+
+ fputs(PrintID(si->sect->magic,4,0),stdout);
+
+ if ( si->head_size )
+ printf(" %4u", si->head_size );
+ else
+ printf(" %s?%s", colout->warn, colout->reset );
+
+ if (si->elem_size)
+ {
+ printf(" %5u*%2u", si->n_elem_head, si->elem_size);
+ if ( si->n_elem_head > si->n_elem )
+ printf(" %s%4u*%s",colout->warn,si->n_elem,colout->reset);
+ else
+ fputs(" - ",stdout);
+ }
+ else
+ fputs(" - - ",stdout);
+
+ printf(" %s%s\n", si->info, si->is_empty ? ", empty" : "" );
+ }
+
+ printf("%s%.*s%s\n", colout->heading, seplen, ThinLine300_3, colout->reset );
+ FREE((void*)sl);
+ }
+
+ ResetRawData(&raw);
+ putchar('\n');
+ return max_err;
+}
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// command list ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+static enumError cmd_list()
+{
+ const uint max_width = GetTermWidth(80,40) - 9;
+ enumError err = SetupPatchingListBMG();
+ if ( err > ERR_WARNING )
+ return err;
+
+ ParamList_t *param;
+ for ( param = first_param; param; param = param->next )
+ {
+ NORMALIZE_FILENAME_PARAM(param);
+
+ bmg_t bmg;
+ enumError err = LoadXBMG(&bmg,true,param->arg,true,opt_ignore>0);
+ if ( err == ERR_NOT_EXISTS || err > ERR_WARNING && opt_ignore )
+ continue;
+ if ( err > ERR_WARNING )
+ return err;
+
+ err = UsePatchingListBMG(&bmg);
+ if ( err > ERR_WARNING )
+ return err;
+
+ printf("\nList [N=%u] %s:%s\n",
+ bmg.item_used, GetNameFF_BMG(&bmg), bmg.fname );
+
+ bmg_item_t * bi = bmg.item;
+ bmg_item_t * bi_end = bi + bmg.item_used;
+ for ( ; bi < bi_end; bi++ )
+ {
+ if ( memcmp(bmg.attrib,bi->attrib,bmg.attrib_used) )
+ {
+ char buf[BMG_ATTRIB_BUF_SIZE];
+ PrintAttribBMG(buf,sizeof(buf),bi->attrib,bmg.attrib_used,0,true);
+ printf("%5x ~ %s\n",bi->mid,buf);
+ if ( bi->text == bmg_null_entry )
+ continue;
+ }
+
+ if ( bi->text == bmg_null_entry )
+ printf("%5x /\n",bi->mid);
+ else if ( bi->text )
+ {
+ PrintString16BMG(iobuf,sizeof(iobuf),bi->text,bi->len,
+ BMG_UTF8_MAX,0,opt_bmg_colors);
+ printf("%5x = %.*s\n", bi->mid, max_width, iobuf );
+ }
+ }
+ ResetBMG(&bmg);
+ }
+
+ ResetPatchingListBMG();
+ return ERR_OK;
+}
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// command slots ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+static enumError cmd_slots()
+{
+ enumError err = SetupPatchingListBMG();
+ if ( err > ERR_WARNING )
+ return err;
+
+ ParamList_t *param;
+ for ( param = first_param; param; param = param->next )
+ {
+ NORMALIZE_FILENAME_PARAM(param);
+
+ bmg_t bmg;
+ enumError err = LoadXBMG(&bmg,true,param->arg,true,opt_ignore>0);
+ if ( err == ERR_NOT_EXISTS || err > ERR_WARNING && opt_ignore )
+ continue;
+ if ( err > ERR_WARNING )
+ return err;
+
+ err = UsePatchingListBMG(&bmg);
+ if ( err > ERR_WARNING )
+ return err;
+
+ bmg_create_t bc;
+ InitializeCreateBMG(&bc,&bmg);
+ bmg_item_t *bi;
+ for ( bi = GetFirstBI(&bc); bi; bi = GetNextBI(&bc) )
+ ;
+
+ const uint seplen = 3*60;
+ printf( "\n"
+ "%sFile: %s:%s\n"
+ "%s%.*s\n"
+ "%sslot/hex mid/hex delta attributes\n"
+ "%s%.*s%s\n"
+ ,
+ colout->heading, GetNameFF_BMG(&bmg), param->arg,
+ colout->heading, seplen, ThinLine300_3,
+ colout->heading,
+ colout->heading, seplen, ThinLine300_3,
+ colout->reset );
+
+ int slot;
+ u32 *pmid = (u32*)bc.mid.buf;
+ bmg_inf_item_t *inf = (bmg_inf_item_t*)bc.inf.buf;
+ char buf[200];
+ for ( slot = 0; slot < bc.n_msg; slot++ )
+ {
+ const u32 mid = ntohl(*pmid++);
+ PrintAttribBMG(buf,sizeof(buf),inf->attrib,bmg.attrib_used,0,true);
+ printf("%7x %9x ", slot, mid );
+ if ( mid == 0xffff )
+ fputs(" -",stdout);
+ else
+ printf("%+7d",(int)mid-slot);
+ printf(" %s\n",buf);
+
+ inf = (bmg_inf_item_t*)( (u8*)inf + bmg.inf_size );
+ }
+ printf("%s%.*s%s\n", colout->heading, seplen, ThinLine300_3, colout->reset );
+
+ ResetCreateBMG(&bc);
+ ResetBMG(&bmg);
+ }
+
+ putchar('\n');
+ ResetPatchingListBMG();
+ return ERR_OK;
+}
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// command diff ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+static enumError diff_files ( ccp fname1, ccp fname2 )
+{
+ if ( verbose > 0 )
+ printf("DIFF %s : %s\n", fname1, fname2 );
+
+ //--- setup bmg structures
+
+ bmg_t bmg1;
+ enumError err = LoadXBMG(&bmg1,true,fname1,true,false);
+ if ( err > ERR_WARNING )
+ return err;
+ err = UsePatchingListBMG(&bmg1);
+ if ( err > ERR_WARNING )
+ return err;
+
+ bmg_t bmg2;
+ err = LoadXBMG(&bmg2,true,fname2,true,false);
+ if ( err > ERR_WARNING )
+ return err;
+ err = UsePatchingListBMG(&bmg2);
+ if ( err > ERR_WARNING )
+ return err;
+
+ //--- diff
+
+ err = DiffBMG( &bmg1, &bmg2, verbose < 0, GetTermWidth(80,40)-1 );
+
+ if ( verbose >= -1 && err == ERR_DIFFER )
+ printf("Content differ: %s : %s\n", bmg1.fname, bmg2.fname );
+ else if ( verbose >= 0 && err == ERR_OK )
+ printf("Content identical: %s : %s\n", bmg1.fname, bmg2.fname );
+
+ //--- reset bmg structures
+
+ ResetBMG(&bmg1);
+ ResetBMG(&bmg2);
+ return err;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static enumError cmd_diff_dest()
+{
+ enumError max_err = ERR_OK;
+ ParamList_t *param;
+ for ( param = first_param; param; param = param->next )
+ {
+ NORMALIZE_FILENAME_PARAM(param);
+
+ char dest[PATH_MAX];
+ SubstDest(dest,sizeof(dest),param->arg,opt_dest,"%F",0,false);
+ const enumError err = diff_files(param->arg,dest);
+ if ( max_err < err )
+ max_err = err;
+ if ( err > ERR_WARNING || err && verbose < -1 )
+ break;
+ }
+ ResetPatchingListBMG();
+ return max_err;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static enumError cmd_diff()
+{
+ if (opt_dest)
+ return cmd_diff_dest();
+
+ if ( n_param != 2 )
+ return ERROR0(ERR_SYNTAX,"Exact 2 sources expected if --dest is not set.\n");
+
+ enumError err = SetupPatchingListBMG();
+ if ( err > ERR_WARNING )
+ return err;
+
+ ASSERT(first_param);
+ ASSERT(first_param->next);
+ err = diff_files(first_param->arg,first_param->next->arg);
+ ResetPatchingListBMG();
+ return err;
+}
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// command patch/encode/decode ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+static enumError cmd_patch ( int cmd_id, ccp cmd_name, ccp def_path )
+{
+ CheckOptDest(def_path,false);
+ enumError err = SetupPatchingListBMG();
+ if ( err > ERR_WARNING )
+ return err;
+
+ ParamList_t *param;
+ for ( param = first_param; param; param = param->next )
+ {
+ NORMALIZE_FILENAME_PARAM(param);
+
+ bmg_t bmg;
+ enumError err = LoadXBMG(&bmg,true,param->arg,cmd_id!=CMD_PATCH,opt_ignore>0);
+ if ( err == ERR_NOT_EXISTS || err > ERR_WARNING && opt_ignore )
+ continue;
+ if ( err > ERR_WARNING )
+ return err;
+
+ char dest[PATH_MAX];
+ const file_format_t dest_ff
+ = cmd_id == CMD_ENCODE || cmd_id == CMD_PATCH && !bmg.is_text_src
+ ? FF_BMG
+ : FF_BMG_TXT;
+
+ SubstDest(dest,sizeof(dest),param->arg,opt_dest,def_path,
+ GetExtFF(dest_ff,0),false);
+
+ if ( verbose >= 0 || testmode )
+ fprintf(stdlog,"%s%s%s %s:%s -> %s:%s\n",
+ verbose > 0 ? "\n" : "",
+ testmode ? "WOULD " : "", cmd_name,
+ GetNameFF_BMG(&bmg), bmg.fname,
+ GetNameFF(dest_ff,0), dest );
+
+ err = UsePatchingListBMG(&bmg);
+ if ( err > ERR_WARNING )
+ return err;
+
+ if (!testmode)
+ {
+ err = dest_ff == FF_BMG
+ ? SaveRawXBMG(&bmg,dest,opt_preserve)
+ : SaveTextXBMG(&bmg,dest,opt_preserve);
+ if ( err > ERR_WARNING )
+ return err;
+ }
+ ResetBMG(&bmg);
+ }
+
+ ResetPatchingListBMG();
+ return ERR_OK;
+}
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// check options ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+static enumError CheckOptions ( int argc, char ** argv, bool is_env )
+{
+ TRACE("CheckOptions(%d,%p,%d) optind=%d\n",argc,argv,is_env,optind);
+
+ optind = 0;
+ int err = 0;
+ ccp filter_bmg = 0;
+
+ for(;;)
+ {
+ const int opt_stat = getopt_long(argc,argv,OptionShort,OptionLong,0);
+ if ( opt_stat == -1 )
+ break;
+
+ RegisterOptionByName(&InfoUI_wbmgt,opt_stat,1,is_env);
+
+ switch ((enumGetOpt)opt_stat)
+ {
+ case GO__ERR: err++; break;
+
+ case GO_VERSION: version_exit();
+ case GO_HELP: help_exit(false);
+ case GO_XHELP: help_exit(true);
+ case GO_ALLOW_ALL: allow_all = true; break;
+ case GO_COMPATIBLE: err += ScanOptCompatible(optarg); break;
+ case GO_WIDTH: err += ScanOptWidth(optarg); break;
+ case GO_QUIET: verbose = verbose > -1 ? -1 : verbose - 1; break;
+ case GO_VERBOSE: verbose = verbose < 0 ? 0 : verbose + 1; break;
+ case GO_LOGGING: logging++; break;
+ case GO_DE: use_de = true; break;
+ case GO_CT_CODE: ctcode_enabled = true; break;
+ case GO_LE_CODE: lecode_enabled = true; break;
+ case GO_COLORS: err += ScanOptColorize(0,optarg,0); break;
+ case GO_NO_COLORS: opt_colorize = COLMD_OFF; break;
+
+ case GO_CHDIR: err += ScanOptChdir(optarg); break;
+ case GO_CONST: break; // [[2do]] err += ScanOptConst(optarg); break;
+
+ case GO_UTF_8: use_utf8 = true; break;
+ case GO_NO_UTF_8: use_utf8 = false; break;
+
+ case GO_TEST: testmode++; break;
+ case GO_FORCE: force_count++; break;
+ case GO_REPAIR_MAGICS: err += ScanOptRepairMagic(optarg); break;
+
+ #if OPT_OLD_NEW
+ case GO_OLD: opt_new = opt_new>0 ? -1 : opt_new-1; break;
+ case GO_STD: opt_new = 0; break;
+ case GO_NEW: opt_new = opt_new<0 ? +1 : opt_new+1; break;
+ #endif
+ case GO_EXTRACT: opt_extract = optarg; break;
+
+ case GO_ESC: err += ScanEscapeChar(optarg) < 0; break;
+ case GO_DEST: SetDest(optarg,false); break;
+ case GO_DEST2: SetDest(optarg,true); break;
+ case GO_OVERWRITE: opt_overwrite = true; break;
+ case GO_NUMBER: opt_number = true; break;
+ case GO_REMOVE_DEST: opt_remove_dest = true; break;
+ case GO_UPDATE: opt_update = true; break;
+ case GO_PRESERVE: opt_preserve = true; break;
+ case GO_IGNORE: opt_ignore++; break;
+ case GO_ALIGN: err += ScanOptAlign(optarg); break;
+
+ case GO_MAX_FILE_SIZE: err += ScanOptMaxFileSize(optarg); break;
+ case GO_TRACKS: err += ScanOptTracks(optarg); break;
+ case GO_ARENAS: err += ScanOptArenas(optarg); break;
+ case GO_POINTS: err += ScanOptMkwPoints(optarg,false); break;
+ case GO_PATCH_BMG: err += ScanOptPatchMessage(optarg); break;
+ case GO_MACRO_BMG: err += ScanOptMacroBMG(optarg); break;
+ case GO_FILTER_BMG: filter_bmg = optarg; break;
+
+ case GO_LONG: long_count++; break;
+ case GO_NO_HEADER: print_header = false; break;
+ case GO_BRIEF: brief_count++; break;
+
+ case GO_BMG_ENCODING: err += ScanOptBmgEncoding(optarg); break;
+ case GO_BMG_INF_SIZE: err += ScanOptBmgInfSize(optarg,true); break;
+ case GO_BMG_MID: err += ScanOptBmgMid(optarg); break;
+ case GO_FORCE_ATTRIB: err += ScanOptForceAttrib(optarg); break;
+ case GO_DEF_ATTRIB: err += ScanOptDefAttrib(optarg); break;
+ case GO_NO_ATTRIB: opt_bmg_no_attrib = true; break;
+ case GO_X_ESCAPES: opt_bmg_x_escapes = true; break;
+ case GO_OLD_ESCAPES: opt_bmg_old_escapes = true; break;
+ case GO_SINGLE_LINE: opt_bmg_single_line++; break;
+ case GO_NO_BMG_COLORS: opt_bmg_colors = 0; break;
+ case GO_BMG_COLORS: opt_bmg_colors = 2; break;
+ case GO_NO_BMG_INLINE: opt_bmg_inline_attrib = false; break;
+ case GO_EXPORT: export_count++; break;
+ case GO_SECTIONS: print_sections++; break;
+
+ // no default case defined
+ // => compiler checks the existence of all enum values
+ }
+ }
+
+ #ifdef DEBUG
+ DumpUsedOptions(&InfoUI_wbmgt,TRACE_FILE,11);
+ #endif
+ NormalizeOptions( verbose > 3 && !is_env ? 2 : 0 );
+ SetupBMG(filter_bmg);
+
+ return !err ? ERR_OK : max_error ? max_error : ERR_SYNTAX;
+}
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// check command ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+static enumError CheckCommand ( int argc, char ** argv )
+{
+ const KeywordTab_t * cmd_ct = CheckCommandHelper(argc,argv,CommandTab);
+ if (!cmd_ct)
+ hint_exit(ERR_SYNTAX);
+
+ TRACE("COMMAND FOUND: #%lld = %s\n",(u64)cmd_ct->id,cmd_ct->name1);
+ current_command = cmd_ct;
+
+ if (!allow_all)
+ {
+ enumError err = VerifySpecificOptions(&InfoUI_wbmgt,cmd_ct);
+ if (err)
+ hint_exit(err);
+ }
+ WarnDepractedOptions(&InfoUI_wbmgt);
+
+ if ( cmd_ct->id != CMD_ARGTEST )
+ {
+ argc -= optind+1;
+ argv += optind+1;
+
+ if ( cmd_ct->id == CMD_TEST )
+ while ( argc-- > 0 )
+ AddParam(*argv++);
+ else
+ while ( argc-- > 0 )
+ AtFileHelper(*argv++,AddParam);
+ }
+
+ enumError err = ERR_OK;
+ switch ((enumCommands)cmd_ct->id)
+ {
+ case CMD_VERSION: version_exit();
+ case CMD_HELP: PrintHelp(&InfoUI_wbmgt,stdout,0,"HELP",0,URI_HOME,
+ first_param ? first_param->arg : 0 ); break;
+ case CMD_ARGTEST: err = cmd_argtest(argc,argv); break;
+ case CMD_TEST: err = cmd_test(); break;
+ case CMD_COLORS: err = Command_COLORS(brief_count?-brief_count:long_count,0,0); break;
+ case CMD_ERROR: err = cmd_error(); break;
+ case CMD_FILETYPE: err = cmd_filetype(); break;
+ case CMD_FILEATTRIB: err = cmd_fileattrib(); break;
+ case CMD_POINTS: err = cmd_points(); break;
+ case CMD_REGEXP: err = cmd_regexp(); break;
+
+ case CMD_EXTRACT: err = cmd_extract(); break;
+ case CMD_SECTIONS: err = cmd_sections(); break;
+ case CMD_LIST: err = cmd_list(); break;
+ case CMD_SLOTS: err = cmd_slots(); break;
+ case CMD_DIFF: err = cmd_diff(); break;
+
+ case CMD_CAT: err = cmd_bmg_cat(false); break;
+ case CMD_MIX: err = cmd_bmg_cat(true); break;
+ case CMD_IDENTIFIER: err = cmd_bmg_identifier(); break;
+ case CMD_DECODE: err = cmd_patch(cmd_ct->id,"DECODE","\1P/\1N.txt"); break;
+ case CMD_ENCODE: err = cmd_patch(cmd_ct->id,"ENCODE","\1P/\1N\1?T"); break;
+ case CMD_PATCH: err = cmd_patch(cmd_ct->id,"PATCH", "\1P/\1F"); break;
+
+ // no default case defined
+ // => compiler checks the existence of all enum values
+
+ case CMD__NONE:
+ case CMD__N:
+ help_exit(false);
+ }
+
+ return PrintErrorStat(err,verbose,cmd_ct->name1);
+}
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// main() ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+#if SZS_WRAPPER
+ int main_wbmgt ( int argc, char ** argv )
+#else
+ int main ( int argc, char ** argv )
+#endif
+{
+ print_title_func = print_title;
+ SetupLib(argc,argv,WBMGT_SHORT);
+
+ //----- process arguments
+
+ if ( argc < 2 )
+ {
+ printf("\n%s\n%s\nVisit %s%s for more info.\n\n",
+ text_logo, TITLE, URI_HOME, WBMGT_SHORT );
+ hint_exit(ERR_OK);
+ }
+
+ enumError err = CheckEnvOptions("WBMGT_OPT",CheckOptions);
+ if (err)
+ hint_exit(err);
+
+ err = CheckOptions(argc,argv,false);
+ if (err)
+ hint_exit(err);
+
+ err = CheckCommand(argc,argv);
+ DUMP_TRACE_ALLOC(TRACE_FILE);
+
+ if (SIGINT_level)
+ err = ERROR0(ERR_INTERRUPT,"Program interrupted by user.");
+ return err;
+}
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// END ///////////////
+///////////////////////////////////////////////////////////////////////////////