?login_element?

Subversion Repositories NedoOS

Rev

Blame | Last modification | View Log | Download

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4.  
  5. #include "mhmt-types.h"
  6. #include "mhmt-parsearg.h"
  7. #include "mhmt-globals.h"
  8.  
  9.  
  10. struct argtbl default_arg_table[] =
  11. {
  12.         {"d",            ARG_MODE,   NULL},
  13.  
  14.         {"g",            ARG_GREEDY, NULL},
  15.  
  16.         {ARGSTR_MEGALZ,  ARG_PTYPE,  NULL},
  17.         {ARGSTR_HRUM,    ARG_PTYPE,  NULL},
  18.         {ARGSTR_HRUST,   ARG_PTYPE,  NULL},
  19.         {ARGSTR_ZX7,     ARG_PTYPE,  NULL},
  20.  
  21.         {"zxh",          ARG_ZXHEAD, NULL},
  22.  
  23.         {ARGSTR_8,       ARG_WORD,   NULL},
  24.         {ARGSTR_16,      ARG_WORD,   NULL},
  25.  
  26.         {"bend",         ARG_BIGEND, NULL},
  27.  
  28.         {ARGSTR_MW256,   ARG_MAXWIN, NULL},
  29.         {ARGSTR_MW512,   ARG_MAXWIN, NULL},
  30.         {ARGSTR_MW1024,  ARG_MAXWIN, NULL},
  31.         {ARGSTR_MW2048,  ARG_MAXWIN, NULL},
  32.         {ARGSTR_MW2176,  ARG_MAXWIN, NULL},
  33.         {ARGSTR_MW4096,  ARG_MAXWIN, NULL},
  34.         {ARGSTR_MW4352,  ARG_MAXWIN, NULL},
  35.         {ARGSTR_MW8192,  ARG_MAXWIN, NULL},
  36.         {ARGSTR_MW16384, ARG_MAXWIN, NULL},
  37.         {ARGSTR_MW32768, ARG_MAXWIN, NULL},
  38.         {ARGSTR_MW65536, ARG_MAXWIN, NULL},
  39.  
  40.         {ARGSTR_PB,      ARG_PREBIN, NULL},
  41.  
  42.         {NULL,           0,          NULL}
  43. };
  44.  
  45.  
  46.  
  47. // main argument parser, sets fields of "struct globals wrk",
  48. // tries to detect all erroneous arguments.
  49. ULONG parse_args(int argc, char* argv[])
  50. {
  51.         struct argtbl argstore[ARG_STORE_SIZE+1]; // last element is always stop-value
  52.  
  53.  
  54.  
  55.         struct argtbl * arg;
  56.  
  57.         ULONG inarg_pos; // position in argv[] array
  58.         ULONG storearg_pos; // position in argstore[] array
  59.  
  60.         ULONG files_num; // number of filenames specified
  61.  
  62.         char * temp_filename;
  63.  
  64.         ULONG last_arg_type;
  65.  
  66.         ULONG maxwin;
  67.  
  68.  
  69.         ULONG i;
  70.         for(i=0;i<ARG_STORE_SIZE+1;i++)
  71.         {
  72.                 argstore[i].name  = NULL;
  73.                 argstore[i].fname = NULL;
  74.                 argstore[i].type  = ARG_NOARG;
  75.         }
  76.  
  77.  
  78.         if( argc<2 )
  79.         {
  80.                 printf("No arguments! Use \"mhmt -h\" or \"mhmt -help\" for help!\n");
  81.                 return 0L;
  82.         }
  83.  
  84.         // shortcut for help request
  85.         if( !cmp_str_nocase( argv[1]+1, "h" ) || !cmp_str_nocase( argv[1]+1, "help" ) )
  86.                 return ARG_PARSER_SHOWHELP;
  87.  
  88.  
  89.         inarg_pos = 1;
  90.         storearg_pos = 0;
  91.         files_num = 0;
  92.  
  93.         // first find all arguments beginning with "-"
  94.         while( inarg_pos<(ULONG)argc && *(argv[inarg_pos])=='-' )
  95.         {
  96.                 arg=match_arg(argv[inarg_pos]+1); // search match...
  97.                 if( arg ) // match!
  98.                 {
  99.                         if( storearg_pos>=ARG_STORE_SIZE )
  100.                         {
  101.                                 printf("Too many arguments!\n");
  102.                                 return ARG_PARSER_ERROR|ARG_PARSER_SHOWHELP;
  103.                         }
  104.  
  105.                         argstore[storearg_pos] = *arg;
  106.  
  107.                         if( arg->type == ARG_PREBIN )
  108.                         {
  109.                                 if( inarg_pos>=(ULONG)(argc-1) )
  110.                                 {
  111.                                         printf("\"-prebin\" has no filename!\n");
  112.                                         return ARG_PARSER_ERROR|ARG_PARSER_SHOWHELP;
  113.                                 }
  114.  
  115.                                 inarg_pos++;
  116.                                
  117.                                 argstore[storearg_pos].fname = (char *)malloc( 1+strlen(argv[inarg_pos]) );
  118.                                 if( !argstore[storearg_pos].fname )
  119.                                 {
  120.                                         printf("Cannot allocate memory for filename string!\n");
  121.                                         return ARG_PARSER_ERROR;
  122.                                 }
  123.  
  124.                                 strcpy( argstore[storearg_pos].fname, argv[inarg_pos] );
  125.                         }
  126.  
  127.                         storearg_pos++;
  128.                 }
  129.                 else // argument does not match predefined set
  130.                 {
  131.                         printf("Wrong arguments!\n");
  132.                         return ARG_PARSER_ERROR|ARG_PARSER_SHOWHELP;
  133.                 }
  134.  
  135.                 inarg_pos++;
  136.         }
  137.  
  138.         // parse filenames then
  139.         while( inarg_pos<(ULONG)argc )
  140.         {
  141.                 if( files_num>=2 ) // there should be no more than two filenames
  142.                 {
  143.                         printf("Too many filenames specified!\n");
  144.                         return ARG_PARSER_ERROR|ARG_PARSER_SHOWHELP;
  145.                 }
  146.  
  147.                 temp_filename = (char *)malloc( 1+strlen(argv[inarg_pos]) );
  148.                 if( !temp_filename )
  149.                 {
  150.                         printf("Cannot allocate memory for filename string!\n");
  151.                         return ARG_PARSER_ERROR;
  152.                 }
  153.  
  154.                 strcpy( temp_filename, argv[inarg_pos] );
  155.  
  156.                 if( files_num==0 )
  157.                         wrk.fname_in = temp_filename;
  158.                 else // only files_num==1, because of condition in the beginning of current "while" cycle
  159.                         wrk.fname_out = temp_filename;
  160.  
  161.                 files_num++;
  162.                 inarg_pos++;
  163.         }
  164.  
  165.         if( !files_num ) // there must be at least 1 filename specified
  166.         {
  167.                 printf("No filenames specified!\n");
  168.                 return ARG_PARSER_ERROR|ARG_PARSER_SHOWHELP;
  169.         }
  170.  
  171.  
  172.         // now optional arguments (starting with "-") are stored in argstore[],
  173.         // all needed filenames are also copied, go proceed configuring with
  174.         // optional arguments
  175.  
  176.         // sort argument array (in increasing .type order) to ensure correct parsing
  177.         sort_args( argstore, ARG_STORE_SIZE );
  178.  
  179.         storearg_pos = 0;
  180.         last_arg_type = ARG_INIT; // there is no such value in argstore[].type
  181.         while( argstore[storearg_pos].type != ARG_NOARG )
  182.         {
  183.                 if( last_arg_type == argstore[storearg_pos].type )
  184.                 {
  185.                         printf("Redundant arguments!\n");
  186.                         return ARG_PARSER_ERROR|ARG_PARSER_SHOWHELP;
  187.                 }
  188.  
  189.                 switch( argstore[storearg_pos].type )
  190.                 {
  191.                 case ARG_MODE:
  192.                         wrk.mode = 1; // set depack mode
  193.                         break;
  194.  
  195.                 case ARG_GREEDY:
  196.                         if( wrk.mode ) // since sorted, argument list causes parsing go from up to down in this "case" list
  197.                         {
  198.                                 printf("No greedy mode specification for DEpacking!\n");
  199.                                 return ARG_PARSER_ERROR;
  200.                         }
  201.                         wrk.greedy = 1; // set greedy packing mode
  202.                         break;
  203.  
  204.                 case ARG_PTYPE:
  205.                         if( !cmp_str_nocase( argstore[storearg_pos].name, ARGSTR_MEGALZ ) )
  206.                         {
  207.                                 wrk.packtype = PK_MLZ;
  208.                                 wrk.zxheader = 0;
  209.                                 wrk.wordbit  = 0;
  210.                                 wrk.bigend   = 0;
  211.                                 wrk.fullbits = 0;
  212.                                 wrk.maxwin   = 4352;
  213.                         }
  214.                         else if( !cmp_str_nocase( argstore[storearg_pos].name, ARGSTR_HRUM ) )
  215.                         {
  216.                                 wrk.packtype = PK_HRM;
  217.                                 wrk.zxheader = 0; // by default, there is NO ZX-HEADER if only -hrm or -hst specified
  218.                                 wrk.wordbit  = 1;
  219.                                 wrk.bigend   = 0;
  220.                                 wrk.fullbits = 1;
  221.                                 wrk.maxwin   = 4096;
  222.                         }
  223.                         else if( !cmp_str_nocase( argstore[storearg_pos].name, ARGSTR_HRUST ) )
  224.                         {
  225.                                 wrk.packtype = PK_HST;
  226.                                 wrk.zxheader = 0; // by default, there is NO ZX-HEADER if only -hrm or -hst specified
  227.                                 wrk.wordbit  = 1;
  228.                                 wrk.bigend   = 0;
  229.                                 wrk.fullbits = 1;
  230.                                 wrk.maxwin   = 65536;
  231.                         }
  232.                         else if( !cmp_str_nocase( argstore[storearg_pos].name, ARGSTR_ZX7 ) )
  233.                         {
  234.                                 wrk.packtype = PK_ZX7;
  235.                                 wrk.zxheader = 0;
  236.                                 wrk.wordbit  = 0;
  237.                                 wrk.bigend   = 0;
  238.                                 wrk.fullbits = 0;
  239.                                 wrk.maxwin   = 2176;
  240.                         }
  241.                         else // there shouldn't be this case, but nevertheless...
  242.                         {
  243.                                 printf("Impossible error #1! Press any key to continue or \"SPACE\" to exit... :-)\n");
  244.                                 return ARG_PARSER_ERROR;
  245.                         }
  246.                         break;
  247.  
  248.                 case ARG_ZXHEAD:
  249.                         // ZX-header is not applicable for PK_MLZ type...
  250.                         // also wrk.packtype has been already set before...
  251.                         if( PK_MLZ==wrk.packtype )
  252.                         {
  253.                                 printf("There couldn't be zx-header in megalz mode!\n");
  254.                                 return ARG_PARSER_ERROR;
  255.                         }
  256.                         wrk.zxheader = 1;
  257.                         break;
  258.  
  259.                 case ARG_WORD:
  260.                         // whether bits must be grouped in words or in bytes
  261.                         if( !cmp_str_nocase( argstore[storearg_pos].name, ARGSTR_8 ) )
  262.                         {
  263.                                 if( wrk.zxheader ) // won't force byte-wise bits when there is a zx-header
  264.                                 {
  265.                                         printf("There can be only 16bit grouping of bits when ZX-header is active!\n");
  266.                                         return ARG_PARSER_ERROR;
  267.                                 }
  268.                                 wrk.wordbit = 0;
  269.                         }
  270.                         else if( !cmp_str_nocase( argstore[storearg_pos].name, ARGSTR_16 ) )
  271.                         {
  272.                                 wrk.wordbit = 1;
  273.                         }
  274.                         else // there shouldn't be this case, but nevertheless...
  275.                         {
  276.                                 printf("Impossible error #2! Press any key to continue or \"SPACE\" to exit... :-)\n");
  277.                                 return ARG_PARSER_ERROR;
  278.                         }
  279.                         break;
  280.  
  281.                 case ARG_BIGEND:
  282.                         // whether word-grouped bits must be big- or little-endian arranged
  283.                         if( wrk.zxheader )
  284.                         {
  285.                                 printf("There can be only little-endian arrangement of bits when ZX-header is active!\n");
  286.                                 return ARG_PARSER_ERROR;
  287.                         }
  288.                         wrk.bigend = 1;
  289.                         break;
  290.  
  291.                 case ARG_MAXWIN:
  292.                         maxwin = get_maxwin( argstore[storearg_pos].name );
  293.                         if( !maxwin ) // there shouldn't be this case, but nevertheless...
  294.                         {
  295.                                 printf("Impossible error #3! Press any key to continue or \"SPACE\" to exit... :-)\n");
  296.                                 return ARG_PARSER_ERROR;
  297.                         }
  298.  
  299.                         // wrk.maxwin is already initialized to the maximum value suitable for given packing type, so check new setting
  300.                         if( maxwin > wrk.maxwin )
  301.                         {
  302.                                 printf("Maximum window specified is too big for given packing type!\n");
  303.                                 return ARG_PARSER_ERROR;
  304.                         }
  305.                         wrk.maxwin = maxwin;
  306.                         break;
  307.  
  308.                 case ARG_PREBIN:
  309.                         wrk.prebin = 1;
  310.                         wrk.fname_prebin = argstore[storearg_pos].fname;
  311.                         break;
  312.  
  313.                 default:
  314.                         // once again impossible error: we shouldn't be here since "while" loop condition...
  315.                         printf("Impossible error #4! Press any key to continue or \"SPACE\" to exit... :-)\n");
  316.                         return ARG_PARSER_ERROR;
  317.                         break;
  318.                 }
  319.  
  320.  
  321.                 last_arg_type = argstore[storearg_pos++].type;
  322.         }
  323.  
  324.  
  325.         return ARG_PARSER_GO;
  326. }
  327.  
  328.  
  329. // sort arguments
  330. void sort_args( struct argtbl * args, ULONG argsize )
  331. {
  332.         struct argtbl temp;
  333.         LONG i,j;
  334.  
  335.         // simple bubble sort since there are not too many arguments
  336.         for( i=(argsize-2); i>=0; i-- )
  337.         {
  338.                 for( j=0; j<=i; j++ )
  339.                 {
  340.                         if( args[j].type > args[j+1].type )
  341.                         {
  342.                                 temp      = args[j];
  343.                                 args[j]   = args[j+1];
  344.                                 args[j+1] = temp;
  345.                         }
  346.                 }
  347.         }
  348. }
  349.  
  350.  
  351. // get maxwin string into number, returns 0 if no match
  352. LONG get_maxwin( char * txtmaxwin )
  353. {
  354.         static char * strings[] =
  355.         {
  356.                 ARGSTR_MW256,
  357.                 ARGSTR_MW512,
  358.                 ARGSTR_MW1024,
  359.                 ARGSTR_MW2048,
  360.                 ARGSTR_MW4096,
  361.                 ARGSTR_MW4352,
  362.                 ARGSTR_MW8192,
  363.                 ARGSTR_MW16384,
  364.                 ARGSTR_MW32768,
  365.                 ARGSTR_MW65536,
  366.                 NULL
  367.         };
  368.  
  369.         static LONG sizes[] =
  370.         {
  371.                 256,
  372.                 512,
  373.                 1024,
  374.                 2048,
  375.                 4096,
  376.                 4352,
  377.                 8192,
  378.                 16384,
  379.                 32768,
  380.                 65536,
  381.                 0
  382.         };
  383.  
  384.         ULONG i;
  385.  
  386.  
  387.         i=0;
  388.         while( strings[i] )
  389.         {
  390.                 if( !cmp_str_nocase( strings[i], txtmaxwin ) )
  391.                 {
  392.                         return sizes[i];
  393.                 }
  394.  
  395.                 i++;
  396.         }
  397.  
  398.         return 0;
  399. }
  400.  
  401.  
  402.  
  403.  
  404.  
  405. // finds matching arg in default_arg_table,
  406. // returns ptr to the found element or NULL if not found
  407. struct argtbl * match_arg(char * argument)
  408. {
  409.         struct argtbl * test_arg = default_arg_table;
  410.  
  411.  
  412.         while( test_arg->name && cmp_str_nocase(test_arg->name,argument) )
  413.                 test_arg++;
  414.  
  415.         return (test_arg->name)?test_arg:NULL;
  416. }
  417.  
  418.  
  419. // compares two char strings, ignoring case (uppercase by default)
  420. // returns 0, if equal, -1 if left lower than right, and +1 otherwise
  421. LONG cmp_str_nocase(char * left, char * right)
  422. {
  423.  
  424.         LONG order=0;
  425.  
  426.         UBYTE leftchar,rightchar;
  427.         UBYTE leftadd,rightadd;
  428.  
  429.         do
  430.         {
  431.                 leftchar  = (UBYTE)*left;
  432.                 rightchar = (UBYTE)*right;
  433.  
  434.                 leftadd  = 0;
  435.                 rightadd = 0;
  436.  
  437.                 left++;
  438.                 right++;
  439.  
  440.                 if( leftchar  >= (UBYTE)'a' ) leftadd  = (UBYTE)('A'-'a');
  441.                 if( rightchar >= (UBYTE)'a' ) rightadd = (UBYTE)('A'-'a');
  442.  
  443.                 if( leftchar  > (UBYTE)'z' ) leftadd  = 0;
  444.                 if( rightchar > (UBYTE)'z' ) rightadd = 0;
  445.  
  446.                 leftchar  += leftadd;
  447.                 rightchar += rightadd;
  448.  
  449.                 if( leftchar<rightchar ) order = (-1);
  450.                 if( leftchar>rightchar ) order = (+1);
  451.  
  452.         } while( (!order) && leftchar && rightchar );
  453.  
  454.         return order;
  455. }
  456.  
  457.