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