/*@@ @routine ParseFile @author Paul Walker @desc 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 the passed in set_function. @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 @var ifp @vdesc The filestream to parse @vtype FILE * @vio in @vcomment @endvar @var set_function @vdesc The function to call to set the value of a parameter @vtype int (*)(const char *, const char *) @vio in @vcomment @endvar @var ConfigData @vdesc Flesh configuration data @vtype tFleshConfig * @vio in @vcomment @endvar @returntype int @returndesc 0 - success @endreturndesc @@*/ int ParseFile(FILE *ifp, int (*set_function)(const char *, const char *, int), tFleshConfig *ConfigData) { /* Buffers for parsing from the file */ char *tokens, *value; char *subtoken, *subvalue; /* 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; int num_errors; /* number of errors in file parsing */ num_errors = 0; /* avoid compiler warning about unused parameter */ ConfigData = ConfigData; /* allocate parse buffers */ tokens = (char *) malloc (4 * BUF_SZ); value = tokens + 1*BUF_SZ; subtoken = tokens + 2*BUF_SZ; subvalue = tokens + 3*BUF_SZ; intoken = 0; inval = 0; while ((c=fgetc(ifp)) != EOF) { #ifdef DEBUG printf("%c",c); #endif /* Main Loop */ while (c == '#' || c == '!' ) { /* Comment line. So forget rest of line */ while ((c=fgetc(ifp)) != '\n' && c != EOF) { #ifdef DEBUG printf("%c",c); #endif } if (c == '\n') { lineno++; } c = fgetc(ifp); #ifdef DEBUG printf("%c",c); #endif } /* End of line */ if (c == '\n') { if(intoken) { fprintf(stderr, "Parse error at line %d. No value supplied.\n", lineno); num_errors++; intoken = 0; } #ifdef DEBUG printf ("LINE %d\n",lineno); #endif lineno ++; } /* Token character */ if (intoken && c != '=') { tokens[intoken++] = c; CheckBuf(intoken,lineno); } /* Start of a new token */ if (c != ' ' && c != '\t' && 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 ("\nNew 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. * This parser DOES strip quotes off of the strings. */ while ((c = fgetc(ifp)) == ' ' || c == '\n' || c == '\t') { #ifdef DEBUG printf("%c",c); #endif if (c == '\n') { #ifdef DEBUG printf ("LINE %d\n",lineno); #endif lineno++; } } if (c == '"') { /* Just handle the 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"); /* deallocate parse buffers */ free (tokens); return 1; } while ((c = fgetc(ifp)) != '"') { #ifdef DEBUG printf("%c",c); #endif /* 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"); #ifdef DEBUG printf ("LINE %d\n",lineno); #endif lineno++; } CheckBuf(p,lineno); } value[p] = '\0'; #ifdef DEBUG printf ("\nString %s -> %s\n", tokens,value); #endif set_function(tokens,value, lineno); } else if (c == '$') { /* We got a define */ /* FIXME: Assume it is a parameter file for now */ char filename[500]; char *dir; char *file; int lpar; CCTK_ParameterFilename(500,filename); Util_SplitFilename(&dir,&file,filename); lpar=((strlen(file)-3)*sizeof(char)); /* ignore everything else on the line */ while (!(c==' ' || c=='\t' || c == '\n' || c == EOF)) { c = fgetc(ifp); #ifdef DEBUG printf("%c",c); #endif } strncpy(value,file,lpar); free(dir); free(file); value[strlen(value)-1] = '\0'; set_function(tokens,value,lineno); } 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); #ifdef DEBUG printf("%c",c); #endif while (!(c==' ' || c=='\t' || c == '\n' || c == EOF)) { value[p++] = c; CheckBuf(p,lineno); c = fgetc(ifp); #ifdef DEBUG printf("%c",c); #endif } value[p] = '\0'; #ifdef DEBUG printf ("Parsed %d characters\n", p); printf("\nFloat/Int: %s -> %s\n", tokens,value); #endif set_function(tokens,value,lineno); if (c=='\n') { #ifdef DEBUG printf ("LINE %d\n",lineno); #endif lineno++; } } else { /* Harder case of multiple tokens */ int ncommas = 0; int pp=0, i; int pt, pv; value[pp++] = 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); #ifdef DEBUG printf("%c",c); #endif while (ncommas < ntokens-1 && c != EOF) { if (!(c == ' ' || c == '\t' || c == '\n')) { value[pp++] = c; CheckBuf(pp,lineno); } if (c == ',') ncommas ++; c = fgetc(ifp); #ifdef DEBUG printf("%c",c); #endif } if (c == ' ' || c == '\t') { /* Great now strip out the spaces */ while((c = fgetc(ifp)) == ' ' || c=='\t' || c == '\n') { #ifdef DEBUG printf("%c",c); #endif if (c=='\n') { #ifdef DEBUG printf ("LINE %d\n",lineno); #endif lineno++; } } } /* And tack the rest on */ value[pp++] = c; CheckBuf(p,lineno); c = fgetc(ifp); #ifdef DEBUG printf("%c",c); #endif while (c != ' ' && c != '\t' && c != '\n' && c != EOF) { value[pp++] = c; CheckBuf(pp,lineno); c = fgetc(ifp); #ifdef DEBUG printf("%c",c); #endif } value[pp] = '\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++) { pp = 0; while (tokens[pt] != ',') { subtoken[pp++] = tokens[pt++]; CheckBuf(p,lineno); } subtoken[pp] = '\0'; pp = 0; while (value[pv] != ',') { subvalue[pp++] = value[pv++]; CheckBuf(pp,lineno); } subvalue[pp] = '\0'; set_function(subtoken,subvalue,lineno); #ifdef DEBUG printf("Setting sub-token %s -> %s\n", subtoken, subvalue); #endif /* Now remember 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 */ pp = 0; while (tokens[pt] != '\0') { subtoken[pp++] = tokens[pt++]; CheckBuf(pp,lineno); } subtoken[pp] = '\0'; pp = 0; while (value[pv] != '\0') { subvalue[pp++] = value[pv++]; CheckBuf(pp,lineno); } subvalue[pp] = '\0'; set_function(subtoken,subvalue,lineno); } } } else { fprintf (stderr, "Parser failed at = on line %d\n", lineno); } } } /* deallocate parse buffers */ free (tokens); return num_errors; }
void CCTK_FCALL cctk_parameterfilename_ (int *retval, int *len, char *name) { *retval = CCTK_ParameterFilename(*len,name); }