X-Git-Url: https://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fconfig.c;h=e228309b2398b23f8a3f28d9d6dbad79157b7523;hb=4a0a2f1f4922d5346c4aee584e7d4a13803bffab;hp=0c5bc21868319394f1645d5d800437f29bcb6588;hpb=2bb81ea2565c3627c954b5c37326db89b0048472;p=flatwaifu.git diff --git a/src/config.c b/src/config.c index 0c5bc21..e228309 100644 --- a/src/config.c +++ b/src/config.c @@ -24,7 +24,8 @@ #include #include #include -#include +#include +#include #include "map.h" #include "sound.h" #include "music.h" @@ -35,261 +36,303 @@ #include "files.h" #include "render.h" #include "error.h" +#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 { + const char *cfg; void *p; - byte t,o; -}cfg_t; + byte t; +} cfg_t; -byte cheat=0; -byte shot_vga=0; -char cd_path[128]=""; -char cfg_file[128]="default.cfg"; +byte cheat; +byte shot_vga; -static char buf[256]; +static FILE *f; +static int ch; -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} +static const cfg_t arg[] = { + {"file", NULL, FILES}, + {"cheat", &cheat, SW_ON}, + {"vga", &shot_vga, SW_ON}, + {"sndvol", &snd_vol, WORD}, + {"musvol",&mus_vol, WORD}, +// {"fullscr", &fullscreen, SW_ON}, +// {"window", &fullscreen, SW_OFF}, + {"mon", &nomon, SW_OFF}, +// {"gamma", &gammaa, DWORD}, + {"warp", &_warp, BYTE}, + {"width", &SCRW, DWORD}, + {"height", &SCRH, DWORD}, +// {"config", NULL, cfg_file, STRING}, + {NULL, NULL, NONE} // end }; -void CFG_args(int argc, char *argv[]) { - int j; - dword n; - char *s; - - logo("CFG_args: проверка командной строки\n"); +static const cfg_t cfg[] = { + {"screenshot", &shot_vga, SW_ON}, + {"sound_volume", &snd_vol, WORD}, + {"music_volume", &mus_vol, WORD}, +// {"fullscreen", &fullscreen, SW_ON}, + {"sky", &w_horiz, SW_ON}, +// {"gamma", &gammaa, DWORD}, + {"screen_width", &SCRW, DWORD}, + {"screen_height", &SCRH, DWORD}, + {"music_random", &music_random, SW_ON}, + {"music_time", &music_time, DWORD}, + {"music_fade", &music_fade, DWORD}, + {"pl1_left", &pl1.kl, KEY}, + {"pl1_right",&pl1.kr, KEY}, + {"pl1_up", &pl1.ku, KEY}, + {"pl1_down", &pl1.kd, KEY}, + {"pl1_jump", &pl1.kj, KEY}, + {"pl1_fire", &pl1.kf, KEY}, + {"pl1_next", &pl1.kwr, KEY}, + {"pl1_prev", &pl1.kwl, KEY}, + {"pl1_use", &pl1.kp, KEY}, + {"pl2_left", &pl2.kl, KEY}, + {"pl2_right",&pl2.kr, KEY}, + {"pl2_up", &pl2.ku, KEY}, + {"pl2_down", &pl2.kd, KEY}, + {"pl2_jump", &pl2.kj, KEY}, + {"pl2_fire", &pl2.kf, KEY}, + {"pl2_next", &pl2.kwr, KEY}, + {"pl2_prev", &pl2.kwl, KEY}, + {"pl2_use", &pl2.kp, KEY}, + {NULL, NULL, NONE} // end +}; - 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_update_key (const char *key, const char *value, const cfg_t *cfg) { + const cfg_t *entry = CFG_find_entry(key, cfg); + if (entry != NULL) { + void *p = entry->p; + switch (entry->t) { + case BYTE: *(byte*)p = atoi(value); break; + case WORD: *(word*)p = atoi(value); break; + case DWORD: *(dword*)p = atoi(value); break; + case STRING: strcpy(p, value); break; // TODO fix this security problem + case SW_ON: *(byte*)p = strcasecmp(value, "on") == 0 ? 1 : 0; break; + case SW_OFF: *(byte*)p = strcasecmp(value, "off") == 0 ? 0 : 1; break; + case FILES: F_addwad(value); break; + case KEY: *(int*)p = I_string_to_key(value); break; + default: assert(0); // unknown type -> something broken } + return 1; + } else { + return 0; + } +} + +/* --- parser --- */ + +static int CFG_open_iterator (const char *name) { + assert(f == NULL); + f = fopen(name, "rb"); + if (f != NULL) { + ch = fgetc(f); + } + return f != NULL; +} + +static void CFG_skip_space (void) { + while (feof(f) == 0 && isspace(ch)) { + ch = fgetc(f); } } -static int get_key (char *name) { - int i; - for(i=1; i 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 0; + } + 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; - } - } +/* --- reader --- */ + +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, cfg); + } + CFG_close_iterator(); + return 1; + } else { + return 0; } +} - logo("CFG_load: загрузка конфигурации из %s\n",pc); - if((h=fopen(pc,"rb"))==NULL) { - perror("Cannot open file");return; +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], arg) != 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]); + } } - 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 = get_key(p2); - if (k) { - *((int *)cfg[j].p)=k; - } else { - logo("Unknown key in cfg: %s=%s\n",p1,p2); - logo("List available key names:\n"); - int i; - for(i=1; icfg; + if (key != NULL) { + switch (entry->t) { + case BYTE: + snprintf(buf, 64, "%i", *(byte*)entry->p); + CFG_write_key_value(f, key, buf); + break; + case WORD: + snprintf(buf, 64, "%i", *(word*)entry->p); + CFG_write_key_value(f, key, buf); + break; + case DWORD: + snprintf(buf, 64, "%i", *(dword*)entry->p); + CFG_write_key_value(f, key, buf); + break; + case STRING: + CFG_write_key_value(f, key, entry->p); + break; + case SW_ON: + case SW_OFF: + str = *(byte*)entry->p ? "on" : "off"; + CFG_write_key_value(f, key, str); + break; + case KEY: + str = I_key_to_string(*(int*)entry->p); + CFG_write_key_value(f, key, str); + break; + case FILES: return 1; // ignore + case NONE: return 0; // end + default: assert(0); // unknown type -> something broken + } } - fclose(oh);fclose(h); - remove("CONFIG.ZZZ"); -*/ + return entry->t == NONE ? 0 : 1; +} + +static int CFG_update_config (const char *old, const char *new, const cfg_t *cfg, const char *msg) { + assert(old != NULL); + assert(new != NULL); + assert(cfg != NULL); + char key[64]; + char value[64]; + FILE *nf = fopen(new, "wb"); + if (nf != NULL) { + if (msg != NULL) { + fwrite("; ", 2, 1, nf); + fwrite(msg, strlen(msg), 1, nf); + fwrite("\n", 1, 1, nf); + } + if (CFG_open_iterator(old)) { + while (CFG_scan_iterator(key, 64, value, 64)) { + if (CFG_find_entry(key, cfg) == NULL) { + CFG_write_key_value(nf, key, value); + } + } + CFG_close_iterator(); + } + int i = 0; + while (CFG_write_entry(nf, &cfg[i])) { + i++; + } + fclose(nf); + } + return nf != NULL; +} + +void CFG_save (void) { + CFG_update_config("doom2d.cfg", "doom2d.cfg", cfg, "generated by doom2d, do not modify"); + //CFG_update_config("doom2d.cfg", "doom2d.tmp", cfg, "temporary file"); + //CFG_update_config("doom2d.tmp", "doom2d.cfg", cfg, "generated by doom2d, do not modify"); + //remove("doom2d.tmp"); }