00001
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 #include "w_defines.h"
00054
00055
00056
00057 #define OPTION_C
00058 #ifdef __GNUC__
00059 # pragma implementation
00060 #endif
00061
00062 #include "w.h"
00063 #include <cstring>
00064 #include <cctype>
00065 #include "w_autodel.h"
00066 #include "option.h"
00067 #include "w_debug.h"
00068
00069 #include "regex_posix.h"
00070
00071 #ifdef EXPLICIT_TEMPLATE
00072 template class w_list_i<option_t,unsafe_list_dummy_lock_t>;
00073 template class w_list_t<option_t,unsafe_list_dummy_lock_t>;
00074 #endif
00075
00076
00077 option_t::option_t() : _name(NULL), _value(NULL), _setFunc(NULL)
00078 {
00079 }
00080
00081 option_t::~option_t()
00082 {
00083 _link.detach();
00084 if (_value) free(_value);
00085 _value = NULL;
00086 _name = NULL;
00087 }
00088
00089 w_rc_t option_t::init(const char* name, const char* newPoss,
00090 const char* defaultVal, const char* descr,
00091 bool req, OptionSetFunc setFunc,
00092 ostream *err_stream)
00093 {
00094 _name = name;
00095 _possible_values = newPoss;
00096 _default_value = defaultVal;
00097 _required = req;
00098 _description = descr;
00099 _setFunc = setFunc;
00100 _set = false;
00101 if (!_required) {
00102 if (_default_value) {
00103 w_rc_t rc = set_value(_default_value, false, err_stream);
00104 _set = false;
00105 return rc;
00106 }
00107 }
00108 return RCOK;
00109 }
00110
00111 bool option_t::match(const char* matchName, bool exact)
00112 {
00113 int i;
00114 bool equal;
00115
00116 i = 0;
00117 equal = true;
00118
00119 DBG(<<"name to match is " << matchName);
00120 while(equal) {
00121 if ( (matchName[i] != '\0') && (_name[i] != '\0') ) {
00122 if (matchName[i] != _name[i]) {
00123 DBG(<<"fails because at " << i <<
00124 " matchName is " << matchName[i] <<
00125 " _name is " << _name[i]
00126 );
00127 equal = false;
00128 }
00129 } else {
00130 if (matchName[i] == '\0') {
00131 break;
00132 } else {
00133 DBG(<<"fails because at " << i <<
00134 " matchName is " << matchName[i] <<
00135 " _name is " << _name[i]
00136 );
00137 equal = false;
00138
00139 }
00140 }
00141 i++;
00142 }
00143
00144 if (i == 0) {
00145 equal = false;
00146 } else {
00147 if (exact && (matchName[i] != '\0' || _name[i] != '\0')) {
00148 equal = false;
00149 }
00150 }
00151 return equal;
00152 }
00153
00154 w_rc_t option_t::set_value(const char* value, bool overRide, ostream* err_stream)
00155 {
00156 DBG(<<"option_t::set_value " << name()
00157 << " value = " << value);
00158 if (_set && !overRide) {
00159
00160 return RCOK;
00161 }
00162
00163 if (value == NULL) {
00164 if (_value) {
00165 free(_value);
00166 _set = false;
00167 }
00168 return RCOK;
00169 } else {
00170 W_DO(_setFunc(this, value, err_stream));
00171 }
00172 return RCOK;
00173 }
00174
00175 w_rc_t option_t::copyValue(const char* value)
00176 {
00177 char* new_value;
00178
00179 if (_value) {
00180 new_value = (char*)realloc(_value, strlen(value)+1);
00181 } else {
00182 new_value = (char*)malloc(strlen(value)+1);
00183 }
00184 if (!new_value) {
00185 return RC(fcOUTOFMEMORY);
00186 }
00187 _value = new_value;
00188 strcpy(_value, value);
00189 _set = true;
00190 return RCOK;
00191 }
00192
00193 w_rc_t option_t::concatValue(const char* value)
00194 {
00195 char* new_value;
00196 const char* separator = "\n";
00197
00198 if (_value) {
00199 new_value = (char*)realloc(_value, strlen(_value) + strlen(separator) + strlen(value)+1);
00200 } else {
00201 new_value = (char*)malloc(strlen(value)+1);
00202 }
00203 if (!new_value) {
00204 return RC(fcOUTOFMEMORY);
00205 }
00206 _value = new_value;
00207 strcat(_value, separator);
00208 strcat(_value, value);
00209 _set = true;
00210 return RCOK;
00211 }
00212
00213 bool option_t::str_to_bool(const char* str, bool& badStr)
00214 {
00215 badStr = true;
00216 if (strlen(str) < 1) return false;
00217
00218 switch (str[0]) {
00219 case 't': case 'T': case 'y': case 'Y':
00220 badStr = false;
00221 return true;
00222
00223 case 'f': case 'F': case 'n': case 'N':
00224 badStr = false;
00225 return false;
00226
00227 default:
00228 return false;
00229 }
00230 }
00231
00232 w_rc_t option_t::set_value_bool(option_t* opt, const char* value, ostream* err_stream)
00233 {
00234 bool badVal;
00235 str_to_bool(value, badVal);
00236 if (badVal) {
00237 if (err_stream) *err_stream << "value must be true,false,yes,no";
00238 return RC(OPT_BadValue);
00239 }
00240 W_DO(opt->copyValue(value));
00241 return RCOK;
00242 }
00243
00244 w_rc_t
00245 option_t::set_value_int4(
00246 option_t* opt,
00247 const char* value,
00248 ostream* err_stream)
00249 {
00250 long l;
00251 char* lastValid;
00252
00253 errno = 0;
00254 l = strtol(value, &lastValid, 0);
00255 if(((l == LONG_MAX) || (l == LONG_MIN)) && errno == ERANGE) {
00256
00257 if (err_stream) {
00258 *err_stream
00259 << "value is out of range for a long integer "
00260 << value;
00261 return RC(OPT_BadValue);
00262 }
00263 }
00264 if (lastValid == value) {
00265
00266 if (err_stream) *err_stream << "no valid integer could be formed from " << value;
00267 return RC(OPT_BadValue);
00268 }
00269
00270 W_DO(opt->copyValue(value));
00271 return RCOK;
00272 }
00273
00274 w_rc_t
00275 option_t::set_value_long(
00276 option_t* opt,
00277 const char* value,
00278 ostream* err_stream)
00279 {
00280
00281 return set_value_int4(opt, value, err_stream);
00282 }
00283
00284 w_rc_t
00285 option_t::set_value_int8(
00286 option_t* opt,
00287 const char* value,
00288 ostream* err_stream)
00289 {
00290
00291 char* lastValid;
00292 errno = 0;
00293
00294
00295
00296 (void) w_base_t::strtoi8(value, &lastValid);
00297 if (errno == ERANGE) {
00298
00299 if (err_stream) {
00300 *err_stream
00301 << "value is out of range for a long integer "
00302 << value;
00303 return RC(OPT_BadValue);
00304 }
00305 }
00306 if (lastValid == value) {
00307
00308 if (err_stream) *err_stream
00309 << "no valid integer could be formed from " << value;
00310 return RC(OPT_BadValue);
00311 }
00312
00313
00314 W_DO(opt->copyValue(value));
00315 return RCOK;
00316 }
00317
00318 w_rc_t
00319 option_t::set_value_long_long(
00320 option_t* opt,
00321 const char* value,
00322 ostream* err_stream)
00323 {
00324 return set_value_int8(opt, value, err_stream);
00325 }
00326
00327 w_rc_t option_t::set_value_charstr(
00328 option_t* opt,
00329 const char* value,
00330 ostream *
00331 )
00332 {
00333 W_DO(opt->copyValue(value));
00334 return RCOK;
00335 }
00336
00337
00338
00339
00340
00341 bool option_group_t::_error_codes_added = false;
00342
00343 #include "opt_einfo_gen.h"
00344
00345 option_group_t::option_group_t(int maxNameLevels)
00346 : _options(W_LIST_ARG(option_t, _link), unsafe_nolock),
00347 _class_name(NULL),
00348 _levelLocation(NULL),
00349 _maxLevels(maxNameLevels),
00350 _numLevels(0)
00351 {
00352 if (!_error_codes_added) {
00353 if (!(w_error_t::insert(
00354 "Options Package",
00355 opt_error_info,
00356 OPT_ERRMAX - OPT_ERRMIN + 1)) ) {
00357 abort();
00358 }
00359 _error_codes_added = true;
00360 }
00361
00362
00363 _class_name = (char*)malloc(1);
00364 _levelLocation = new char*[_maxLevels];
00365
00366 if (_class_name == NULL || _levelLocation == NULL) {
00367 W_FATAL(fcOUTOFMEMORY);
00368 }
00369 _class_name[0] = '\0';
00370 }
00371
00372 option_group_t::~option_group_t()
00373 {
00374 w_list_i<option_t,unsafe_list_dummy_lock_t> scan(_options);
00375
00376 while (scan.next()) {
00377 delete scan.curr();
00378 }
00379 if (_class_name) free(_class_name);
00380 if (_levelLocation) delete[] _levelLocation;
00381 }
00382
00383 w_rc_t option_group_t::add_option(
00384 const char* name, const char* newPoss,
00385 const char* default_value, const char* description,
00386 bool required, option_t::OptionSetFunc setFunc,
00387 option_t*& newOpt,
00388 ostream *err_stream
00389 )
00390 {
00391 DBG(<<"option_group_t::add_option " << name );
00392 W_DO(lookup(name, true, newOpt));
00393 if (newOpt) return RC(OPT_Duplicate);
00394
00395 newOpt = new option_t();
00396 if (!newOpt) return RC(fcOUTOFMEMORY);
00397 w_rc_t rc = newOpt->init(name, newPoss,
00398 default_value, description, required, setFunc, err_stream);
00399 if (rc.is_error()) {
00400 delete newOpt;
00401 newOpt = NULL;
00402 return rc;
00403 }
00404 _options.append(newOpt);
00405 return RCOK;
00406 }
00407
00408 w_rc_t option_group_t::add_class_level(const char* name)
00409 {
00410 if (_numLevels == _maxLevels) {
00411 return RC(OPT_TooManyClasses);
00412 }
00413
00414 char* new_str = (char*)realloc(_class_name, strlen(_class_name)+strlen(name)+2);
00415 if (!new_str) {
00416 return RC(fcOUTOFMEMORY);
00417 }
00418 _class_name = new_str;
00419 _levelLocation[_numLevels] = &(_class_name[strlen(_class_name)]);
00420 _numLevels++;
00421 strcat(_class_name, name);
00422 strcat(_class_name, ".");
00423
00424 return RCOK;
00425 }
00426
00427 w_rc_t option_group_t::lookup(const char* name, bool exact, option_t*& returnOption)
00428 {
00429 DBG(<<"option_group_t::lookup " << name << " exact=" << exact);
00430 w_rc_t rc;
00431
00432 returnOption = NULL;
00433
00434 w_list_i<option_t,unsafe_list_dummy_lock_t> scan(_options);
00435 while (scan.next()) {
00436 DBG(<<"scan.curr()==|" << scan.curr()->name() <<"|");
00437 if (scan.curr()->match(name, exact)) {
00438 DBG(<<"match");
00439 if (returnOption != NULL) {
00440 returnOption = NULL;
00441 rc = RC(OPT_Duplicate);
00442 } else {
00443
00444 returnOption = scan.curr();
00445 }
00446 break;
00447 } else {
00448 DBG(<<"nomatch");
00449 }
00450 }
00451 DBG(<<"option_group_t::lookup " << name << " scan done" );
00452 return rc;
00453 }
00454
00455 w_rc_t
00456 option_group_t::lookup_by_class(
00457 const char* optClassName,
00458 option_t*& returnOption,
00459 bool exact
00460 )
00461 {
00462 const char* c;
00463 const char* lastSpecial;
00464
00465 int lastNewSpecial;
00466 w_rc_t rc;
00467 int newClen;
00468 const char* regex = NULL;
00469 bool backSlash = false;
00470
00471 DBG(<<"option_group_t::lookup_by_class " << optClassName);
00472
00473
00474
00475 int newC_len = strlen(optClassName)*2;
00476 char* newC = new char[newC_len];
00477 if (!newC) return RC(fcOUTOFMEMORY);
00478 w_auto_delete_array_t<char> newC_delete(newC);
00479
00480
00481
00482 lastSpecial = optClassName-1;
00483 lastNewSpecial = 0;
00484 newC[lastNewSpecial] = '^';
00485 for (c = optClassName, newClen = 1; *c != '\0'; c++, newClen++) {
00486 if (!backSlash) {
00487 switch (*c) {
00488 case '*':
00489 newC[newClen] = '.';
00490 newClen++;
00491 newC[newClen] = '*';
00492 lastSpecial = c;
00493 lastNewSpecial = newClen;
00494 break;
00495 case '.':
00496 newC[newClen] = '\\';
00497 newClen++;
00498 newC[newClen] = '.';
00499 lastSpecial = c;
00500 lastNewSpecial = newClen;
00501 break;
00502 case '?':
00503 newC[newClen++] = '[';
00504 newC[newClen++] = '^';
00505 newC[newClen++] = '.';
00506 newC[newClen++] = ']';
00507 newC[newClen] = '*';
00508 lastSpecial = c;
00509 lastNewSpecial = newClen;
00510 break;
00511 case ':':
00512
00513 rc = RC(OPT_Syntax);
00514 break;
00515 case ' ': case '\t':
00516 rc = RC(OPT_IllegalClass);
00517 break;
00518 case '\\':
00519 backSlash = true;
00520 newClen--;
00521 break;
00522 default:
00523 newC[newClen] = *c;
00524 }
00525
00526 } else {
00527 newC[newClen] = *c;
00528 backSlash = false;
00529 }
00530
00531 if (lastNewSpecial == newC_len) {
00532 rc = RC(OPT_ClassTooLong);
00533 }
00534 }
00535
00536 if (rc.is_error()) return rc;
00537
00538 if (*c != '\0') {
00539 return RC(OPT_Syntax);
00540 } else {
00541 newC[newClen] = *c;
00542 }
00543
00544
00545 if (lastSpecial == (optClassName-1)) {
00546 return RC(OPT_IllegalClass);
00547 }
00548
00549 newC[lastNewSpecial+1] = '$';
00550 newC[lastNewSpecial+2] = '\0';
00551
00552 if (newC[1] == '$') {
00553 strcat(newC, ".*");
00554 }
00555
00556 regex = re_comp(newC);
00557 if (regex != NULL) {
00558 cerr << "regular expression error: " << regex << endl;
00559 rc = RC(OPT_IllegalClass);
00560 } else {
00561 if (re_exec(_class_name) == 1) {
00562 DBG(<<"re_exec("<<_class_name<<") returned 1");
00563
00564
00565 const char* option = lastSpecial+1;
00566 return lookup(option, exact, returnOption);
00567 } else {
00568 DBG(<<"re_exec("<<_class_name<<") failed");
00569 rc = RC(OPT_NoClassMatch);
00570 }
00571
00572 }
00573
00574 delete regex;
00575 returnOption = NULL;
00576 return rc;
00577 }
00578
00579 w_rc_t
00580 option_group_t::set_value(
00581 const char* name, bool exact,
00582 const char* value, bool overRide,
00583 ostream* err_stream)
00584 {
00585 DBG(<<"option_group_t::set_value: " << name
00586 << " exact=" << exact);
00587 option_t* opt = 0;
00588 W_DO(lookup(name, exact, opt));
00589 if (!opt) {
00590 DBG(<<"nomatch");
00591 return RC(OPT_NoOptionMatch);
00592 }
00593 DBG(<<"MATCH");
00594 W_DO(opt->set_value(value, overRide, err_stream));
00595 return RCOK;
00596 }
00597
00598
00599 void
00600 option_group_t::print_usage(bool longForm, ostream& err_stream)
00601 {
00602 option_t* current;
00603
00604 w_list_i<option_t,unsafe_list_dummy_lock_t> scan(_options);
00605 while (scan.next()) {
00606 current = scan.curr();
00607 if (current->is_required()) {
00608 err_stream << " ";
00609 } else {
00610 err_stream << " [";
00611 }
00612 if (current->possible_values() == NULL) {
00613 err_stream << "-" << current->name();
00614 } else {
00615 err_stream << "-" << current->name()
00616 << " <" << current->possible_values() << ">";
00617 }
00618
00619 if (!current->is_required()) err_stream << "]";
00620
00621 if (longForm) {
00622 err_stream << "\n\t\t" << current->description() << "\n";
00623 if (current->default_value() == NULL) {
00624 err_stream << "\t\tdefault value: <none>\n";
00625 } else {
00626 err_stream << "\t\tdefault value: " << current->default_value() << "\n";
00627 }
00628 }
00629 }
00630 if (!longForm) err_stream << endl;
00631 err_stream << "[brackets means optional]" << endl;
00632
00633 return;
00634 }
00635
00636 void option_group_t::print_values(bool longForm, ostream& err_stream)
00637 {
00638 option_t* current;
00639
00640 err_stream << "Values for options of class " << _class_name << ":";
00641 if (longForm) err_stream << "\n";
00642 w_list_i<option_t,unsafe_list_dummy_lock_t> scan(_options);
00643 while (scan.next()) {
00644 current = scan.curr();
00645 if (current->is_set()) {
00646 if (!current->is_required()) {
00647 err_stream << " [-" << current->name() << " ";
00648 } else {
00649 err_stream << " -" << current->name() << " ";
00650 }
00651 if (current->value() == NULL) {
00652 err_stream << "<not-set>";
00653 } else {
00654 err_stream << current->value();
00655 }
00656 if (!current->is_required()) err_stream << "]";
00657
00658 if (longForm) err_stream << "\n";
00659 }
00660 }
00661 if (!longForm) err_stream << endl;
00662
00663 return;
00664 }
00665
00666 w_rc_t option_group_t::check_required(ostream* err_stream)
00667 {
00668 DBG(<<"option_group_t::check_required");
00669 w_rc_t rc;
00670 option_t* curr;
00671 bool at_least_one_not_set = false;
00672
00673 w_list_i<option_t,unsafe_list_dummy_lock_t> scan(_options);
00674 while ((curr = scan.next())) {
00675 if (curr->is_required() && !curr->is_set()) {
00676 if (err_stream) *err_stream << "option <" << curr->name() << "> is required but not set\n";
00677 at_least_one_not_set = true;
00678 }
00679 }
00680 if (at_least_one_not_set) rc = RC(OPT_NotSet);
00681 return rc;
00682 }
00683
00684 w_rc_t option_group_t::parse_command_line(const char** argv, int& argc, size_t min_len, ostream* err_stream)
00685 {
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695 w_rc_t rc;
00696 int i;
00697 option_t* opt;
00698
00699 i = 0;
00700 while (i < argc && !rc.is_error()) {
00701 if (argv[i][0] == '-' && strlen(argv[i]) > min_len) {
00702 rc = lookup(argv[i]+1, false, opt);
00703 if (!rc.is_error() && opt) {
00704
00705 if (i+1 == argc) {
00706
00707 if (err_stream) *err_stream << "missing argument for " << argv[i];
00708
00709 argc--;
00710 rc = RC(OPT_BadValue);
00711 } else {
00712
00713 rc = opt->set_value(argv[i+1], true, err_stream);
00714 if (rc.is_error()) {
00715 if (err_stream) *err_stream << "bad value for argument " << argv[i];
00716 }
00717
00718
00719 for (int j = i+2; j < argc; j++) {
00720 argv[j-2] = argv[j];
00721 }
00722 argc -= 2;
00723 }
00724 } else if (!rc.is_error()) {
00725
00726 i++;
00727 } else {
00728
00729 }
00730 } else {
00731 i++;
00732 }
00733 }
00734 return(rc);
00735 }
00736
00737
00738
00739
00740
00741 const char *option_stream_scan_t::default_label = "istream";
00742
00743 option_stream_scan_t::option_stream_scan_t(istream &is, option_group_t *list)
00744 : _input(is),
00745 _optList(list),
00746 _line(0),
00747 _label(default_label),
00748 _lineNum(0)
00749 {
00750 }
00751
00752 option_stream_scan_t::~option_stream_scan_t()
00753 {
00754 if (_line) {
00755 delete [] _line;
00756 _line = 0;
00757 }
00758 if (_label != default_label) {
00759 delete [] _label;
00760 _label = default_label;
00761 }
00762 }
00763
00764
00765 void option_stream_scan_t::setLabel(const char *newLabel)
00766 {
00767 if (_label != default_label) {
00768 delete [] _label;
00769 _label = default_label;
00770 }
00771 if (newLabel) {
00772
00773 char *s = new char[strlen(newLabel) + 1];
00774 if (s) {
00775 strcpy(s, newLabel);
00776 _label = s;
00777 }
00778 }
00779 }
00780
00781 w_rc_t option_stream_scan_t::scan(
00782 bool overRide,
00783 ostream& err_stream,
00784 bool exact,
00785 bool mismatch_ok
00786 )
00787 {
00788 option_t* optInfo;
00789 int optBegin, optEnd, valBegin, valEnd, valLength;
00790 int i;
00791 bool backSlash = false;
00792 const char* optionName = NULL;
00793
00794 if (!_line) {
00795 _line = new char[_maxLineLen+1];
00796 if (!_line)
00797 return RC(fcOUTOFMEMORY);
00798 }
00799
00800 DBG(<<"scanning options stream " << _label);
00801
00802 w_rc_t rc;
00803 while ( !rc.is_error() && (_input.getline(_line, _maxLineLen) != NULL) ) {
00804 _lineNum++;
00805 DBG(<<"scan line " << _lineNum);
00806
00807 if (strlen(_line)+1 >= _maxLineLen) {
00808 err_stream << "line " << _lineNum << " is too long";
00809 rc = RC(OPT_IllegalDescLine);
00810 break;
00811 }
00812
00813
00814
00815
00816 optBegin = -1;
00817 optEnd = -1;
00818 for (i = 0; _line[i] != '\0'; i++) {
00819 if (optBegin < 0) {
00820
00821 if (isspace(_line[i])) {
00822 continue;
00823 } else {
00824 optBegin = i;
00825 }
00826 }
00827 if (_line[i] == '\\') {
00828 backSlash = !backSlash;
00829 if (backSlash) continue;
00830 }
00831 if (_line[i] == ':' && !backSlash) {
00832 optEnd = i;
00833 break;
00834 }
00835 backSlash = false;
00836 }
00837
00838
00839 if (optBegin < 0 || _line[optBegin] == '#' || _line[optBegin] == '!') {
00840 continue;
00841 }
00842
00843
00844 if (optEnd < 0) {
00845 err_stream << "syntax error at " << _label << ":" << _lineNum;
00846 rc = RC(OPT_Syntax);
00847 break;
00848 }
00849 _line[optEnd] = '\0';
00850
00851 optionName = _line+optBegin;
00852
00853 rc = _optList->lookup_by_class(optionName, optInfo, exact);
00854 if (!rc.is_error() && optInfo == NULL) {
00855
00856 rc = RC(OPT_NoOptionMatch);
00857 }
00858
00859 switch (rc.err_num()) {
00860 case 0:
00861 break;
00862 case OPT_NoClassMatch:
00863
00864 break;
00865 case OPT_NoOptionMatch:
00866 if(!mismatch_ok) {
00867 err_stream << "unknown option at " << _label << ":" << _lineNum;
00868 }
00869 break;
00870 case OPT_Duplicate:
00871 err_stream << "option name is not unique at "
00872 << _label << ":" << _lineNum;
00873 break;
00874 case OPT_Syntax:
00875 err_stream << "syntax error at " << _label << ":" << _lineNum;
00876 break;
00877 case OPT_IllegalClass:
00878 err_stream << "illegal/missing option class at "
00879 << _label << ":" << _lineNum;
00880 break;
00881 default:
00882 err_stream << "general error in option at "
00883 << _label << ":" << _lineNum;
00884 break;
00885 }
00886
00887 if (rc.is_error()) {
00888 if (rc.err_num() == OPT_NoClassMatch) {
00889
00890 rc = RCOK;
00891 }
00892 if (mismatch_ok && rc.err_num() == OPT_NoOptionMatch) {
00893
00894 rc = RCOK;
00895 }
00896 continue;
00897 }
00898
00899
00900
00901
00902 valBegin = -1;
00903 valEnd = -1;
00904 for (i = optEnd+1; _line[i] != '\0'; i++) {
00905
00906 if (isspace(_line[i])) {
00907 if (valBegin < 0) {
00908 continue;
00909 }
00910 } else {
00911 if (valBegin < 0) {
00912 valBegin = i;
00913 }
00914 valEnd = i;
00915 }
00916 }
00917
00918 if (valBegin < 0) {
00919 err_stream << "syntax error (missing option value) at "
00920 << _label << ":" << _lineNum;
00921 rc = RC(OPT_Syntax);
00922 break;
00923 }
00924
00925
00926 if (_line[valBegin] == '"') {
00927 valBegin++;
00928 if (_line[valEnd] != '"') {
00929 err_stream << "syntax error (missing \") at "
00930 << _label << ":" << _lineNum;
00931 rc = RC(OPT_Syntax);
00932 break;
00933 }
00934 valEnd--;
00935 }
00936 valLength = valEnd - valBegin + 1;
00937
00938 if (valLength < 0) {
00939 err_stream << "syntax error (bad option value) at "
00940 << _label << ":" << _lineNum;
00941 rc = RC(OPT_Syntax);
00942 break;
00943 }
00944
00945 if (rc.is_error()) {
00946 continue;
00947 }
00948
00949
00950 if (optInfo != NULL) {
00951 _line[valEnd+1] = '\0';
00952 rc = optInfo->set_value(_line+valBegin, overRide, &err_stream);
00953 if (rc.is_error()) {
00954 err_stream << "Option value error at "
00955 << _label << ":" << _lineNum;
00956 break;
00957 }
00958 }
00959
00960 }
00961 DBG(<<"last line scanned: " << _lineNum);
00962
00963 return rc;
00964 }
00965
00966 option_file_scan_t::option_file_scan_t(const char* optFile, option_group_t* list)
00967 : _fileName(optFile),
00968 _optList(list)
00969 {
00970 }
00971
00972 option_file_scan_t::~option_file_scan_t()
00973 {
00974 }
00975
00976 w_rc_t option_file_scan_t::scan(
00977 bool overRide,
00978 ostream& err_stream,
00979 bool exact,
00980 bool mismatch_ok
00981 )
00982 {
00983 w_rc_t e;
00984
00985 DBG(<<"scanning options file " << _fileName);
00986
00987 ifstream f(_fileName);
00988
00989 if (!f) {
00990 e = RC(fcOS);
00991 DBG(<<"scan: open failure file " << _fileName);
00992 err_stream << "Could not open the option file " << _fileName;
00993 return e;
00994 }
00995 DBG(<<"scanning options file " << _fileName);
00996
00997 option_stream_scan_t ss(f, _optList);
00998 ss.setLabel(_fileName);
00999
01000 return ss.scan(overRide, err_stream, exact, mismatch_ok);
01001 }
01002