home *** CD-ROM | disk | FTP | other *** search
/ Media Share 9 / MEDIASHARE_09.ISO / graphics / gif-util.zip / GETARG.C < prev    next >
Text File  |  1989-08-01  |  24KB  |  573 lines

  1. /***************************************************************************
  2. *  Routines to grab the    parameters from    the command line :           *
  3. * All the routines except the main one,    starts with GA (Get Arguments) to  *
  4. * prevent from names conflicts.                           *
  5. * It is    assumed    in these routine that any pointer, for any type    has the       *
  6. * same length (i.e. length of int pointer is equal to char pointer etc.)   *
  7. *                                       *
  8. *  The following routines are available    in this    module:               *
  9. * 1. int GAGetArgs(argc, argv, CtrlStr, Variables...)               *
  10. *    where argc, argv as received on entry.                   *
  11. *       CtrlStr is the contrl string    (see below)               *
  12. *       Variables are all the variables to be set according to CtrlStr. *
  13. *       Note    that all the variables MUST be transfered by address.       *
  14. *    return 0 on correct parsing, otherwise error number (see GetArg.h).   *
  15. * 2. GAPrintHowTo(CtrlStr)                           *
  16. *    Print the control string to stderr, in the    correct    format needed.       *
  17. *    This feature is very useful in case of error during GetArgs parsing.  *
  18. *    Chars equal to SPACE_CHAR are not printed (regular spaces are NOT     *
  19. *    allowed, and so using SPACE_CHAR you can create space in PrintHowTo). *
  20. * 3. GAPrintErrMsg(Error)                           *
  21. *    Print the error to    stderr,    according to Error (usually returned by       *
  22. *    GAGetArgs).                               *
  23. *                                       *
  24. *     CtrlStr format:                               *
  25. *   The    control    string passed to GetArgs controls the way argv (argc) are  *
  26. * parsed. Each entry in    this string must not have any spaces in    it. The       *
  27. * First    Entry is the name of the program which is usually ignored except   *
  28. * when GAPrintHowTo is called. All the other entries (except the last one  *
  29. * which    we will    come back to it    later) must have the following format:       *
  30. * 1. One letter    which sets the option letter.                   *
  31. * 2. '!' or '%'    to determines if this option is    really optional    ('%') or   *
  32. *    it    must exists ('!')...                           *
  33. * 3. '-' allways.                               *
  34. * 4. Alpha numeric string, usually ignored, but    used by    GAPrintHowTo to       *
  35. *    print the meaning of this input.                       *
  36. * 5. Sequences starts with '!' or '%'. Again if    '!' then this sequence       *
  37. *    must exists (only if its option flag is given of course), and if '%'  *
  38. *    it    is optional. Each sequence will    continue with one or two       *
  39. *    characters    which defines the kind of the input:               *
  40. *    a.    d, x, o, u - integer is expected (decimal, hex, octal base or       *
  41. *          unsigned).                           *
  42. *    b.    D, X, O, U - long integer is expected (same as above).           *
  43. *    c.    f    - float    number is expected.                   *
  44. *    d.    F    - double number    is expected.                   *
  45. *    e.    s    - string is expected.                       *
  46. *    f.    *?    - any number of    '?' kind (d, x, o, u, D, X, O, U, f, F, s) *
  47. *          will match this one. If '?' is numeric, it scans until   *
  48. *          none numeric input is given. If '?' is 's' then it scans *
  49. *          up to the next option or end of argv.               *
  50. *                                       *
  51. *   If the last    parameter given    in the CtrlStr,    is not an option (i.e. the *
  52. * second char is not in    ['!', '%'] and the third one is not '-'), all what *
  53. * remained from    argv is    linked to it.                       *
  54. *                                       *
  55. *   The    variables passed to GAGetArgs (starting    from 4th parameter) MUST   *
  56. * match    the order of the CtrlStr:                       *
  57. *   For    each option, one integer address must be passed. This integer must *
  58. * initialized by 0. If that option is given in the command line, it will   *
  59. * be set to one.                               *
  60. *   In addition, the sequences that might follow an option require the       *
  61. * following parameters to pass:                           *
  62. * 1. d, x, o, u - pointer to integer (int *).                   *
  63. * 2. D, X, O, U - pointer to long (long *).                   *
  64. * 3. f         - pointer to float      (float *).                   *
  65. * 4. F         - pointer to double  (double *).                   *
  66. * 5. s         - pointer to char      (char    *). NO allocation is needed!       *
  67. * 6. *?         - TWO variables are passed    for each wild request. the first   *
  68. *           one is (address of) integer, and    it will    return number of   *
  69. *           parameters actually matched this    sequence, and the second   *
  70. *           one is a    pointer    to pointer to ?    (? **),    and will return    an *
  71. *           address to a block of pointers to ? kind, terminated with   *
  72. *           NULL pointer. NO    pre-allocation is needed.           *
  73. *           note that these two variables are pretty    like the argv/argc *
  74. *           pair...                               *
  75. *                                       *
  76. *   Examples:                                   *
  77. *                                       *
  78. *    "Example1  i%-OneInteger!d  s%-Strings!*s  j%-  k!-Float!f  Files"       *
  79. * Will match: Example1 -i 77 -s    String1    String2    String3    -k 88.2    File1 File2*
  80. *   or match: Example1 -s String1 -k 88.3 -i 999 -j               *
  81. *    but not: Example1 -i 77 78    (option    i expects one integer, k must be). *
  82. * Note the option k must exists, and that the order of the options is not  *
  83. * not important. In the    first examples File1 & File2 will match    the Files  *
  84. * in the command line.                               *
  85. * A call to GAPrintHowTo with this CtrlStr will    print to stderr:       *
  86. * Example1 [-i OneIngeter] [-s Strings...] [-j]    -k Float Files...       *
  87. *                                       *
  88. *   Notes:                                   *
  89. *                                       *
  90. * 1. This module assumes that all the pointers to all kind of data types   *
  91. *    have the same length and format, i.e. sizeof(int *) == sizeof(char    *).*
  92. *                                       *
  93. *                      Gershon Elber    Ver 0.2     Mar 88       *
  94. ****************************************************************************
  95. * History:                                   *
  96. * 11 Mar 88 - Version 1.0 by Gershon Elber.                   *
  97. ***************************************************************************/
  98.  
  99. #include <stdio.h>
  100. #include <stdlib.h>
  101. #include <string.h>
  102. #include <alloc.h>
  103. #include "GetArg.h"
  104.  
  105. #define    MYMALLOC        /* If no "MyAlloc" routine elsewhere define this */
  106.  
  107. #define    MAX_PARAM    100        /* maximum number of parameters allowed. */
  108. #define    CTRL_STR_MAX_LEN    1024
  109.  
  110. #define SPACE_CHAR    '|'       /* The character not to print using HowTo */
  111.  
  112. #ifndef    TRUE
  113. #define    TRUE -1
  114. #define    FALSE 0
  115. #define    OK    0
  116. #endif
  117.  
  118. #define    ISSPACE(x) ((x)    <= ' ')           /* Not conventional - but works fine! */
  119. /* The two characters '%' and '!' are used in the control string: */
  120. #define    ISCTRLCHAR(x) (((x) == '%') || ((x) == '!'))
  121.  
  122. static char *GAErrorToken;/* On error code, ErrorToken is set to point on it */
  123.  
  124. static int GATestAllSatis(char *CtrlStrCopy, char *CtrlStr, int *argc,
  125.     char ***argv, int *Parameters[MAX_PARAM], int *ParamCount);
  126. static int GAUpdateParameters(int *Parameters[], int *ParamCount,
  127.     char *Option, char *CtrlStrCopy, char *CtrlStr, int *argc,
  128.     char ***argv);
  129. static int GAGetParmeters(int *Parameters[], int *ParamCount,
  130.     char *CtrlStrCopy , char *Option, int *argc, char ***argv);
  131. static int GAGetMultiParmeters(int *Parameters[], int *ParamCount,
  132.     char *CtrlStrCopy, int *argc, char ***argv);
  133. static void GASetParamCount(char *CtrlStr, int Max, int *ParamCount);
  134. static void GAByteCopy(char *Dst, char *Src, unsigned n);
  135. static int GAOptionExists(int argc, char **argv);
  136. #ifdef    MYMALLOC
  137. static char *MyMalloc(unsigned size);
  138. #endif    MyMALLOC
  139.  
  140. /***************************************************************************
  141. * Routine to access the    command    line argument and interpret them:       *
  142. * Return OK (0)    is case    of succesfull parsing, error code else...       *
  143. ***************************************************************************/
  144. int GAGetArgs(int argc, char **argv, char *CtrlStr, ...)
  145. {
  146.      int i, Error = FALSE, ParamCount = 0,
  147.      *Parameters[MAX_PARAM];        /* Save here parameter addresses */
  148.      char *Option, CtrlStrCopy[CTRL_STR_MAX_LEN];
  149.  
  150.      strcpy(CtrlStrCopy, CtrlStr);
  151.      /*    Using base address of parameters we access other parameters addr: */
  152.      /*    Note that me (for sure!) samples data beyond the current function */
  153.      /*    frame, but we only read    it, so we are almost o.k ...          */
  154.      for (i=1; i<=MAX_PARAM; i++) Parameters[i-1] = (int *) *(i+&CtrlStr);
  155.  
  156.      --argc; argv++;         /* Skip the program name (first in argv/c list) */
  157.      while (argc >= 0) {
  158.      if (!GAOptionExists(argc, argv)) break;         /* The loop */
  159.      argc--;
  160.      Option    = *(argv++);
  161.      if ((Error = GAUpdateParameters(Parameters, &ParamCount, Option,
  162.           CtrlStrCopy, CtrlStr, &argc, &argv)) != FALSE) return Error;
  163.      }
  164.      /*    Check for results and update trail of command line: */
  165.      return GATestAllSatis(CtrlStrCopy, CtrlStr, &argc, &argv, Parameters,
  166.                                  &ParamCount);
  167. }
  168.  
  169. /***************************************************************************
  170. * Routine to search for    unsatisfied flags - simply scan    the list for !-       *
  171. * sequence. Before this    scan, this routine updates the rest of the command *
  172. * line into the    last two parameters if it is requested by the CtrlStr       *
  173. * (last    item in    CtrlStr    is NOT an option).                   *
  174. * Return OK if all satisfied, CMD_ERR_AllSatis error else.           *
  175. ***************************************************************************/
  176. static int GATestAllSatis(char *CtrlStrCopy, char *CtrlStr, int *argc,
  177.     char ***argv, int *Parameters[MAX_PARAM], int *ParamCount)
  178. {
  179.     int    i;
  180.     static char    *LocalToken = "-?";
  181.  
  182.     /* Check is    last item is an    option.    If not then copy rest of command */
  183.     /* line into it as 1. NumOfprm, 2. pointer to block    of pointers.     */
  184.     for    (i=strlen(CtrlStr)-1; ((i>0) &&    (!ISSPACE(CtrlStr[i]))); i--);
  185.     if (!ISCTRLCHAR(CtrlStr[i+2])) {
  186.     GASetParamCount(CtrlStr, i, ParamCount);    /* Point in correct prm. */
  187.     *Parameters[(*ParamCount)++] = *argc;
  188.     GAByteCopy((char *) Parameters[(*ParamCount)++], (char *) argv,
  189.                             sizeof(char *));
  190.     }
  191.  
  192.     i =    0;
  193.     while (++i < strlen(CtrlStrCopy))
  194.     if ((CtrlStrCopy[i] == '-') && (CtrlStrCopy[i-1] == '!')) {
  195.         GAErrorToken = LocalToken;
  196.         LocalToken[1] = CtrlStrCopy[i-2];         /* Set the corrent flag */
  197.         return CMD_ERR_AllSatis;
  198.     }
  199.  
  200.     return OK;
  201. }
  202.  
  203. /***************************************************************************
  204. * Routine to update the    parameters according to    the given Option:       *
  205. ***************************************************************************/
  206. static int GAUpdateParameters(int *Parameters[], int *ParamCount,
  207.        char *Option, char *CtrlStrCopy, char *CtrlStr, int *argc, char ***argv)
  208. {
  209.     int    i;
  210.  
  211.     if (Option[0] != '-') {
  212.     GAErrorToken = Option;
  213.     return CMD_ERR_NotAnOpt;
  214.     }
  215.     i =    0;                /* Scan the CtrlStrCopy for that option: */
  216.     while (i+2 < strlen(CtrlStrCopy)) {
  217.     if ((CtrlStrCopy[i] == Option[1]) && (ISCTRLCHAR(CtrlStrCopy[i+1]))
  218.         && (CtrlStrCopy[i+2] == '-')) {
  219.         /* We found    that option! */
  220.         break;
  221.     }
  222.     i++;
  223.     }
  224.     if (i+2 >= strlen(CtrlStrCopy)) {
  225.     GAErrorToken = Option;
  226.     return CMD_ERR_NoSuchOpt;
  227.     }
  228.  
  229.     /* If we are here, then we found that option in CtrlStr - Strip it off:  */
  230.     CtrlStrCopy[i] = CtrlStrCopy[i+1] =    CtrlStrCopy[i+2] = (char) ' ';
  231.     GASetParamCount(CtrlStr, i, ParamCount);/*Set it to point in correct prm */
  232.     i += 3;
  233.     *Parameters[(*ParamCount)++] = 1;     /* Set boolean flag for that option */
  234.     if (ISSPACE(CtrlStrCopy[i])) return    OK; /* Only a boolean flag is needed */
  235.  
  236.     /* Skip the    text between the bolean    option and data    follows: */
  237.     while (!ISCTRLCHAR(CtrlStrCopy[i]))    i++;
  238.     /* Get the parameters and return the propriete return code:    */
  239.     return GAGetParmeters(Parameters, ParamCount, &CtrlStrCopy[i],
  240.                               Option, argc, argv);
  241. }
  242.  
  243. /***************************************************************************
  244. * Routine to get parameters according to the CtrlStr given from    argv/c :   *
  245. ***************************************************************************/
  246. static int GAGetParmeters(int *Parameters[], int *ParamCount,
  247.     char *CtrlStrCopy , char *Option, int *argc, char ***argv)
  248. {
  249.     int    i = 0, ScanRes;
  250.  
  251.     while (!(ISSPACE(CtrlStrCopy[i]))) {
  252.     switch (CtrlStrCopy[i+1]) {
  253.         case 'd':                      /* Get signed integers */
  254.         ScanRes    = sscanf(*((*argv)++), "%d",
  255.                      (int *) Parameters[(*ParamCount)++]);
  256.         break;
  257.         case 'u':                    /* Get unsigned integers */
  258.         ScanRes    = sscanf(*((*argv)++), "%u",
  259.                     (unsigned *) Parameters[(*ParamCount)++]);
  260.         break;
  261.         case 'x':                     /* Get hex integers */
  262.         ScanRes    = sscanf(*((*argv)++), "%x",
  263.                      (int *) Parameters[(*ParamCount)++]);
  264.         break;
  265.         case 'o':                       /* Get octal integers */
  266.         ScanRes    = sscanf(*((*argv)++), "%o",
  267.                      (int *) Parameters[(*ParamCount)++]);
  268.         break;
  269.         case 'D':                 /* Get signed long integers */
  270.         ScanRes    = sscanf(*((*argv)++), "%ld",
  271.                     (long *) Parameters[(*ParamCount)++]);
  272.         break;
  273.         case 'U':                   /* Get unsigned long integers */
  274.         ScanRes    = sscanf(*((*argv)++), "%lu",
  275.                    (unsigned long *) Parameters[(*ParamCount)++]);
  276.         break;
  277.         case 'X':                    /* Get hex long integers */
  278.         ScanRes    = sscanf(*((*argv)++), "%lx",
  279.                     (long *) Parameters[(*ParamCount)++]);
  280.         break;
  281.         case 'O':                  /* Get octal long integers */
  282.         ScanRes    = sscanf(*((*argv)++), "%lo",
  283.                     (long *) Parameters[(*ParamCount)++]);
  284.         break;
  285.         case 'f':                     /* Get float number */
  286.         ScanRes    = sscanf(*((*argv)++), "%f",
  287.                        (float *) Parameters[(*ParamCount)++]);
  288.         case 'F':                  /* Get double float number */
  289.         ScanRes    = sscanf(*((*argv)++), "%lf",
  290.                       (double *) Parameters[(*ParamCount)++]);
  291.         break;
  292.         case 's':                       /* It as a string */
  293.         ScanRes    = 1;                     /* Allways O.K. */
  294.         GAByteCopy((char *) Parameters[(*ParamCount)++],
  295.                     (char *) ((*argv)++), sizeof(char *));
  296.         break;
  297.         case '*':                /* Get few parameters into one : */
  298.         ScanRes    = GAGetMultiParmeters(Parameters, ParamCount,
  299.                           &CtrlStrCopy[i], argc, argv);
  300.         if ((ScanRes ==    0) && (CtrlStrCopy[i] == '!')) {
  301.             GAErrorToken = Option;
  302.             return CMD_ERR_WildEmpty;
  303.         }
  304.         break;
  305.     }
  306.     /* If reading fails and    this number is a must (!) then error : */
  307.     if ((ScanRes ==    0) && (CtrlStrCopy[i] == '!')) {
  308.         GAErrorToken = Option;
  309.         return CMD_ERR_NumRead;
  310.     }
  311.     if (CtrlStrCopy[i+1] !=    '*') {
  312.          (*argc)--;         /* Everything is OK - update to next parameter: */
  313.          i += 2;              /* Skip to next parameter (if any) */
  314.     }
  315.     else i += 3;                      /* Skip the '*' also ! */
  316.     }
  317.  
  318.     return OK;
  319. }
  320.  
  321. /***************************************************************************
  322. * Routine to get few parameters    into one pointer such that the returned       *
  323. * pointer actually points on a block of    pointers to the    parameters...       *
  324. * For example *F means a pointer to pointers on    floats.               *
  325. * Returns number of parameters actually    read.                   *
  326. * This routine assumes that all    pointers (on any kind of scalar) has the   *
  327. * same size (and the union below is totally ovelapped bteween dif. arrays) *
  328. ***************************************************************************/
  329. static int GAGetMultiParmeters(int *Parameters[], int *ParamCount,
  330.     char *CtrlStrCopy, int *argc, char ***argv)
  331. {
  332.     int    i = 0, ScanRes,    NumOfPrm = 0, **Pmain, **Ptemp;
  333.     union TmpArray {    /* Save here the temporary data before copying it to */
  334.     int    *IntArray[MAX_PARAM];          /* the returned pointer block. */
  335.     long   *LngArray[MAX_PARAM];
  336.     float  *FltArray[MAX_PARAM];
  337.     double *DblArray[MAX_PARAM];
  338.     char   *ChrArray[MAX_PARAM];
  339.     } TmpArray;
  340.  
  341.     do {
  342.     switch(CtrlStrCopy[2]) {     /* CtrlStr == '!*?' or '%*?' where ? is */
  343.         case 'd':               /* Format to read the parameters: */
  344.         TmpArray.IntArray[NumOfPrm] = (int *) MyMalloc(sizeof(int));
  345.         ScanRes    = sscanf(*((*argv)++), "%d",
  346.                        (int *) TmpArray.IntArray[NumOfPrm++]);
  347.         break;
  348.         case 'u':
  349.         TmpArray.IntArray[NumOfPrm] = (int *) MyMalloc(sizeof(int));
  350.         ScanRes    = sscanf(*((*argv)++), "%u",
  351.                   (unsigned    int *) TmpArray.IntArray[NumOfPrm++]);
  352.         break;
  353.         case 'o':
  354.         TmpArray.IntArray[NumOfPrm] = (int *) MyMalloc(sizeof(int));
  355.         ScanRes    = sscanf(*((*argv)++), "%o",
  356.                        (int *) TmpArray.IntArray[NumOfPrm++]);
  357.         break;
  358.         case 'x':
  359.         TmpArray.IntArray[NumOfPrm] = (int *) MyMalloc(sizeof(int));
  360.         ScanRes    = sscanf(*((*argv)++), "%x",
  361.                        (int *) TmpArray.IntArray[NumOfPrm++]);
  362.         break;
  363.         case 'D':
  364.         TmpArray.LngArray[NumOfPrm] = (long *) MyMalloc(sizeof(long));
  365.         ScanRes    = sscanf(*((*argv)++), "%ld",
  366.                       (long *) TmpArray.IntArray[NumOfPrm++]);
  367.         break;
  368.         case 'U':
  369.         TmpArray.LngArray[NumOfPrm] = (long *) MyMalloc(sizeof(long));
  370.         ScanRes    = sscanf(*((*argv)++), "%lu",
  371.                  (unsigned long *) TmpArray.IntArray[NumOfPrm++]);
  372.         break;
  373.         case 'O':
  374.         TmpArray.LngArray[NumOfPrm] = (long *) MyMalloc(sizeof(long));
  375.         ScanRes    = sscanf(*((*argv)++), "%lo",
  376.                       (long *) TmpArray.IntArray[NumOfPrm++]);
  377.         break;
  378.         case 'X':
  379.         TmpArray.LngArray[NumOfPrm] = (long *) MyMalloc(sizeof(long));
  380.         ScanRes    = sscanf(*((*argv)++), "%lx",
  381.                       (long *) TmpArray.IntArray[NumOfPrm++]);
  382.         break;
  383.         case 'f':
  384.         TmpArray.FltArray[NumOfPrm] = (float *)    MyMalloc(sizeof(float));
  385.         ScanRes    = sscanf(*((*argv)++), "%f",
  386.                      (float *) TmpArray.LngArray[NumOfPrm++]);
  387.         break;
  388.         case 'F':
  389.         TmpArray.DblArray[NumOfPrm] =
  390.                        (double *) MyMalloc(sizeof(double));
  391.         ScanRes    = sscanf(*((*argv)++), "%lf",
  392.                     (double *) TmpArray.LngArray[NumOfPrm++]);
  393.         break;
  394.         case 's':
  395.         while ((*argc) && ((**argv)[0] != '-'))    {
  396.             TmpArray.ChrArray[NumOfPrm++] = *((*argv)++);
  397.             (*argc)--;
  398.         }
  399.         ScanRes    = 0;            /* Force quit from do - loop */
  400.         NumOfPrm++;        /* Updated again immediately after loop! */
  401.         (*argv)++;                           /* "" */
  402.         break;
  403.     }
  404.     (*argc)--;
  405.     }
  406.     while (ScanRes == 1);          /* Exactly one parameter was read. */
  407.     (*argv)--; NumOfPrm--; (*argc)++;
  408.  
  409.     /* Now allocate the    block with the exact size, and set it: */
  410.     Ptemp = Pmain = (int **) MyMalloc((unsigned) (NumOfPrm+1) *    sizeof(int *));
  411.     /* And here    we use the assumption that all pointers    are the    same: */
  412.     for    (i=0; i<NumOfPrm; i++) *(Ptemp++) = TmpArray.IntArray[i];
  413.     *(Ptemp) = (int *) NULL;        /* Close the block with NULL pointer */
  414.  
  415.     /* That it save the    number of parameters read as first parameter to    */
  416.     /* return and the pointer to the block as second, and return:    */
  417.     *Parameters[(*ParamCount)++] = NumOfPrm;
  418.     GAByteCopy((char *)    Parameters[(*ParamCount)++], (char *) &Pmain,
  419.                                  sizeof(char *));
  420.     return NumOfPrm;
  421. }
  422.  
  423. /***************************************************************************
  424. * Routine to scan the CtrlStr, upto Max    and count the number of    parameters *
  425. * to that point:                               *
  426. * 1. Each option is counted as one parameter - boolean variable    (int)       *
  427. * 2. Within an option, each %? or !? is    counted    once - pointer to something*
  428. * 3. Within an option, %*? or !*? is counted twice - one for item count       *
  429. *    and one for pointer to block pointers.                   *
  430. * Note ALL variables are passed    by address and so of fixed size    (address). *
  431. ***************************************************************************/
  432. static void GASetParamCount(char *CtrlStr, int Max, int *ParamCount)
  433. {
  434.     int    i;
  435.  
  436.     *ParamCount    = 0;
  437.     for    (i=0; i<Max; i++) if (ISCTRLCHAR(CtrlStr[i])) {
  438.     if (CtrlStr[i+1] == '*') *ParamCount +=    2;
  439.     else             (*ParamCount)++;
  440.     }
  441. }
  442.  
  443. /***************************************************************************
  444. * Routine to copy exactly n bytes fro Src to Dst. Note system library       *
  445. * routine strncpy should do the    same, but it stops on NULL char    !       *
  446. ***************************************************************************/
  447. static void GAByteCopy(char *Dst, char *Src, unsigned n)
  448. {
  449.     while (n--)    *(Dst++) = *(Src++);
  450. }
  451.  
  452. /***************************************************************************
  453. * Routine to check if more option (i.e.    first char == '-') exists in the   *
  454. * given    list argc, argv:                           *
  455. ***************************************************************************/
  456. static int GAOptionExists(int argc, char **argv)
  457. {
  458.     while (argc--) if ((*(argv++))[0] == '-') return TRUE;
  459.     return FALSE;
  460. }
  461.  
  462. /***************************************************************************
  463. * Routine to print some    error messages,    for this module:           *
  464. ***************************************************************************/
  465. void GAPrintErrMsg(int Error)
  466. {
  467.     fprintf(stderr, "Error in command line parsing - ");
  468.     switch (Error) {
  469.     case 0:;
  470.         break;
  471.     case CMD_ERR_NotAnOpt:
  472.         fprintf(stderr, "None option Found");
  473.         break;
  474.     case CMD_ERR_NoSuchOpt:
  475.         fprintf(stderr, "Undefined option Found");
  476.         break;
  477.     case CMD_ERR_WildEmpty:
  478.         fprintf(stderr, "Empty input for '!*?' seq.");
  479.         break;
  480.     case CMD_ERR_NumRead:
  481.         fprintf(stderr, "Failed on reading number");
  482.         break;
  483.     case CMD_ERR_AllSatis:
  484.         fprintf(stderr, "Fail to satisfy");
  485.         break;
  486.     }
  487.     fprintf(stderr, " - '%s'\n", GAErrorToken);
  488. }
  489.  
  490. /***************************************************************************
  491. * Routine to print correct format of command line allowed:           *
  492. ***************************************************************************/
  493. void GAPrintHowTo(char *CtrlStr)
  494. {
  495.     int    i = 0, SpaceFlag;
  496.  
  497.     fprintf(stderr, "Usage: ");
  498.     /* Print program name - first word in ctrl.    str. (optional)    : */
  499.     while (!(ISSPACE(CtrlStr[i])) && (!ISCTRLCHAR(CtrlStr[i+1])))
  500.     fprintf(stderr, "%c", CtrlStr[i++]);
  501.  
  502.     while (i < strlen(CtrlStr))    {
  503.     while ((ISSPACE(CtrlStr[i])) &&    (i < strlen(CtrlStr))) i++;
  504.     switch (CtrlStr[i+1]) {
  505.         case '%':
  506.         fprintf(stderr, " [-%c", CtrlStr[i++]);
  507.         i += 2;             /* Skip the '%-' or '!- after the char! */
  508.         SpaceFlag = TRUE;
  509.         while (!ISCTRLCHAR(CtrlStr[i]) && (i < strlen(CtrlStr))    &&
  510.             (!ISSPACE(CtrlStr[i])))
  511.             if (SpaceFlag) {
  512.             if (CtrlStr[i++] == SPACE_CHAR)
  513.                  fprintf(stderr, " ");
  514.             else fprintf(stderr, " %c", CtrlStr[i-1]);
  515.             SpaceFlag = FALSE;
  516.             }
  517.             else if (CtrlStr[i++] == SPACE_CHAR)
  518.                   fprintf(stderr, " ");
  519.              else fprintf(stderr, "%c", CtrlStr[i-1]);
  520.         while (!ISSPACE(CtrlStr[i]) && (i < strlen(CtrlStr))) {
  521.             if (CtrlStr[i] == '*') fprintf(stderr, "...");
  522.             i++;                  /* Skip the rest of it */
  523.         }
  524.         fprintf(stderr, "]");
  525.         break;
  526.         case '!':
  527.         fprintf(stderr, " -%c", CtrlStr[i++]);
  528.         i += 2;             /* Skip the '%-' or '!- after the char! */
  529.         SpaceFlag = TRUE;
  530.         while (!ISCTRLCHAR(CtrlStr[i]) && (i < strlen(CtrlStr))    &&
  531.             (!ISSPACE(CtrlStr[i])))
  532.             if (SpaceFlag) {
  533.             fprintf(stderr, " %c", CtrlStr[i++]);
  534.             SpaceFlag = FALSE;
  535.             }
  536.             else fprintf(stderr, "%c", CtrlStr[i++]);
  537.         while (!ISSPACE(CtrlStr[i]) && (i < strlen(CtrlStr))) {
  538.             if (CtrlStr[i] == '*') fprintf(stderr, "...");
  539.             i++;                  /* Skip the rest of it */
  540.         }
  541.         break;
  542.         default:               /* Not checked, but must be last one! */
  543.         fprintf(stderr, " ");
  544.         while (!ISSPACE(CtrlStr[i]) && (i < strlen(CtrlStr)) &&
  545.                !ISCTRLCHAR(CtrlStr[i]))
  546.             fprintf(stderr, "%c", CtrlStr[i++]);
  547.         fprintf(stderr, "\n");
  548.         return;
  549.     }
  550.     }
  551.     fprintf(stderr, "\n");
  552. }
  553.  
  554. #ifdef    MYMALLOC
  555.  
  556. /***************************************************************************
  557. * My Routine to    allocate dynamic memory. All program requests must call    *
  558. * this routine (no direct call to malloc). Dies if no memory.           *
  559. ***************************************************************************/
  560. static char *MyMalloc(unsigned size)
  561. {
  562.     char *p;
  563.  
  564.     if ((p = malloc(size)) != NULL) return p;
  565.  
  566.     fprintf(stderr, "Not enough memory, exit\n");
  567.     exit(2);
  568.  
  569.     return NULL;                     /* Makes warning silent */
  570. }
  571.  
  572. #endif    MYMALLOC
  573.