home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / IRIT / IRITS.ZIP / CONFIG.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-05-05  |  9.6 KB  |  276 lines

  1. /*****************************************************************************
  2. *   General routines to    configuration file reading:                 *
  3. * The config file (same name as program, type .cfg) must have th following   *
  4. * format: one variable setup per line, each line consists of two params.     *
  5. * The first is variable name, which is text string without white spaces.     *
  6. * The second param. contains its value, which might be boolean (TRUE/FALSE), *
  7. * integer, or real type.                             *
  8. *   The main routine should get a structure consists of 3 elements per         *
  9. * variable: the string to match, the variable to save the data read from     *
  10. * config file, and the type (Boolean, Integer, Real), for type checking.     *
  11. * See config.h for exact definition of this data structure.             *
  12. *                                         *
  13. * Version 0.2 - adding String Type.                         *
  14. *                                         *
  15. * Written by:  Gershon Elber                   Ver 0.2, Jan. 1989    *
  16. *****************************************************************************/
  17.  
  18. #ifdef __MSDOS__
  19. #include <stdlib.h>
  20. #include <alloc.h>
  21. #include <conio.h>
  22. #include <dir.h>
  23. #endif /* __MSDOS__ */
  24.  
  25. #include <stdio.h>
  26. #include <string.h>
  27. #include "program.h"
  28. #include "config.h"
  29.  
  30. /* #define    DEBUG   Uncomment it for simple test case (see config.bat). */
  31.  
  32. #define TAB    9
  33.  
  34. /* Some fatal errors that cause this module to die... */
  35. #define    ERR_ONLY_NAME        1
  36. #define    ERR_BOOL_EXPECTED    2
  37. #define    ERR_INT_EXPECTED    3
  38. #define    ERR_REAL_EXPECTED    4
  39. #define    ERR_STRING_EXPECTED    5
  40. #define    ERR_NOT_EXISTS        6
  41.  
  42. static char *ConfigPath;
  43.  
  44. static void UpdateVariable(char *Line, ConfigStruct *SetUp, int NumVar,
  45.                              int LineCount);
  46. static void PrintConfigError(int ErrorNum, int LineCount);
  47. static FILE *FindFile(char *FileName);
  48.  
  49. /*****************************************************************************
  50. * Routine to print the current configuration data structure contents.         *
  51. *****************************************************************************/
  52. void ConfigPrint(ConfigStruct *SetUp, int NumVar)
  53. {
  54.     int i;
  55.  
  56.     fprintf(stderr, "\nCurrent defaults:\n\n");
  57.  
  58.     for (i=0; i<NumVar; i++)
  59.         switch (SetUp[i].VarType) {
  60.         case SU_BOOLEAN_TYPE:
  61.         if (* ((int *) SetUp[i].VarData))
  62.              fprintf(stderr, "\t%-20s = TRUE\n", SetUp[i].VarName);
  63.         else fprintf(stderr, "\t%-20s = FALSE\n", SetUp[i].VarName);
  64.         break;
  65.         case SU_INTEGER_TYPE:
  66.         fprintf(stderr, "\t%-20s = %d\n", SetUp[i].VarName,
  67.                     * ((int *) SetUp[i].VarData));
  68.         break;
  69.         case SU_REAL_TYPE:
  70.         fprintf(stderr, "\t%-20s = %lg\n", SetUp[i].VarName,
  71.                     * ((double *) SetUp[i].VarData));
  72.         break;
  73.         case SU_STRING_TYPE:
  74.         fprintf(stderr, "\t%-20s = \"%s\"\n", SetUp[i].VarName,
  75.                     * ((char **) SetUp[i].VarData));
  76.         break;
  77.     }
  78. }
  79.  
  80. /*****************************************************************************
  81. * Main routine of config module. Gets the program name (it updates the type) *
  82. * PrgmName, and the structure defines the acceptable variables Setup.         *
  83. *****************************************************************************/
  84. void Config(char *PrgmName, ConfigStruct *SetUp, int NumVar)
  85. {
  86.     int i, LineCount = 0;
  87.     char CfgName[FILE_NAME_LEN], Line[LINE_LEN], *Cptr;
  88.     FILE *f;
  89.  
  90.     i = strlen(PrgmName) - 1;             /* Skip the full path name: */
  91.     while (i && PrgmName[i] != '\\' && PrgmName[i] != '/'
  92.           && PrgmName[i] != ':') i--;
  93.     if (i) i++;
  94.  
  95.     strcpy(CfgName, &PrgmName[i]);
  96.     Cptr = strchr(CfgName, '.');
  97.     if (Cptr != NULL) *Cptr = 0;             /* Delete old type. */
  98.     strcat(CfgName, ".cfg");            /* And add the config file type. */
  99.     if ((f = FindFile(CfgName)) == NULL) return;     /* Search via path var. */
  100.  
  101.     while (!feof(f)) {
  102.     fgets(Line, LINE_LEN, f);
  103.     LineCount++;
  104.  
  105.     i = 0;    /* Delete all the part after the ; (The comment) if was any. */
  106.     while (Line[i] != 0 && Line[i] != ';') i++;
  107.         if (Line[i]) Line[i] = 0;
  108.  
  109.     i = 0;               /* Now test if that line is empty or not: */
  110.     while (Line[i] != 0 && Line[i] <= ' ') i++;    /* Skip white spaces. */
  111.  
  112.     if (Line[i]) UpdateVariable(Line, SetUp, NumVar, LineCount);
  113.     }
  114.  
  115.     fclose(f);
  116. }
  117.  
  118. /*****************************************************************************
  119. *   Routine to interpret the input Line and update the appropriate variable  *
  120. * in SetUp data structure. NumVar holds number of entries in SetUp Table.    *
  121. *****************************************************************************/
  122. static void UpdateVariable(char *Line, ConfigStruct *SetUp, int NumVar,
  123.                              int LineCount)
  124. {
  125.     int i, j;
  126.     char VarName[LINE_LEN], VarData[LINE_LEN], *StrStart, *StrEnd, *NewStr;
  127.     double Dummy;      /* Force linking of floating point scanf routines. */
  128.  
  129.     i = j = 0;
  130.     while (Line[i] > ' ') {              /* Copy the Variable name: */
  131.     VarName[i] = Line[i];
  132.     i++;
  133.     }
  134.     VarName[i] = 0;
  135.  
  136.     while (Line[i] != 0 && Line[i] <= ' ') i++;
  137.     if (Line[i] == 0) PrintConfigError(ERR_ONLY_NAME, LineCount);
  138.  
  139.     while (Line[i] >= ' ' || Line[i] == TAB)      /* Copy the Variable data: */
  140.     VarData[j++] = Line[i++];
  141.     VarData[j] = 0;
  142.  
  143.     for (i=0; i<NumVar; i++) if (strcmp(VarName, SetUp[i].VarName) == 0)
  144.     switch (SetUp[i].VarType) {
  145.         case SU_BOOLEAN_TYPE:
  146.         if (strnicmp(VarData, "True", 4) == 0 ||
  147.             strnicmp(VarData, "False", 5) == 0)
  148.             *((int *) SetUp[i].VarData) =
  149.             (strnicmp (VarData, "True", 4) == 0);
  150.         else PrintConfigError(ERR_BOOL_EXPECTED, LineCount);
  151.         return;
  152.         case SU_INTEGER_TYPE:
  153.         if (sscanf(VarData, "%d", (int *) SetUp[i].VarData) != 1)
  154.             PrintConfigError(ERR_INT_EXPECTED, LineCount);
  155.         return;
  156.         case SU_REAL_TYPE:
  157.         if (sscanf(VarData, "%lf", &Dummy) != 1) {
  158.             PrintConfigError(ERR_REAL_EXPECTED, LineCount);
  159.             return;
  160.         }
  161.         *((double *) SetUp[i].VarData) = Dummy;
  162.         return;
  163.         case SU_STRING_TYPE:
  164.         if ((StrStart = strchr(VarData, '"')) != NULL &&
  165.             (StrEnd = strrchr(VarData, '"')) != NULL &&
  166.             StrEnd != StrStart) {
  167.             NewStr = malloc(1 + ((unsigned int) (StrEnd - StrStart)));
  168.             j = 0;
  169.             while (++StrStart != StrEnd) NewStr[j++] = *StrStart;
  170.             NewStr[j] = 0;
  171.             *((char **) SetUp[i].VarData) = NewStr;
  172.         }
  173.         else PrintConfigError(ERR_STRING_EXPECTED, LineCount);
  174.         return;
  175.     }
  176.     PrintConfigError(ERR_NOT_EXISTS, LineCount);
  177. }
  178.  
  179. /*****************************************************************************
  180. *   Routine to print fatal configuration file error, and die.             *
  181. *****************************************************************************/
  182. static void PrintConfigError(int ErrorNum, int LineCount)
  183. {
  184.     fprintf(stderr, "Config. file error [%s line %d]: ",
  185.                         ConfigPath, LineCount);
  186.  
  187.     switch (ErrorNum) {
  188.     case ERR_ONLY_NAME:
  189.         fprintf(stderr, "Only Name found\n");
  190.         break;
  191.         case ERR_BOOL_EXPECTED:
  192.         fprintf(stderr, "Boolean type expected\n");
  193.         break;
  194.     case ERR_INT_EXPECTED:
  195.         fprintf(stderr, "Integer type expected\n");
  196.         break;
  197.     case ERR_REAL_EXPECTED:
  198.         fprintf(stderr, "Real type expected\n");
  199.         break;
  200.     case ERR_STRING_EXPECTED:
  201.         fprintf(stderr, "String (within \") type expected\n");
  202.         break;
  203.     case ERR_NOT_EXISTS:
  204.         fprintf(stderr, "No such set up option\n");
  205.         break;
  206.     }
  207.  
  208.     MyExit('c');
  209. }
  210.  
  211. /*****************************************************************************
  212. *   Routine to search for a file and open it according to attribute at all   *
  213. * directories defined by PATH environment variable and current dir.         *
  214. *****************************************************************************/
  215. static FILE *FindFile(char *FileName)
  216. {
  217.     FILE *f;
  218.  
  219.     ConfigPath = searchpath(FileName);
  220.     if ((f = fopen(ConfigPath, "rt")) != NULL) return f;
  221.  
  222.     fprintf(stderr, "Warning: No config. file (%s) found.\n", FileName);
  223.  
  224.     return (FILE *) NULL;
  225. }
  226.  
  227. #ifdef DEBUG
  228.  
  229. /*****************************************************************************
  230. *   Exit routine                                 *
  231. *****************************************************************************/
  232. void MyExit(int ExitCode)
  233. {
  234.     exit(ExitCode);
  235. }
  236.  
  237. /*****************************************************************************
  238. *   Simple test routine. use it with cnfgtest.bat which rename the program   *
  239. * name so that this module will recognize the appropriate configuration file *
  240. *****************************************************************************/
  241. void main(int argc, char **argv)
  242. {
  243.     static int Test1, Test2, Test3, Test4;
  244.     static double Test5, Test6;
  245.     static char *Test7, *Test8;
  246.  
  247.     ConfigStruct SetUp[] =
  248.     { { "TestOne",   (VoidPtr) &Test1, SU_BOOLEAN_TYPE },
  249.       { "TestTwo",   (VoidPtr) &Test2, SU_BOOLEAN_TYPE },
  250.       { "Test333",   (VoidPtr) &Test3, SU_INTEGER_TYPE },
  251.       { "Testing4",  (VoidPtr) &Test4, SU_INTEGER_TYPE },
  252.       { "TestReal5", (VoidPtr) &Test5, SU_REAL_TYPE },
  253.       { "TestReal6", (VoidPtr) &Test6, SU_REAL_TYPE },
  254.       { "String7",     (VoidPtr) &Test7, SU_STRING_TYPE },
  255.       { "String8",   (VoidPtr) &Test8, SU_STRING_TYPE } };
  256.  
  257.     Test1 = Test2 = Test3 = Test4 = 9999;
  258.     Test5 = Test6 = 0.9999;
  259.     Test7 = Test8 = NULL;
  260.  
  261.     printf("Before:\nTest1 = %d, Test2 = %d, Test3 = %d, Test4 = %d\n"
  262.         "Test5 = %lf, Test6 = %lf\nTest7 = \"%s\"\nTest8 = \"%s\"\n",
  263.         Test1, Test2, Test3, Test4, Test5, Test6, Test7, Test8);
  264.  
  265.     Config(*argv, SetUp, 8); /* Do it! */
  266.  
  267.     printf("After:\nTest1 = %d, Test2 = %d, Test3 = %d, Test4 = %d\n"
  268.         "Test5 = %lf, Test6 = %lf\nTest7 = \"%s\"\nTest8 = \"%s\"\n",
  269.         Test1, Test2, Test3, Test4, Test5, Test6, Test7, Test8);
  270.  
  271.     printf("\nConfigPrint prints:\n");
  272.     ConfigPrint(SetUp, 8);
  273. }
  274.  
  275. #endif /* DEBUG */
  276.