home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************
- * General routines to configuration file reading: *
- * The config file (same name as program, type .cfg) must have th following *
- * format: one variable setup per line, each line consists of two params. *
- * The first is variable name, which is text string without white spaces. *
- * The second param. contains its value, which might be boolean (TRUE/FALSE), *
- * integer, or real type. *
- * The main routine should get a structure consists of 3 elements per *
- * variable: the string to match, the variable to save the data read from *
- * config file, and the type (Boolean, Integer, Real), for type checking. *
- * See config.h for exact definition of this data structure. *
- * *
- * Version 0.2 - adding String Type. *
- * *
- * Written by: Gershon Elber Ver 0.2, Jan. 1989 *
- *****************************************************************************/
-
- #ifdef __MSDOS__
- #include <stdlib.h>
- #include <alloc.h>
- #include <conio.h>
- #include <dir.h>
- #endif /* __MSDOS__ */
-
- #include <stdio.h>
- #include <string.h>
- #include "irit_sm.h"
- #include "config.h"
-
- /* #define DEBUG Uncomment it for simple test case (see config.bat). */
-
- #define TAB 9
-
- /* Some fatal errors that cause this module to die... */
- #define ERR_ONLY_NAME 1
- #define ERR_BOOL_EXPECTED 2
- #define ERR_INT_EXPECTED 3
- #define ERR_REAL_EXPECTED 4
- #define ERR_STRING_EXPECTED 5
- #define ERR_NOT_EXISTS 6
-
- static char *ConfigPath;
-
- static void UpdateVariable(char *Line, ConfigStruct *SetUp, int NumVar,
- int LineCount);
- static void PrintConfigError(int ErrorNum, int LineCount);
- static FILE *FindFile(char *FileName);
-
- /*****************************************************************************
- * Routine to print the current configuration data structure contents. *
- *****************************************************************************/
- void ConfigPrint(ConfigStruct *SetUp, int NumVar)
- {
- int i;
-
- fprintf(stderr, "\nCurrent defaults:\n\n");
-
- for (i = 0; i < NumVar; i++)
- switch (SetUp[i].VarType) {
- case SU_BOOLEAN_TYPE:
- if (* ((int *) SetUp[i].VarData))
- fprintf(stderr, "\t%-20s = TRUE\n", SetUp[i].VarName);
- else
- fprintf(stderr, "\t%-20s = FALSE\n", SetUp[i].VarName);
- break;
- case SU_INTEGER_TYPE:
- fprintf(stderr, "\t%-20s = %d\n", SetUp[i].VarName,
- * ((int *) SetUp[i].VarData));
- break;
- case SU_REAL_TYPE:
- #ifdef __MSDOS__
- fprintf(stderr, "\t%-20s = %g\n", SetUp[i].VarName,
- #else
- fprintf(stderr, "\t%-20s = %lg\n", SetUp[i].VarName,
- #endif /* __MSDOS__ */
- * ((RealType *) SetUp[i].VarData));
- break;
- case SU_STRING_TYPE:
- fprintf(stderr, "\t%-20s = \"%s\"\n", SetUp[i].VarName,
- * ((char **) SetUp[i].VarData));
- break;
- }
- }
-
- /*****************************************************************************
- * Main routine of config module. Gets the program name (it updates the type) *
- * PrgmName, and the structure defines the acceptable variables Setup. *
- *****************************************************************************/
- void Config(char *PrgmName, ConfigStruct *SetUp, int NumVar)
- {
- int i, LineCount = 0;
- char CfgName[PATH_NAME_LEN], Line[LINE_LEN_LONG], *Cptr;
- FILE *f;
-
- i = strlen(PrgmName) - 1; /* Skip the full path name: */
- while (i && PrgmName[i] != '\\' && PrgmName[i] != '/'
- && PrgmName[i] != ':') i--;
- if (i) i++;
-
- strcpy(CfgName, &PrgmName[i]);
- Cptr = strchr(CfgName, '.');
- if (Cptr != NULL) *Cptr = 0; /* Delete old type. */
- strcat(CfgName, ".cfg"); /* And add the config file type. */
- if ((f = FindFile(CfgName)) == NULL) return; /* Search via path var. */
-
- while (!feof(f)) {
- fgets(Line, LINE_LEN_LONG, f);
- LineCount++;
-
- i = 0; /* Delete all the part after the ; (The comment) if was any. */
- while (Line[i] != 0 && Line[i] != ';') i++;
- if (Line[i]) Line[i] = 0;
-
- i = 0; /* Now test if that line is empty or not: */
- while (Line[i] != 0 && Line[i] <= ' ') i++; /* Skip white spaces. */
-
- if (Line[i]) UpdateVariable(Line, SetUp, NumVar, LineCount);
- }
-
- fclose(f);
- }
-
- /*****************************************************************************
- * Routine to interpret the input Line and update the appropriate variable *
- * in SetUp data structure. NumVar holds number of entries in SetUp Table. *
- *****************************************************************************/
- static void UpdateVariable(char *Line, ConfigStruct *SetUp, int NumVar,
- int LineCount)
- {
- int i, j;
- char VarName[LINE_LEN_LONG], VarData[LINE_LEN_LONG], *StrStart, *StrEnd,
- *NewStr;
- RealType Dummy; /* Force linking of floating point scanf routines. */
-
- i = j = 0;
- while (Line[i] > ' ') { /* Copy the Variable name: */
- VarName[i] = Line[i];
- i++;
- }
- VarName[i] = 0;
-
- while (Line[i] != 0 && Line[i] <= ' ') i++;
- if (Line[i] == 0) PrintConfigError(ERR_ONLY_NAME, LineCount);
-
- while (Line[i] >= ' ' || Line[i] == TAB) /* Copy the Variable data: */
- VarData[j++] = Line[i++];
- VarData[j] = 0;
-
- for (i = 0; i < NumVar; i++) if (strcmp(VarName, SetUp[i].VarName) == 0)
- switch (SetUp[i].VarType) {
- case SU_BOOLEAN_TYPE:
- if (strnicmp(VarData, "True", 4) == 0 ||
- strnicmp(VarData, "False", 5) == 0)
- *((int *) SetUp[i].VarData) =
- (strnicmp (VarData, "True", 4) == 0);
- else
- PrintConfigError(ERR_BOOL_EXPECTED, LineCount);
- return;
- case SU_INTEGER_TYPE:
- if (sscanf(VarData, "%d", (int *) SetUp[i].VarData) != 1)
- PrintConfigError(ERR_INT_EXPECTED, LineCount);
- return;
- case SU_REAL_TYPE:
- #ifdef __MSDOS__
- if (sscanf(VarData, "%f", &Dummy) != 1) {
- #else
- if (sscanf(VarData, "%lf", &Dummy) != 1) {
- #endif /* __MSDOS__ */
- PrintConfigError(ERR_REAL_EXPECTED, LineCount);
- return;
- }
- *((RealType *) SetUp[i].VarData) = Dummy;
- return;
- case SU_STRING_TYPE:
- if ((StrStart = strchr(VarData, '"')) != NULL &&
- (StrEnd = strrchr(VarData, '"')) != NULL &&
- StrEnd != StrStart) {
- NewStr = malloc(1 + ((unsigned int) (StrEnd - StrStart)));
- j = 0;
- while (++StrStart != StrEnd) NewStr[j++] = *StrStart;
- NewStr[j] = 0;
- *((char **) SetUp[i].VarData) = NewStr;
- }
- else
- PrintConfigError(ERR_STRING_EXPECTED, LineCount);
- return;
- }
- PrintConfigError(ERR_NOT_EXISTS, LineCount);
- }
-
- /*****************************************************************************
- * Routine to print fatal configuration file error, and die. *
- *****************************************************************************/
- static void PrintConfigError(int ErrorNum, int LineCount)
- {
- fprintf(stderr, "Config. file error [%s line %d]: ",
- ConfigPath, LineCount);
-
- switch (ErrorNum) {
- case ERR_ONLY_NAME:
- fprintf(stderr, "Only Name found.\n");
- break;
- case ERR_BOOL_EXPECTED:
- fprintf(stderr, "Boolean type expected.\n");
- break;
- case ERR_INT_EXPECTED:
- fprintf(stderr, "Integer type expected.\n");
- break;
- case ERR_REAL_EXPECTED:
- fprintf(stderr, "Real type expected.\n");
- break;
- case ERR_STRING_EXPECTED:
- fprintf(stderr, "String (within \") type expected.\n");
- break;
- case ERR_NOT_EXISTS:
- fprintf(stderr, "No such set up option.\n");
- break;
- }
-
- exit('c');
- }
-
- /*****************************************************************************
- * Routine to search for a file and open it according to attribute at all *
- * directories defined by PATH environment variable and current dir. *
- *****************************************************************************/
- static FILE *FindFile(char *FileName)
- {
- FILE *f;
-
- ConfigPath = searchpath(FileName);
- if ((f = fopen(ConfigPath, "rt")) != NULL) return f;
-
- fprintf(stderr, "Warning: No config. file (%s) found.\n", FileName);
-
- return NULL;
- }
-
- #ifdef DEBUG
-
- /*****************************************************************************
- * Simple test routine. use it with cnfgtest.bat which rename the program *
- * name so that this module will recognize the appropriate configuration file *
- * The arguments below assume double or non MSDOS system!. *
- *****************************************************************************/
- void main(int argc, char **argv)
- {
- static int Test1, Test2, Test3, Test4;
- static double Test5, Test6;
- static char *Test7, *Test8;
-
- ConfigStruct SetUp[] =
- { { "TestOne", (VoidPtr) &Test1, SU_BOOLEAN_TYPE },
- { "TestTwo", (VoidPtr) &Test2, SU_BOOLEAN_TYPE },
- { "Test333", (VoidPtr) &Test3, SU_INTEGER_TYPE },
- { "Testing4", (VoidPtr) &Test4, SU_INTEGER_TYPE },
- { "TestReal5", (VoidPtr) &Test5, SU_REAL_TYPE },
- { "TestReal6", (VoidPtr) &Test6, SU_REAL_TYPE },
- { "String7", (VoidPtr) &Test7, SU_STRING_TYPE },
- { "String8", (VoidPtr) &Test8, SU_STRING_TYPE } };
-
- Test1 = Test2 = Test3 = Test4 = 9999;
- Test5 = Test6 = 0.9999;
- Test7 = Test8 = NULL;
-
- printf("Before:\nTest1 = %d, Test2 = %d, Test3 = %d, Test4 = %d\n"
- "Test5 = %lf, Test6 = %lf\nTest7 = \"%s\"\nTest8 = \"%s\"\n",
- Test1, Test2, Test3, Test4, Test5, Test6, Test7, Test8);
-
- Config(*argv, SetUp, 8); /* Do it! */
-
- printf("After:\nTest1 = %d, Test2 = %d, Test3 = %d, Test4 = %d\n"
- "Test5 = %lf, Test6 = %lf\nTest7 = \"%s\"\nTest8 = \"%s\"\n",
- Test1, Test2, Test3, Test4, Test5, Test6, Test7, Test8);
-
- printf("\nConfigPrint prints:\n");
- ConfigPrint(SetUp, 8);
- }
-
- #endif /* DEBUG */
-