- #include <stdio.h> 
- #include <stdlib.h> 
- #include <string.h> 
-   
- #include "mhmt-types.h" 
- #include "mhmt-parsearg.h" 
- #include "mhmt-globals.h" 
-   
-   
- struct argtbl default_arg_table[] = 
- { 
-         {"d",            ARG_MODE,   NULL}, 
-   
-         {"g",            ARG_GREEDY, NULL}, 
-   
-         {ARGSTR_MEGALZ,  ARG_PTYPE,  NULL}, 
-         {ARGSTR_HRUM,    ARG_PTYPE,  NULL}, 
-         {ARGSTR_HRUST,   ARG_PTYPE,  NULL}, 
-         {ARGSTR_ZX7,     ARG_PTYPE,  NULL}, 
-   
-         {"zxh",          ARG_ZXHEAD, NULL}, 
-   
-         {ARGSTR_8,       ARG_WORD,   NULL}, 
-         {ARGSTR_16,      ARG_WORD,   NULL}, 
-   
-         {"bend",         ARG_BIGEND, NULL}, 
-   
-         {ARGSTR_MW256,   ARG_MAXWIN, NULL}, 
-         {ARGSTR_MW512,   ARG_MAXWIN, NULL}, 
-         {ARGSTR_MW1024,  ARG_MAXWIN, NULL}, 
-         {ARGSTR_MW2048,  ARG_MAXWIN, NULL}, 
-         {ARGSTR_MW2176,  ARG_MAXWIN, NULL}, 
-         {ARGSTR_MW4096,  ARG_MAXWIN, NULL}, 
-         {ARGSTR_MW4352,  ARG_MAXWIN, NULL}, 
-         {ARGSTR_MW8192,  ARG_MAXWIN, NULL}, 
-         {ARGSTR_MW16384, ARG_MAXWIN, NULL}, 
-         {ARGSTR_MW32768, ARG_MAXWIN, NULL}, 
-         {ARGSTR_MW65536, ARG_MAXWIN, NULL}, 
-   
-         {ARGSTR_PB,      ARG_PREBIN, NULL}, 
-   
-         {NULL,           0,          NULL} 
- }; 
-   
-   
-   
- // main argument parser, sets fields of "struct globals wrk", 
- // tries to detect all erroneous arguments. 
- ULONG parse_args(int argc, char* argv[]) 
- { 
-         struct argtbl argstore[ARG_STORE_SIZE+1]; // last element is always stop-value 
-   
-   
-   
-         struct argtbl * arg; 
-   
-         ULONG inarg_pos; // position in argv[] array 
-         ULONG storearg_pos; // position in argstore[] array 
-   
-         ULONG files_num; // number of filenames specified 
-   
-         char * temp_filename; 
-   
-         ULONG last_arg_type; 
-   
-         ULONG maxwin; 
-   
-   
-         ULONG i; 
-         for(i=0;i<ARG_STORE_SIZE+1;i++) 
-         { 
-                 argstore[i].name  = NULL; 
-                 argstore[i].fname = NULL; 
-                 argstore[i].type  = ARG_NOARG; 
-         } 
-   
-   
-         if( argc<2 ) 
-         { 
-                 printf("No arguments! Use \"mhmt -h\" or \"mhmt -help\" for help!\n"); 
-                 return 0L; 
-         } 
-   
-         // shortcut for help request 
-         if( !cmp_str_nocase( argv[1]+1, "h" ) || !cmp_str_nocase( argv[1]+1, "help" ) ) 
-                 return ARG_PARSER_SHOWHELP; 
-   
-   
-         inarg_pos = 1; 
-         storearg_pos = 0; 
-         files_num = 0; 
-   
-         // first find all arguments beginning with "-" 
-         while( inarg_pos<(ULONG)argc && *(argv[inarg_pos])=='-' ) 
-         { 
-                 arg=match_arg(argv[inarg_pos]+1); // search match... 
-                 if( arg ) // match! 
-                 { 
-                         if( storearg_pos>=ARG_STORE_SIZE ) 
-                         { 
-                                 printf("Too many arguments!\n"); 
-                                 return ARG_PARSER_ERROR|ARG_PARSER_SHOWHELP; 
-                         } 
-   
-                         argstore[storearg_pos] = *arg; 
-   
-                         if( arg->type == ARG_PREBIN ) 
-                         { 
-                                 if( inarg_pos>=(ULONG)(argc-1) ) 
-                                 { 
-                                         printf("\"-prebin\" has no filename!\n"); 
-                                         return ARG_PARSER_ERROR|ARG_PARSER_SHOWHELP; 
-                                 } 
-   
-                                 inarg_pos++; 
-                                  
-                                 argstore [- storearg_pos ]- . fname = (char *)malloc( 1+strlen(- argv [- inarg_pos ]) );
-                                 if( !argstore[storearg_pos].fname ) 
-                                 { 
-                                         printf("Cannot allocate memory for filename string!\n"); 
-                                         return ARG_PARSER_ERROR; 
-                                 } 
-   
-                                 strcpy(-  argstore [- storearg_pos ]- . fname,-  argv [- inarg_pos ] );
 
-                         } 
-   
-                         storearg_pos++; 
-                 } 
-                 else // argument does not match predefined set 
-                 { 
-                         return ARG_PARSER_ERROR|ARG_PARSER_SHOWHELP; 
-                 } 
-   
-                 inarg_pos++; 
-         } 
-   
-         // parse filenames then 
-         while( inarg_pos<(ULONG)argc ) 
-         { 
-                 if( files_num>=2 ) // there should be no more than two filenames 
-                 { 
-                         printf("Too many filenames specified!\n"); 
-                         return ARG_PARSER_ERROR|ARG_PARSER_SHOWHELP; 
-                 } 
-   
-                 temp_filename  = (char *)malloc( 1+strlen(- argv [- inarg_pos ]) );
-                 if( !temp_filename ) 
-                 { 
-                         printf("Cannot allocate memory for filename string!\n"); 
-                         return ARG_PARSER_ERROR; 
-                 } 
-   
-                 strcpy(-  temp_filename ,-  argv [- inarg_pos ] );
 
-   
-                 if( files_num==0 ) 
-                         wrk.fname_in = temp_filename; 
-                 else // only files_num==1, because of condition in the beginning of current "while" cycle 
-                         wrk.fname_out = temp_filename; 
-   
-                 files_num++; 
-                 inarg_pos++; 
-         } 
-   
-         if( !files_num ) // there must be at least 1 filename specified 
-         { 
-                 printf("No filenames specified!\n"); 
-                 return ARG_PARSER_ERROR|ARG_PARSER_SHOWHELP; 
-         } 
-   
-   
-         // now optional arguments (starting with "-") are stored in argstore[], 
-         // all needed filenames are also copied, go proceed configuring with 
-         // optional arguments 
-   
-         // sort argument array (in increasing .type order) to ensure correct parsing 
-         sort_args( argstore, ARG_STORE_SIZE ); 
-   
-         storearg_pos = 0; 
-         last_arg_type = ARG_INIT; // there is no such value in argstore[].type 
-         while( argstore[storearg_pos].type != ARG_NOARG ) 
-         { 
-                 if( last_arg_type == argstore[storearg_pos].type ) 
-                 { 
-                         printf("Redundant arguments!\n"); 
-                         return ARG_PARSER_ERROR|ARG_PARSER_SHOWHELP; 
-                 } 
-   
-                 switch( argstore[storearg_pos].type ) 
-                 { 
-                 case ARG_MODE: 
-                         wrk.mode = 1; // set depack mode 
-                         break; 
-   
-                 case ARG_GREEDY: 
-                         if( wrk.mode ) // since sorted, argument list causes parsing go from up to down in this "case" list 
-                         { 
-                                 printf("No greedy mode specification for DEpacking!\n"); 
-                                 return ARG_PARSER_ERROR; 
-                         } 
-                         wrk.greedy = 1; // set greedy packing mode 
-                         break; 
-   
-                 case ARG_PTYPE: 
-                         if( !cmp_str_nocase( argstore[storearg_pos].name, ARGSTR_MEGALZ ) ) 
-                         { 
-                                 wrk.packtype = PK_MLZ; 
-                                 wrk.zxheader = 0; 
-                                 wrk.wordbit  = 0; 
-                                 wrk.bigend   = 0; 
-                                 wrk.fullbits = 0; 
-                                 wrk.maxwin   = 4352; 
-                         } 
-                         else if( !cmp_str_nocase( argstore[storearg_pos].name, ARGSTR_HRUM ) ) 
-                         { 
-                                 wrk.packtype = PK_HRM; 
-                                 wrk.zxheader = 0; // by default, there is NO ZX-HEADER if only -hrm or -hst specified 
-                                 wrk.wordbit  = 1; 
-                                 wrk.bigend   = 0; 
-                                 wrk.fullbits = 1; 
-                                 wrk.maxwin   = 4096; 
-                         } 
-                         else if( !cmp_str_nocase( argstore[storearg_pos].name, ARGSTR_HRUST ) ) 
-                         { 
-                                 wrk.packtype = PK_HST; 
-                                 wrk.zxheader = 0; // by default, there is NO ZX-HEADER if only -hrm or -hst specified 
-                                 wrk.wordbit  = 1; 
-                                 wrk.bigend   = 0; 
-                                 wrk.fullbits = 1; 
-                                 wrk.maxwin   = 65536; 
-                         } 
-                         else if( !cmp_str_nocase( argstore[storearg_pos].name, ARGSTR_ZX7 ) ) 
-                         { 
-                                 wrk.packtype = PK_ZX7; 
-                                 wrk.zxheader = 0; 
-                                 wrk.wordbit  = 0; 
-                                 wrk.bigend   = 0; 
-                                 wrk.fullbits = 0; 
-                                 wrk.maxwin   = 2176; 
-                         } 
-                         else // there shouldn't be this case, but nevertheless... 
-                         { 
-                                 printf("Impossible error #1! Press any key to continue or \"SPACE\" to exit... :-)\n"); 
-                                 return ARG_PARSER_ERROR; 
-                         } 
-                         break; 
-   
-                 case ARG_ZXHEAD: 
-                         // ZX-header is not applicable for PK_MLZ type... 
-                         // also wrk.packtype has been already set before... 
-                         if( PK_MLZ==wrk.packtype ) 
-                         { 
-                                 printf("There couldn't be zx-header in megalz mode!\n"); 
-                                 return ARG_PARSER_ERROR; 
-                         } 
-                         wrk.zxheader = 1; 
-                         break; 
-   
-                 case ARG_WORD: 
-                         // whether bits must be grouped in words or in bytes 
-                         if( !cmp_str_nocase( argstore[storearg_pos].name, ARGSTR_8 ) ) 
-                         { 
-                                 if( wrk.zxheader ) // won't force byte-wise bits when there is a zx-header 
-                                 { 
-                                         printf("There can be only 16bit grouping of bits when ZX-header is active!\n"); 
-                                         return ARG_PARSER_ERROR; 
-                                 } 
-                                 wrk.wordbit = 0; 
-                         } 
-                         else if( !cmp_str_nocase( argstore[storearg_pos].name, ARGSTR_16 ) ) 
-                         { 
-                                 wrk.wordbit = 1; 
-                         } 
-                         else // there shouldn't be this case, but nevertheless... 
-                         { 
-                                 printf("Impossible error #2! Press any key to continue or \"SPACE\" to exit... :-)\n"); 
-                                 return ARG_PARSER_ERROR; 
-                         } 
-                         break; 
-   
-                 case ARG_BIGEND: 
-                         // whether word-grouped bits must be big- or little-endian arranged 
-                         if( wrk.zxheader ) 
-                         { 
-                                 printf("There can be only little-endian arrangement of bits when ZX-header is active!\n"); 
-                                 return ARG_PARSER_ERROR; 
-                         } 
-                         wrk.bigend = 1; 
-                         break; 
-   
-                 case ARG_MAXWIN: 
-                         maxwin = get_maxwin( argstore[storearg_pos].name ); 
-                         if( !maxwin ) // there shouldn't be this case, but nevertheless... 
-                         { 
-                                 printf("Impossible error #3! Press any key to continue or \"SPACE\" to exit... :-)\n"); 
-                                 return ARG_PARSER_ERROR; 
-                         } 
-   
-                         // wrk.maxwin is already initialized to the maximum value suitable for given packing type, so check new setting 
-                         if( maxwin > wrk.maxwin ) 
-                         { 
-                                 printf("Maximum window specified is too big for given packing type!\n"); 
-                                 return ARG_PARSER_ERROR; 
-                         } 
-                         wrk.maxwin = maxwin; 
-                         break; 
-   
-                 case ARG_PREBIN: 
-                         wrk.prebin = 1; 
-                         wrk.fname_prebin = argstore[storearg_pos].fname; 
-                         break; 
-   
-                 default: 
-                         // once again impossible error: we shouldn't be here since "while" loop condition... 
-                         printf("Impossible error #4! Press any key to continue or \"SPACE\" to exit... :-)\n"); 
-                         return ARG_PARSER_ERROR; 
-                         break; 
-                 } 
-   
-   
-                 last_arg_type = argstore[storearg_pos++].type; 
-         } 
-   
-   
-         return ARG_PARSER_GO; 
- } 
-   
-   
- // sort arguments 
- void sort_args( struct argtbl * args, ULONG argsize ) 
- { 
-         struct argtbl temp; 
-         LONG i,j; 
-   
-         // simple bubble sort since there are not too many arguments 
-         for( i=(argsize-2); i>=0; i-- ) 
-         { 
-                 for( j=0; j<=i; j++ ) 
-                 { 
-                         if( args[j].type > args[j+1].type ) 
-                         { 
-                                 temp      = args[j]; 
-                                 args[j]   = args[j+1]; 
-                                 args[j+1] = temp; 
-                         } 
-                 } 
-         } 
- } 
-   
-   
- // get maxwin string into number, returns 0 if no match 
- LONG get_maxwin( char * txtmaxwin ) 
- { 
-         static char * strings[] = 
-         { 
-                 ARGSTR_MW256, 
-                 ARGSTR_MW512, 
-                 ARGSTR_MW1024, 
-                 ARGSTR_MW2048, 
-                 ARGSTR_MW4096, 
-                 ARGSTR_MW4352, 
-                 ARGSTR_MW8192, 
-                 ARGSTR_MW16384, 
-                 ARGSTR_MW32768, 
-                 ARGSTR_MW65536, 
-                 NULL 
-         }; 
-   
-         static LONG sizes[] = 
-         { 
-                 256, 
-                 512, 
-                 1024, 
-                 2048, 
-                 4096, 
-                 4352, 
-                 8192, 
-                 16384, 
-                 32768, 
-                 65536, 
-                 0 
-         }; 
-   
-         ULONG i; 
-   
-   
-         i=0; 
-         while( strings[i] ) 
-         { 
-                 if( !cmp_str_nocase( strings[i], txtmaxwin ) ) 
-                 { 
-                         return sizes[i]; 
-                 } 
-   
-                 i++; 
-         } 
-   
-         return 0; 
- } 
-   
-   
-   
-   
-   
- // finds matching arg in default_arg_table, 
- // returns ptr to the found element or NULL if not found 
- struct argtbl * match_arg(char * argument) 
- { 
-         struct argtbl * test_arg = default_arg_table; 
-   
-   
-         while( test_arg->name && cmp_str_nocase(test_arg->name,argument) ) 
-                 test_arg++; 
-   
-         return (test_arg->name)?test_arg:NULL; 
- } 
-   
-   
- // compares two char strings, ignoring case (uppercase by default) 
- // returns 0, if equal, -1 if left lower than right, and +1 otherwise 
- LONG cmp_str_nocase(char * left, char * right) 
- { 
-   
-         LONG order=0; 
-   
-         UBYTE leftchar,rightchar; 
-         UBYTE leftadd,rightadd; 
-   
-         do 
-         { 
-                 leftchar  = (UBYTE)*left; 
-                 rightchar = (UBYTE)*right; 
-   
-                 leftadd  = 0; 
-                 rightadd = 0; 
-   
-                 left++; 
-                 right++; 
-   
-                 if( leftchar  >= (UBYTE)'a' ) leftadd  = (UBYTE)('A'-'a'); 
-                 if( rightchar >= (UBYTE)'a' ) rightadd = (UBYTE)('A'-'a'); 
-   
-                 if( leftchar  > (UBYTE)'z' ) leftadd  = 0; 
-                 if( rightchar > (UBYTE)'z' ) rightadd = 0; 
-   
-                 leftchar  += leftadd; 
-                 rightchar += rightadd; 
-   
-                 if( leftchar<rightchar ) order = (-1); 
-                 if( leftchar>rightchar ) order = (+1); 
-   
-         } while( (!order) && leftchar && rightchar ); 
-   
-         return order; 
- } 
-   
-