Category : C Source Code
Archive   : POLY3DS.ZIP
Filename : CONFIG.C

 
Output of file : CONFIG.C contained in archive : POLY3DS.ZIP
/*****************************************************************************
* 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
#include
#include
#include
#endif /* __MSDOS__ */

#include
#include
#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 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);
}

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], 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 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.\n", FileName);

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", (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 */


  3 Responses to “Category : C Source Code
Archive   : POLY3DS.ZIP
Filename : CONFIG.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/