00001
00007
00008
00009
00010
00011
00012 #include <stdlib.h>
00013 #include <string.h>
00014 #include "ParseOptions.h"
00015 #include "ConfigList.h"
00016 #include "InfoStream.h"
00017
00018 #include "strlib.h"
00019
00020
00021 const char *rstring(Range r)
00022 {
00023 switch (r) {
00024 case FREE_RANGE: return "unconstrained";
00025 case POSITIVE: return "positive";
00026 case NOT_NEGATIVE: return "non-negative";
00027 case NEGATIVE: return "negative";
00028 case NOT_POSITIVE: return "non-positive";
00029 default: return "error in rstring(Range )";
00030 }
00031 }
00032
00033 static const char *unit_string_array[N_UNITS_UNDEFINED+1] = {
00034 "", "fs", "ns", "sec", "min", "hr", "A", "nm", "m",
00035 "kcal", "kJ", "eV", "K", "undefined units"
00036 };
00037
00038 const char *ustring(Units u)
00039 {
00040 return unit_string_array[u];
00041 }
00042
00043
00044 Units static next(Units u) {
00045 switch (u) {
00046 case N_UNIT: return N_FSEC;
00047 case N_FSEC: return N_NSEC;
00048 case N_NSEC: return N_SEC;
00049 case N_SEC: return N_MIN;
00050 case N_MIN: return N_HOUR;
00051 case N_HOUR: return N_ANGSTROM;
00052 case N_ANGSTROM: return N_NANOMETER;
00053 case N_NANOMETER: return N_METER;
00054 case N_METER: return N_KCAL;
00055 case N_KCAL: return N_KJOULE;
00056 case N_KJOULE: return N_EV;
00057 case N_EV: return N_KELVIN;
00058 case N_KELVIN: return N_UNITS_UNDEFINED;
00059 default: return N_UNITS_UNDEFINED;
00060 }
00061 }
00062
00063
00064 Units ParseOptions::atoUnits(const char *s) {
00065 Units u;
00066 for (u=N_UNIT; u!=N_UNITS_UNDEFINED; u = next(u)) {
00067 if (!strcasecmp(unit_string_array[u], s)) return u;
00068 }
00069 if (!strcasecmp(s, "Angstrom")) return N_ANGSTROM;
00070 if (!strcasecmp(s, "kcal/mol")) return N_KCAL;
00071 if (!strcasecmp(s, "kJ/mol")) return N_KJOULE;
00072 return N_UNITS_UNDEFINED;
00073 }
00074
00075
00076
00077
00078 static BigReal scaling_factors[N_UNITS_UNDEFINED+1] = {
00079 1, 1, 1000, 1E15, 60E15, 3600E15, 1, 10, 1E10, 1, 1/4.1855, 1/23.052,
00080 1, 0
00081 };
00082
00083
00084
00085 BigReal convert(Units to, Units from)
00086 {
00087
00088
00089 if (from == N_UNIT && to == N_UNIT) { return 1.0; }
00090 if ((from == N_NSEC || from == N_FSEC || from == N_SEC || from == N_MIN ||
00091 from == N_HOUR) &&
00092 (to == N_NSEC || to == N_FSEC || to == N_SEC || to == N_MIN ||
00093 to == N_HOUR)) {
00094 return scaling_factors[from]/scaling_factors[to];
00095 }
00096 if ((from == N_METER || from == N_NANOMETER || from == N_ANGSTROM) &&
00097 (to == N_METER || to == N_NANOMETER || to == N_ANGSTROM)) {
00098 return scaling_factors[from]/scaling_factors[to];
00099 }
00100 if ((from == N_KCAL || from == N_KJOULE || from == N_EV) &&
00101 (to == N_KCAL || to == N_KJOULE || to == N_EV)) {
00102 return scaling_factors[from]/scaling_factors[to];
00103 }
00104 if (from == N_KELVIN && to == N_KELVIN) {
00105 return scaling_factors[from]/scaling_factors[to];
00106 }
00107 return 0.0;
00108 }
00109
00110 static char *Strdup(const char *newname)
00111 {
00112 char *tmp = new char[strlen(newname)+1];
00113 strcpy(tmp, newname);
00114 return tmp;
00115 }
00116
00117
00118 void ParseOptions::DataElement::init(const char *newname,
00119 const char *newparent, int optional, const char *err) {
00120 name = Strdup(newname);
00121 index = -1;
00122 is_optional = optional;
00123 is_defined = FALSE;
00124 parent = Strdup(newparent);
00125 parent_ptr = NULL;
00126 error_message = Strdup(err);
00127 type = UNDEF;
00128 has_default = FALSE;
00129 many_allowed = FALSE;
00130 idef = 0;
00131 iptr = NULL;
00132 range = FREE_RANGE;
00133 units = N_UNIT;
00134 }
00135
00136 #define dataelement_cons_macro_default(Mtype, MType, Mptr, Mdef) \
00137 ParseOptions::DataElement::DataElement(const char *newname, \
00138 const char *newparent, int optional, const char *err, \
00139 Mtype *ptr, Mtype defalt) \
00140 { \
00141 init(newname, newparent, optional, err); \
00142 type = MType; \
00143 Mptr = ptr; \
00144 Mdef = defalt; \
00145 has_default = TRUE; \
00146 }
00147
00148 #define dataelement_cons_macro(Mtype, MType, Mptr) \
00149 ParseOptions::DataElement::DataElement(const char *newname, \
00150 const char *newparent, int optional, const char *err, \
00151 Mtype *ptr) \
00152 { \
00153 init(newname, newparent, optional, err); \
00154 type = MType; \
00155 Mptr = ptr; \
00156 }
00157
00158 dataelement_cons_macro_default(BigReal, FLOAT, fptr, fdef);
00159 dataelement_cons_macro_default(int, INT, iptr, idef);
00160 dataelement_cons_macro_default(unsigned int, UINT, uiptr, uidef);
00161 dataelement_cons_macro_default(Vector, VECTOR, vptr, vdef);
00162
00163
00164 dataelement_cons_macro(BigReal, FLOAT, fptr);
00165 dataelement_cons_macro(Vector, VECTOR, vptr);
00166 dataelement_cons_macro(int, INT, iptr);
00167 dataelement_cons_macro(unsigned int, UINT, uiptr);
00168
00169 dataelement_cons_macro(char, STRING, sptr);
00170
00171
00172
00173 ParseOptions::DataElement::DataElement(const char *newname,
00174 const char *newparent, int optional, const char *err, StringList **ptr,
00175 int many)
00176 {
00177 init(newname, newparent, optional, err);
00178 type = DataElement::STRINGLIST;
00179 slptr = ptr;
00180 has_default = FALSE;
00181 many_allowed = many;
00182 }
00183
00184
00185 ParseOptions::DataElement::~DataElement(void) {
00186 if (name) delete[] name;
00187 if (parent) delete[] parent;
00188 if (error_message) delete[] error_message;
00189 }
00191
00192
00193
00194 ParseOptions::ParseOptions(void) {
00195 configList = NULL;
00196 array_size = 0;
00197 array_max_size = 20;
00198 data_array = new DataElement*[array_max_size];
00199 DataElement *tmp = new DataElement("main", "main", TRUE,
00200 "Error in ParseOptions",
00201 (int *) NULL, 0);
00202 tmp->type = DataElement::UNDEF;
00203 add_element(tmp);
00204 }
00205
00206
00207 ParseOptions::~ParseOptions(void) {
00208 for (int i=0; i<array_size; i++) {
00209 delete data_array[i];
00210 }
00211 delete [] data_array;
00212 }
00213
00214
00215 void ParseOptions::add_element(DataElement *el) {
00216 if (array_size == array_max_size) {
00217 array_max_size += 30;
00218 DataElement **tmp = new DataElement*[array_max_size];
00219 memcpy(tmp, data_array, array_size * sizeof(DataElement *));
00220 delete [] data_array;
00221 data_array = tmp;
00222 }
00223 el->index = array_size;
00224 data_array[array_size++] = el;
00225 }
00226
00227
00228
00229 int ParseOptions::make_dependencies(DataElement *el) {
00230 int i;
00231
00232 if (!strcasecmp(el->name, el->parent)) {
00233 return FALSE;
00234 }
00235
00236 for (i=0; i<array_size; i++) {
00237 if (!strcasecmp(data_array[i]->name, el->name) &&
00238 el != data_array[i]) {
00239 return FALSE;
00240 }
00241 }
00242
00243
00244 for (i=0; i<array_size; i++) {
00245 if (!strcasecmp(data_array[i]->name, el->parent)) {
00246 el->parent_ptr = data_array[i];
00247 break;
00248 }
00249 }
00250
00251
00252
00253 for (i=0; i<array_size; i++) {
00254 if (!data_array[i]->parent_ptr) {
00255 if (!strcasecmp(data_array[i]->parent,
00256 el->name)) {
00257 data_array[i]->parent_ptr = el;
00258 }
00259 }
00260 }
00261 return TRUE;
00262 }
00263
00264
00266 #define parse_input_macro_default(fctnname, type, optional) \
00267 int ParseOptions::fctnname(const char *parent, const char *newname, \
00268 const char *msg, type *ptr, type defalt) \
00269 { \
00270 DataElement *tmp = new DataElement(newname, parent, optional, msg, \
00271 ptr, defalt); \
00272 if (!make_dependencies(tmp)) { \
00273 iout << iERROR << "ParseOption '" << newname << "' already exists" << "\n" << endi; \
00274 return FALSE; \
00275 } \
00276 add_element(tmp); \
00277 return TRUE; \
00278 }
00279 #define parse_input_macro(fctnname, type, optional) \
00280 int ParseOptions::fctnname(const char *parent, const char *newname, \
00281 const char *msg, type *ptr) \
00282 { \
00283 DataElement *tmp = new DataElement(newname, parent, optional, msg, \
00284 ptr); \
00285 if (!make_dependencies(tmp)) { \
00286 iout << iERROR << "ParseOption '" << newname << "' already exists" << "\n" << endi; \
00287 return FALSE; \
00288 } \
00289 add_element(tmp); \
00290 return TRUE; \
00291 }
00292 #define parse_input_macro_default_b(fctnname, type, optional, extra) \
00293 int ParseOptions::fctnname(const char *parent, const char *newname, \
00294 const char *msg, type *ptr, type defalt) \
00295 { \
00296 DataElement *tmp = new DataElement(newname, parent, optional, msg, \
00297 ptr, defalt); \
00298 if (!make_dependencies(tmp)) { \
00299 iout << iERROR << "ParseOption '" << newname << "' already exists" << "\n" << endi; \
00300 return FALSE; \
00301 } \
00302 add_element(tmp); \
00303 extra; \
00304 return TRUE; \
00305 }
00306 #define parse_input_macro_b(fctnname, type, optional, extra) \
00307 int ParseOptions::fctnname(const char *parent, const char *newname, \
00308 const char *msg, type *ptr) \
00309 { \
00310 DataElement *tmp = new DataElement(newname, parent, optional, msg, \
00311 ptr); \
00312 if (!make_dependencies(tmp)) { \
00313 iout << iERROR << "ParseOption '" << newname << "' already exists" << "\n" << endi; \
00314 return FALSE; \
00315 } \
00316 add_element(tmp); \
00317 extra; \
00318 return TRUE; \
00319 }
00320
00321 parse_input_macro(require, BigReal, FALSE);
00322 parse_input_macro(require, Vector, FALSE);
00323 parse_input_macro(require, int, FALSE);
00324 parse_input_macro(require, unsigned int, FALSE);
00325 parse_input_macro_b(requireB, int, FALSE, tmp->type = DataElement::BOOL);
00326 parse_input_macro(require, char, FALSE);
00327
00328 parse_input_macro(optional, BigReal, TRUE);
00329 parse_input_macro(optional, Vector, TRUE);
00330 parse_input_macro(optional, int, TRUE);
00331 parse_input_macro(optional, unsigned int, TRUE);
00332 parse_input_macro_b(optionalB, int, TRUE, tmp->type = DataElement::BOOL);
00333 parse_input_macro(optional, char, TRUE);
00334
00335 parse_input_macro_default(require, BigReal, FALSE);
00336 parse_input_macro_default(require, Vector, FALSE);
00337 parse_input_macro_default(require, int, FALSE);
00338 parse_input_macro_default(require, unsigned int, FALSE);
00339 parse_input_macro_default_b(requireB, int, FALSE, tmp->type=DataElement::BOOL);
00340
00341 parse_input_macro_default(optional, BigReal, TRUE);
00342 parse_input_macro_default(optional, Vector, TRUE);
00343 parse_input_macro_default(optional, int, TRUE);
00344 parse_input_macro_default(optional, unsigned int, TRUE);
00345 parse_input_macro_default_b(optionalB, int, TRUE, tmp->type=DataElement::BOOL);
00346
00347 #define parse_stringlist_macro(fctn, xxx) \
00348 int ParseOptions::fctn(const char *parent, const char *newname, \
00349 const char *msg, StringList **ptr, int many_allowed)\
00350 { \
00351 DataElement *tmp = new DataElement(newname, parent, xxx, msg, \
00352 ptr, many_allowed); \
00353 if (!make_dependencies(tmp)) { \
00354 iout << iERROR << "ParseOption '" << newname << "' already exists" << "\n" << endi;\
00355 return FALSE; \
00356 } \
00357 add_element(tmp); \
00358 return TRUE; \
00359 }
00360 parse_stringlist_macro(require, FALSE);
00361 parse_stringlist_macro(optional, TRUE);
00362
00363
00364
00365
00366
00367 int ParseOptions::check_children(int idx, int *flgs)
00368 {
00369 if (flgs[idx]) {
00370 return 0;
00371 }
00372 flgs[idx] = 1;
00373 for (int i=0; i<array_size; i++) {
00374 if (data_array[i]->parent_ptr == data_array[idx]) {
00375 if (!check_children(i, flgs)) {
00376 return 0;
00377 }
00378 }
00379 }
00380 return 1;
00381 }
00382
00383
00384
00385
00386 Bool ParseOptions::check_consistancy(void) {
00387 int i;
00388
00389 {
00390 int has_error = FALSE;
00391 for(i=1; i<array_size; i++) {
00392 if (!data_array[i]->parent_ptr) {
00393
00394 iout << iERROR << "Configuration element '" << data_array[i]->name
00395 << "' defined, but the parent element" << "\n" << endi;
00396 iout << iERROR << " '" << data_array[i]->parent << "' is nowhere "
00397 << "to be found" << "\n" << endi;
00398 has_error = TRUE;
00399 }
00400 }
00401 if (has_error) return 0;
00402 }
00403
00404
00405 int *arr = new int[array_size];
00406 for (i=0; i<array_size; i++) {
00407 arr[i] = 0;
00408 }
00409 if (!check_children(0, arr)) {
00410
00411 iout << iERROR << "Loop found in ParseOptions data" << "\n" << endi;
00412 delete [] arr;
00413 return 0;
00414 }
00415
00416
00417 {
00418 int has_error = FALSE;
00419 for (i=1; i<array_size; i++) {
00420 if (arr[i] == 0) {
00421
00422 if (has_error == FALSE) {
00423 iout << iERROR
00424 << "Found data in ParseOptions which are inaccessible "
00425 << "to" << "\n" << endi;
00426 iout << iERROR
00427 << "the main data heirarchy. Errors in:" << "\n" << endi;
00428 has_error = TRUE;
00429 }
00430 iout << iERROR << " '" << data_array[i]->name << "' depends on '"
00431 << data_array[i]->parent << "'" << "\n" << endi;
00432 }
00433 }
00434 if (has_error) {
00435 delete [] arr;
00436 return 0;
00437 }
00438 }
00439
00440 delete [] arr;
00441 return 1;
00442 }
00443
00444
00445 int ParseOptions::atoBool(const char *s)
00446 {
00447 if (!strcasecmp(s, "on")) return 1;
00448 if (!strcasecmp(s, "off")) return 0;
00449 if (!strcasecmp(s, "true")) return 1;
00450 if (!strcasecmp(s, "false")) return 0;
00451 if (!strcasecmp(s, "yes")) return 1;
00452 if (!strcasecmp(s, "no")) return 0;
00453 if (!strcasecmp(s, "1")) return 1;
00454 if (!strcasecmp(s, "0")) return 0;
00455 return -1;
00456 }
00457
00458
00459
00460
00461
00462
00463
00464 Bool ParseOptions::is_parent_node(DataElement *el) {
00465 for (int i=1; i<array_size; i++) {
00466 if (data_array[i]->parent_ptr == el) {
00467 return 1;
00468 }
00469 }
00470 return 0;
00471 }
00472
00473
00474
00475 Bool ParseOptions::scan_float(DataElement *data, const char *s)
00476 {
00477 double input_value;
00478 BigReal fval;
00479 char units_str[80];
00480 char tmp_str[80];
00481 int count = sscanf(s, "%lf%s%s", &input_value, units_str, tmp_str);
00482 fval = input_value;
00483 if (count == 1) {
00484 data->fdata = fval;
00485 return TRUE;
00486 }
00487 if (count == 2) {
00488 Units u = atoUnits(units_str);
00489 if (u == N_UNITS_UNDEFINED) {
00490 iout << iERROR << "Could not understand units '" << units_str
00491 << "' in option '" << data->name << " = " << s
00492 << "\n" << endi;
00493 return FALSE;
00494 }
00495 BigReal scale = convert(data->units, u);
00496 if (scale == 0) {
00497 iout << iERROR << "Could not translate from units '" << ustring(u)
00498 << "' to '" << ustring(data->units) << "' for option '"
00499 << data->name << "'" << "\n" << endi;
00500 return FALSE;
00501 }
00502
00503 data->fdata = fval * scale;
00504 return TRUE;
00505 }
00506 if (count <=0) {
00507 iout << iERROR << "Expecting value and optional units for option '"
00508 << data->name << "'" << "\n" << endi;
00509 }
00510 if (count > 2) {
00511 iout << iERROR << "Too much information given to '" << data -> name
00512 << " = " << s << "'" << "\n" << endi;
00513 iout << iERROR << " - expecting a value and optional units" << "\n" << endi;
00514 }
00515 return FALSE;
00516 }
00517
00518
00519 Bool ParseOptions::scan_vector(DataElement *data, const char *s)
00520 {
00521 Vector v;
00522 if (!v.set(s)) {
00523 iout << iERROR << "Could not translate the value '" << s << "'" << "\n" << endi;
00524 iout << iERROR << " into a Vector for the option '" << data->name << "'"
00525 << "\n" << endi;
00526 return FALSE;
00527 }
00528 data->vdata = v;
00529 return TRUE;
00530 }
00531
00532
00533
00534 Bool ParseOptions::scan_int(DataElement *data, const char *s)
00535 {
00536 int ival;
00537 char units_str[80];
00538 char tmp_str[80];
00539 int count = sscanf(s, "%d%s%s", &ival, units_str, tmp_str);
00540 if (count == 1) {
00541 data->idata = ival;
00542 return TRUE;
00543 }
00544 iout << iERROR << "Expecting only a number for '" << data->name
00545 << "' input, got: " << s << "\n" << endi;
00546 return FALSE;
00547 }
00548
00549
00550
00551 Bool ParseOptions::scan_uint(DataElement *data, const char *s)
00552 {
00553 unsigned int ival;
00554 char units_str[80];
00555 char tmp_str[80];
00556 int count = sscanf(s, "%u%s%s", &ival, units_str, tmp_str);
00557 if (count == 1) {
00558 data->idata = ival;
00559 return TRUE;
00560 }
00561 iout << iERROR << "Expecting only a number for '" << data->name
00562 << "' input, got: " << s << "\n" << endi;
00563 return FALSE;
00564 }
00565
00566 Bool ParseOptions::scan_bool(DataElement *data, const char *s)
00567 {
00568 int tmp = atoBool(s);
00569
00570 if (tmp == -1)
00571 {
00572 iout << iERROR << "ParseOptions can't understand '" << s << "' for the "
00573 << "\n" << endi;
00574 iout << iERROR << " Boolean variable '" << data->name << "'" << "\n" << endi;
00575
00576 data->idata = FALSE;
00577
00578 return FALSE;
00579 }
00580
00581 data->idata = tmp;
00582
00583 return TRUE;
00584 }
00585
00586
00587
00588 #define set_macro(type, field, fieldptr) \
00589 int ParseOptions::set_##type(DataElement *el) \
00590 { \
00591 if (el->range == FREE_RANGE || \
00592 (el->range == POSITIVE && el->field > 0) || \
00593 (el->range == NOT_NEGATIVE && el->field >= 0) || \
00594 (el->range == NEGATIVE && el->field < 0) || \
00595 (el->range == NOT_POSITIVE && el->field <= 0)) { \
00596 if (el->fieldptr) *(el->fieldptr) = el->field; \
00597 return 1; \
00598 } \
00599 iout << iERROR << "'" << el->name << "' was set to " << el->field << " but it " \
00600 << "should be " << rstring(el->range) \
00601 << "\n" << endi; \
00602 return 0; \
00603 }
00604 set_macro(float, fdata, fptr);
00605 set_macro(int, idata, iptr);
00606 set_macro(uint, uidata, uiptr);
00607
00608
00609 #define simple_set_macro(type, field, fieldptr) \
00610 void ParseOptions::set_##type(DataElement *el) \
00611 { \
00612 if (el->fieldptr) *(el->fieldptr) = el->field; \
00613 }
00614
00615 simple_set_macro(bool, idata, iptr);
00616 simple_set_macro(vector, vdata, vptr);
00617 simple_set_macro(stringlist, sldata, slptr);
00618
00619
00620 void ParseOptions::set_string(DataElement *el)
00621 {
00622 if (el->sptr) strcpy(el->sptr, el->sldata->data);
00623 }
00624
00625
00626
00627 Bool ParseOptions::set(const ConfigList& clist)
00628 {
00629
00630 int cont = TRUE, i;
00631 StringList *slptr;
00632 DataElement *data;
00633 int has_error = FALSE;
00634 int *checked = new int[array_size];
00635 configList = &clist;
00636
00637
00638
00639
00640 for (i=0; i<array_size; i++)
00641 {
00642 checked[i] = FALSE;
00643 }
00644
00645
00646 data_array[0]->is_defined = TRUE;
00647 checked[0] = TRUE;
00648
00649
00650 while (cont)
00651 {
00652 cont = FALSE;
00653 for (i=1; i<array_size; i++)
00654 {
00655 data = data_array[i];
00656
00657
00658
00659 if (!checked[data->index] &&
00660 checked[data-> parent_ptr -> index] &&
00661 data -> parent_ptr -> is_defined)
00662 {
00663 cont = TRUE;
00664 checked[data->index] = TRUE;
00665
00666
00667 slptr = clist.find(data->name);
00668
00669 if (slptr != NULL)
00670 {
00671
00672
00673
00674
00675 if (!data->many_allowed && slptr->next != NULL)
00676 {
00677 iout << iERROR << "Multiple definitions of '" << data->name << "'" << "\n" << endi;
00678 iout << iERROR << " in the configuration file are not allowed" << "\n" << endi;
00679 has_error = TRUE;
00680 }
00681
00682 data->is_defined = TRUE;
00683
00684
00685 if (data->type == DataElement::FLOAT)
00686 {
00687 if (!scan_float(data, slptr->data))
00688 has_error = TRUE;
00689 }
00690 else if (data->type == DataElement::VECTOR)
00691 {
00692 if (!scan_vector(data, slptr->data))
00693 has_error = TRUE;
00694 }
00695 else if (data->type == DataElement::INT)
00696 {
00697 if (!scan_int(data, slptr->data))
00698 has_error = TRUE;
00699 }
00700 else if (data->type == DataElement::UINT)
00701 {
00702 if (!scan_uint(data, slptr->data))
00703 has_error = TRUE;
00704 }
00705 else if (data->type == DataElement::BOOL)
00706 {
00707 if (!scan_bool(data, slptr->data))
00708 has_error = TRUE;
00709 }
00710 else if (data->type == DataElement::STRINGLIST ||
00711 data->type == DataElement::STRING )
00712 {
00713 data->sldata = slptr;
00714 }
00715 else
00716 {
00717 iout << iERROR << "Unknown ParseOption data type " << (int)(data->type) << " for "
00718 << "variable " << data->name << "\n" << endi;
00719 }
00720 }
00721 else
00722 {
00723 if (data->has_default)
00724 {
00725 data->is_defined = TRUE;
00726
00727 if (data->type == DataElement::FLOAT)
00728 {
00729 data->fdata = data->fdef;
00730 }
00731 else if (data->type == DataElement::VECTOR)
00732 {
00733 data->vdata = data->vdef;
00734 }
00735 else if (data->type == DataElement::UINT)
00736 {
00737 data->uidata = data->uidef;
00738 }
00739 else if (data->type == DataElement::INT ||
00740 data->type == DataElement::BOOL)
00741 {
00742 data->idata = data->idef;
00743 }
00744 else
00745 {
00746 iout << iERROR << "Unknown ParseOption data type " << (int)(data->type) << " for "
00747 << "variable " << data->name << "\n" << endi;
00748 }
00749 }
00750 }
00751
00752
00753
00754
00755 if (!data->is_defined)
00756 {
00757 if (!data->is_optional)
00758 {
00759 has_error = TRUE;
00760 iout << iERROR << "'" << data->name << "' is a required configuration option" << "\n" << endi;
00761
00762
00763 if (data->parent_ptr != data_array[0])
00764 {
00765 iout << iERROR << " when '" << data->parent_ptr -> name << "' is set" << "\n" << endi;
00766 }
00767
00768 iout << iERROR << data->name << " defines: " << data->error_message << "\n" << endi;
00769
00770 }
00771 }
00772 else
00773 {
00774 if (data->type == DataElement::FLOAT)
00775 {
00776 if (!set_float(data))
00777 has_error = TRUE;
00778 }
00779 else if ( data -> type == DataElement::VECTOR)
00780 {
00781 set_vector(data);
00782 }
00783 else if ( data -> type == DataElement::INT)
00784 {
00785 if (!set_int(data))
00786 has_error = TRUE;
00787 }
00788 else if ( data -> type == DataElement::UINT)
00789 {
00790 if (!set_uint(data))
00791 has_error = TRUE;
00792 }
00793 else if ( data -> type == DataElement::BOOL)
00794 {
00795 set_bool(data);
00796
00797 if (is_parent_node(data))
00798 {
00799
00800
00801
00802 data->is_defined = data->idata;
00803 }
00804 }
00805 else if ( data -> type == DataElement::STRINGLIST)
00806 {
00807 set_stringlist(data);
00808 }
00809 else if ( data -> type == DataElement::STRING)
00810 {
00811 set_string(data);
00812 }
00813 else
00814 {
00815
00816 }
00817 }
00818 }
00819 }
00820 }
00821
00822
00823
00824
00825
00826
00827 {
00828 int flg = 0;
00829
00830 for (int i=1; i<array_size; i++)
00831 {
00832 if (!checked[i]) {
00833 data = data_array[i];
00834 if (clist.find(data->name)) {
00835 if (flg == 0) {
00836 flg = 1;
00837 iout << iWARN
00838 << "The following variables were set in the\n";
00839 iout << iWARN
00840 << "configuation file but were not needed" << "\n" << endi;
00841 }
00842 iout << iWARN << " " << data->name << "\n" << endi;
00843 }
00844 }
00845 }
00846 }
00847
00848
00849 {
00850 int flg = 0;
00851 ConfigList::ConfigListNode const *ptr;
00852 for (ptr = clist.head(); ptr != NULL; ptr = ptr -> next) {
00853 if (!exists(ptr -> name)) {
00854 if (flg == 0) {
00855 flg = 1;
00856 has_error = TRUE;
00857 iout << iERROR
00858 << "The following variables were set in the\n";
00859 iout << iERROR
00860 << "configuration file but are NOT VALID\n" << endi;
00861 }
00862 iout << iERROR << " " << ptr -> name << "\n" << endi;
00863 }
00864 }
00865 }
00866
00867 delete [] checked;
00868 return !has_error;
00869 }
00870
00871
00872 ParseOptions::DataElement *ParseOptions::internal_find(const char* name)
00873 {
00874 for (int i=1; i<array_size; i++) {
00875 if (!strcasecmp(name, data_array[i]->name)) {
00876 return data_array[i];
00877 }
00878 }
00879 return NULL;
00880 }
00881
00882
00883 Bool ParseOptions::exists(const char *name)
00884 {
00885 if (!name) return 0;
00886 if (internal_find(name)) {
00887 return 1;
00888 }
00889 return 0;
00890 }
00891
00892 Bool ParseOptions::defined(const char *name)
00893 {
00894 if (!name) return FALSE;
00895 DataElement *tmp = internal_find(name);
00896 if (!tmp) return FALSE;
00897 if (tmp->is_defined) {
00898 return TRUE;
00899 }
00900 return FALSE;
00901 }
00902
00904
00905
00906
00907 Bool ParseOptions::get(const char* name, int *val) {
00908 if (!val) return FALSE;
00909 DataElement *el = internal_find(name);
00910 if (el == NULL || !el->is_defined) {
00911 return FALSE;
00912 }
00913 switch (el->type) {
00914 case DataElement::FLOAT :
00915 iout << iWARN
00916 << "ParseOptions doing a conversion from float to int for '"
00917 << name << "'" << "\n" << endi;
00918 *val = (int) el->fdata;
00919 return TRUE;
00920 case DataElement::INT:
00921 case DataElement::BOOL:
00922 *val = el->idata;
00923 return TRUE;
00924 case DataElement::STRINGLIST :
00925 case DataElement::STRING :
00926 iout << iWARN
00927 << "ParseOptions doing a conversion from StringList[0] to int "
00928 << "for '" << name << "'" << "\n" << endi;
00929 *val = atoi(el->sldata->data);
00930 return TRUE;
00931 case DataElement::VECTOR :
00932 iout << iERROR
00933 << "ParseOptions cannot convert from Vector to int for '"
00934 << name << "'" << "\n" << endi;
00935 return FALSE;
00936 default:
00937 iout << iERROR
00938 << "Unknown data type " << (int)(el->type) << " for '" << name << "'"
00939 << "\n" << endi;
00940 }
00941 return FALSE;
00942 }
00943
00944 Bool ParseOptions::get(const char* name, BigReal *val) {
00945 if (!val) return FALSE;
00946 DataElement *el = internal_find(name);
00947 if (el == NULL || !el->is_defined) {
00948 return FALSE;
00949 }
00950 switch (el -> type) {
00951 case DataElement::FLOAT:
00952 *val = el->fdata;
00953 return TRUE;
00954 case DataElement::INT:
00955 iout << iWARN
00956 << "ParseOptions doing a conversion from int to float '"
00957 << name << "'" << "\n" << endi;
00958 *val = (BigReal) el->idata;
00959 return TRUE;
00960 case DataElement::BOOL:
00961 iout << iWARN
00962 << "ParseOptions doing a conversion from boolean to float for '"
00963 << name << "'" << "\n" << endi;
00964 *val = (BigReal) el->idata;
00965 return TRUE;
00966 case DataElement::STRING:
00967 case DataElement::STRINGLIST:
00968 iout << iWARN
00969 << "ParseOptions doing a conversion from StringList[0] to float "
00970 << "for '" << name << "'" << "\n" << endi;
00971 *val = atof(el->sldata->data);
00972 return TRUE;
00973 case DataElement::VECTOR :
00974 iout << iERROR
00975 << "ParseOptions cannot convert from Vector to float for '"
00976 << name << "'" << "\n" << endi;
00977 return FALSE;
00978 default:
00979 iout << iERROR
00980 << "Unknown data type " << (int)(el->type) << " for '" << name << "'"
00981 << "\n" << endi;
00982 }
00983 return FALSE;
00984 }
00985 Bool ParseOptions::get(const char *name, Vector *val) {
00986 if (!val) return FALSE;
00987 DataElement *el = internal_find(name);
00988 if (el == NULL || !el->is_defined) {
00989 return FALSE;
00990 }
00991 switch (el -> type) {
00992 case DataElement::FLOAT:
00993 iout << iERROR
00994 << "ParseOptions cannot convert from float to Vector for '"
00995 << name << "'" << "\n" << endi;
00996 return FALSE;
00997 case DataElement::INT:
00998 iout << iERROR
00999 << "ParseOptions cannot convert from int to Vector for '"
01000 << name << "'" << "\n" << endi;
01001 return FALSE;
01002 case DataElement::STRING:
01003 case DataElement::STRINGLIST:{
01004 iout << iWARN
01005 << "ParseOptions doing a conversion from StringList[0] to "
01006 << "Vector for '" << name << "'" << "\n" << endi;
01007 Vector v;
01008 if (!v.set(el->sldata->data)) {
01009 iout << iERROR
01010 << "Could not convert '" << el->sldata->data
01011 << "' to a Vector";
01012 return FALSE;
01013 }
01014 *val = v;
01015 return TRUE;
01016 }
01017 case DataElement::VECTOR :
01018 *val = el->vdata;
01019 return TRUE;
01020 default:
01021 iout << iERROR
01022 << "Unknown data type " << (int)(el->type) << " for '" << name << "'"
01023 << "\n" << endi;
01024
01025 }
01026 return FALSE;
01027 }
01028 Bool ParseOptions::get(const char *name, StringList **val) {
01029 if (!val) return FALSE;
01030 DataElement *el = internal_find(name);
01031 if (el == NULL || !el->is_defined) {
01032 return FALSE;
01033 }
01034
01035
01036 if (!configList) { return FALSE; }
01037 *val = configList->find(name);
01038 if (!*val) { return FALSE; }
01039 return TRUE;
01040 }
01041
01042
01043 Bool ParseOptions::get(const char *name, char *val, int n)
01044 {
01045 if (!val || n<0) {return FALSE;}
01046 StringList *tmp;
01047 if (!get(name, &tmp)) {val[0]=STRINGNULL; return FALSE; }
01048 int i=n;
01049 while (i>0 && tmp) {
01050 tmp=tmp->next;
01051 i--;
01052 }
01053 if (tmp) {
01054 strcpy(val, tmp->data);
01055 return TRUE;
01056 }
01057 val[0] = STRINGNULL;
01058 return FALSE;
01059 }
01060
01061
01062 int ParseOptions::num(const char *name)
01063 {
01064 DataElement *el = internal_find(name);
01065 if (!el || !el ->is_defined) {
01066 return 0;
01067 }
01068 if (!el->many_allowed) {
01069 return 1;
01070 }
01071 StringList *tmp;
01072 if (!get(name, &tmp)) { return 0; }
01073 int i=0;
01074 while (tmp) {
01075 i++;
01076 tmp=tmp->next;
01077 }
01078 return i;
01079 }
01080
01081
01082
01083 void ParseOptions::range(const char *name, Range newrange)
01084 {
01085 DataElement *el = internal_find(name);
01086 if (!el) {
01087 iout << iERROR
01088 << "Trying to set the range of undefined variable '"
01089 << name << "'" << "\n" << endi;
01090 return;
01091 }
01092 el->range = newrange;
01093
01094 }
01095 Range ParseOptions::range(const char *name)
01096 {
01097 DataElement *el = internal_find(name);
01098 if (!el) {
01099 iout << iERROR
01100 << "Trying to get the range of undefined variable '"
01101 << name << "'" << "\n" << endi;
01102 return FREE_RANGE;
01103 }
01104 return el->range;
01105 }
01106
01107
01108 Bool ParseOptions::units(const char *name, Units units)
01109 {
01110 DataElement *tmp = internal_find(name);
01111 if (!tmp) {
01112 iout << iERROR
01113 << name << " not found so units not set" << "\n" << endi;
01114 return FALSE;
01115 }
01116 if ((tmp -> type == DataElement::INT && units != N_UNIT) ||
01117 (tmp -> type != DataElement::INT &&
01118 tmp -> type != DataElement::FLOAT)) {
01119 iout << iERROR
01120 << "Cannot set units '" << ustring(units) << "' for option '"
01121 << name << "'; wrong data type" << "\n" << endi;
01122 return FALSE;
01123 }
01124 tmp -> units = units;
01125 return TRUE;
01126 }
01127
01128 Bool ParseOptions::units(const char *name, Units *units)
01129 {
01130 DataElement *tmp = internal_find(name);
01131 *units = N_UNIT;
01132 if (!tmp) {
01133 iout << iERROR
01134 << "'" << name << "' doesn't exist so cannot get its units"
01135 << "\n" << endi;
01136 return FALSE;
01137 }
01138 if (tmp -> type != DataElement::INT &&
01139 tmp -> type != DataElement::FLOAT) {
01140 iout << iERROR
01141 << "Can only get units for FLOAT and INT variables, and '"
01142 << name << "' isn't one of those" << "\n" << endi;
01143 return FALSE;
01144 }
01145 *units = tmp->units;
01146 return TRUE;
01147 }
01148