home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programming
/
powerprogramming1994.iso
/
progtool
/
irit
/
drawfuns.arc
/
CONFIG.C
next >
Wrap
C/C++ Source or Header
|
1989-07-30
|
10KB
|
274 lines
/*****************************************************************************
* 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 *
*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <alloc.h>
#include <conio.h>
#include <dir.h>
#include "Program.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:
fprintf(stderr, "\t%-20s = %lg\n", SetUp[i].VarName,
* ((double *) 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[FILE_NAME_LEN], Line[LINE_LEN], *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, 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);
}
}
/*****************************************************************************
* 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], VarData[LINE_LEN], *StrStart, *StrEnd, *NewStr;
double 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:
if (sscanf(VarData, "%lf", &Dummy) != 1) {
PrintConfigError(ERR_REAL_EXPECTED, LineCount);
return;
}
*((double *) 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;
}
MyExit('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, press anything to continue:",
FileName);
getch();
fprintf(stderr, "\n");
return (FILE *) NULL;
}
#ifdef DEBUG
/*****************************************************************************
* Exit routine *
*****************************************************************************/
void MyExit(int ExitCode)
{
exit(ExitCode);
}
/*****************************************************************************
* Simple test routine. use it with cnfgtest.bat which rename the program *
* name so that this module will recognize the appropriate configuration file *
*****************************************************************************/
void main(int argc, char **argv)
{
static int Test1, Test2, Test3, Test4;
static double Test5, Test6;
static char *Test7, *Test8;
ConfigStruct SetUp[] =
{ { "TestOne", (void *) &Test1, SU_BOOLEAN_TYPE },
{ "TestTwo", (void *) &Test2, SU_BOOLEAN_TYPE },
{ "Test333", (void *) &Test3, SU_INTEGER_TYPE },
{ "Testing4", (void *) &Test4, SU_INTEGER_TYPE },
{ "TestReal5", (void *) &Test5, SU_REAL_TYPE },
{ "TestReal6", (void *) &Test6, SU_REAL_TYPE },
{ "String7", (void *) &Test7, SU_STRING_TYPE },
{ "String8", (void *) &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