/* $Id: parsefile.c,v 1.4 2002/03/02 21:02:21 sverrehu Exp $ */ /************************************************************************** * * FILE parsefile.c * MODULE OF Card game. * * WRITTEN BY Sverre H. Huseby * **************************************************************************/ #include #include #include #include #include #include #include "parsefile.h" /************************************************************************** * * * P R I V A T E D A T A * * * **************************************************************************/ static int lineNum; static const char *fname; /************************************************************************** * * * P R I V A T E F U N C T I O N S * * * **************************************************************************/ static void fpFree(int argc, char **argv) { int q; for (q = 0; q < argc; q++) free(argv[q]); free(argv); } static int isSplitChar(int c) { return (c == '=' || c == ':' || c == '#' || c == '"'); } static int fpSplitLine(const char *line, int *argc, char ***argv) { const char *from, *to; char *token; int tokenLen, addTo; *argc = 0; *argv = NULL; from = to = line; while (*from) { addTo = 0; while (isspace(*to)) ++to; from = to; if (*to == '#') { break; } else if (*to == '"') { ++to; from = to; while (*to && *to != '"') ++to; if (!*to) { msgError("unbalanced `\"' in `%s', line %d\n", fname, lineNum); fpFree(*argc, *argv); return -1; } addTo = 1; } else if (isSplitChar(*to)) { ++to; } else while (*to && !isspace(*to) && !isSplitChar(*to)) ++to; tokenLen = to - from; token = xmalloc(tokenLen + 1); memcpy(token, from, tokenLen); token[tokenLen] = '\0'; *argv = xrealloc(*argv, (*argc + 1) * sizeof(char *)); (*argv)[*argc] = token; ++*argc; to += addTo; from = to; } return 0; } static int pfReadLine(FILE *f, int (*func)(int argc, char *argv[])) { #define CHUNK_SIZE 10 int ret, c, len, argc; char *line, **argv; ++lineNum; len = 0; line = xmalloc(CHUNK_SIZE); *line = '\0'; while ((c = getc(f)) != '\n' && c != EOF) { if ((len + 1) % CHUNK_SIZE == 0) line = xrealloc(line, len + 1 + CHUNK_SIZE); line[len] = c; line[++len] = '\0'; } if (fpSplitLine(line, &argc, &argv) != 0) { free(line); return -1; } /* dont call handler function for empty lines */ ret = argc ? func(argc, argv) : 1; free(line); fpFree(argc, argv); return ret; } /************************************************************************** * * * P U B L I C F U N C T I O N S * * * **************************************************************************/ /*------------------------------------------------------------------------- * * NAME pfParseFile * * FUNCTION * * SYNOPSIS #include ".h" * void (void); * * INPUT * * OUTPUT * * RETURNS * * DESCRIPTION * */ int pfParseFile(const char *filename, int (*func)(int argc, char *argv[]), int noFileOk) { int ret = 0; FILE *f; if ((f = fopen(filename, "r")) == NULL) { if (noFileOk) return 0; msgPerror(filename); return -1; } msgVerbose(1, "reading `%s'\n", filename); fname = filename; lineNum = 0; while (!feof(f)) if ((ret = pfReadLine(f, func)) <= 0) break; if (ret > 0) ret = 0; fclose(f); return ret; } int pfStrCaseCmp(const char *s1, const char *s2) { int diff; do { diff = tolower(*s2++) - tolower(*s1); } while (!diff && *s1++); return diff; } int pfGetCurrentLine(void) { return lineNum; } const char * pfGetCurrentFile(void) { return fname; } int pfGetBooleanValue(const char *s) { if (pfStrCaseCmp(s, "yes") == 0 || pfStrCaseCmp(s, "on") == 0 || pfStrCaseCmp(s, "true") == 0 || pfStrCaseCmp(s, "1") == 0) return 1; if (pfStrCaseCmp(s, "no") == 0 || pfStrCaseCmp(s, "off") == 0 || pfStrCaseCmp(s, "false") == 0 || pfStrCaseCmp(s, "0") == 0) return 0; msgError("illegal boolean value `%s' in `%s', line %d\n", s, fname, lineNum); return -1; }