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

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