home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / EFFO / forum16.lzh / SOFTWARE / C / DIV_UTILITIES / if.c < prev    next >
Text File  |  1991-03-24  |  8KB  |  302 lines

  1. /*******************************************************************************
  2. | Programmbeschreibung:
  3. |   Testet eine angegebene Bedingung und fuehrt in Abhaengigkeit vom Resultat
  4. |   des Tests unterschiedliche Teile der Argumentliste als Shell-Kommandozei-
  5. |   len aus.
  6. +-------------------------------------------------------------------------------
  7. | Autoren:   Kuerzel   Name
  8. |            MM        Martin Moser, Jakob-Brucker-Str 15, 8950 Kaufbeuren
  9. +-------------------------------------------------------------------------------
  10. | Version   Datum      Kuerzel   Arbeitsbericht
  11. | 1.0       26.11.90   MM        Urversion
  12. +-------------------------------------------------------------------------------
  13. | Besonderheiten:
  14. |   Das Programm wurde auf moeglichst einfache Erweiterbarkeit ausgelegt.
  15. |   Eigene Tests lassen sich einbauen, indem ein entsprechender Initiali-
  16. |   sierungsaufruf in die Funktion 'initCL' eingebaut und eine ent-
  17. |   sprechende Testfunktion programmiert wird.
  18. *******************************************************************************/
  19.  
  20.  
  21. /********** include - Files **********/
  22. #include <stdio.h>
  23. #include <errno.h>
  24. #include "../DEFS/bool.h"
  25. #include <module.h>
  26. #include <strings.h>
  27.  
  28.  
  29. /********** interne Definitionen **********/
  30. #define EmptyList (struct c *) NULL
  31.  
  32. #define Any 0     /* loaded: der Modultyp ist unerheblich */
  33.  
  34.  
  35. /********** interne Makros **********/
  36. #define ErrExit(s, n)              exit(_errmsg(n, s))
  37. #define AddCond(f, t, a, p, d, cl) cl = addCond(f, t, a, p, d, cl)
  38.  
  39.  
  40. /********** interne Strukturen **********/
  41. struct c {                /* Sturuktur zur Beschreibung eines Tests */
  42.     bool     (*f)();                    /* Adresse der Testfunktion */
  43.     char     *t;                                  /* Name des Tests */
  44.     int      a;                            /* Stelligkeit des Tests */
  45.     char     *p,            /* Schema fuer Parameterliste des Tests */
  46.              *d;                      /* Kurzbeschreibung des Tests */
  47.     struct c *n;            /* Verkettungselement fuer Listenaufbau */
  48. };
  49.  
  50.  
  51. /********** Testfunktionen **********/
  52. /* > varVal: eine Umgebungsvariable auf einen Wert testen */
  53. bool varVal(argv, i)
  54. char *argv[];
  55. int  i;
  56. {
  57.     return(strcmp(getenv(argv[i + 1]), argv[i + 2]) == 0 ? 
  58.         True : False);
  59. }
  60.  
  61.  
  62. /* > loaded: testen, ob ein Modul bereits im Speicher ist */
  63. bool loaded(argv, i)
  64. char *argv[];
  65. int  i;
  66. {
  67.     mod_exec *m;
  68.     
  69.     if ((int) (m = modlink(argv[i + 1], Any)) != -1) {
  70.         munlink(m);
  71.         return(True);
  72.     } else
  73.         return(False);
  74. }
  75.  
  76.  
  77. /* > def: testen, ob eine Umgebungsvariable bereits definiert ist */
  78. bool def(argv, i)
  79. char *argv[];
  80. int  i;
  81. {
  82.     return(getenv(argv[i + 1]) == NULL ? False : True);
  83. }
  84.  
  85.  
  86. /********** interne Funktionen **********/
  87. /* > releaseCL: Liste der Tests wieder freigeben */
  88. void releaseCL(cl)
  89. struct c *cl;
  90. {
  91.     struct c *h;
  92.  
  93.     /* Alle Elemente der Liste freigeben */
  94.     while (cl != EmptyList) {
  95.         h  = cl;
  96.         cl = cl->n;
  97.         free(h);
  98.     }
  99. }
  100.  
  101.  
  102. /* >> addCond: Test in die Liste aufnehmen */
  103. struct c *addCond(f, t, a, p, d, cl)
  104. bool     (*f)();
  105. char     *t;
  106. int      a;
  107. char     *p, *d;
  108. struct c *cl;
  109. {
  110.     struct c *h = (struct c *) malloc(sizeof(struct c));
  111.  
  112.     /* Test, ob neues Listenelement erzeugt werden konnte */    
  113.     if (h == EmptyList) {
  114.         releaseCL(cl);
  115.         ErrExit("not enough memory for condition list", errno);
  116.     }
  117.     
  118.     /* Komponenten des neuen Listenelements besetzen */
  119.     h->f = f;
  120.     h->t = t;
  121.     h->a = a;
  122.     h->p = p;
  123.     h->d = d;
  124.     h->n = cl;
  125.  
  126.     return(h);
  127. }
  128.  
  129.  
  130. /* > initCL: Liste der zulaessigen Test aufbauen */
  131. struct c *initCL(cl)
  132. struct c *cl;
  133. {
  134.     AddCond(varVal, "varval", 2, "<var> <val>",
  135.         "true, if envir. variable <var> has value <val>", cl);
  136.         
  137.     AddCond(loaded, "loaded", 1, "<mod>",
  138.         "true, if module <mod> is already loaded", cl);
  139.         
  140.     AddCond(def, "def", 1, "<var>",
  141.         "true, if environment variable <var> is defined", cl);
  142.         
  143.     return(cl);
  144. }
  145.  
  146.  
  147. /* >> strEqu: Stringvergleich ohne Unterscheidung Gross/Kleinschrift */
  148. bool strEqu(s1, s2)
  149. char *s1, *s2;
  150. {
  151.     while (*s1 != '\0' && *s2 != '\0' && toupper(*s1) == toupper(*s2)) {
  152.         s1++;
  153.         s2++;
  154.     }
  155.     
  156.     return(toupper(*s1) == toupper(*s2));
  157. }
  158.  
  159.  
  160. /* > findArg: Ein Argument in der Kommandozeile suchen */
  161. int findArg(s, n, argc, argv)
  162. char *s;
  163. int  n, argc;
  164. char *argv[];
  165. {
  166.     while (n < argc && ! strEqu(s, argv[n]))
  167.         n++;
  168.         
  169.     return(n < argc ? n : -1);
  170. }
  171.     
  172.  
  173. /* > help: kurze Funktionsbeschreibung und Fehlertext ausgeben */
  174. void help(cl, s, n)
  175. struct c *cl;
  176. char     *s;
  177. int      n;
  178. {
  179.     struct c *h = cl;                              /* Hilfsvariable */
  180.  
  181.     /* Funktionsbeschreibung ausgeben */    
  182.     printf("Syntax: if [not] <cond> {<arg>} {<cmd1>} [else ");
  183.     printf("{<cmd2>}] endif\n");
  184.     printf("Function: if the [negated] condition <cond> depending ");
  185.     printf("on the arguments\n");
  186.     printf("          <arg> is true, then hand the commands <cmd1> ");
  187.     printf("to the shell for\n");
  188.     printf("          execution, else, if provided, <cmd2>.\n");
  189.  
  190.     /* Liste der vorhandenen Tests ausgeben */
  191.     printf("Conditions available:\n");
  192.     while (h != EmptyList) {
  193.         printf("    %-6.6s %-18.18s %s\n", h->t, h->p, h->d);
  194.         h = h->n;
  195.     } 
  196.     
  197.     printf("Options:\n");
  198.     printf("     (none)\n");
  199.     
  200.     /* Gegebenenfalls Fehlermeldung ausgeben und Programm beenden */
  201.     if (n > 0) {
  202.         releaseCL(cl);
  203.         ErrExit(s, n);
  204.     }
  205. }
  206.  
  207.  
  208. /* >> dispatchTest: den gewuenschten Test in der Liste suchen */
  209. struct c *dispatchTest(s, cl)
  210. char     *s;
  211. struct c *cl;
  212. {
  213.     struct c *h = cl;
  214.     
  215.     /* Test in Liste suchen */
  216.     while (h != EmptyList && ! strEqu(s, h->t))
  217.         h = h->n;
  218.         
  219.     if (h == EmptyList)
  220.         help(cl, "unknown test", 1);
  221.         
  222.     return(h);
  223. }
  224.  
  225.  
  226. /* >> execCmds: Argumente als Systemkommandos ausfuehren */
  227. void execCmds(argv, i, n)
  228. char *argv[];
  229. int  i, n;
  230. {
  231.     while (n-- > 0)
  232.         system(argv[i++]);
  233. }
  234.  
  235.  
  236. /* > evalCond: Bedingung auswerten */
  237. void evalCond(argc, argv, cl)
  238. int      argc;
  239. char     *argv[];
  240. struct c *cl;
  241. {
  242.     struct c *c;                /* Deskriptor des selektierten Tests */
  243.     int      i = 1,     /* Index fuer Argumente in der Kommandozeile */
  244.              j,                                      /* Hilfsgroesse */
  245.              m,      /* Anzahl der Kommandos zwischen Test und ENDIF */
  246.              n;                      /* bzw. zwischen ELSE und ENDIF */
  247.     bool     p = True;                /* positiven Test voraussetzen */
  248.     
  249.     /* Feststellen, ob negierter Test */
  250.     if (strEqu(argv[i], "not")) {
  251.         p = False;
  252.         i++;
  253.     }
  254.     
  255.     /* Art des Test auslesen und Anzahl der Argumente pruefen */
  256.     c = dispatchTest(argv[i], cl);
  257.     j = i + c->a + 1;
  258.     if (j >= argc)
  259.         help(cl, "wrong number of arguments", 1);
  260.  
  261.     /* ELSE und ENDIF suchen */
  262.     n = findArg("else", j, argc, argv);
  263.     m = findArg("endif", (n >= 0 ? n + 1 : j), argc, argv);
  264.     if (m < 0) 
  265.         help(cl, "missing 'endif' (maybe wrong number of arguments)", 1);
  266.         
  267.     /* Test ausfuehren */
  268.     if ((c->f)(argv, i) == p)
  269.         execCmds(argv, j, (n >= 0 ? n : m) - j);
  270.     else
  271.         if (n >= 0)
  272.             execCmds(argv, n + 1, m - n - 1);
  273. }
  274.     
  275.  
  276. /********** Hauptprogramm **********/
  277. main(argc, argv)
  278. int  argc;
  279. char *argv[];
  280. {
  281.     struct c *cl;                                /* Liste der Tests */
  282.     
  283.     /* Liste der Tests aufbauen */
  284.     cl = initCL(EmptyList);
  285.  
  286.     /* Funktionsbeschreibung ausgeben oder Test ausfuehren */
  287.     if (findArg("-?", 1, argc, argv) >= 1) 
  288.         help(cl, "", 0);
  289.     else if (argc < 3)
  290.         help(cl, "incorrect syntax", 1);
  291.     else 
  292.         evalCond(argc, argv, cl);
  293.  
  294.     /* Liste der Tests freigeben */
  295.     releaseCL(cl);
  296.     
  297.     exit(0);
  298. }
  299.  
  300.  
  301. /***************************** Ende des Files *********************************/
  302.