00001 #include "copyright.h"
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078 #include <stdio.h>
00079 #include <stdlib.h>
00080 #include <string.h>
00081 #include <stdarg.h>
00082 #include <ctype.h>
00083 #include "defs.h"
00084 #include "prototypes.h"
00085
00086 static int now_open = 0;
00087 static char *now_filename = NULL;
00088
00089
00090
00091 typedef struct Par_s {
00092 char *name;
00093 char *value;
00094 char *comment;
00095 struct Par_s *next;
00096 } Par;
00097
00098
00099
00100 typedef struct Block_s {
00101 char *name;
00102 Par *p;
00103 int max_name_len;
00104 int max_value_len;
00105 struct Block_s *next;
00106 } Block;
00107
00108
00109
00110 typedef void (*proc)(void);
00111 static Block *base_block = NULL;
00112 static int debug = 0;
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132 static void *allocate(size_t size);
00133 static char *my_strdup(char *in);
00134 static char *skipwhite(char *cp);
00135 static void str_term(char *cp);
00136 static char *line_block_name(char *line);
00137 static void add_par(Block *bp, char *name, char *value, char *comment);
00138 static void add_par_line(Block *bp, char *line);
00139 static Block *add_block(char *name);
00140 static Block *find_block(char *name);
00141 static Par *find_par(Block *bp, char *name);
00142 static void free_all(void);
00143 static char *par_getsl(char *block, char *name);
00144 void par_debug(int level);
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156 void par_open(char *filename)
00157 {
00158 FILE *fp;
00159 char line[MAXLEN];
00160 char *block_name, *cp;
00161 Block *bp = NULL;
00162
00163 if (now_open) ath_error("Parameter file %s still open\n",now_filename);
00164 if (now_filename) free(now_filename);
00165 fp = fopen(filename,"r");
00166 if (fp == NULL)
00167 ath_error("Parameter file %s could not be opened, try -i PARFILE\n"
00168 ,filename);
00169 if (debug) fprintf(stdout,"Opening \"%s\" for parameter access\n",filename);
00170 now_open = 1;
00171 now_filename = my_strdup(filename);
00172
00173 while (fgets(line,MAXLEN,fp)) {
00174 cp = skipwhite(line);
00175 if (*cp == '\0') continue;
00176 if (*cp == '#') continue;
00177 if (strncmp(cp,"<par_end>",9) == 0) break;
00178 if (*cp == '<') {
00179 block_name = line_block_name(cp);
00180 bp = add_block(block_name);
00181 continue;
00182 }
00183 add_par_line(bp,cp);
00184 }
00185 fclose(fp);
00186 return;
00187 }
00188
00189
00190
00191
00192
00193
00194 void par_cmdline(int argc, char *argv[])
00195 {
00196 int i;
00197 char *sp, *ep;
00198 char *block, *name, *value;
00199 Block *bp;
00200 Par *pp;
00201 int len;
00202
00203 if (debug) printf("PAR_CMDLINE: \n");
00204 for (i=1; i<argc; i++) {
00205 block = argv[i];
00206 sp = strchr(block,'/');
00207 if ((sp = strchr(block,'/')) == NULL) continue;
00208 *sp = '\0';
00209 name = sp + 1;
00210
00211 if((ep = strchr(name,'=')) == NULL){
00212 *sp = '/';
00213 continue;
00214 }
00215 *ep = '\0';
00216 value = ep + 1;
00217
00218 if (debug) printf("PAR_CMDLINE: %s/%s=%s\n",block,name,value);
00219 bp = find_block(block);
00220 if (bp == NULL) ath_error("par_cmdline: Block \"%s\" not found\n",block);
00221 pp = find_par(bp,name);
00222 if (pp == NULL) ath_error("par_cmdline: Par \"%s\" not found\n",name);
00223 free(pp->value);
00224 pp->value = my_strdup(value);
00225
00226 len = (int)strlen(value);
00227 bp->max_value_len = len > bp->max_value_len ? len : bp->max_value_len;
00228
00229
00230 *sp = '/';
00231 *ep = '=';
00232 }
00233 }
00234
00235
00236
00237
00238
00239 int par_exist(char *block, char *name)
00240 {
00241 Block *bp;
00242 Par *pp;
00243
00244 if (!now_open) ath_error("par_exist: No open parameter file\n");
00245 if (block == NULL) ath_error("par_exist: no block name specified\n");
00246 if (name == NULL) ath_error("par_exist: no par name specified\n");
00247 bp = find_block(block);
00248 if (bp == NULL) return 0;
00249 pp = find_par(bp,name);
00250 return (pp == NULL ? 0 : 1);
00251 }
00252
00253
00254
00255
00256
00257 char *par_gets(char *block, char *name)
00258 {
00259 char *pp = par_getsl(block,name);
00260 return my_strdup(pp);
00261 }
00262
00263
00264
00265
00266
00267 int par_geti(char *block, char *name)
00268 {
00269 char *pp = par_getsl(block,name);
00270 return atoi(pp);
00271 }
00272
00273
00274
00275
00276
00277 double par_getd(char *block, char *name)
00278 {
00279 char *pp = par_getsl(block,name);
00280 return atof(pp);
00281 }
00282
00283
00284
00285
00286
00287
00288 char *par_gets_def(char *block, char *name, char *def)
00289 {
00290 if (par_exist(block,name)) {
00291 char *pp = par_getsl(block,name);
00292 return my_strdup(pp);
00293 }
00294
00295 par_sets(block,name,def,"Default Value");
00296 return my_strdup(def);
00297 }
00298
00299
00300
00301
00302
00303
00304 int par_geti_def(char *block, char *name, int def)
00305 {
00306 if (par_exist(block,name)) {
00307 char *pp = par_getsl(block,name);
00308 return atoi(pp);
00309 }
00310
00311 par_seti(block,name,"%d",def,"Default Value");
00312 return def;
00313 }
00314
00315
00316
00317
00318
00319
00320 double par_getd_def(char *block, char *name, double def)
00321 {
00322 if (par_exist(block,name)) {
00323 char *pp = par_getsl(block,name);
00324 return atof(pp);
00325 }
00326
00327 par_setd(block,name,"%.15e",def,"Default Value");
00328 return def;
00329 }
00330
00331
00332
00333
00334
00335 void par_sets(char *block, char *name, char *sval, char *comment)
00336 {
00337 Block *bp = add_block(block);
00338
00339 add_par(bp,name,sval,comment);
00340 return;
00341 }
00342
00343
00344
00345
00346
00347
00348 void par_seti(char *block, char *name, char *fmt, int ival, char *comment)
00349 {
00350 Block *bp = add_block(block);
00351 char sval[MAXLEN];
00352
00353 sprintf(sval,fmt,ival);
00354 add_par(bp,name,sval,comment);
00355 return;
00356 }
00357
00358
00359
00360
00361
00362
00363 void par_setd(char *block, char *name, char *fmt, double dval, char *comment)
00364 {
00365 Block *bp = add_block(block);
00366 char sval[MAXLEN];
00367
00368 sprintf(sval,fmt,dval);
00369 add_par(bp,name,sval,comment);
00370 return;
00371 }
00372
00373
00374
00375
00376
00377 void par_dump(int mode, FILE *fp)
00378 {
00379 char fmt[80];
00380 Block *bp;
00381 Par *pp;
00382
00383 if(mode != 2)
00384 fprintf(fp,"# --------------------- PAR_DUMP -----------------------\n\n");
00385
00386 for(bp = base_block; bp != NULL; bp = bp->next){
00387 if (mode == 1)
00388 fprintf(fp,"%s::\n",bp->name);
00389 else{
00390 fprintf(fp,"<%s>\n",bp->name);
00391 sprintf(fmt,"%%-%ds = %%-%ds",bp->max_name_len,bp->max_value_len);
00392 }
00393
00394 for(pp = bp->p; pp != NULL; pp = pp->next){
00395 if (mode == 1)
00396 fprintf(fp," %s/%s = %s\n",bp->name,pp->name,pp->value);
00397 else{
00398 fprintf(fp,fmt,pp->name,pp->value);
00399 if(pp->comment == NULL) fprintf(fp,"\n");
00400 else fprintf(fp," # %s\n",pp->comment);
00401 }
00402 }
00403 fputc('\n',fp);
00404 }
00405
00406 if(mode == 2)
00407 fprintf(fp,"<par_end>\n");
00408 else
00409 fprintf(fp,"# --------------------- PAR_DUMP -------------------------\n");
00410
00411 return;
00412 }
00413
00414
00415
00416
00417
00418 void par_close(void)
00419 {
00420 if (!now_open){
00421 fprintf(stderr,"[par_close]: No open parameter file\n");
00422 return;
00423 }
00424 now_open = 0;
00425 free_all();
00426 }
00427
00428
00429
00430
00431
00432
00433
00434 #ifdef MPI_PARALLEL
00435 void par_dist_mpi(const int mytid, MPI_Comm comm)
00436 {
00437 char line[MAXLEN];
00438 Block *bp = NULL;
00439 Par *pp;
00440 int count;
00441 char *block_name;
00442
00443 if(mytid == 0){
00444 if (!now_open) ath_error("Parameter file is not open\n");
00445 if(debug)
00446 fprintf(stdout,"[par_dist_mpi]: Sending Parameter file \"%s\"\n",
00447 now_filename);
00448
00449
00450 count = 1 + (int)strlen(now_filename);
00451 if(MPI_SUCCESS != MPI_Bcast(&count, 1, MPI_INT, 0, comm))
00452 ath_error("[par_dist_mpi]: Error on calling MPI_Bcast\n");
00453
00454 if(MPI_SUCCESS != MPI_Bcast(now_filename, count, MPI_CHAR, 0, comm))
00455 ath_error("[par_dist_mpi]: Error on calling MPI_Bcast\n");
00456
00457 for(bp = base_block; bp != NULL; bp = bp->next){
00458
00459 sprintf(line,"<%s>",bp->name);
00460
00461
00462 count = 1 + (int)strlen(line);
00463 if(MPI_SUCCESS != MPI_Bcast(&count, 1, MPI_INT, 0, comm))
00464 ath_error("[par_dist_mpi]: Error on calling MPI_Bcast\n");
00465 if(MPI_SUCCESS != MPI_Bcast(line, count, MPI_CHAR, 0, comm))
00466 ath_error("[par_dist_mpi]: Error on calling MPI_Bcast\n");
00467
00468 for(pp = bp->p; pp != NULL; pp = pp->next){
00469
00470 if(pp->comment == NULL)
00471 sprintf(line,"%s = %s",pp->name,pp->value);
00472 else
00473 sprintf(line,"%s = %s # %s",pp->name,pp->value,pp->comment);
00474
00475
00476 count = 1 + (int)strlen(line);
00477 if(MPI_SUCCESS != MPI_Bcast(&count, 1, MPI_INT, 0, comm))
00478 ath_error("[par_dist_mpi]: Error on calling MPI_Bcast\n");
00479 if(MPI_SUCCESS != MPI_Bcast(line, count, MPI_CHAR, 0, comm))
00480 ath_error("[par_dist_mpi]: Error on calling MPI_Bcast\n");
00481 }
00482 }
00483
00484 count = -1;
00485 if(MPI_SUCCESS != MPI_Bcast(&count, 1, MPI_INT, 0, comm))
00486 ath_error("[par_dist_mpi]: Error on calling MPI_Bcast\n");
00487 if(debug)
00488 fprintf(stdout,"[par_dist_mpi]: Parent all done...\n");
00489 }
00490 else{
00491 if (now_open) ath_error("Parameter %s file is already open\n",now_filename);
00492
00493
00494 if(MPI_SUCCESS != MPI_Bcast(&count, 1, MPI_INT, 0, comm))
00495 ath_error("[par_dist_mpi]: Error on calling MPI_Bcast\n");
00496
00497 if(MPI_SUCCESS != MPI_Bcast(line, count, MPI_CHAR, 0, comm))
00498 ath_error("[par_dist_mpi]: Error on calling MPI_Bcast\n");
00499 now_filename = my_strdup(line);
00500
00501 now_open = 1;
00502 if(debug)
00503 fprintf(stdout,"[par_dist_mpi]: Recieving Parameter file \"%s\"\n",
00504 now_filename);
00505
00506 if(MPI_SUCCESS != MPI_Bcast(&count, 1, MPI_INT, 0, comm))
00507 ath_error("[par_dist_mpi]: Error on calling MPI_Bcast\n");
00508 while(count > 0){
00509 if(MPI_SUCCESS != MPI_Bcast(line, count, MPI_CHAR, 0, comm))
00510 ath_error("[par_dist_mpi]: Error on calling MPI_Bcast\n");
00511
00512 if (*line == '<') {
00513 block_name = line_block_name(line);
00514 bp = add_block(block_name);
00515 }
00516 else
00517 add_par_line(bp,line);
00518
00519 if(MPI_SUCCESS != MPI_Bcast(&count, 1, MPI_INT, 0, comm))
00520 ath_error("[par_dist_mpi]: Error on calling MPI_Bcast\n");
00521 }
00522
00523 if(debug)
00524 fprintf(stdout,"[par_dist_mpi]: Child all done...\n");
00525 }
00526
00527 return;
00528 }
00529 #endif
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539 static void *allocate(size_t size)
00540 {
00541 void *mem = calloc(1,size);
00542
00543 if(mem == NULL) ath_error("allocate: not enough memory for %d bytes\n",size);
00544 return mem;
00545 }
00546
00547
00548
00549
00550
00551 static char *my_strdup(char *in)
00552 {
00553 char *out = ath_strdup(in);
00554 if(out == NULL) ath_error("Error allocating memory for a new string\n");
00555 return out;
00556 }
00557
00558
00559
00560
00561
00562
00563
00564 static char *skipwhite(char *cp)
00565 {
00566 while(isspace(*cp))
00567 cp++;
00568 return cp;
00569 }
00570
00571
00572
00573
00574
00575
00576
00577
00578 static void str_term(char *cp)
00579 {
00580 do{
00581 cp--;
00582 }while(isspace(*cp));
00583
00584 *(++cp) = '\0';
00585
00586 return;
00587 }
00588
00589
00590
00591
00592
00593
00594
00595 static char *line_block_name(char *line)
00596 {
00597 char *sp, *cp;
00598
00599
00600
00601 sp = cp = skipwhite(line+1);
00602 while (*cp != '\0' && *cp != '>')
00603 cp++;
00604 if (*cp != '>') ath_error("Blockname %s does not appear terminated\n",sp);
00605 str_term(cp);
00606
00607 return sp;
00608 }
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619 static void add_par(Block *bp, char *name, char *value, char *comment)
00620 {
00621 Par *pp;
00622 Par **pnext;
00623 int len;
00624
00625 len = (int)strlen(name);
00626 bp->max_name_len = len > bp->max_name_len ? len : bp->max_name_len;
00627
00628 len = (int)strlen(value);
00629 bp->max_value_len = len > bp->max_value_len ? len : bp->max_value_len;
00630
00631 if(debug){
00632 printf(" add_par: %-16s = %s",name,value);
00633 if(comment == NULL) printf("\n");
00634 else printf(" # %s\n",comment);
00635 printf(" max_name_len = %d\n max_value_len = %d\n",
00636 bp->max_name_len,bp->max_value_len);
00637 }
00638
00639 for(pnext = &(bp->p); (pp = *pnext) != NULL; pnext = &(pp->next)){
00640 if(strcmp(pp->name,name) == 0){
00641
00642 free(pp->value);
00643 pp->value = my_strdup(value);
00644
00645 if(comment != NULL){
00646 if(pp->comment != NULL) free(pp->comment);
00647 pp->comment = my_strdup(comment);
00648 }
00649 return;
00650 }
00651 }
00652
00653
00654 pp = *pnext = (Par *) allocate(sizeof(Par));
00655
00656 pp->name = my_strdup(name);
00657 pp->value = my_strdup(value);
00658 pp->comment = (comment == NULL ? NULL : my_strdup(comment));
00659 pp->next = NULL;
00660 return;
00661 }
00662
00663
00664
00665
00666
00667
00668
00669 static void add_par_line(Block *bp, char *line)
00670 {
00671 char *cp;
00672 char *name, *equal=NULL, *value=NULL, *hash=NULL, *comment=NULL, *nul;
00673
00674 if(bp == NULL)
00675 ath_error("[add_par_line]: (no block name) while parsing line \n%s\n",line);
00676
00677 name = skipwhite(line);
00678
00679 for(cp = name; *cp != '\0'; cp++){
00680 if(*cp == '='){
00681 if(equal == NULL){
00682 equal = cp;
00683 value = skipwhite(cp + 1);
00684 }
00685 }
00686 if(*cp == '#'){
00687 hash = cp;
00688 comment = skipwhite(cp + 1);
00689 break;
00690 }
00691 }
00692
00693 while(*cp != '\0') cp++;
00694 nul = cp;
00695
00696 if(equal == NULL)
00697 ath_error("No '=' found in line \"%s\"\n",line);
00698
00699 str_term(equal);
00700
00701 if(hash == NULL){
00702 str_term(nul);
00703 }
00704 else{
00705 str_term(hash);
00706
00707 if(*comment == '\0')
00708 comment = NULL;
00709 else
00710 str_term(nul);
00711 }
00712
00713 add_par(bp,name,value,comment);
00714 }
00715
00716
00717
00718
00719
00720 static Block *add_block(char *name)
00721 {
00722 Block *bp;
00723 Block **pnext;
00724
00725 if (debug) printf("add_block: %s\n",name);
00726
00727 for(pnext = &base_block; (bp = *pnext) != NULL; pnext = &(bp->next)){
00728 if(strcmp(bp->name,name) == 0) return bp;
00729 }
00730
00731 bp = *pnext = (Block *) allocate(sizeof(Block));
00732
00733 bp->name = my_strdup(name);
00734 bp->p = NULL;
00735 bp->max_name_len = 0;
00736 bp->max_value_len = 0;
00737 bp->next = NULL;
00738 return bp;
00739 }
00740
00741
00742
00743
00744
00745 static Block *find_block(char *name)
00746 {
00747 Block *bp;
00748
00749 if (debug) printf("find_block: %s\n",name);
00750 for(bp = base_block; bp != NULL; bp = bp->next){
00751 if (strcmp(bp->name,name) == 0) return bp;
00752 }
00753
00754 return NULL;
00755 }
00756
00757
00758
00759
00760
00761 static Par *find_par(Block *bp, char *name)
00762 {
00763 Par *pp;
00764
00765 if (debug) printf("find_par: %s\n",name);
00766 for(pp = bp->p; pp != NULL; pp = pp->next){
00767 if (strcmp(pp->name,name) == 0) return pp;
00768 }
00769
00770 return NULL;
00771 }
00772
00773
00774
00775
00776
00777 static void free_all(void)
00778 {
00779 Block *bp1, *bp;
00780 Par *pp1, *pp;
00781
00782 if (now_filename) free(now_filename);
00783 now_filename = NULL;
00784
00785 for(bp = base_block; bp != NULL; bp = bp1){
00786 bp1 = bp->next;
00787 for(pp = bp->p; pp != NULL; pp = pp1){
00788 pp1 = pp->next;
00789 if (pp->name) free(pp->name);
00790 if (pp->value) free(pp->value);
00791 if (pp->comment) free(pp->comment);
00792 free(pp);
00793 }
00794 if (bp->name) free(bp->name);
00795 free(bp);
00796 }
00797 base_block = NULL;
00798 }
00799
00800
00801
00802
00803
00804
00805
00806 static char *par_getsl(char *block, char *name)
00807 {
00808 Block *bp;
00809 Par *pp;
00810
00811 if (!now_open) ath_error("par_gets: No open parameter file\n");
00812 if (block == NULL) ath_error("par_gets: no block name specified\n");
00813 if (name == NULL) ath_error("par_gets: no par name specified\n");
00814 bp = find_block(block);
00815 if (bp == NULL) ath_error("par_gets: Block \"%s\" not found\n",block);
00816 pp = find_par(bp,name);
00817 if (pp == NULL)
00818 ath_error("par_gets: Par \"%s\" not found in Block \"%s\"\n",name,block);
00819 return pp->value;
00820 }
00821
00822
00823
00824
00825
00826
00827 void par_debug(int level) {
00828 debug = level;
00829 }
00830
00831
00832
00833
00834
00835 #if defined(TESTBED)
00836 #if defined MPI_PARALLEL
00837 int main(int argc, char *argv[])
00838 {
00839 int mytid;
00840
00841 int namelen;
00842 char processor_name[MPI_MAX_PROCESSOR_NAME];
00843
00844 par_debug(0);
00845
00846 if(MPI_SUCCESS != MPI_Init(&argc,&argv))
00847 ath_error("Error on calling MPI_Init\n");
00848
00849
00850
00851 MPI_Comm_rank(MPI_COMM_WORLD,&mytid);
00852
00853 MPI_Get_processor_name(processor_name,&namelen);
00854
00855 printf("My task id / rank = %d on %s\n",mytid, processor_name);
00856
00857
00858 if(mytid != 0)
00859 printf("My Parent's task id / rank = 0\n");
00860 else{
00861 printf("I am the Parent\n");
00862
00863 if (argc == 1) {
00864 printf("Usage: %s par-file [block-name par-name]\n",argv[0]);
00865 exit(0);
00866 }
00867
00868 par_open(argv[1]);
00869 par_cmdline(argc,argv);
00870 if (argc == 4) {
00871 char *cp = par_gets(argv[2],argv[3]);
00872 printf("PAR_GETS: %s.%s = \"%s\"\n",argv[2],argv[3],cp);
00873 printf("PAR_GETI: %s.%s = \"%d\" as integer\n",
00874 argv[2],argv[3],par_geti(argv[2],argv[3]));
00875 printf("PAR_GETD: %s.%s = \"%g\" as double\n",
00876 argv[2],argv[3],par_getd(argv[2],argv[3]));
00877 free(cp);
00878 }
00879 }
00880
00881 par_dist_mpi(mytid,MPI_COMM_WORLD);
00882 par_dump(0,stdout);
00883 par_close();
00884
00885 MPI_Finalize();
00886
00887 return 0;
00888 }
00889
00890 #else
00891
00892 int main(int argc, char *argv[])
00893 {
00894 if (argc == 1) {
00895 printf("Usage: %s par-file [block-name par-name]\n",argv[0]);
00896 exit(0);
00897 }
00898
00899 par_debug(0);
00900 par_open(argv[1]);
00901 par_cmdline(argc,argv);
00902 if (argc == 4) {
00903 char *cp = par_gets(argv[2],argv[3]);
00904 int ival;
00905 double dval;
00906 char *sval = "hello world";
00907 printf("PAR_GETS: %s.%s = \"%s\"\n",argv[2],argv[3],cp);
00908 printf("PAR_GETI: %s.%s = \"%d\" as integer\n",
00909 argv[2],argv[3],par_geti(argv[2],argv[3]));
00910 printf("PAR_GETD: %s.%s = \"%g\" as double\n",
00911 argv[2],argv[3],par_getd(argv[2],argv[3]));
00912 free(cp);
00913 }
00914 par_dump(0,stdout);
00915 par_close();
00916 return 0;
00917 }
00918 #endif
00919 #endif