home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1994 #1 / monster.zip / monster / PROG_C / SNIP9404.ZIP / GETOPTS.C < prev    next >
C/C++ Source or Header  |  1994-04-03  |  6KB  |  194 lines

  1. /*
  2. **  GETOPTS.C - Universal command line options parser
  3. **
  4. **  Original Copyright 1993 by Bob Stout as part of
  5. **  the MicroFirm Function Library (MFL)
  6. **
  7. **  This subset version is hereby donated to the public domain.
  8. */
  9.  
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include "portable.h"
  14. #include "getopts.h"
  15.  
  16. #define NUL '\0'
  17. #define MAX_XARGS 512
  18.  
  19. int   xargc;
  20. char *xargv[MAX_XARGS];
  21.  
  22. /*
  23. **  getopts()
  24. **
  25. **  Parameters: 1 - argc from main()
  26. **              2 - argv from main()
  27. **              3 - your program's options[] array
  28. **
  29. **  Returns: Number of options specified or -1 if error
  30. **
  31. **  Note: Your program should declare the global options[] array which
  32. **        specifies all options recognized by getopts().
  33. */
  34.  
  35. int getopts(int argc, char *argv[])
  36. {
  37.       int i, count, argidx = 0;
  38.       char *argp;
  39.     FILE *argfile;
  40.     char argline[256];
  41.       struct Option_Tag *ptr;
  42.  
  43.       xargc = argc;
  44.       xargv[argidx++] = argv[0];
  45.       for (i = 1, count = 0; i < argc; ++i)
  46.       {
  47.             if (strchr("-/", argv[i][0]) && !strchr("-/", argv[i][1]))
  48.             {
  49.                   /*
  50.                   ** Found a switch - If the 2nd character is also a switch
  51.                   ** character. If so, then it's a literal and is skipped
  52.                   */
  53.  
  54.                   if (strchr("-/", argv[i][1]))
  55.                         continue;
  56.  
  57.                   for (ptr = options; ptr->buf; ++ptr)
  58.                   {
  59.                         if ((int)argv[i][1] == ptr->letter) switch (ptr->type)
  60.                         {
  61.                         case Boolean_Tag:
  62.                               if ('-' == argv[i][2])
  63.                                     *((Boolean_T *)(ptr->buf)) = FALSE;
  64.                               else  *((Boolean_T *)(ptr->buf)) = TRUE;
  65.                               ++count;
  66.                               --xargc;
  67.                               break;
  68.  
  69.                         case Word_Tag:
  70.                               sscanf(&argv[i][2], "%hd", (short *)(ptr->buf));
  71.                               ++count;
  72.                               --xargc;
  73.                               break;
  74.  
  75.                         case DWord_Tag:
  76.                               sscanf(&argv[i][2], "%ld", (long *)(ptr->buf));
  77.                               ++count;
  78.                               --xargc;
  79.                               break;
  80.  
  81.                         case Double_Tag:
  82.                               sscanf(&argv[i][2], "%lg", (double *)(ptr->buf);
  83.                               ++count;
  84.                               --xargc;
  85.                               break;
  86.  
  87.                         case String_Tag:
  88.                               strcpy(ptr->buf, &argv[i][2]);
  89.                               ++count;
  90.                               --xargc;
  91.                               break;
  92.  
  93.                         default:
  94.                               return ERROR;
  95.                         }
  96.                   }
  97.             }
  98.             else                          /* It must be a file name     */
  99.             {
  100.                   DOSFileData ffblk;
  101.  
  102.                   /* Set argp to point to the filename                  */
  103.  
  104.                   if (strchr("-/", argv[i][0]))
  105.                         argp = &argv[i][1];
  106.                   else  argp =  argv[i];
  107.  
  108.                   /* If no wildcards, just copy it */
  109.  
  110.                   if (!strchr(argp, '*') && !strchr(argp, '?'))
  111.                   {
  112.                         xargv[argidx++] = argp;
  113.                         continue;
  114.                   }
  115.  
  116.                   /* Expand wildcards, if possible                      */
  117.  
  118.                   if (0 == FIND_FIRST(argp, 0xff, &ffblk))
  119.                   {
  120.                         char path[FILENAME_MAX], *p;
  121.  
  122.                         /* Save the path for re-attachment              */
  123.  
  124.                         if (NULL == (p = strrchr(argp, '\\')))
  125.                               p = strrchr(argp, '/');
  126.                         if (p)
  127.                         {
  128.                               char ch = *p;
  129.  
  130.                               *p = NUL;
  131.                               strcat(strcpy(path, argp), "\\");
  132.                               *p = ch;
  133.                         }
  134.                         else  *path = NUL;
  135.                         --xargc;
  136.                         do
  137.                         {                             
  138.                               xargv[argidx] = malloc(strlen(ffblk.name)
  139.                                     + strlen(path) + 2);
  140.                               strcat(strcpy(xargv[argidx], path), ffblk.name);
  141.                               ++argidx;
  142.                               ++xargc;
  143.                         
  144.                         } while (0 == FIND_NEXT(&ffblk));
  145.                   }
  146.             }
  147.       }
  148.       return count;
  149. }
  150.  
  151. #ifdef TEST
  152.  
  153. #include <stdlib.h>
  154.  
  155. Boolean_T test1 = TRUE, test2 = FALSE;
  156. int   test3     = -37;
  157. long  test4     = 100000L;
  158. char  test5[80] = "Default string";
  159.  
  160. struct Option_Tag options[] = {
  161.       {'A',  Boolean_Tag, &test1 },             /* Valid options        */
  162.       {'B',  Boolean_Tag, &test2 },
  163.       {'C',  Word_Tag,    &test3 },
  164.       {'D',  DWord_Tag,   &test4 },
  165.       {'E',  String_Tag,   test5 },
  166.       {'\0', ERROR,        NULL  }              /* Terminating record   */
  167. };
  168.  
  169. #define TFprint(v) ((v) ? "TRUE" : "FALSE")
  170.  
  171. int main(int argc, char *argv[])
  172. {
  173.       int i;
  174.  
  175.       printf("Defaults:\ntest1 = %s\ntest2 = %s\ntest3 = %d\ntest4 = %ld\n"
  176.             "test5 = \"%s\"\n\n", TFprint(test1), TFprint(test2), test3,
  177.             test4, test5);
  178.  
  179.       printf("getopts() returned %d\n", getopts(argc, argv));
  180.  
  181.       printf("Options are now:\ntest1 = %s\ntest2 = %s\ntest3 = %d\n"
  182.             "test4 = %ld\ntest5 = \"%s\"\n\n", TFprint(test1),
  183.             TFprint(test2), test3, test4, test5);
  184.  
  185.       puts("Hit any key to continue");
  186.       getch();
  187.       for (i = 0; i < xargc; ++i)
  188.             printf("xargv[%d] = \"%s\"\n", i, xargv[i]);
  189.       printf("\nxargc = %d\n", xargc);
  190.       return 0;
  191. }
  192.  
  193. #endif
  194.