From: Mark Tearle Date: Sat, 27 Dec 2014 04:08:13 +0000 (+0800) Subject: Initial move to common config code directory X-Git-Url: https://git.ucc.asn.au/?p=tpg%2Fopendispense2.git;a=commitdiff_plain;h=6d657891a5410b7d93cc90f376a3ef27b72b20f6;hp=9efbcb2400665aa3f54e51486e805711bec07587 Initial move to common config code directory --- diff --git a/src/common/config.c b/src/common/config.c new file mode 100644 index 0000000..2328a88 --- /dev/null +++ b/src/common/config.c @@ -0,0 +1,242 @@ +/* + * OpenDispense 2 + * UCC (University [of WA] Computer Club) Electronic Accounting System + * + * config.c - Configuration file parser + * + * This file is licenced under the 3-clause BSD Licence. See the file + * COPYING for full details. + */ +#include +#include +#include "config.h" +#include +#include +#include + +#define MAX_LINE_LEN 128 + +// === TYPES === +typedef struct sConfigValue tConfigValue; +typedef struct sConfigKey tConfigKey; + +// === STRUCTURES === +struct sConfigValue +{ + tConfigValue *Next; + char Data[]; +}; + +struct sConfigKey +{ + tConfigKey *NextKey; + tConfigValue *FirstValue; + tConfigValue *LastValue; + int ValueCount; + char KeyName[]; +}; + +// === PROTOTYPES === +void Config_ParseFile(const char *Filename); +void Config_AddValue(const char *Key, const char *Value); +void Config_int_AddValueToKey(tConfigKey *Key, const char *Value); +tConfigKey *Config_int_GetKey(const char *KeyName, int bCreate); + int Config_GetValueCount(const char *KeyName); +const char *Config_GetValue(const char *KeyName, int Index); + +// === GLOBALS === +tConfigKey *gConfig; + +// === CODE === +void Config_ParseFile(const char *Filename) +{ + FILE *fp; + char line[MAX_LINE_LEN]; + regex_t regexp_option; + regex_t regexp_empty; + + CompileRegex(®exp_option, "^\\s*([^ \t]+)\\s+(.+)$", REG_EXTENDED); // + CompileRegex(®exp_empty, "^\\s*$", REG_EXTENDED); // + + fp = fopen(Filename, "r"); + if(!fp) { + fprintf(stderr, "Unable to open config file '%s'\n", Filename); + perror("Config_ParseFile"); + exit(-1); + } + + while( fgets(line, sizeof(line), fp) ) + { + regmatch_t matches[3]; + + // Trim and clean up + { + int i; + for( i = 0; line[i]; i ++ ) + { + if( line[i] == '#' || line[i] == ';' ) { + line[i] = '\0'; + break; + } + } + + while( i --, isspace(line[i]) ) + line[i] = 0; + } + + + if( regexec(®exp_empty, line, 1, matches, 0) == 0 ) + continue ; + + if( RunRegex(®exp_option, line, 3, matches, "Parsing configuration file") ) + { + fprintf(stderr, "Syntax error\n- %s", line); + continue ; + } + + line[matches[1].rm_eo] = 0; + line[matches[2].rm_eo] = 0; + + Config_AddValue(line + matches[1].rm_so, line + matches[2].rm_so); + } + + fclose(fp); + regfree(®exp_option); + regfree(®exp_empty); +} + +void Config_AddValue(const char *Key, const char *Value) +{ + tConfigKey *key; + + // Find key (creating if needed) + key = Config_int_GetKey(Key, 1); + + Config_int_AddValueToKey(key, Value); +} + +void Config_int_AddValueToKey(tConfigKey *Key, const char *Value) +{ + tConfigValue *newVal; + // Create value + newVal = malloc(sizeof(tConfigValue) + strlen(Value) + 1); + newVal->Next = NULL; + strcpy(newVal->Data, Value); + + #if 1 + // Add to the end of the key's list + if(Key->LastValue) + Key->LastValue->Next = newVal; + else + Key->FirstValue = newVal; + Key->LastValue = newVal; + #else + // Add to the start of the key's list + if(Key->LastValue == NULL) + Key->LastValue = newVal; + newVal->Next = Key->FirstValue; + Key->FirstValue = newVal; + #endif + Key->ValueCount ++; +} + +/** + * \brief + */ +tConfigKey *Config_int_GetKey(const char *KeyName, int bCreate) +{ + tConfigKey *key, *prev = NULL; + + // Search the sorted list of keys + for( key = gConfig; key; prev = key, key = key->NextKey ) + { + int cmp = strcmp(key->KeyName, KeyName); + if(cmp == 0) return key; // Equal, return + if(cmp > 0) break; // Greater, fast exit + } + + if( bCreate ) + { + // Create new key + key = malloc(sizeof(tConfigKey) + strlen(KeyName) + 1); + key->FirstValue = NULL; + key->LastValue = NULL; + key->ValueCount = 0; + strcpy(key->KeyName, KeyName); + + // Append + if(prev) { + key->NextKey = prev->NextKey; + prev->NextKey = key; + } + else { + key->NextKey = gConfig; + gConfig = key; + } + } + else + { + key = NULL; + } + + return key; +} + +int Config_GetValueCount(const char *KeyName) +{ + tConfigKey *key = Config_int_GetKey(KeyName, 0); + if(!key) return 0; + + return key->ValueCount; +} + +const char *Config_GetValue(const char *KeyName, int Index) +{ + tConfigKey *key; + tConfigValue *val; + + key = Config_int_GetKey(KeyName, 0); + if(!key) { + fprintf(stderr, "Unknown key '%s'\n", KeyName); + exit(1); + return NULL; + } + + if(Index < 0 || Index >= key->ValueCount) return NULL; + + for( val = key->FirstValue; Index && val; val = val->Next, Index -- ); + + ASSERT(val != NULL); + + return val->Data; +} + +int Config_GetValue_Bool(const char *KeyName, int Index) +{ + const char *val = Config_GetValue(KeyName, Index); + if(!val) return -1; + + if( atoi(val) == 1 ) return 1; + if( val[0] == '0' && val[1] == '\0' ) return 0; + + if( strcasecmp(val, "true") == 0 ) return 1; + if( strcasecmp(val, "false") == 0 ) return 0; + + if( strcasecmp(val, "yes") == 0 ) return 1; + if( strcasecmp(val, "no") == 0 ) return 0; + + return -1; +} + +int Config_GetValue_Int(const char *KeyName, int Index) +{ + int tmp; + const char *val = Config_GetValue(KeyName, Index); + if(!val) return -1; + + if( (tmp = atoi(val)) ) return tmp; + if( val[0] == '0' && val[1] == '\0' ) return 0; + + return -1; +} + diff --git a/src/common/config.h b/src/common/config.h new file mode 100644 index 0000000..1e7583e --- /dev/null +++ b/src/common/config.h @@ -0,0 +1,32 @@ +/* + * OpenDispense2 + * + * This code is published under the terms of the Acess licence. + * See the file COPYING for details. + * + * config.h - Config Header + */ +#ifndef _CONFIG_H_ +#define _CONFIG_H_ + +#include +extern void CompileRegex(regex_t *Regex, const char *Pattern, int Flags); +extern int RunRegex(regex_t *regex, const char *string, int nMatches, regmatch_t *matches, const char *errorMessage); + +// === HELPER MACROS === +#define _EXPSTR(x) #x +#define EXPSTR(x) _EXPSTR(x) + +#define ASSERT(cnd) do{if(!(cnd)){fprintf(stderr, "ASSERT failed at "__FILE__":"EXPSTR(__LINE__)" - "EXPSTR(cnd)"\n");exit(-1);}}while(0) + + + +// --- Config Database --- +extern void Config_ParseFile(const char *Filename); +extern void Config_AddValue(const char *Key, const char *Value); +extern int Config_GetValueCount(const char *KeyName); +extern const char *Config_GetValue(const char *KeyName, int Index); +extern int Config_GetValue_Bool(const char *KeyName, int Index); +extern int Config_GetValue_Int(const char *KeyName, int Index); + +#endif diff --git a/src/server/Makefile b/src/server/Makefile index f2ca968..dcd6f0d 100644 --- a/src/server/Makefile +++ b/src/server/Makefile @@ -29,10 +29,16 @@ install: $(BIN) $(BIN): $(OBJ) $(CC) -o $(BIN) $(OBJ) $(LINKFLAGS) -obj/%.o: %.c +obj/%.o: %.c @mkdir -p $(dir $@) $(CC) -c $< -o $@ $(CFLAGS) $(CPPFLAGS) @cpp $< -MM -MF $@.d + +obj/%.o: ../common/%.c + @mkdir -p $(dir $@) + $(CC) -c $< -o $@ $(CFLAGS) $(CPPFLAGS) + @cpp $< -MM -MF $@.d + -include $(DEPFILES) diff --git a/src/server/common.h b/src/server/common.h index 8a80497..1bdca84 100644 --- a/src/server/common.h +++ b/src/server/common.h @@ -17,12 +17,8 @@ #define DEFAULT_ITEM_FILE "/etc/opendispense/items.cfg" // === HELPER MACROS === -#define _EXPSTR(x) #x -#define EXPSTR(x) _EXPSTR(x) -#define UNUSED(var) unused__##var __attribute__((__unused__)) - -#define ASSERT(cnd) do{if(!(cnd)){fprintf(stderr, "ASSERT failed at "__FILE__":"EXPSTR(__LINE__)" - "EXPSTR(cnd)"\n");exit(-1);}}while(0) +#define UNUSED(var) unused__##var __attribute__((__unused__)) // === STRUCTURES === typedef struct sItem tItem; @@ -103,12 +99,4 @@ extern void Log_Info(const char *Format, ...); #define Debug_Notice(msg, v...) fprintf(stderr, "%08llun: "msg"\n", (unsigned long long)time(NULL) ,##v) #define Debug_Debug(msg, v...) fprintf(stderr, "%08llud: "msg"\n", (unsigned long long)time(NULL) ,##v) -// --- Config Database --- -extern void Config_ParseFile(const char *Filename); -extern void Config_AddValue(const char *Key, const char *Value); -extern int Config_GetValueCount(const char *KeyName); -extern const char *Config_GetValue(const char *KeyName, int Index); -extern int Config_GetValue_Bool(const char *KeyName, int Index); -extern int Config_GetValue_Int(const char *KeyName, int Index); - #endif diff --git a/src/server/config.c b/src/server/config.c deleted file mode 100644 index 4630b58..0000000 --- a/src/server/config.c +++ /dev/null @@ -1,242 +0,0 @@ -/* - * OpenDispense 2 - * UCC (University [of WA] Computer Club) Electronic Accounting System - * - * config.c - Configuration file parser - * - * This file is licenced under the 3-clause BSD Licence. See the file - * COPYING for full details. - */ -#include -#include -#include "common.h" -#include -#include -#include - -#define MAX_LINE_LEN 128 - -// === TYPES === -typedef struct sConfigValue tConfigValue; -typedef struct sConfigKey tConfigKey; - -// === STRUCTURES === -struct sConfigValue -{ - tConfigValue *Next; - char Data[]; -}; - -struct sConfigKey -{ - tConfigKey *NextKey; - tConfigValue *FirstValue; - tConfigValue *LastValue; - int ValueCount; - char KeyName[]; -}; - -// === PROTOTYPES === -void Config_ParseFile(const char *Filename); -void Config_AddValue(const char *Key, const char *Value); -void Config_int_AddValueToKey(tConfigKey *Key, const char *Value); -tConfigKey *Config_int_GetKey(const char *KeyName, int bCreate); - int Config_GetValueCount(const char *KeyName); -const char *Config_GetValue(const char *KeyName, int Index); - -// === GLOBALS === -tConfigKey *gConfig; - -// === CODE === -void Config_ParseFile(const char *Filename) -{ - FILE *fp; - char line[MAX_LINE_LEN]; - regex_t regexp_option; - regex_t regexp_empty; - - CompileRegex(®exp_option, "^\\s*([^ \t]+)\\s+(.+)$", REG_EXTENDED); // - CompileRegex(®exp_empty, "^\\s*$", REG_EXTENDED); // - - fp = fopen(Filename, "r"); - if(!fp) { - fprintf(stderr, "Unable to open config file '%s'\n", Filename); - perror("Config_ParseFile"); - exit(-1); - } - - while( fgets(line, sizeof(line), fp) ) - { - regmatch_t matches[3]; - - // Trim and clean up - { - int i; - for( i = 0; line[i]; i ++ ) - { - if( line[i] == '#' || line[i] == ';' ) { - line[i] = '\0'; - break; - } - } - - while( i --, isspace(line[i]) ) - line[i] = 0; - } - - - if( regexec(®exp_empty, line, 1, matches, 0) == 0 ) - continue ; - - if( RunRegex(®exp_option, line, 3, matches, "Parsing configuration file") ) - { - fprintf(stderr, "Syntax error\n- %s", line); - continue ; - } - - line[matches[1].rm_eo] = 0; - line[matches[2].rm_eo] = 0; - - Config_AddValue(line + matches[1].rm_so, line + matches[2].rm_so); - } - - fclose(fp); - regfree(®exp_option); - regfree(®exp_empty); -} - -void Config_AddValue(const char *Key, const char *Value) -{ - tConfigKey *key; - - // Find key (creating if needed) - key = Config_int_GetKey(Key, 1); - - Config_int_AddValueToKey(key, Value); -} - -void Config_int_AddValueToKey(tConfigKey *Key, const char *Value) -{ - tConfigValue *newVal; - // Create value - newVal = malloc(sizeof(tConfigValue) + strlen(Value) + 1); - newVal->Next = NULL; - strcpy(newVal->Data, Value); - - #if 1 - // Add to the end of the key's list - if(Key->LastValue) - Key->LastValue->Next = newVal; - else - Key->FirstValue = newVal; - Key->LastValue = newVal; - #else - // Add to the start of the key's list - if(Key->LastValue == NULL) - Key->LastValue = newVal; - newVal->Next = Key->FirstValue; - Key->FirstValue = newVal; - #endif - Key->ValueCount ++; -} - -/** - * \brief - */ -tConfigKey *Config_int_GetKey(const char *KeyName, int bCreate) -{ - tConfigKey *key, *prev = NULL; - - // Search the sorted list of keys - for( key = gConfig; key; prev = key, key = key->NextKey ) - { - int cmp = strcmp(key->KeyName, KeyName); - if(cmp == 0) return key; // Equal, return - if(cmp > 0) break; // Greater, fast exit - } - - if( bCreate ) - { - // Create new key - key = malloc(sizeof(tConfigKey) + strlen(KeyName) + 1); - key->FirstValue = NULL; - key->LastValue = NULL; - key->ValueCount = 0; - strcpy(key->KeyName, KeyName); - - // Append - if(prev) { - key->NextKey = prev->NextKey; - prev->NextKey = key; - } - else { - key->NextKey = gConfig; - gConfig = key; - } - } - else - { - key = NULL; - } - - return key; -} - -int Config_GetValueCount(const char *KeyName) -{ - tConfigKey *key = Config_int_GetKey(KeyName, 0); - if(!key) return 0; - - return key->ValueCount; -} - -const char *Config_GetValue(const char *KeyName, int Index) -{ - tConfigKey *key; - tConfigValue *val; - - key = Config_int_GetKey(KeyName, 0); - if(!key) { - fprintf(stderr, "Unknown key '%s'\n", KeyName); - exit(1); - return NULL; - } - - if(Index < 0 || Index >= key->ValueCount) return NULL; - - for( val = key->FirstValue; Index && val; val = val->Next, Index -- ); - - ASSERT(val != NULL); - - return val->Data; -} - -int Config_GetValue_Bool(const char *KeyName, int Index) -{ - const char *val = Config_GetValue(KeyName, Index); - if(!val) return -1; - - if( atoi(val) == 1 ) return 1; - if( val[0] == '0' && val[1] == '\0' ) return 0; - - if( strcasecmp(val, "true") == 0 ) return 1; - if( strcasecmp(val, "false") == 0 ) return 0; - - if( strcasecmp(val, "yes") == 0 ) return 1; - if( strcasecmp(val, "no") == 0 ) return 0; - - return -1; -} - -int Config_GetValue_Int(const char *KeyName, int Index) -{ - int tmp; - const char *val = Config_GetValue(KeyName, Index); - if(!val) return -1; - - if( (tmp = atoi(val)) ) return tmp; - if( val[0] == '0' && val[1] == '\0' ) return 0; - - return -1; -} - diff --git a/src/server/handler_coke.c b/src/server/handler_coke.c index ff051c8..b9a9cf3 100644 --- a/src/server/handler_coke.c +++ b/src/server/handler_coke.c @@ -11,6 +11,7 @@ * - Remember, the coke machine echoes your text back to you! */ #include "common.h" +#include "../common/config.h" #include #include #include diff --git a/src/server/main.c b/src/server/main.c index 284002b..c8be473 100644 --- a/src/server/main.c +++ b/src/server/main.c @@ -21,6 +21,7 @@ #include #include #include "../cokebank.h" +#include "../common/config.h" // === IMPORTS === extern void Init_Handlers(void); diff --git a/src/server/server.c b/src/server/server.c index c41cc2c..11846bb 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -10,6 +10,7 @@ #include #include #include "common.h" +#include "../common/config.h" #include #include #include