diff options
author | goodale <goodale@17b73243-c579-4c4c-a9d2-2d5706c11dac> | 1999-01-12 15:47:18 +0000 |
---|---|---|
committer | goodale <goodale@17b73243-c579-4c4c-a9d2-2d5706c11dac> | 1999-01-12 15:47:18 +0000 |
commit | 391b49d22eee294fc82feafa1e6184f152642fdd (patch) | |
tree | 0682a95e393f02c123fee1c432035c6454c96d8b /src/util/ParseFile.c | |
parent | e78e35dc287466b7d4bdd78bedb5d14f0558093a (diff) |
Routine to parse a parameter file and pass the resulting tokens to
an arbitrary function.
Nicked from Paul's Cactus parser.
Tom
git-svn-id: http://svn.cactuscode.org/flesh/trunk@46 17b73243-c579-4c4c-a9d2-2d5706c11dac
Diffstat (limited to 'src/util/ParseFile.c')
-rw-r--r-- | src/util/ParseFile.c | 402 |
1 files changed, 402 insertions, 0 deletions
diff --git a/src/util/ParseFile.c b/src/util/ParseFile.c new file mode 100644 index 00000000..d6d5a97d --- /dev/null +++ b/src/util/ParseFile.c @@ -0,0 +1,402 @@ + /*@@ + @file ParseFile.c + @date Tue Jan 12 15:58:31 1999 + @author Tom Goodale + @desc + Routines to read in a parameter file and pass the resulting data + to a user-supplied subroutine. + Currently taken from the old cactus ones and slightly modifed. + @enddesc + @@*/ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <assert.h> + +static char *rcsid = "$Id$"; + +/* Local definitions and functions */ +#ifndef WIN32 +#define BOLDON "\033[1m" +#define BOLDOFF "\033[0m" +#else +#define BOLDON "" +#define BOLDOFF "" +#endif + +#define BUF_SZ 1024 + +static void CheckBuf(int, int); +static void removeSpaces(char *stripMe); + + + +/*@@ + @routine ParseFile + @author Paul Walker + @desc The meat of the matter! + This routine actually parses the parameter file. The + syntax we allow is + <ul> + <li>a = b + <li>a,b,c = d,e,f + <li># rest of the line is ignored + <li>x = "string value" + </ul> + So it is easy to parse + <p> + We go through the file looking for stuff and then set + it in the global database using calls to @seeroutine + setIntVal, @seeroutine setFloatVal, @seeroutine setDoubleVal + and @seeroutine setStringVal. + @enddesc + @history + @hdate Tue Jan 12 16:41:36 1999 @hauthor Tom Goodale + @hdesc Moved to CCTK. + Changed to pass data to arbitrary function. + Changed to take a file descriptor rather than a filename. + @endhistory + @@*/ + + +int ParseFile(FILE *ifp, + int (*set_function)(const char *, const char *)) +{ + /* Buffers for parsing from the file */ + char tokens[BUF_SZ], value[BUF_SZ]; + /* Positions in the buffers */ + int ntokens; + /* Status flags */ + int intoken, inval; + /* Current char. Have to make it an int so we can compare with + EOF. See man 3 fgetc + */ + int c; + /* line number */ + int lineno = 1; + + intoken = 0; inval = 0; + + while ((c=fgetc(ifp)) != EOF) + { + /* Main Loop */ + while (c == '#') + { + /* Comment line. So forget rest of line */ + while ((c=fgetc(ifp)) != '\n' && c != EOF); + c = fgetc(ifp); + } + + /* End of line */ + if (c == '\n') { + lineno ++; +#ifdef DEBUG + printf ("LINE %d\n",lineno); +#endif + } + + /* Token character */ + if (intoken && c != '=') + { + tokens[intoken++] = c; + CheckBuf(intoken,lineno); + } + + + /* Start of a new token */ + if (c != ' ' && c != '\n' && !inval && !intoken) + { + intoken = 0; + tokens[intoken++] = c; + } + + /* End of a token signified by an = */ + if (c == '=') + { + if (intoken) + { + unsigned int ll; + tokens[intoken] = '\0'; /* Very important! */ + intoken = 0; + inval = 0; + removeSpaces(tokens); + ntokens = 1; + for (ll=0;ll < strlen(tokens); ll++) + if (tokens[ll] == ',') ntokens++; +#ifdef DEBUG + printf ("New token! >>%s<<\n",tokens); + printf ("%d token elements\n",ntokens); +#endif + + /* Scan ahead to the beginning of the value + * and check if the value is a string or + * not. UNLIKE shalfs parser, this one DOES + * strip quotes off of the strings. Bye bye + * to StripQuotes routines... + */ + while ((c = fgetc(ifp)) == ' ' || c == '\n' || c == '\t'); + if (c == '"') + { + /* Just handle the damn thing. */ + int p = 0; + if (ntokens > 1) + { + fprintf (stderr, "%s%s%s\n", + "WARNING: Multiple string ", + "tokens not supported for ", + tokens); + fprintf(stderr, "This is a fatal error"); + return 1; + } + while ((c = fgetc(ifp)) != '"') + { + /* Make an important decision NOT to include + * line feeds in the string parameters + */ + if (c != '\n') value[p++] = c; + if (c == '\n') + { + printf ("%sWarning:%s Quoted string contains newline for token %s\n", + BOLDON, BOLDOFF, tokens); + printf ("This could indicated a parameter file error or missing quote\n"); + } + CheckBuf(p,lineno); + } + value[p] = '\0'; +#ifdef DEBUG + printf ("String %s -> %s\n", + tokens,value); +#endif + set_function(tokens,value); + + + } + else + { + int p = 0; + value[p++] = c; + if (ntokens == 1) + { + /* Simple case. We have an int + or a double which contain no + spaces! */ + c = fgetc(ifp); + while (!(c==' ' || c=='\t' || c == '\n' || c == EOF)) + { + value[p++] = c; + CheckBuf(p,lineno); + c = fgetc(ifp); + } + value[p] = '\0'; +#ifdef DEBUG + printf ("Parsed %d characters\n", p); + printf("Float/Int: %s -> %s\n", tokens,value); +#endif + set_function(tokens,value); + + } + else + { + /* Harder case of multiple tokens */ + int ncommas = 0; + int p=0, i; + char subtoken[BUF_SZ], subvalue[BUF_SZ]; + int pt, pv; + + value[p++] = c; + /* OK, since we only have numbers in the + old input stream, we can go along getting + ntokens-1 commas, stripping spaces, and + make a nice little string. + */ + c = fgetc(ifp); + while (ncommas < ntokens-1 && c != EOF) + { + if (!(c == ' ' || c == '\t' || c == '\n')) + { + value[p++] = c; + CheckBuf(p,lineno); + } + if (c == ',') ncommas ++; + c = fgetc(ifp); + } + if (c == ' ' || c == '\t') + { + /* Great now strip out the spaces */ + while((c = fgetc(ifp)) == ' ' || c=='\t' || c == '\n'); + } + + /* And tack the rest on */ + value[p++] = c; + CheckBuf(p,lineno); + + c = fgetc(ifp); + while (c != ' ' && c != '\t' && c != '\n' && c != EOF) + { + value[p++] = c; + CheckBuf(p,lineno); + c = fgetc(ifp); + } + value[p] = '\0'; +#ifdef DEBUG + printf("Comma list: %s -> %s\n", + tokens,value); +#endif + /* So parse out the tokens */ + pt = 0; + pv = 0; + for (i=0;i<ncommas;i++) + { + p = 0; + while (tokens[pt] != ',') + { + subtoken[p++] = tokens[pt++]; + CheckBuf(p,lineno); + } + subtoken[p] = '\0'; + p = 0; + while (value[pv] != ',') + { + subvalue[p++] = value[pv++]; + CheckBuf(p,lineno); + } + subvalue[p] = '\0'; + + set_function(subtoken,subvalue); +#ifdef DEBUG + printf("Setting sub-token %s -> %s\n", + subtoken, subvalue); +#endif + /* Now remeber we are sitting on a comma + * in both our input strings, so bump by one + */ + pv ++; pt ++; + } + /* And OK, so now we have one parameter left + * so lets handle that + */ + p = 0; + while (tokens[pt] != '\0') + { + subtoken[p++] = tokens[pt++]; + CheckBuf(p,lineno); + } + subtoken[p] = '\0'; + p = 0; + while (value[pv] != '\0') + { + subvalue[p++] = value[pv++]; + CheckBuf(p,lineno); + } + subvalue[p] = '\0'; + + set_function(subtoken,subvalue); + } + } + } + else + { + fprintf (stderr, "Parser failed at = on line %d\n", + lineno); + } + } + } + + return 0; +} + +/*@@ + @routine CheckBuf + @author Paul Walker + @desc + A simple description and warning message in case of + a fixed parse buffer overflow. + @enddesc + @@*/ + +static void CheckBuf(int p, int l) +{ + if (p >= BUF_SZ) { + fprintf(stderr,"WARNING: Parser buffer overflow on line %d\n", + l); + fprintf(stderr,"This indicates either an incorrect parm file or\n"); + fprintf(stderr,"the need to recompile doParse.C with a bigger\n"); + fprintf(stderr,"BUF_SZ parm.\n"); + + assert(0); + exit(1); + } +} + + +/*@@ + @routine removeSpaces + @author Paul Walker + @desc + removes the spaces from a char * <b>in place</b>. Beware + that this function will change the input value and if you + want to keep a copy you have to do so yourself! + @enddesc + @comment + The silly user (eg, me) may think to call @seeroutine trimString + then this routine in order to remove all spaces from a string. + But, duh, @seeroutine trimString is a <i>subset</i> of this, you + dummy! + @endcomment + @@*/ + +static void removeSpaces(char *stripMe) +{ + char *s; + unsigned int i,j; + s = (char *)malloc((strlen(stripMe)+2)*sizeof(char)); + strcpy(s,stripMe); + for (i=0,j=0;i<strlen(s);i++) + if (s[i] != ' ' && s[i] != '\t' && s[i] != '\n') + stripMe[j++] = s[i]; + stripMe[j] = '\0'; + free(s); +} + + +/* #define TEST_ParseFile */ + +#ifdef TEST_ParseFile + +int parameter_printer(const char *param, const char *val) +{ + printf("Parameter %s has value %s\n", param, val); + + return 0; +} + +int main(int argc, char *argv[]) +{ + int retval; + FILE *parameter_file; + + if(argc > 1) + { + parameter_file = fopen(argv[1], "r"); + if(parameter_file) + { + ParseFile(parameter_file, parameter_printer); + fclose(parameter_file); + retval = 0; + } + else + { + retval=2; + } + } + else + { + printf("Usage: %s <filename>\n", argv[0]); + retval = 1; + }; + + return 0; +} + +#endif |