home *** CD-ROM | disk | FTP | other *** search
/ Gold Fish 3 / goldfish_volume_3.bin / files / gfx / 3d / irit / misc_lib / config.c next >
Encoding:
C/C++ Source or Header  |  1995-02-12  |  13.3 KB  |  344 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 <string.h>
  20. #include "irit_sm.h"
  21. #include "config.h"
  22. #include "imalloc.h"
  23.  
  24. /* #define    DEBUG1   Uncomment it for simple test case (see config.bat). */
  25.  
  26. #define TAB    9
  27.  
  28. /* Some fatal errors that cause this module to die... */
  29. #define    ERR_ONLY_NAME        1
  30. #define    ERR_BOOL_EXPECTED    2
  31. #define    ERR_INT_EXPECTED    3
  32. #define    ERR_REAL_EXPECTED    4
  33. #define    ERR_STRING_EXPECTED    5
  34. #define    ERR_NOT_EXISTS        6
  35.  
  36. static char *ConfigPath;
  37.  
  38. static void UpdateVariable(char *Line,
  39.                ConfigStruct *SetUp,
  40.                int NumVar,
  41.                int LineCount);
  42. static void PrintConfigError(int ErrorNum, int LineCount);
  43. static FILE *FindFile(char *PrgmName, char *FileName);
  44.  
  45. /*****************************************************************************
  46. * DESCRIPTION:                                                               M
  47. * Routine to print the current configuration data structure contents.         M
  48. *                                                                            *
  49. * PARAMETERS:                                                                M
  50. *   SetUp:     Configuration data based.                                     M
  51. *   NumVar:    Number of entries on configuration data base.                 M
  52. *                                                                            *
  53. * RETURN VALUE:                                                              M
  54. *   void                                                                     M
  55. *                                                                            *
  56. * KEYWORDS:                                                                  M
  57. *   ConfigPrint, configuration, cfg files                                    M
  58. *****************************************************************************/
  59. void ConfigPrint(ConfigStruct *SetUp, int NumVar)
  60. {
  61.     int i;
  62.  
  63.     fprintf(stderr, "\nCurrent defaults:\n\n");
  64.  
  65.     for (i = 0; i < NumVar; i++) {
  66.     char VarName[LINE_LEN];
  67.  
  68.     if (SetUp[i].SomeInfo != NULL && strlen(SetUp[i].SomeInfo) > 0)
  69.         sprintf(VarName, "%s [%s]", SetUp[i].VarName, SetUp[i].SomeInfo);
  70.     else
  71.         sprintf(VarName, SetUp[i].VarName);
  72.  
  73.         switch (SetUp[i].VarType) {
  74.         case SU_BOOLEAN_TYPE:
  75.         if (* ((int *) SetUp[i].VarData))
  76.             fprintf(stderr, "\t%-20s = TRUE\n", VarName);
  77.         else
  78.             fprintf(stderr, "\t%-20s = FALSE\n", VarName);
  79.         break;
  80.         case SU_INTEGER_TYPE:
  81.         fprintf(stderr, "\t%-20s = %d\n", VarName,
  82.                     * ((int *) SetUp[i].VarData));
  83.         break;
  84.         case SU_REAL_TYPE:
  85.         fprintf(stderr, "\t%-20s = %g\n", VarName,
  86.                     * ((RealType *) SetUp[i].VarData));
  87.         break;
  88.         case SU_STRING_TYPE:
  89.         fprintf(stderr, "\t%-20s = \"%s\"\n", VarName,
  90.                     * ((char **) SetUp[i].VarData));
  91.         break;
  92.     }
  93.     }
  94. }
  95.  
  96. /*****************************************************************************
  97. * DESCRIPTION:                                                               M
  98. * Main routine of configuration file handling.                     M
  99. *  Gets the program name, PrgmName, and the configuration data base that     M
  100. *  defines the acceptable variables, Setup, with Numvarentries.             M
  101. *                                                                            *
  102. * PARAMETERS:                                                                M
  103. *   PrgmName:  Name of program that uses this data base.                     M
  104. *   SetUp:     Configuration data based.                                     M
  105. *   NumVar:    Number of entries on configuration data base.                 M
  106. *                                                                            *
  107. * RETURN VALUE:                                                              M
  108. *   void                                                                     M
  109. *                                                                            *
  110. * KEYWORDS:                                                                  M
  111. *   Config, configuration, cfg files                                         M
  112. *****************************************************************************/
  113. void Config(char *PrgmName, ConfigStruct *SetUp, int NumVar)
  114. {
  115.     int i, LineCount = 0;
  116.     char CfgName[PATH_NAME_LEN], Line[LINE_LEN_LONG], *Cptr;
  117.     FILE *f;
  118.  
  119.     i = strlen(PrgmName) - 1;             /* Skip the full path name: */
  120.     while (i && PrgmName[i] != '\\' && PrgmName[i] != '/'
  121.           && PrgmName[i] != ':') i--;
  122.     if (i)
  123.     i++;
  124.  
  125.     strcpy(CfgName, &PrgmName[i]);
  126.     Cptr = strchr(CfgName, '.');
  127.     if (Cptr != NULL)
  128.     *Cptr = 0;                     /* Delete old type. */
  129.     strcat(CfgName, ".cfg");            /* And add the config file type. */
  130.     if ((f = FindFile(PrgmName, CfgName)) == NULL)
  131.     return;                         /* Search via path var. */
  132.  
  133.     while (!feof(f)) {
  134.     fgets(Line, LINE_LEN_LONG, f);
  135.     LineCount++;
  136.  
  137.     i = 0;    /* Delete all the part after the ; (The comment) if was any. */
  138.     while (Line[i] != 0 && Line[i] != ';') i++;
  139.         if (Line[i])
  140.         Line[i] = 0;
  141.  
  142.     i = 0;               /* Now test if that line is empty or not: */
  143.     while (Line[i] != 0 && Line[i] <= ' ') i++;    /* Skip white spaces. */
  144.  
  145.     if (Line[i])
  146.         UpdateVariable(Line, SetUp, NumVar, LineCount);
  147.     }
  148.  
  149.     fclose(f);
  150. }
  151.  
  152. /*****************************************************************************
  153. * DESCRIPTION:                                                               *
  154. *   Routine to interpret the input Line and update the appropriate variable  *
  155. * in SetUp data structure. NumVar holds number of entries in SetUp Table.    *
  156. *                                                                            *
  157. * PARAMETERS:                                                                *
  158. *   Line:       Single line from a configuration file to interpret.          *
  159. *   SetUp:      Configuration data based.                                    *
  160. *   NumVar:     Number of entries on configuration data base.                *
  161. *   LineCount:  Line number.                                                 *
  162. *                                                                            *
  163. * RETURN VALUE:                                                              *
  164. *   void                                                                     *
  165. *****************************************************************************/
  166. static void UpdateVariable(char *Line,
  167.                ConfigStruct *SetUp,
  168.                int NumVar,
  169.                int LineCount)
  170. {
  171.     int i, j;
  172.     char VarName[LINE_LEN_LONG], VarData[LINE_LEN_LONG], *StrStart, *StrEnd,
  173.     *NewStr;
  174.     RealType Dummy;      /* Force linking of floating point scanf routines. */
  175.  
  176.     i = j = 0;
  177.     while (Line[i] > ' ') {              /* Copy the Variable name: */
  178.     VarName[i] = Line[i];
  179.     i++;
  180.     }
  181.     VarName[i] = 0;
  182.  
  183.     while (Line[i] != 0 && Line[i] <= ' ') i++;
  184.     if (Line[i] == 0)
  185.     PrintConfigError(ERR_ONLY_NAME, LineCount);
  186.  
  187.     while (Line[i] >= ' ' || Line[i] == TAB)      /* Copy the Variable data: */
  188.     VarData[j++] = Line[i++];
  189.     VarData[j] = 0;
  190.  
  191.     for (i = 0; i < NumVar; i++)
  192.     if (strcmp(VarName, SetUp[i].VarName) == 0)
  193.         switch (SetUp[i].VarType) {
  194.             case SU_BOOLEAN_TYPE:
  195.             if (strnicmp(VarData, "True", 4) == 0 ||
  196.             strnicmp(VarData, "False", 5) == 0)
  197.                 *((int *) SetUp[i].VarData) =
  198.                 (strnicmp (VarData, "True", 4) == 0);
  199.             else
  200.                 PrintConfigError(ERR_BOOL_EXPECTED, LineCount);
  201.             return;
  202.         case SU_INTEGER_TYPE:
  203.             if (sscanf(VarData, "%d", (int *) SetUp[i].VarData) != 1)
  204.                 PrintConfigError(ERR_INT_EXPECTED, LineCount);
  205.             return;
  206.         case SU_REAL_TYPE:
  207. #ifdef DOUBLE
  208.             if (sscanf(VarData, "%lf", &Dummy) != 1) {
  209. #else
  210.             if (sscanf(VarData, "%f", &Dummy) != 1) {
  211. #endif /* DOUBLE */
  212.             PrintConfigError(ERR_REAL_EXPECTED, LineCount);
  213.             return;
  214.             }
  215.             *((RealType *) SetUp[i].VarData) = Dummy;
  216.             return;
  217.         case SU_STRING_TYPE:
  218.             if ((StrStart = strchr(VarData, '"')) != NULL &&
  219.             (StrEnd = strrchr(VarData, '"')) != NULL &&
  220.             StrEnd != StrStart) {
  221.             NewStr = IritMalloc(1 + ((unsigned int)
  222.                             (StrEnd - StrStart)));
  223.             j = 0;
  224.             while (++StrStart != StrEnd)
  225.                 NewStr[j++] = *StrStart;
  226.             NewStr[j] = 0;
  227.             *((char **) SetUp[i].VarData) = NewStr;
  228.             }
  229.             else
  230.             PrintConfigError(ERR_STRING_EXPECTED, LineCount);
  231.             return;
  232.        }
  233.  
  234.     PrintConfigError(ERR_NOT_EXISTS, LineCount);
  235. }
  236.  
  237. /*****************************************************************************
  238. * DESCRIPTION:                                                               *
  239. *   Routine to print fatal configuration file error, and die.             *
  240. *                                                                            *
  241. * PARAMETERS:                                                                *
  242. *   ErrorNum:   Error number.                                                *
  243. *   LineCount:  Line where error had occured, in configuration file.         *
  244. *                                                                            *
  245. * RETURN VALUE:                                                              *
  246. *   void                                                                     *
  247. *****************************************************************************/
  248. static void PrintConfigError(int ErrorNum, int LineCount)
  249. {
  250.     fprintf(stderr, "Config. file error [%s line %d]: ",
  251.                         ConfigPath, LineCount);
  252.  
  253.     switch (ErrorNum) {
  254.     case ERR_ONLY_NAME:
  255.         fprintf(stderr, "Only Name found.\n");
  256.         break;
  257.         case ERR_BOOL_EXPECTED:
  258.         fprintf(stderr, "Boolean type expected.\n");
  259.         break;
  260.     case ERR_INT_EXPECTED:
  261.         fprintf(stderr, "Integer type expected.\n");
  262.         break;
  263.     case ERR_REAL_EXPECTED:
  264.         fprintf(stderr, "Real type expected.\n");
  265.         break;
  266.     case ERR_STRING_EXPECTED:
  267.         fprintf(stderr, "String (within \") type expected.\n");
  268.         break;
  269.     case ERR_NOT_EXISTS:
  270.         fprintf(stderr, "No such set up option.\n");
  271.         break;
  272.     }
  273.  
  274.     exit('c');
  275. }
  276.  
  277. /*****************************************************************************
  278. * DESCRIPTION:                                                               *
  279. *   Routine to search for a file and open it according to attribute at all   *
  280. * directories defined by PATH environment variable and current dir.         *
  281. *                                                                            *
  282. * PARAMETERS:                                                                *
  283. *   PrgmName:   Name of program that uses the configuration file.            *
  284. *   FileName:   Name of configuration file.                                  *
  285. *                                                                            *
  286. * RETURN VALUE:                                                              *
  287. *   FILE *:    Open file is found, NULL otherwise                            *
  288. *****************************************************************************/
  289. static FILE *FindFile(char *PrgmName, char *FileName)
  290. {
  291.     FILE *f;
  292.  
  293.     ConfigPath = searchpath(FileName);
  294.     if ((f = fopen(ConfigPath, "rt")) != NULL)
  295.     return f;
  296.  
  297.     fprintf(stderr, "%s: Warning: No config. file (%s) found.\n",
  298.         PrgmName, FileName);
  299.  
  300.     return NULL;
  301. }
  302.  
  303. #ifdef DEBUG_CONFIG
  304.  
  305. /*****************************************************************************
  306. * DESCRIPTION:                                                               *
  307. *   Simple test routine.                                                     *
  308. *****************************************************************************/
  309. void main(int argc, char **argv)
  310. {
  311.     static int Test1, Test2, Test3, Test4;
  312.     static double Test5, Test6;
  313.     static char *Test7, *Test8;
  314.  
  315.     ConfigStruct SetUp[] =
  316.     { { "TestOne",   (VoidPtr) &Test1, SU_BOOLEAN_TYPE },
  317.       { "TestTwo",   (VoidPtr) &Test2, SU_BOOLEAN_TYPE },
  318.       { "Test333",   (VoidPtr) &Test3, SU_INTEGER_TYPE },
  319.       { "Testing4",  (VoidPtr) &Test4, SU_INTEGER_TYPE },
  320.       { "TestReal5", (VoidPtr) &Test5, SU_REAL_TYPE },
  321.       { "TestReal6", (VoidPtr) &Test6, SU_REAL_TYPE },
  322.       { "String7",     (VoidPtr) &Test7, SU_STRING_TYPE },
  323.       { "String8",   (VoidPtr) &Test8, SU_STRING_TYPE } };
  324.  
  325.     Test1 = Test2 = Test3 = Test4 = 9999;
  326.     Test5 = Test6 = 0.9999;
  327.     Test7 = Test8 = NULL;
  328.  
  329.     printf("Before:\nTest1 = %d, Test2 = %d, Test3 = %d, Test4 = %d\n"
  330.         "Test5 = %lf, Test6 = %lf\nTest7 = \"%s\"\nTest8 = \"%s\"\n",
  331.         Test1, Test2, Test3, Test4, Test5, Test6, Test7, Test8);
  332.  
  333.     Config(*argv, SetUp, 8); /* Do it! */
  334.  
  335.     printf("After:\nTest1 = %d, Test2 = %d, Test3 = %d, Test4 = %d\n"
  336.         "Test5 = %lf, Test6 = %lf\nTest7 = \"%s\"\nTest8 = \"%s\"\n",
  337.         Test1, Test2, Test3, Test4, Test5, Test6, Test7, Test8);
  338.  
  339.     printf("\nConfigPrint prints:\n");
  340.     ConfigPrint(SetUp, 8);
  341. }
  342.  
  343. #endif /* DEBUG_CONFIG */
  344.