Rewrote the key=value parser into something more sensible

Also updated the readme
This commit is contained in:
Andrei "Akari" Alexeyev 2017-03-16 08:33:38 +02:00
parent 455039edb4
commit 52286cac7f
3 changed files with 56 additions and 67 deletions

View file

@ -52,21 +52,18 @@ BGM (as well as SFX) may be in `.wav`, `.flac`, or `.ogg` format; additionally
you may try another formats such as `.mp3`, `.aiff`, `.mod`, `.xm`, etc. if
your build of SDL2_mixer supports these formats.
Complete music pack consists of 16 bgm\_\*.(ogg/wav/flac) files, where \* mean:
Complete music pack consists of 16 bgm\_\*.(ogg/wav/flac) files, where \* means:
```
credits BGM for credits screen
ending BGM for ending
gameover BGM for game over screen
menu BGM for menus (excluding in-game menu which pauses BGM)
stageN N=1..6, standard stage theme
stageNboss N=1..6, boss theme for a stage
credits BGM for credits screen
ending BGM for ending
gameover BGM for game over screen
menu BGM for menus (excluding in-game menu which pauses BGM)
stageN N=1..6, standard stage theme
stageNboss N=1..6, boss theme for a stage
```
If you want to specify stage/boss theme names to be shown during gameplay, you
may do it in `bgm/bgm.conf` file. This file contains some lines, each of which
consists of bgm filename (without extension), space of tab, and theme name.
No space/tab allowed either in beginning of line or BGM filenames listed in
this file; theme names may contain them.
may do it by editing the [`bgm/bgm.conf`](bgm/bgm.conf) file.
## Sound problems

View file

@ -365,9 +365,8 @@ static void config_set(const char *key, const char *val, void *data) {
void config_load(const char *filename) {
char *path = config_path(filename);
config_init();
parse_keyvalue_file_cb(path, config_set, NULL);
if(!parse_keyvalue_file_cb(path, config_set, NULL)) {
log_warn("Errors occured while parsing the configuration file");
}
free(path);
}
#undef SYNTAXERROR
#undef BUFFERERROR

View file

@ -258,65 +258,58 @@ char* read_all(const char *filename, int *outsize) {
}
bool parse_keyvalue_stream_cb(SDL_RWops *strm, KVCallback callback, void *data) {
const size_t bufsize = 128;
static const size_t bufsize = 256;
static const char separator[] = "= ";
#define SYNTAXERROR { log_warn("Syntax error on line %i, aborted! [%s:%i]", line, __FILE__, __LINE__); return false; }
#define BUFFERERROR { log_warn("String exceed the limit of %li, aborted! [%s:%i]", (long int)bufsize, __FILE__, __LINE__); return false; }
char buffer[bufsize];
int lineno = 0;
int errors = 0;
int i = 0, found, line = 0;
char c, buf[bufsize], key[bufsize], val[bufsize];
loopstart: while(SDL_RWgets(strm, buffer, bufsize)) {
char *ptr = buffer;
char *sep, *key, *val;
while(c = (char)SDL_ReadU8(strm)) {
if(c == '#' && !i) {
i = 0;
while((char)SDL_ReadU8(strm) != '\n');
} else if(c == ' ') {
if(!i) SYNTAXERROR
++lineno;
buf[i] = 0;
i = 0;
strcpy(key, buf);
found = 0;
while(c = (char)SDL_ReadU8(strm)) {
if(c == '=') {
if(++found > 1) SYNTAXERROR
} else if(c != ' ') {
if(!found || c == '\n') SYNTAXERROR
do {
if(c == '\n') {
if(!i) SYNTAXERROR
buf[i] = 0;
i = 0;
strcpy(val, buf);
found = 0;
++line;
callback(key, val, data);
break;
} else if(c != '\r') {
buf[i++] = c;
if(i == bufsize)
BUFFERERROR
}
} while(c = (char)SDL_ReadU8(strm));
break;
}
} if(found) SYNTAXERROR
} else {
buf[i++] = c;
if(i == bufsize)
BUFFERERROR
while(isspace(*ptr)) {
if(!*(++ptr)) {
// blank line
goto loopstart;
}
}
if(*ptr == '#') {
// comment
continue;
}
sep = strstr(ptr, separator);
if(!sep) {
++errors;
log_warn("Syntax error on line %i: missing separator", lineno);
continue;
}
// split it up
*sep = 0;
key = ptr;
val = sep + sizeof(separator) - 1;
// the separator may be preceeded by any kind of whitespace, so strip it from the key
while(isspace(*(ptr = strchr(key, 0) - 1))) {
*ptr = 0;
}
// strip any kind of line endings from the value
while(strchr("\r\n", *(ptr = strchr(val, 0) - 1))) {
*ptr = 0;
}
callback(key, val, data);
}
return true;
#undef SYNTAXERROR
#undef BUFFERERROR
return !errors;
}
bool parse_keyvalue_file_cb(const char *filename, KVCallback callback, void *data) {