/* *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * * * CitcomS by Louis Moresi, Shijie Zhong, Lijie Han, Eh Tan, * Clint Conrad, Michael Gurnis, and Eun-seo Choi. * Copyright (C) 1994-2005, California Institute of Technology. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* Routines which read filenames from the command line and then parse the contents as parameters for citcom */ #include #include #include "global_defs.h" #include "parsing.h" #define MAXLINE 1024 /* max length of line in input file */ #define MAXNAME 64 /* max length of name */ #define MAXVALUE 1024 /* max length of value */ #define MAXFILENAME 64 /* max length of par file name */ #define MAXVECTOR 10 /* max # of elements for unspecified vectors */ #define STRANGE_NUM -98765.4321 /* abbreviations: */ #define AL struct arglist #define PROGNAME ext_par.progname #define FLAGS ext_par.argflags #define ARGLIST ext_par.arglist #define ARGHEAD ext_par.arghead #define ARGBUF ext_par.argbuf #define NLIST ext_par.nlist #define NBUF ext_par.nbuf #define LISTMAX ext_par.listmax #define BUFMAX ext_par.bufmax #define LISTFILE ext_par.listout #define LISTINC 32 /* increment size for arglist */ #define BUFINC 1024 /* increment size for argbuf */ struct ext_par /* global variables for getpar */ { char *progname; int argflags; struct arglist *arglist; struct arglist *arghead; char *argbuf; int nlist; int nbuf; int listmax; int bufmax; FILE *listout; } ext_par; struct arglist /* structure of list set up by setpar */ { int argname_offset; int argval_offset; int hash; }; int VERBOSE = 0; int DESCRIBE = 0; int BEGINNER = 0; int interpret_control_string(); void setup_parser(struct All_variables *E, char *filename) { void unique_copy_file(); FILE * fp; char *pl,*pn,*pv; char t1, t2, line[MAXLINE], name[MAXNAME], value[MAXVALUE]; int i,j,k; int m=E->parallel.me; /* should get file length & cpp &c before any further parsing */ /* for now, read one filename from the command line, we'll parse that ! */ /* this section moved to main() */ /* if (ac < 2) { */ /* fprintf(stderr,"Usage: citcom PARAMETERFILE\n"); */ /* exit(10); */ /* } */ if ((fp = fopen(filename,"r")) == NULL) { fprintf(stderr,"(Parsing #1) File: %s is unreadable\n",filename); exit(11); } /* now the parameter file is open, read into memory */ while( fgets(line,MAXLINE,fp) != NULL ) { pl= line; /* loop over entries on each line */ loop: while(*pl==' ' || *pl=='\t') pl++; if(*pl=='\0'|| *pl=='\n') continue; /* end of line */ if(*pl=='#') continue; /* end of interpretable part of line */ /* get name */ pn= name; while(*pl != '=' && *pl != '\0' && *pl != ' ' && *pl != '\n' /* FIX by Glenn Nelson */ && *pl != '\t') *pn++ = *pl++; *pn = '\0'; if(*pl == '=') pl++; /* get value */ *value= '\0'; pv= value; if(*pl=='"' || *pl=='\'') t1= t2= *pl++; else { t1= ' '; t2= '\t'; } while(*pl!=t1 && *pl!=t2 && *pl!='\0' && *pl!='\n') *pv++= *pl++; *pv= '\0'; if(*pl=='"' || *pl=='\'') pl++; add_to_parameter_list(name,value); goto loop; } fclose(fp); ARGHEAD= ARGLIST; /* Now we can use our routines to check & set their own flags ! */ input_boolean("VERBOSE",&i,"off",m); input_boolean("DESCRIBE",&j,"off",m); input_boolean("BEGINNER",&k,"off",m); VERBOSE=i; DESCRIBE=j; BEGINNER=k; /* make this an optional behavior */ input_boolean("copy_input_file",&k,"on",m); if(k) unique_copy_file(E,filename,"copy"); } void shutdown_parser(struct All_variables *E) { if(ARGLIST != NULL) free(ARGLIST); if(ARGBUF != NULL) free(ARGBUF); ARGBUF= NULL; ARGLIST= NULL; } /* add an entry to arglist, expanding memory */ void add_to_parameter_list(char *name, char *value) { struct arglist *alptr; int len; char *ptr; /* check arglist memory */ if(NLIST >= LISTMAX) { LISTMAX += LISTINC; if(ARGLIST == NULL) ARGLIST= (AL *)malloc(LISTMAX * sizeof(AL)); else ARGLIST= (AL *)realloc(ARGLIST,LISTMAX * sizeof(AL)); } /* check argbuf memory */ len= strlen(name) + strlen(value) + 2; /* +2 for terminating nulls */ if(NBUF+len >= BUFMAX) { BUFMAX += BUFINC; if(ARGBUF == NULL) ARGBUF= (char *)malloc(BUFMAX); else ARGBUF= (char *)realloc(ARGBUF,BUFMAX); } if(ARGBUF == NULL || ARGLIST == NULL) fprintf(stderr,"cannot allocate memory\n"); /* add name */ alptr= ARGLIST + NLIST; alptr->hash= compute_parameter_hash_table(name); alptr->argname_offset = NBUF; ptr= ARGBUF + NBUF; do *ptr++ = *name; while(*name++); /* add value */ NBUF += len; alptr->argval_offset= ptr - ARGBUF; do *ptr++ = *value; while(*value++); NLIST++; } int compute_parameter_hash_table(char *s) { int h; h= s[0]; if(s[1]) h |= (s[1])<<8; else return(h); if(s[2]) h |= (s[2])<<16; else return(h); if(s[3]) h |= (s[3])<<24; return(h); } int input_int(char *name, int *value, char *interpret, int m) { struct arglist *alptr; int h, found; char *str; int exists,essential; double Default,minvalue,maxvalue; if(m==0) if(DESCRIBE) fprintf(stderr,"input_int: searching for '%s' with default/range '%s'\n", name,(interpret == NULL) ? "**EMPTY**" : interpret); exists = interpret_control_string(interpret,&essential,&Default,&minvalue,&maxvalue); *value = (int)(Default); h=compute_parameter_hash_table(name); found=0; /* search list backwards, stopping at first find */ for(alptr= ARGLIST +(NLIST-1); alptr >= ARGHEAD; alptr--) { if(alptr->hash != h) continue; if(strcmp(ARGBUF+alptr->argname_offset,name) != 0) continue; str= ARGBUF + alptr->argval_offset; sscanf(str,"%d",value); found=1; break; } if(essential && !found) { fprintf(stderr,"There MUST be an entry for the parameter %s\n",name); exit(12); } if((minvalue!=STRANGE_NUM) && (*value < (int) minvalue)) { *value = (int) minvalue; } if((maxvalue!=STRANGE_NUM) && (*value > (int) maxvalue)) { *value = (int) maxvalue; } if(m==0) if(VERBOSE) { if (found) fprintf(stderr,"%25s: (int) = %d \n",name,*value); else if (Default != STRANGE_NUM) fprintf(stderr,"%25s: (int) = not found (%d) \n",name,(int)(Default)); else { fprintf(stderr,"%25s: (int) = not found (no default) \n",name); if(BEGINNER) { fprintf(stderr,"\t\t Previously set value gives ..."); fprintf(stderr,"%d\n",*value); } } } return(found); } /* in the case of a string default=NULL forces input */ int input_string(char *name, char *value, char *Default, int m) { char *sptr; struct arglist *alptr; int h, hno, hyes, found; char line[MAXLINE], *str, *noname; int essential; if(m==0) if(DESCRIBE) fprintf(stderr,"input_string: searching for '%s' with default '%s'\n", name,(Default == NULL) ? "no default" : Default); h=compute_parameter_hash_table(name); essential=found=0; if (Default != NULL) /* Cannot use "Essential" as this is a valid input */ strcpy(value,Default); else essential=1; /* search list backwards, stopping at first find */ for(alptr= ARGLIST +(NLIST-1); alptr >= ARGHEAD; alptr--) { if(alptr->hash != h) continue; if(strcmp(ARGBUF+alptr->argname_offset,name) != 0) continue; str= ARGBUF + alptr->argval_offset; strcpy(value,str); found=1; break; } if(essential && !found) { fprintf(stderr,"There MUST be an entry for the parameter %s\n",name); exit(12); } if(m==0) if(VERBOSE) fprintf(stderr,"%25s: (string) = %s (%s)\n",name, (found ? value : "not found"), (Default != NULL ? Default : "no default")); return(found); } /* supports name=on/off too */ int input_boolean(char *name, int *value, char *interpret, int m) { char *sptr; struct arglist *alptr; int h, hno, hyes, found; char line[MAXLINE], *str, *noname; int essential; double Default,minvalue,maxvalue; if(m==0) if(DESCRIBE) fprintf(stderr,"input_boolean: searching for '%s' with default/range '%s'\n", name,(interpret == NULL) ? "**EMPTY**" : interpret); interpret_control_string(interpret,&essential,&Default,&minvalue,&maxvalue); *value = (int)(Default); h=compute_parameter_hash_table(name); found=0; /* search list backwards, stopping at first find */ for(alptr= ARGLIST +(NLIST-1); alptr >= ARGHEAD; alptr--) { if(alptr->hash != h) continue; if(strcmp(ARGBUF+alptr->argname_offset,name) != 0) continue; str= ARGBUF + alptr->argval_offset; found=1; break; } if(!found) {if(m==0) if(VERBOSE){ if (Default != STRANGE_NUM) fprintf(stderr,"%25s: (boolean int) = not found (%d) \n",name,(int)(Default)); else{ fprintf(stderr,"%25s: (boolean int) = not found (no default) \n",name); if(BEGINNER){ fprintf(stderr,"\t\t Previously set value gives ..."); fprintf(stderr,"%d\n",*value); } } } return(0); } if((strstr(str,"on")!=NULL) || (strstr(str,"ON")!=NULL)) *value=1; else if ((strstr(str,"off") != NULL) || (strstr(str,"OFF")!=NULL)) *value=0; else /* assume some numerical value */ *value=atoi(str); if(m==0) if(VERBOSE) fprintf(stderr,"%25s: (boolean int) = %d \n",name,*value); return(found); } int input_float(char *name, float *value, char *interpret, int m) { char *sptr; struct arglist *alptr; int h, hno, hyes, found; char line[MAXLINE], *str, *noname; int exists,essential; double Default,minvalue,maxvalue; if(m==0) if(DESCRIBE) fprintf(stderr,"input_float: searching for '%s' with default/range '%s'\n", name,(interpret == NULL) ? "**EMPTY**" : interpret); exists=interpret_control_string(interpret,&essential,&Default,&minvalue,&maxvalue); *value = (float) Default; h=compute_parameter_hash_table(name); found=0; /* search list backwards, stopping at first find */ for(alptr= ARGLIST +(NLIST-1); alptr >= ARGHEAD; alptr--) { if(alptr->hash != h) continue; if(strcmp(ARGBUF+alptr->argname_offset,name) != 0) continue; str= ARGBUF + alptr->argval_offset; sscanf(str,"%f",value); found=1; break; } if(essential && !found) { fprintf(stderr,"There MUST be an entry for the parameter %s\n",name); exit(12); } if((minvalue!=STRANGE_NUM) && (*value < (float) minvalue)) *value = (float) minvalue; if((maxvalue!=STRANGE_NUM) && (*value > (float) maxvalue)) *value = (float) maxvalue; if(m==0) if(VERBOSE) { if (found) fprintf(stderr,"%25s: (float) = %g \n",name,*value); else if (Default != STRANGE_NUM) fprintf(stderr,"%25s: (float) = not found (%g) \n",name,Default); else { fprintf(stderr,"%25s: (float) = not found (no default) \n",name); if(BEGINNER) { fprintf(stderr,"\t\t Previously set value gives ..."); fprintf(stderr,"%g\n",*value); } } } return(found); } int input_double(char *name, double *value, char *interpret, int m) { char *sptr; struct arglist *alptr; int h, hno, hyes, found; char line[MAXLINE], *str, *noname; int exists,essential; double Default,minvalue,maxvalue; if(m==0) if(DESCRIBE) fprintf(stderr,"input_double: searching for '%s' with default/range '%s'\n", name,(interpret == NULL) ? "**EMPTY**" : interpret); exists=interpret_control_string(interpret,&essential,&Default,&minvalue,&maxvalue); *value = Default; h=compute_parameter_hash_table(name); found=0; /* search list backwards, stopping at first find */ for(alptr= ARGLIST +(NLIST-1); alptr >= ARGHEAD; alptr--) { if(alptr->hash != h) continue; if(strcmp(ARGBUF+alptr->argname_offset,name) != 0) continue; str= ARGBUF + alptr->argval_offset; sscanf(str,"%lf",value); found=1; break; } if(essential && !found) { fprintf(stderr,"There MUST be an entry for the parameter %s\n",name); exit(12); } if((minvalue!=STRANGE_NUM) && (*value < minvalue)) *value = minvalue; if((maxvalue!=STRANGE_NUM) && (*value > maxvalue)) *value = maxvalue; if(m==0) if(VERBOSE) { if (found) fprintf(stderr,"%25s: (double) = %g \n",name,*value); else if (Default != STRANGE_NUM) fprintf(stderr,"%25s: (double) = not found (%g) \n",name,Default); else { fprintf(stderr,"%25s: (double) = not found (no default) \n",name); if(BEGINNER) { fprintf(stderr,"\t\t Previously set value gives ..."); fprintf(stderr,"%g\n",*value); } } } return(found); } int input_int_vector(char *name, int number,int *value,int m) { char *sptr; struct arglist *alptr; char control_string[500]; int h,i, hno, hyes, found; char line[MAXLINE], *str, *noname; if(m==0) if(DESCRIBE) fprintf(stderr,"input_int_vector: searching for %s (%d times)\n",name,number); h=compute_parameter_hash_table(name); found=0; /* search list backwards, stopping at first find */ for(alptr= ARGLIST +(NLIST-1); alptr >= ARGHEAD; alptr--) { if(alptr->hash != h) continue; if(strcmp(ARGBUF+alptr->argname_offset,name) != 0) continue; str= ARGBUF + alptr->argval_offset; found=1; break; } /* now interpret vector */ if(!found) return(0); for(h=0;h= ARGHEAD; alptr--) { if(alptr->hash != h) continue; if(strcmp(ARGBUF+alptr->argname_offset,name) != 0) continue; str= ARGBUF + alptr->argval_offset; found=1; break; } /* now interpret vector */ if(!found) return(0); for(h=0;h= ARGHEAD; alptr--) { if(alptr->hash != h) continue; if(strcmp(ARGBUF+alptr->argname_offset,name) != 0) continue; str= ARGBUF + alptr->argval_offset; found=1; break; } /* now interpret vector */ if(!found) return(0); for(h=0;h= ARGHEAD; alptr--) { if(alptr->hash != h) continue; if(strcmp(ARGBUF+alptr->argname_offset,name) != 0) continue; str= ARGBUF + alptr->argval_offset; found=1; break; } if(!found) return(0); /* now interpret vector */ for(h=0;h