home *** CD-ROM | disk | FTP | other *** search
/ Gold Fish 3 / goldfish_volume_3.bin / files / text / tex / pastex / source / driver / util / amiga / getopt.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-11  |  28.5 KB  |  1,158 lines

  1. /*
  2. **    This file generated by localize 2.9 (AmigaDOS 2.1) from GetOpt.c
  3. */
  4. /*********************************************************************
  5.  *                                                                   *
  6.  *                                                                   *
  7.  *  GetOpt.c         enthaelt die Routinen zum Auswerten der         *
  8.  *                   Kommando-Zeile und der Environment-Variable.    *
  9.  *                                                                   *
  10.  *                                     *
  11.  *                   30-May-91  Georg Hessmann                       *
  12.  *                                                                   *
  13.  *                                                                   *
  14.  *********************************************************************/
  15.  
  16. #include "defines.h"
  17.  
  18. #include <stdarg.h>
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <stddef.h>
  22. #include <string.h>
  23. #include <ctype.h>
  24. #include <math.h>
  25.  
  26. #include <exec/types.h>
  27. #include <dos/dos.h>
  28. #include <workbench/workbench.h>
  29. #include <workbench/startup.h>
  30.  
  31. #include <clib/exec_protos.h>
  32. #include <clib/dos_protos.h>
  33. #include <clib/icon_protos.h>
  34.  
  35. #include <pragmas/exec_pragmas.h>
  36. #include <pragmas/dos_pragmas.h>
  37. #include <pragmas/icon_pragmas.h>
  38.  
  39. extern struct ExecBase        *SysBase;
  40. extern struct DosLibrary    *DOSBase;
  41. extern struct Library        *IconBase;
  42.  
  43. extern struct WBStartup        *WBenchMsg;
  44.  
  45.  
  46.  
  47. #include "globals.h"
  48. #include "globals.i"
  49.  
  50.  
  51. #define TEX        /* ShowDVI/DVIprint */
  52.  
  53. #include "GetOpt.h"
  54. #include "GetOpt.i"
  55.  
  56.  
  57.  
  58.  
  59. /*
  60.  * Fuer die locale-Library:
  61.  *
  62.  * Hier duerfen *nur* die MSG_#? Nummern eingebunden werden!
  63.  * Achtung:
  64.  * Es muss/sollte 'multiple-include' erlaubt sein!
  65.  */
  66. #include "local.i"
  67.  
  68. #undef  CATCOMP_ARRAY
  69. #undef  CATCOMP_BLOCK
  70. #undef  CATCOMP_STRINGS
  71. #define CATCOMP_NUMBERS
  72. #include "localstr.h"
  73.  
  74.  
  75.  
  76. /*
  77.  * lokale Funktionen
  78.  *
  79.  */
  80.  
  81. static BOOL MyNameFromLock (BPTR lock, char *buffer, long len);
  82.  
  83. static void FillLocHlpTxt         (struct Options opt[]);
  84.  
  85. static void __stdargs GetOptError (int keynr, struct Options opt[], char *format,...);
  86. static BOOL ExamineKeyword        (int keynr, char *option, BOOL *use_option, struct Options opt[]);
  87. static BOOL ScanArgVektor         (int argc, char *argv[], struct Options opt[]);
  88. static BOOL ScanString            (char *envcont, struct Options opt[]);
  89. static BOOL ScanEnvString         (char *envname, struct Options opt[]);
  90. static BOOL ScanWBArgs              (struct Options opt[]);
  91. static BOOL check_req_para        (struct Options opt[]);
  92. static int  StrOptiCmp          (char *option, char *para, char **arg);
  93.  
  94.  
  95. #ifdef TEX
  96.  
  97. /* Tabelle der Seitengroessen */
  98. struct PSizes psizes[] = {
  99.   { "A0",   84.09/2.54, 118.92/2.54 },
  100.   { "A1",   59.46/2.54,  84.09/2.54 },
  101.   { "A2",   42.04/2.54,  59.46/2.54 },
  102.   { "A3",   29.73/2.54,  42.04/2.54 },
  103.   { "A4",   21.02/2.54,  29.73/2.54 },
  104.   { "A5",   14.87/2.54,  21.02/2.54 },
  105.   { "A6",   10.51/2.54,  14.87/2.54 },
  106.   { "A7",    7.43/2.54,  10.51/2.54 },
  107.   { "A0r", 118.92/2.54,  84.09/2.54 },
  108.   { "A1r",  84.09/2.54,  59.46/2.54 },
  109.   { "A2r",  59.46/2.54,  42.04/2.54 },
  110.   { "A3r",  42.04/2.54,  29.73/2.54 },
  111.   { "A4r",  29.73/2.54,  21.02/2.54 },
  112.   { "A5r",  21.02/2.54,  14.87/2.54 },
  113.   { "A6r",  14.87/2.54,  10.51/2.54 },
  114.   { "A7r",  10.51/2.54,   7.43/2.54 },
  115.   { NULL, 0, 0}
  116. };
  117.  
  118.  
  119. /*
  120.  * dimen_to_inch() returns the dimension given in the first argument
  121.  * in inches in the second argument. It returns 0, if all is ok, otherwise
  122.  * a value != 0.
  123.  */
  124.  
  125. struct unit_table { char *unit; float factor; };
  126.  
  127. static struct unit_table unittable[] = {
  128.   {"pt", 72.27},    {"bp", 72.0},
  129.   {"cm", 2.54},        {"mm", 25.4},
  130.   {"in", 1.0},        {"mi", 1000.0},    /* "milli-inches" for TPIC */
  131.   {"pc", 72.27/12},    {"sp", 72.27/65536},
  132.   {"dd", 72.27/(1238/1157)},
  133.   {"cc", 72.27/12/(1238/1157)},
  134.   {NULL, 0.0}
  135. };
  136.  
  137. int dimen_to_inch(char *str, float *inch_value, int *isTrue)
  138.   register struct unit_table *d;
  139.   float value;
  140.   char  unitArr[8];    /* we need min. 2+1 characters for %2s  + 4 fuer 'true' !! */
  141.   char * unit = unitArr;
  142.   
  143.   if (sscanf(str, "%f%6s", &value, unit) != 2) {
  144.     return 1;
  145.   }
  146.   
  147.   if (strnicmp(unit, "true", 4) == 0) {
  148.     *isTrue = TRUE;
  149.     unit  += 4;
  150.   }
  151.   else {
  152. #ifdef TEX_TRUE_DIM
  153.     *isTrue = FALSE;
  154. #else
  155.     *isTrue = TRUE;
  156. #endif
  157.   }
  158.  
  159.   for (d = unittable; d->unit != NULL; d++) {
  160.     if (stricmp(d->unit, unit) == 0) {
  161.     *inch_value = value / d->factor;
  162.     return 0; // alles ok...lasse negative Werte wieder zu...wenn man die nicht will, so soll man sie wo anders ausschliessen!
  163.     //return ((*inch_value) < 0.0);    // mag keine negativen Dimensionen
  164.     }
  165.   }
  166.   return 1;
  167. }
  168.  
  169. #endif /* TEX */
  170.  
  171.  
  172.  
  173. /*
  174.  * MyNameFromLock()
  175.  *
  176.  * Macht was der Name verspricht...
  177.  * Wenn der lock auf ein Directory zeigt wird zusaetzlich noch ein '/'
  178.  * angehaengt.
  179.  *
  180.  */
  181.  
  182.  
  183. static BOOL MyNameFromLock(BPTR lock, char *buffer, long len)
  184. {
  185.   BPTR lock1;
  186.   char strh[108], *h;
  187.   struct FileInfoBlock *fib;
  188.   int l;
  189.  
  190.   if (lock == (BPTR)NULL) {
  191.     if (len < 5) {
  192.       return FALSE;
  193.     }
  194.     strcpy(buffer, "SYS:");
  195.     return TRUE;
  196.   }
  197.  
  198.   buffer[0]='\0';
  199.   l = 1;    /* 1 wg. '\0' Byte */
  200.  
  201.   fib = (struct FileInfoBlock *)xmalloc((unsigned)sizeof(struct FileInfoBlock));
  202.  
  203.   if (Examine(lock,fib) == 0) {
  204.     xfree(fib);
  205.     return FALSE;
  206.   }
  207.  
  208.   l += strlen(fib->fib_FileName);
  209.   if (l < len) {
  210.     strcpy(buffer, fib->fib_FileName);
  211.   }
  212.  
  213.   if (fib->fib_DirEntryType > 0 ) {        /* Directory? */
  214.      if (++l < len) {
  215.        strcat(buffer,"/");
  216.      }
  217.   }
  218.  
  219.   lock1 = ParentDir(lock);
  220.   /** UnLock((BPTR)lock); NEIN der uebergebene Lock wird NICHT freigegeben! */
  221.   lock = lock1;
  222.  
  223.   while (lock!=(BPTR)NULL) {
  224.     if (Examine(lock,fib)==0) {
  225.       xfree(fib);
  226.       return FALSE;
  227.     }
  228.     else {
  229.        l += strlen(fib->fib_FileName) + 1;
  230.        if (l < len) {
  231.          strcpy(strh,fib->fib_FileName);
  232.          strcat(strh,"/");
  233.          strcat(strh,buffer);
  234.          strcpy(buffer,strh);
  235.        }
  236.     }
  237.     lock1 = ParentDir(lock);
  238.     UnLock((BPTR)lock);
  239.     lock = lock1;
  240.    }
  241.   h = strchr(buffer,'/');
  242.   if (h != NULL) {
  243.     h[0] = ':';
  244.   }
  245.   xfree((char *)fib);
  246.  
  247.   return (BOOL)(l < len);
  248. }
  249.  
  250.  
  251.  
  252. /*
  253.  * FillLocHlpTxt()
  254.  *
  255.  * Nimmt die msg_ Nummern und setzt die hlp_txt Felder in opt[].
  256.  *
  257.  */
  258.  
  259. static void FillLocHlpTxt(struct Options opt[])
  260. {
  261.   int k;
  262.   
  263.   for (k=0; opt[k].type != OPT_LAST_ENTRY; k++) {
  264.     if (opt[k].msg_hlp_txt > 0) {
  265.       opt[k].hlp_txt     = GetTeXString(opt[k].msg_hlp_txt);
  266.       opt[k].msg_hlp_txt = 0;    // nur einmal GetTeXString() machen
  267.     }
  268.     if (opt[k].msg_hlp_txt2 > 0) {
  269.       opt[k].hlp_txt2     = GetTeXString(opt[k].msg_hlp_txt2);
  270.       opt[k].msg_hlp_txt2 = 0;    // nur einmal GetTeXString() machen
  271.     }
  272.   }
  273. }
  274.  
  275.  
  276.  
  277. /*
  278.  * GetOptError()
  279.  *
  280.  * keynr ist das aktuelle Keywort oder -1
  281.  * format,... ist der Errorstring.
  282.  *
  283.  */
  284.  
  285. static void __stdargs GetOptError(int keynr, struct Options opt[], char *format,...)
  286. {
  287.   va_list argptr;
  288.   char buffer[512];        /* stack! */
  289.   int len;
  290.   
  291.   va_start(argptr, format);
  292.   vsprintf(buffer, format, argptr);
  293.   va_end(argptr);
  294.  
  295.   len = strlen(buffer);
  296.   if (len >511) {
  297.     Fatal(20,MSG_GETOPT_LINEBUF_OVERFLOW);
  298.   }
  299.  
  300.   if (keynr == -1) {
  301.     Warning(MSG_GETOPT_ERROR,buffer);
  302.   }
  303.   else {
  304.     if (opt[keynr].name == NULL) {
  305.       Warning(MSG_GETOPT_ERROR,opt[keynr].hlp_txt);
  306.     }
  307.     else {
  308.       Warning(MSG_GETOPT_ERROR_KEY,opt[keynr].name, opt[keynr].hlp_txt);
  309.     }
  310.     WarningStr("\t   %s",buffer);
  311.   }
  312.  
  313. }
  314.  
  315.  
  316. /*
  317.  * ExamineKeyword()
  318.  *
  319.  * Nimmt 'keynr' und einen Option String und updated das 'result' Feld.
  320.  * use_option gibt an, ob 'option' gebraucht wurde.
  321.  *
  322.  */
  323.  
  324. static BOOL ExamineKeyword(int keynr, char *option, BOOL *use_option, struct Options opt[])
  325. {
  326.   void *res = opt[keynr].result;
  327.   BOOL  error  = 0;
  328.   float tmp;
  329.  
  330.   switch (opt[keynr].type) {
  331.      case OPT_HELP:
  332.          *(long *)res = TRUE;
  333.          *use_option = FALSE;
  334.          opt[keynr].is_given = TRUE;
  335.          break;
  336.      case OPT_BOOLEAN:
  337.      if (option == NULL) {
  338.            *(long *)res = TRUE;        /* wenn nichts angegeben => TRUE */
  339.            *use_option = FALSE;
  340.      }
  341.      else {
  342.            if (stricmp(option, "on") == 0) {
  343.              *(long *)res = TRUE;
  344.              *use_option = TRUE;
  345.            }
  346.            else {
  347.              if (stricmp(option, "off") == 0) {
  348.                *(long *)res = FALSE;
  349.                *use_option = TRUE;
  350.              }
  351.              else {
  352.                *(long *)res = TRUE;    /* wenn nichts angegeben => TRUE */
  353.                *use_option = FALSE;
  354.              }
  355.             }
  356.          }
  357.          opt[keynr].is_given = TRUE;
  358.          break;
  359.      case OPT_STRING:
  360.          if (option == NULL) {
  361.            error = 1;
  362.            GetOptError(keynr, opt, GetTeXString(MSG_GETOPT_NO_OPTION_STRING));
  363.          }
  364.          else {
  365.            *(char **)res = option;
  366.            *use_option = TRUE;
  367.            opt[keynr].is_given = TRUE;
  368.          }
  369.          break;
  370.      case OPT_LONG:
  371.          if (option == NULL) {
  372.            error = 1;
  373.            GetOptError(keynr, opt, GetTeXString(MSG_GETOPT_MISSING_NUM));
  374.          }
  375.          else {
  376.            if (sscanf(option,"%ld", res) == 1) {
  377.              *use_option = TRUE;
  378.              opt[keynr].is_given = TRUE;
  379.            }
  380.            else {
  381.              GetOptError(keynr, opt, GetTeXString(MSG_GETOPT_NO_NUMBER),option);
  382.              error = 1;
  383.            }
  384.          }
  385.          break;
  386.      case OPT_FLOAT:
  387.          if (option == NULL) {
  388.            error = 1;
  389.            GetOptError(keynr, opt, GetTeXString(MSG_GETOPT_MISSING_REAL));
  390.          }
  391.          else {
  392.            if (sscanf(option,"%f", &tmp) == 1) {
  393.              *use_option = TRUE;
  394.              *(float *)res = tmp;
  395.              opt[keynr].is_given = TRUE;
  396.            }
  397.            else {
  398.              GetOptError(keynr, opt, GetTeXString(MSG_GETOPT_NO_REAL), option);
  399.              error = 1;
  400.            }
  401.          }
  402.          break;
  403. #ifdef TEX
  404.      case OPT_TEX_DIM:
  405.          if (option == NULL) {
  406.            error = 1;
  407.            GetOptError(keynr, opt, GetTeXString(MSG_GETOPT_MISSING_TEX));
  408.          }
  409.          else {
  410.            int isTrue;
  411.            if (dimen_to_inch(option, &tmp, &isTrue)) {
  412.              error = 1;
  413.              GetOptError(keynr, opt, GetTeXString(MSG_GETOPT_NO_TEX), option);
  414.            }
  415.            else {
  416.              *use_option   = TRUE;
  417.              *(float *)res = tmp;
  418.              opt[keynr].special  = isTrue;
  419.              opt[keynr].is_given = TRUE;
  420.            }
  421.          }
  422.          break;
  423. #endif
  424.      default:
  425.          GetOptError(keynr, opt, GetTeXString(MSG_GETOPT_UNKNOWN_PARAM));
  426.          break;
  427.   }
  428.  
  429.   return error;
  430. }
  431.  
  432.  
  433. /*
  434.  * ScanArgVetor()
  435.  *
  436.  * nimmt argc/argv, opt[] und updated das result Flag
  437.  *
  438.  * LIMITATION:
  439.  *   Leider kann zu jedem Keyword nur eine Option ausgewertet werden!
  440.  *
  441.  */
  442.  
  443. static BOOL ScanArgVektor(int argc, char *argv[], struct Options opt[])
  444. {
  445.   int i, j;
  446.   int  keynr;            /* Nummer des gefundenen Keywords (-1: kein Keyword) */
  447.   char *para;            /* aktueller Parameter -- Keyword */
  448.   char *option;            /* Option zum Keyword (falls gebraucht) */
  449.   BOOL conc_opt;        /* zusammengesetzte Option */
  450.   BOOL found;
  451.   BOOL error=FALSE;        /* ist ein Fehler aufgetreten? */
  452.  
  453.   for (i=0; i<argc && !error; i++) {    /* Schleife ueber alle Argumente */
  454.  
  455.     para = argv[i];            /* aktueller Parameter */
  456.     keynr = -1;                /* bisher kein Keyword */
  457.  
  458.     found = FALSE;            /* suche nach dem passenden Keyword */
  459.     conc_opt = FALSE;
  460.  
  461.       for (j=0; opt[j].type != OPT_LAST_ENTRY; j++) {
  462.       if (opt[j].name != NULL) {
  463.  
  464.         /* suche ob Keyword passt */
  465.     char *rest = NULL;
  466.     if (StrOptiCmp(opt[j].name, para, &rest) == 0) {
  467.       if (rest != NULL) {
  468.         conc_opt = TRUE;
  469.         option = rest;
  470.       }
  471.       else {
  472.         option = (i == argc-1) ? NULL : argv[i+1];
  473.       }
  474.       found = TRUE;
  475.     }
  476.     /* opt.abbrev is case sensitive for Unix like options */
  477.     else if (opt[j].abbrev != NULL && strncmp(opt[j].abbrev, para, opt[j].alen) == 0) {
  478.       switch(para[opt[j].alen]) {
  479.         case '\0':
  480.           found = TRUE;
  481.           option = (i == argc-1) ? NULL : argv[i+1];
  482.           break;
  483.         case '=':
  484.           found = TRUE;
  485.           conc_opt = TRUE;
  486.           option = ¶[opt[j].alen+1];
  487.           break;
  488.         /*default: not found */
  489.       }
  490.     }
  491.     if (found) {
  492.       keynr = j;
  493.       break;
  494.     }
  495.       }        /* name != NULL */
  496.     }        /* for    i    */
  497.  
  498.     if (found) {                /* Keyword gefunden? */
  499.       BOOL use_option = FALSE;    /* wurde die Option fuer keynr gebraucht */
  500.       error = ExamineKeyword(keynr, option, &use_option, opt);
  501.       if (!error) {
  502.         if (use_option) {
  503.           if (!conc_opt) {
  504.             i++;                /* ein Parameter als Option verbraucht */
  505.           }
  506.         }
  507.         else {
  508.           if (conc_opt) {
  509.             if (opt[keynr].type == OPT_BOOLEAN) {
  510.               GetOptError(keynr, opt, GetTeXString(MSG_GETOPT_WRONG_ONOFF_PARAM),option);
  511.             }
  512.             else {
  513.               /* der Fall kann *nie* auftreten, aber sicher ist sicher... */
  514.               GetOptError(keynr, opt, GetTeXString(MSG_GETOPT_NO_PARAM_EXPECTED),option);
  515.             }
  516.             error = TRUE;
  517.           }
  518.         }
  519.       }
  520.     }
  521.     else {                    /* kein Keyword */
  522.       int k;
  523.       /* hier neue Bedeutung fuer 'found'! */
  524.       /* found = FALSE; */            /* Platz gefunden? */
  525.       for (k=0; opt[k].type != OPT_LAST_ENTRY; k++) {
  526.         if (opt[k].type == OPT_OPTIONSTRING && !opt[k].is_given) {
  527.           /* noch freien Option-Platz gefunden */
  528.           found = TRUE;
  529.           *((char **)opt[k].result) = strdup(argv[i]);
  530.           opt[k].is_given = TRUE;
  531.       break;
  532.         }
  533.       }
  534.       
  535.       if (!found) {
  536.         GetOptError(keynr, opt, GetTeXString(MSG_GETOPT_UNKNOWN_KEYWORD),para);
  537.         error = 1;
  538.       }
  539.  
  540.     }    /* found    */
  541.   }    /* for    i    */
  542.   
  543.   return error;
  544. }
  545.  
  546.  
  547. /*
  548.  * ScanString()
  549.  *
  550.  * Zerlegt die Ausgabe von getenv() in ein argc/argv Feld.
  551.  *    (Thank's Dave!)
  552.  */
  553.  
  554. static BOOL ScanString(char *envcont, struct Options opt[])
  555. {
  556.   register char *ptr;
  557.   int argc = 0;       /* Zähler für gefundene Argumente */
  558.   char *argv[40];     /* 40 Zeiger auf Strings */
  559.   char *begin;
  560.   char c;
  561.   BOOL somethingfound = FALSE;
  562.   BOOL inanf;        /* in Anfuehrungszeichen?? */
  563.   BOOL error = FALSE;
  564.   
  565.   ptr = envcont;
  566.  
  567.   while (isspace(*ptr)) ptr++;    /* Leerzeichen am Anfang ueberlesen */
  568.   begin = ptr;            /* begin zeigt auf den Anfang des ersten Params */
  569.   inanf = FALSE;
  570.  
  571.   while ((c = *ptr++) && argc < 40) {
  572.  
  573.     if (isspace(c)) {
  574.       if (inanf) continue;            /* SPACE in Anf.: no action */
  575.       else {
  576.         *(ptr-1) = '\0';            /* String beenden */
  577.         argv[argc++] = begin;            /* Anfang des String eintragen */
  578.         while (isspace(*ptr)) ptr ++;        /* Leerzeichen am Anfang ueberlesen */
  579.         begin = ptr;                /* begin zeigt auf den Anfang des ..*/
  580.       }
  581.     }
  582.     else {
  583.       if (c == '"') {
  584.     if (*ptr == '"') {            /* Zwei " nacheinander sind ein " */
  585.            register char *d=ptr,*s=ptr+1;
  586.            while (*d++ = *s++);            /* String zusammenziehen */
  587.                         /* kein !! ptr++; denn das 2. " ist ueberkopiert */
  588.         }
  589.         else {
  590.           inanf = !inanf;
  591.         }
  592.       }
  593.       else {
  594.         somethingfound = TRUE;
  595.       }
  596.     }
  597.   }
  598.  
  599.   if (argc >= 40) {
  600.     GetOptError(-1, opt, GetTeXString(MSG_GETOPT_TOO_MANY_ENV_ARGS));
  601.     return 1;
  602.   }
  603.  
  604.   if (somethingfound && begin != ptr) {
  605.     argv[argc++] = begin;
  606.   }
  607.  
  608.   if (argc != 0) {
  609.     error = ScanArgVektor(argc, argv, opt);
  610.   }
  611.   
  612.   return error;
  613. }
  614.  
  615.  
  616.  
  617. /*
  618.  * ScanEnvString()
  619.  *
  620.  * Liest den 'envname' String aus und ruft ScanString() auf.
  621.  *
  622.  */
  623.  
  624. static BOOL ScanEnvString(char *envname, struct Options opt[])
  625. {
  626.   char *envcont;        /* Inhalt der Env-Variablen */
  627.   char *ptr;
  628.   BOOL error = FALSE;
  629.   
  630.   if ((ptr = getenv(envname)) != NULL) {
  631.     envcont = malloc(strlen(ptr)+1);
  632.     /* envcont = strdup(ptr); */
  633.     if (envcont == NULL) {
  634.       GetOptError(-1, opt, GetTeXString(MSG_GETOPT_NO_MEM_FOR_ENV));
  635.       error = TRUE;
  636.     }
  637.     else {
  638.       strcpy(envcont, ptr);
  639.       ScanString(envcont, opt);
  640.     }
  641.   }
  642.   
  643.   return error;
  644. }
  645.  
  646.  
  647.  
  648. /*
  649.  * ScanWBArgs()
  650.  *
  651.  * Liest die Workbench Argumente.
  652.  *
  653.  */
  654.  
  655.  
  656.  
  657. static BOOL ScanWBArgs(struct Options opt[])
  658. {
  659.   BPTR oldlock;
  660.   struct WBArg *arg;
  661.   struct DiskObject *diskobj;
  662.   char *ptr, *option;
  663.   int keynr, i;
  664.   BOOL error, use_option, found, was_icon_base;
  665.   
  666.   error = FALSE;
  667.  
  668.   arg = WBenchMsg->sm_ArgList;            /* Programmname überspringen */
  669.  
  670.   if (IconBase != NULL) {
  671.     /* ShowDVI macht die selber auf und braucht die auch weiterhin... */
  672.     was_icon_base = TRUE;
  673.   }
  674.   else {
  675.     IconBase = OpenLibrary("icon.library", 0);
  676.     if (IconBase == NULL) {
  677.       return TRUE;    /* Fehler! */
  678.     }
  679.     was_icon_base = FALSE;
  680.   }
  681.  
  682.   for (i=0; i< WBenchMsg->sm_NumArgs; i++, arg++) {
  683.  
  684.     oldlock = CurrentDir(arg->wa_Lock);        /* Verzeichnis auswaehlen */
  685.     diskobj = GetDiskObject(arg->wa_Name);
  686.  
  687.     if (diskobj != NULL) {
  688.       keynr = 0;
  689.       while (opt[keynr].type != OPT_LAST_ENTRY) {
  690.  
  691.         ptr = FindToolType(diskobj->do_ToolTypes, opt[keynr].name);
  692.         if (ptr == NULL ) {
  693.           ptr = FindToolType(diskobj->do_ToolTypes, opt[keynr].abbrev);
  694.         }
  695.  
  696.         if (ptr != NULL) {
  697.           if (*ptr != '\0') {
  698.             option = strdup(ptr);            /* dupliziere String, wird laenger benoetigt */
  699.           }
  700.           else {
  701.             option = ptr;                /* leerer String muss nicht dupliziert werden */
  702.           }
  703.           if (option != NULL) {
  704.             if (*option == '\0') option = NULL;        /* leerer String == NULL String */
  705.         error = ExamineKeyword(keynr, option, &use_option, opt);
  706.         if (!error) {
  707.           if (!use_option && option != NULL) {
  708.                 if (opt[keynr].type == OPT_BOOLEAN) {
  709.                   GetOptError(keynr, opt, GetTeXString(MSG_GETOPT_WRONG_ONOFF_PARAM),option);
  710.                 }
  711.                 else {
  712.                   /* der Fall kann *nie* auftreten, aber sicher ist sicher... */
  713.                   GetOptError(keynr, opt, GetTeXString(MSG_GETOPT_NO_PARAM_EXPECTED),option);
  714.                 }
  715.                 error = TRUE;
  716.           }
  717.         }
  718.       }
  719.         }
  720.  
  721.         keynr++;
  722.       }
  723.  
  724.       if (i > 0) {
  725.         /* alle Filenamen, ausser dem Prognamen, werden als OPT_OPTIONSTING abgelegt */
  726.  
  727.         found = FALSE;                /* Platz gefunden? */
  728.         keynr = 0;
  729.         while (opt[keynr].type != OPT_LAST_ENTRY && !found) {
  730.           if (opt[keynr].type == OPT_OPTIONSTRING && *((long *)opt[keynr].result) == 0L) {
  731.             char buffer[150];
  732.         if (MyNameFromLock(arg->wa_Lock, buffer, 149)) { 
  733.           if (strlen(buffer) + strlen(arg->wa_Name) < 149) {
  734.             strcat(buffer, arg->wa_Name);
  735.                 found = TRUE;
  736.                 *((char **)opt[keynr].result) = strdup(buffer);
  737.                 opt[keynr].is_given = TRUE;
  738.           }
  739.         }
  740.           }
  741.           keynr++;
  742.         }
  743.         
  744.         if (!found) {
  745.           GetOptError(keynr, opt, GetTeXString(MSG_GETOPT_SUPER_FILE),arg->wa_Name);
  746.           error = 1;
  747.         }
  748.       }
  749.  
  750.       FreeDiskObject(diskobj);
  751.       CurrentDir(oldlock);           /* altes Verzeichnis wieder */
  752.     }
  753.     else {
  754.       /* diskobj == NULL */
  755.       GetOptError(-1, opt, GetTeXString(MSG_GETOPT_NO_INFO), arg->wa_Name);
  756.       /* error = 1; nicht unbedingt ein Fehler (wg. WB 2.0) */
  757.     }
  758.   }
  759.  
  760.   if (!was_icon_base) {
  761.     CloseLibrary(IconBase);
  762.     IconBase = NULL;
  763.   }
  764.   
  765.   return error;
  766. }
  767.  
  768.  
  769.  
  770. static BOOL check_req_para(struct Options opt[])
  771. {
  772.   int k;
  773.  
  774.   for (k=0; opt[k].type != OPT_LAST_ENTRY; k++) {
  775.     if (opt[k].required == OPT_REQUIRED && !opt[k].is_given  ) {
  776.       GetOptError(k, opt, GetTeXString(MSG_GETOPT_PARAM_REQU));
  777.       return TRUE;
  778.     }
  779.   }
  780.   return FALSE;
  781. }
  782.  
  783.  
  784.  
  785. /*
  786.  * Funktionen nach aussen. ----------------------------------------------
  787.  *
  788.  */
  789.  
  790.  
  791.  
  792.   /**********************************************************************/
  793.   /* GetOptShortHelp: Gibt eine kurze Hilfe aus.            */
  794.   /*                    helpline    Vorgegebener Zeilenanfang.        */
  795.   /*            linelength  Auf wieviel Zeichen pro Zeile soll    */
  796.   /*                    die Ausgabe formatiert werden.    */
  797.   /*            opt         Array der Parameterdefinitionen.    */
  798.   /*              Der Text wird mit der Funktion Message ausgegeben */
  799.   /**********************************************************************/
  800.  
  801. void GetOptShortHelp(char *helpline, int linelength, struct Options opt[])
  802. {
  803.   char tmp[104], line[104], *ptr;
  804.   int k, len, used;
  805.  
  806.   FillLocHlpTxt(opt);
  807.  
  808.   if (linelength > 100) linelength = 100;
  809.  
  810.   strncpy(line, helpline, 100);
  811.   len = strlen(line);
  812.   used = FALSE;
  813.  
  814.   for (k=0; opt[k].type != OPT_LAST_ENTRY; k++) {
  815.     ptr = NULL;
  816.     tmp[0] = '\0';
  817.  
  818.     switch (opt[k].type) {
  819.      case OPT_HELP:
  820.          ptr = "";
  821.          break;
  822.      case OPT_BOOLEAN:
  823.          ptr = " on|off";
  824.          break;
  825.      case OPT_STRING:
  826.          ptr = " str";
  827.          break;
  828.      case OPT_LONG:
  829.          ptr = " number";
  830.          break;
  831.      case OPT_FLOAT:
  832.          ptr = " real";
  833.          break;
  834. #ifdef TEX
  835.      case OPT_TEX_DIM:
  836.          ptr = " TeX-dim";
  837.          break;
  838. #endif
  839.      case OPT_OPTIONSTRING:
  840.          sprintf(tmp, "%.50s", opt[k].hlp_txt);
  841.          break;
  842.     }
  843.     if (ptr != NULL) {
  844.       if (opt[k].name != NULL) {
  845.         sprintf(tmp, "%.20s%s",opt[k].name, ptr);
  846.       }
  847.       /* else: gibt's nicht! opt[k].name == NULL <==> OPT_OPTIONSTRING */
  848.     }
  849.  
  850.     if (!opt[k].hidden) {
  851.       if (strlen(tmp)+len > linelength) {
  852.         if (used) {
  853.           MessageStr(line);
  854.           strcpy(line,"\t");
  855.           len = 8;
  856.           //used = FALSE;
  857.         }
  858.         else {
  859.           return;  /* ein Eintrag alleine ist schon laenger als die Zeile... */
  860.         }
  861.       }
  862.  
  863.       if (opt[k].required == OPT_NOT_REQUIRED) {
  864.         strcat(line, "[");
  865.         strcat(line, tmp);
  866.         strcat(line, "]  ");
  867.         len += 2;
  868.       }
  869.       else {
  870.         strcat(line, tmp);
  871.         strcat(line, "  ");
  872.       }
  873.       len += strlen(tmp) + 2;
  874.       used = TRUE;
  875.     }
  876.   }
  877.   if (used) MessageStr(line);
  878. }
  879.  
  880.  
  881.  
  882.   /**********************************************************************/
  883.   /* GetOptHelp:  Gibt fuer jede Option eine Zeile Hilfstext aus.    */
  884.   /*          Mit Angabe der derzeitigen Belegung des result-Feldes    */
  885.   /*          als Defaultangabe.                    */
  886.   /*            opt    Array der Parameterdefinitionen.    */
  887.   /**********************************************************************/
  888.  
  889. void GetOptHelp(struct Options opt[])
  890. {
  891.   int k;
  892.   void *res;
  893.   char helpline[200], tmp[200], t2[100];
  894.   
  895.   FillLocHlpTxt(opt);
  896.  
  897.   for (k=0; opt[k].type != OPT_LAST_ENTRY; k++) {
  898.     res = opt[k].result;
  899.     
  900.     helpline[0] = '\0';
  901.  
  902.     if (opt[k].name == NULL) {
  903.       sprintf(tmp,GetTeXString(MSG_GETOPT_TAB_TAB_DEF), opt[k].hlp_txt);
  904.     }
  905.     else {
  906.       if (opt[k].abbrev != NULL) {
  907.         sprintf(t2, "%.20s|%.20s", opt[k].name, opt[k].abbrev);
  908.       }
  909.       else {
  910.         strcpy(t2, opt[k].name);
  911.       }
  912.       if (strlen(t2) > 7) {
  913.         strcat(t2,"\t");
  914.       }
  915.       else {
  916.         strcat(t2,"\t\t");
  917.       }
  918.       if (opt[k].type == OPT_HELP) {
  919.         sprintf(tmp,"\t%.50s%.50s", t2, opt[k].hlp_txt);
  920.       }
  921.       else {
  922.         sprintf(tmp,GetTeXString(MSG_GETOPT_TAB_DEF), t2, opt[k].hlp_txt);
  923.       }
  924.     }
  925.  
  926.     /* Vorsicht vor Overflow! */
  927.     if (strlen(tmp)+strlen(helpline) > 200-20) {
  928.       continue;
  929.     }
  930.  
  931.     strcat(helpline,tmp);
  932.  
  933.     switch (opt[k].type) {
  934.      case OPT_HELP:
  935.          /* HELP hat kein Default-Wert... */
  936.          break;
  937.      case OPT_BOOLEAN:
  938.          if (*(long *)res) {
  939.            strcat(helpline,"on");
  940.          }
  941.          else {
  942.            strcat(helpline,"off");
  943.          }
  944.          break;
  945.      case OPT_STRING:
  946.          if (*(char **)res == NULL) {
  947.            strcat(helpline,GetTeXString(MSG_GETOPT_NO_DEFAULT));
  948.          }
  949.          else {
  950.            if (strlen(*(char **)res)+strlen(helpline) < 200) {
  951.              strcat(helpline, *(char **)res);
  952.            }
  953.          }
  954.          break;
  955.      case OPT_LONG:
  956.          sprintf(tmp,"%ld", *(long *)res);
  957.          strcat(helpline, tmp);
  958.          break;
  959.      case OPT_FLOAT:
  960.          sprintf(tmp, "%f", *(float *)res);
  961.          strcat(helpline, tmp);
  962.          break;
  963. #ifdef TEX
  964.      case OPT_TEX_DIM:
  965.          if (fabs((double)*(float *)res+(double)13.13) > 0.01) {
  966.            sprintf(tmp, "%.2fin", *(float *)res);
  967. #ifdef TEX_TRUE_DIM
  968.            if (opt[k].special) {
  969.              sprintf(tmp, "%.2ftruein", *(float *)res);
  970.            }
  971.            else {
  972.              sprintf(tmp, "%.2fin", *(float *)res);
  973.            }
  974. #endif
  975.            strcat(helpline, tmp);
  976.          }
  977.          else {
  978.            strcat(helpline,GetTeXString(MSG_GETOPT_NO_DEFAULT));
  979.          }
  980.          break;
  981. #endif
  982.      case OPT_OPTIONSTRING:
  983.          if (*(char **)res == NULL) {
  984.            strcat(helpline,GetTeXString(MSG_GETOPT_NO_DEFAULT));
  985.          }
  986.          else {
  987.            if (strlen(*(char **)res)+strlen(helpline) < 200) {
  988.              strcat(helpline, *(char **)res);
  989.            }
  990.          }
  991.          break;
  992.     }
  993.     if (opt[k].type != OPT_HELP) {
  994.       strcat(helpline,")");
  995.     }
  996.     if (!opt[k].hidden) {
  997.       MessageStr(helpline);                /* !!! */
  998.       if (opt[k].hlp_txt2 != NULL) {
  999.         MessageStr("\t\t\t%s", opt[k].hlp_txt2);    /* !!! */
  1000.       }
  1001.     }
  1002.   }
  1003. }
  1004.  
  1005.  
  1006.  
  1007.   /**********************************************************************/
  1008.   /* CheckOpt_Given: Wurde Option angegeben ?                */
  1009.   /*    Die Option wird anhand des 'result' Eintrags erkannt.        */
  1010.   /*    Ergebnis: -1: nicht gefunden, 0: nicht angegeben, sonst 1.    */
  1011.   /**********************************************************************/
  1012.  
  1013. int CheckOpt_Given(void *which, struct Options opt[])
  1014. {
  1015.   struct Options *o;
  1016.  
  1017.   FillLocHlpTxt(opt);
  1018.  
  1019.   for (o=opt; o->type != OPT_LAST_ENTRY; o++) {
  1020.     if (o->result == which) return (int)o->is_given;
  1021.   }
  1022.   return -1;
  1023. }
  1024.  
  1025.  
  1026.  
  1027.  
  1028.   /**********************************************************************/
  1029.   /* GetOneOpt: Liefert den struct der Option zurueck.            */
  1030.   /**********************************************************************/
  1031. struct Options * GetOneOpt(void *which, struct Options opt[])
  1032. {
  1033.   struct Options *o;
  1034.  
  1035.   FillLocHlpTxt(opt);
  1036.  
  1037.   for (o=opt; o->type != OPT_LAST_ENTRY; o++) {
  1038.     if (o->result == which) return o;
  1039.   }
  1040.   return NULL;
  1041. }
  1042.  
  1043.  
  1044.  
  1045.   /**********************************************************************/
  1046.   /* GetOpt:    Parameter-Parse Funktion.                */
  1047.   /*        Liest erst die Environmentvariable aus und wertet dann    */
  1048.   /*        argc/argv aus.                        */
  1049.   /*            argc    Direkt aus main() zu uebernehmen.    */
  1050.   /*            argv    Direkt aus main() zu uebernehmen.    */
  1051.   /*            envname    Name der Environmentvariable.        */
  1052.   /*            opt    Array der Parameterdefinitionen.    */
  1053.   /**********************************************************************/
  1054.  
  1055.  
  1056. BOOL GetOpt(int argc, char *argv[], char *envname, int interaktiv, struct Options opt[])
  1057. {
  1058.   BOOL error;
  1059.   int k, helpfeld;
  1060.   int frmwb = FALSE;
  1061.  
  1062.   FillLocHlpTxt(opt);
  1063.  
  1064.   /* Initialisiere 'len' Feld */
  1065.   for (k=0; opt[k].type != OPT_LAST_ENTRY; k++) {
  1066.     /* auf 0 ist alles sowieso schon gesetzt */
  1067.     if (opt[k].name != NULL) {
  1068.       opt[k].len = strlen(opt[k].name);
  1069.     }
  1070.     if (opt[k].abbrev != NULL) {
  1071.       opt[k].alen = strlen(opt[k].abbrev);
  1072.     }
  1073.     if (opt[k].type == OPT_HELP) {
  1074.       helpfeld = k;
  1075.     }
  1076.   }
  1077.  
  1078.   error = ScanEnvString(envname, opt);
  1079.   if (!error) {
  1080.     if (argc == 0) {
  1081.       frmwb = TRUE;
  1082.       interaktiv = FALSE;
  1083.       error = ScanWBArgs(opt);
  1084.     }
  1085.     else {
  1086.       error = ScanArgVektor(argc-1, &(argv[1]), opt);
  1087.     }
  1088.   }
  1089.   
  1090.   if (!frmwb && opt[helpfeld].is_given) {
  1091.     char *buf, *ptr, *p, *str;
  1092.  
  1093.     if ((buf = malloc(255)) != NULL) {        // ausnahmsweise kein xmalloc()
  1094.       error = FALSE;
  1095.       GetOptShortHelp("", 73, opt);
  1096.  
  1097.       if (interaktiv) {
  1098.         fprintf(stdout,GetTeXString(MSG_GETOPT_PRESS_RET));    /*hes: printf ist ok, wenn schon fgets verwendet wird*/
  1099.         ptr = fgets(buf, 254, stdin);
  1100.  
  1101.         if (ptr) {
  1102.           p = strrchr(ptr, '\n');
  1103.           if (p != NULL) *p = '\0';
  1104.         }
  1105.         else {
  1106.           buf[0] = '\0';
  1107.         }
  1108.  
  1109.         if (buf[0] != '\0') {
  1110.           opt[helpfeld].is_given = FALSE;
  1111.           *((long *)opt[helpfeld].result) = FALSE;
  1112.           str = strdup(ptr);        /* der Speicher muss fest bleiben! */
  1113.           error = ScanString(str, opt);
  1114.         }
  1115.       }
  1116.       free(buf);                // *kein* xfree()
  1117.     }
  1118.   }
  1119.  
  1120.   if (!error) {
  1121.     error = check_req_para(opt);
  1122.   }
  1123.  
  1124.   if (opt[helpfeld].is_given) {
  1125.     error = FALSE;    /* Bei Hilfe wird alles verziehen! */
  1126.   }
  1127.   return error;
  1128. }
  1129.  
  1130.  
  1131.   /**********************************************************************/
  1132.   /* StrOptiCmp: Vergleicht Option mit Parameter, wobei mindestens    */
  1133.   /*    soviele Buchstaben uebereinstimmen muessen, wie Grossbuchstaben    */
  1134.   /*    im Optionsnamen stehen.                        */
  1135.   /*    Ergebnis: 0 fuer Ok, sonst -1                    */
  1136.   /* 'rest' wird nur bei Uebereinstimmung mit anschliessendem '='    */
  1137.   /* gueltig und zeigt dann auf den Rest des Strings nach dem '='.    */
  1138.   /**********************************************************************/
  1139. static int StrOptiCmp(char *option, char *para, char **arg)
  1140. {
  1141.    /*char *start = para;*/
  1142.    for (; *option  != '\0' && isupper(*option); option++, para++) {
  1143.      if (*para == '\0' || *option != toupper(*para)) return -1;
  1144.    }
  1145.    for (; *para; para++, option++) {
  1146.      if (*option == '\0' || toupper(*para) != toupper(*option))
  1147.        if (*para == '=') {
  1148.          *arg = para+1;
  1149.          return 0;
  1150.        }
  1151.        else {
  1152.          return -1;
  1153.        }
  1154.    }
  1155.    return 0;
  1156. }
  1157.