From e5a6f7533ac0d87aca1084509533211af42b92e0 Mon Sep 17 00:00:00 2001 From: DeaDDooMER Date: Fri, 3 Apr 2020 18:39:03 +0400 Subject: [PATCH] config: rewrite config parser --- src/config.c | 389 ++++++++++++++++++++++----------------------------- src/config.h | 4 +- src/files.c | 2 +- src/files.h | 2 +- 4 files changed, 173 insertions(+), 224 deletions(-) diff --git a/src/config.c b/src/config.c index c51e9ee..af211ae 100644 --- a/src/config.c +++ b/src/config.c @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include "map.h" #include "sound.h" #include "music.h" @@ -37,243 +39,192 @@ #include "input.h" #include "my.h" -enum{NONE,BYTE,WORD,DWORD,STRING,SW_ON,SW_OFF,FILES,KEY}; +enum {NONE, BYTE, WORD, DWORD, STRING, SW_ON, SW_OFF, FILES, KEY}; -typedef struct{ - char *par,*cfg; +typedef struct cfg_t { + char *par, *cfg; void *p; - byte t,o; -}cfg_t; - -byte cheat=0; -byte shot_vga=0; -char cd_path[128]=""; -char cfg_file[128]="default.cfg"; - -static char buf[256]; - -static cfg_t cfg[]={ - {"file",NULL,NULL,FILES,0}, - {"cheat",NULL,&cheat,SW_ON,0}, - {"vga","screenshot",&shot_vga,SW_ON,0}, - {"sndvol","sound_volume",&snd_vol,WORD,0}, - {"musvol","music_volume",&mus_vol,WORD,0}, -// {"fullscr","fullscreen",&fullscreen,SW_ON,0}, -// {"window",NULL,&fullscreen,SW_OFF,0}, - {NULL,"sky",&w_horiz,SW_ON,0}, - {"mon",NULL,&nomon,SW_OFF,0}, -// {"gamma","gamma",&gammaa,DWORD,0}, - {"warp",NULL,&_warp,BYTE,0}, - {"width","screen_width",&SCRW,DWORD,0}, - {"height","screen_height",&SCRH,DWORD,0}, - {NULL,"music_random",&music_random,SW_ON,0}, - {NULL,"music_time",&music_time,DWORD,0}, - {NULL,"music_fade",&music_fade,DWORD,0}, - {NULL,"pl1_left", &pl1.kl,KEY,0}, - {NULL,"pl1_right",&pl1.kr,KEY,0}, - {NULL,"pl1_up", &pl1.ku,KEY,0}, - {NULL,"pl1_down", &pl1.kd,KEY,0}, - {NULL,"pl1_jump", &pl1.kj,KEY,0}, - {NULL,"pl1_fire", &pl1.kf,KEY,0}, - {NULL,"pl1_next", &pl1.kwr,KEY,0}, - {NULL,"pl1_prev", &pl1.kwl,KEY,0}, - {NULL,"pl1_use", &pl1.kp,KEY,0}, - {NULL,"pl2_left", &pl2.kl,KEY,0}, - {NULL,"pl2_right",&pl2.kr,KEY,0}, - {NULL,"pl2_up", &pl2.ku,KEY,0}, - {NULL,"pl2_down", &pl2.kd,KEY,0}, - {NULL,"pl2_jump", &pl2.kj,KEY,0}, - {NULL,"pl2_fire", &pl2.kf,KEY,0}, - {NULL,"pl2_next", &pl2.kwr,KEY,0}, - {NULL,"pl2_prev", &pl2.kwl,KEY,0}, - {NULL,"pl2_use", &pl2.kp,KEY,0}, - {"config",NULL,cfg_file,STRING,0}, - {NULL,NULL,NULL,NONE,0} + byte t; +} cfg_t; + +byte cheat; +byte shot_vga; + +static FILE *f; +static int ch; + +static cfg_t cfg[] = { + {"file", NULL, NULL, FILES}, + {"cheat", NULL, &cheat, SW_ON}, + {"vga", "screenshot", &shot_vga, SW_ON}, + {"sndvol", "sound_volume", &snd_vol, WORD}, + {"musvol", "music_volume", &mus_vol, WORD}, +// {"fullscr", "fullscreen", &fullscreen, SW_ON}, +// {"window", NULL, &fullscreen, SW_OFF}, + {NULL, "sky", &w_horiz, SW_ON}, + {"mon", NULL, &nomon, SW_OFF}, +// {"gamma", "gamma", &gammaa, DWORD}, + {"warp", NULL, &_warp, BYTE}, + {"width", "screen_width", &SCRW, DWORD}, + {"height", "screen_height", &SCRH, DWORD}, + {NULL, "music_random", &music_random, SW_ON}, + {NULL, "music_time", &music_time, DWORD}, + {NULL, "music_fade", &music_fade, DWORD}, + {NULL, "pl1_left", &pl1.kl, KEY}, + {NULL, "pl1_right",&pl1.kr, KEY}, + {NULL, "pl1_up", &pl1.ku, KEY}, + {NULL, "pl1_down", &pl1.kd, KEY}, + {NULL, "pl1_jump", &pl1.kj, KEY}, + {NULL, "pl1_fire", &pl1.kf, KEY}, + {NULL, "pl1_next", &pl1.kwr, KEY}, + {NULL, "pl1_prev", &pl1.kwl, KEY}, + {NULL, "pl1_use", &pl1.kp, KEY}, + {NULL, "pl2_left", &pl2.kl, KEY}, + {NULL, "pl2_right",&pl2.kr, KEY}, + {NULL, "pl2_up", &pl2.ku, KEY}, + {NULL, "pl2_down", &pl2.kd, KEY}, + {NULL, "pl2_jump", &pl2.kj, KEY}, + {NULL, "pl2_fire", &pl2.kf, KEY}, + {NULL, "pl2_next", &pl2.kwr, KEY}, + {NULL, "pl2_prev", &pl2.kwl, KEY}, + {NULL, "pl2_use", &pl2.kp, KEY}, +// {"config", NULL, cfg_file, STRING}, + {NULL, NULL, NULL, NONE} // end }; -void CFG_args(int argc, char *argv[]) { - int j; - dword n; - char *s; +static int CFG_open_iterator (const char *name) { + assert(f == NULL); + f = fopen(name, "rb"); + if (f != NULL) { + ch = fgetc(f); + } + return f != NULL; +} - logo("CFG_args: проверка командной строки\n"); +static void CFG_skip_space (void) { + while (feof(f) == 0 && isspace(ch)) { + ch = fgetc(f); + } +} - int i; - char *pbuf = buf; - for (i=1;i0) if(cfg[j-1].t==SW_OFF && cfg[j-1].p==cfg[j].p) cfg[j-1].o=1; - break; - case SW_OFF: - *((byte *)cfg[j].p)=OFF; - if(cfg[j+1].t==SW_ON && cfg[j+1].p==cfg[j].p) cfg[j+1].o=1; - if(j>0) if(cfg[j-1].t==SW_ON && cfg[j-1].p==cfg[j].p) cfg[j-1].o=1; - break; - case FILES: - for(s=strtok(NULL," \r\n\t");s;s=strtok(NULL," \r\n\t")) { - if(*s=='/' || *s=='-') goto next; -#ifdef DEMO - logo(" %s НЕ подключен!\n",s); -#else - F_addwad(s); -#endif - }break; - default: - ERR_failinit("!!! Неизвестный тип в cfg !!!"); - } - cfg[j].o=1;break; +static int CFG_scan_iterator (char *key, int keylen, char *value, int valuelen) { + assert(key != NULL); + assert(keylen > 0); + assert(value != NULL); + assert(valuelen > 0); + int i; + int found = 0; + while (feof(f) == 0 && found == 0) { + CFG_skip_space(); + if (ch == ';') { + CFG_skip_line(); + } else if (feof(f) == 0) { + found = 1; + i = 0; + while (feof(f) == 0 && isspace(ch) == 0 && ch != '=') { + if (i < keylen - 1) { + key[i] = ch; + i += 1; + } + ch = fgetc(f); + } + key[i] = 0; + CFG_skip_space(); + if (feof(f) == 0 && ch == '=') { + ch = fgetc(f); + CFG_skip_space(); + } + i = 0; + while (feof(f) == 0 && ch != '\n' && ch != '\r') { + if (i < valuelen - 1) { + value[i] = ch; + i += 1; + } + ch = fgetc(f); + } + value[i] = 0; + CFG_skip_line(); } } + return found; } -void CFG_load(void) { - int j; - FILE *h; - dword n; - char s[128]; - char *p1,*p2; +static void CFG_close_iterator (void) { + assert(f != NULL); + fclose(f); + f = NULL; +} - char pc[50]; - char *e = getenv("HOME"); - strncpy(pc, e, 30); - strcpy(&pc[strlen(pc)], "/default.cfg"); - if (!fexists(pc)) { - strcpy(pc, "default.cfg"); - if (!fexists(pc)) { - strcpy(pc, "/usr/share/doom2d-rembo/default.cfg"); - if (!fexists(pc)) { - logo("default.cfg not found\n"); - return; - } - } +static int CFG_update_key (const char *key, const char *value, int iscfg) { +// logo("CFG_update_key: [%s] [%s] %i\n", key, value, iscfg); + int i = 0; + while (cfg[i].t != NONE && ((iscfg ? cfg[i].cfg : cfg[i].par) == NULL || strcasecmp(key, iscfg ? cfg[i].cfg : cfg[i].par) != 0)) { + i += 1; } + switch (cfg[i].t) { + case BYTE: *(byte*)cfg[i].p = atoi(value); break; + case WORD: *(word*)cfg[i].p = atoi(value); break; + case DWORD: *(dword*)cfg[i].p = atoi(value); break; + case STRING: cfg[i].p = strcpy(malloc(strlen(value) + 1), value); break; + case SW_ON: *(byte*)cfg[i].p = strcasecmp(value, "on") == 0 ? 1 : 0; break; + case SW_OFF: *(byte*)cfg[i].p = strcasecmp(value, "off") == 0 ? 0 : 1; break; + case FILES: F_addwad(value); break; + case KEY: *(int*)cfg[i].p = I_string_to_key(value); break; + case NONE: return 0; + default: assert(0); // unknown type -> something broken + } + return 1; +} - logo("CFG_load: загрузка конфигурации из %s\n",pc); - if((h=fopen(pc,"rb"))==NULL) { - perror("Cannot open file");return; +static int CFG_read_config (const char *name) { + char key[64]; + char value[64]; + assert(name != NULL); + if (CFG_open_iterator(name)) { + while (CFG_scan_iterator(key, 64, value, 64)) { + CFG_update_key(key, value, 1); + } + CFG_close_iterator(); + return 1; + } else { + return 0; } - while(!feof(h)) { - F_readstr(h,s,127); - if(*s==';' || s[1]==';') - continue; // comment - if(!(p1=strtok(s,"\r\n\t=;"))) - continue; //if(!(p1=strtok(s,"\r\n\t =;"))) continue; - if(!(p2=strtok(NULL,"\r\n\t=;"))) - continue;//if(!(p2=strtok(NULL,"\r\n\t =;"))) continue; - for(j=0;cfg[j].t;++j) { - if(cfg[j].cfg && !cfg[j].o) { - if(strcasecmp(p1,cfg[j].cfg)==0) { - switch(cfg[j].t) { - case BYTE: - n=strtol(p2,NULL,0); - *((byte *)cfg[j].p)=(byte)n; - break; - case WORD: - n=strtol(p2,NULL,0); - *((word *)cfg[j].p)=(word)n; - break; - case DWORD: - n=strtol(p2,NULL,0); - *((dword *)cfg[j].p)=n; - break; - case STRING: - strcpy((char *)cfg[j].p,p2); - break; - case SW_ON: - case SW_OFF: - if(strcasecmp(p2,"ON")==0) { - *((byte *)cfg[j].p)=ON; - break; - } - if(strcasecmp(p2,"OFF")==0) { - *((byte *)cfg[j].p)=OFF; - break; - } - *((byte *)cfg[j].p)=strtol(p2,NULL,0); - break; - case FILES: - break; - case KEY: - { - int k = I_string_to_key(p2); - if (k != KEY_UNKNOWN) { - *((int *)cfg[j].p)=k; - } else { - int i; - logo("Unknown key in cfg: %s=%s\n",p1,p2); - logo("List available key names:\n"); - for(i = 1; i <= KEY__LAST; i++) { - logo(" %s\n", I_key_to_string(i)); - } - } - } - break; - default: - ERR_failinit("!!! Неизвестный тип в cfg !!!"); - } // switch - break; - } // if - } // if - } // for - } // while - fclose(h); } -void CFG_save(void) { -/* - char s[140],str[140]; - char *p; - FILE *h,*oh; +void CFG_args (int argc, const char **argv) { + int i; + for (i = 1; i < argc; i++) { + if (argv[i][0] == '-' && argv[i][1] != 0) { + if (i + 1 >= argc) { + ERR_failinit("CFG_args: not enough arguments for parameter %s\n", argv[i]); + } else { + if (CFG_update_key(&argv[i][1], argv[i + 1], 0) != 0) { + ERR_failinit("CFG_args: unknown parameter %s\n", argv[i]); + } + i += 1; + } + } else { + ERR_failinit("CFG_args: something wrong here: %s\n", argv[i]); + } + } +} - remove("CONFIG.ZZZ"); - if(rename(cfg_file,"CONFIG.ZZZ")) return; - if(!(h=fopen("CONFIG.ZZZ","rt"))) - {rename("CONFIG.ZZZ",cfg_file);return;} - if(!(oh=fopen(cfg_file,"wt"))) - {fclose(h);rename("CONFIG.ZZZ",cfg_file);return;} - for(;;) { - if(!fgets(s,128,h)) break; - strcpy(str,s); - if(!(p=strtok(str,"\r\n\t =;"))) {fprintf(oh,"%s",s);continue;} - if(strcasecmp(p,"sound_volume")==0) - sprintf(s,"sound_volume=%d\n",snd_vol); - else if(strcasecmp(p,"music_volume")==0) - sprintf(s,"music_volume=%d\n",mus_vol); - else if(strcasecmp(p,"gamma")==0) - sprintf(s,"gamma=%d\n",gammaa); - else if(strcasecmp(p,"sound_interp")==0) - sprintf(s,"sound_interp=%s\n",s_interp?"on":"off"); - fprintf(oh,"%s",s); +void CFG_load (void) { + if (CFG_read_config("default.cfg") == 0) { + // TODO alt config at $HOME and system directories } - fclose(oh);fclose(h); - remove("CONFIG.ZZZ"); -*/ + CFG_read_config("user.cfg"); +} + +void CFG_save (void) { + // TODO } diff --git a/src/config.h b/src/config.h index 9601b89..72a5355 100644 --- a/src/config.h +++ b/src/config.h @@ -26,10 +26,8 @@ extern byte cheat; extern byte shot_vga; -extern char cd_path[128]; -extern char cfg_file[128]; -void CFG_args (int argc, char *argv[]); +void CFG_args (int argc, char **argv); void CFG_load (void); void CFG_save (void); diff --git a/src/files.c b/src/files.c index 5527171..f7037cf 100644 --- a/src/files.c +++ b/src/files.c @@ -155,7 +155,7 @@ void F_loadgame (int n) { } } -void F_addwad (char *fn) { +void F_addwad (const char *fn) { int i; for(i=0;i