18 #include "Parameters.h" 20 #include "MathConstant.h" 22 #include "PhoneHome.h" 30 int Parameter::nameCol = 30;
31 int Parameter::statusCol = 15;
33 Parameter::Parameter(
char c,
const char * desc,
void * v)
35 ch = (char) tolower(c);
36 description =
new char [strlen(desc) + 1];
37 strcpy(description, desc);
45 bool Parameter::Read(
int ,
char ** argv,
int argn)
48 char c = (char) tolower(argv[argn][p]);
50 if ((c ==
'-') || (c ==
'/'))
53 c = (char) tolower(argv[argn][p]);
58 Translate(&(argv[argn][++p]));
64 bool Parameter::TranslateExtras(
const char * ,
const char *)
69 void Parameter::warning(
const char * format, ...)
75 buffer.vprintf(format, ap);
81 (*warnings) += buffer;
84 void IntParameter::Translate(
const char * value)
86 *(
int *) var = atoi(value);
89 bool IntParameter::TranslateExtras(
const char * value,
const char * extras)
91 if (value[0] != 0 || !CheckInteger(extras))
99 void IntParameter::Status()
101 fprintf(stderr,
"%*s : %*d (-%c9999)\n", nameCol, description,
102 statusCol, *(
int *) var, ch);
105 void SwitchParameter::Translate(
const char * value)
110 *(
bool *) var =
true;
113 *(
bool *) var =
false;
116 *(
bool *) var = ! * (
bool *) var;
119 warning(
"Command line parameter -%c%s: the option '%c' has no meaning\n",
120 ch, value, value[0]);
124 void SwitchParameter::Status()
126 fprintf(stderr,
"%*s : %*s (-%c[+|-])\n", nameCol, description,
127 statusCol, *(
bool *) var ==
false ?
"OFF" :
"ON", ch);
130 DoubleParameter::DoubleParameter(
char c,
const char * desc,
double & v)
136 void DoubleParameter::Translate(
const char * value)
139 *(
double *) var = atof(value);
141 *(
double *) var = _NAN_;
144 bool DoubleParameter::TranslateExtras(
const char * value,
const char * extras)
146 if (value[0] != 0 || !CheckDouble(extras))
154 void DoubleParameter::Status()
156 double absolute_value = fabs(* (
double *) var);
158 if (*(
double *) var == _NAN_)
159 fprintf(stderr,
"%*s : %*s (-%c99.999)\n", nameCol, description,
160 statusCol,
"NAN", ch);
161 else if (absolute_value >= 0.00095)
162 fprintf(stderr,
"%*s : % *.*f (-%c99.999)\n", nameCol, description,
163 statusCol, precision, * (
double *) var, ch);
164 else if (absolute_value <= 1e-15)
165 fprintf(stderr,
"%*s : % *.0f (-%c99.999)\n", nameCol, description,
166 statusCol, * (
double *) var, ch);
168 fprintf(stderr,
"%*s : %*.0e (-%c99.999)\n", nameCol, description,
169 statusCol, *(
double *) var, ch);
172 void StringParameter::Translate(
const char * value)
179 bool StringParameter::TranslateExtras(
const char * value,
const char * extras)
181 if ((value[0] != 0) || ((!required) && (extras[0] ==
'-')))
191 void StringParameter::Status()
193 fprintf(stderr,
"%*s : %*s (-%cname)\n", nameCol, description,
194 statusCol, (
const char *)(*(
String *) var), ch);
197 void ListParameter::Status()
201 for (l = options; l->ch != 0; l++)
202 if (l->code == *((
int *)var))
205 fprintf(stderr,
"%*s : %*s (-%c[%s])\n", nameCol, description,
206 statusCol, l->description, ch, (
const char *) key);
209 void ListParameter::Translate(
const char * value)
213 for (l = options; l->ch != 0; l++)
214 if (tolower(l->ch) == tolower(value[0]))
217 if (l->ch == 0 && tolower(value[0]) != 0)
218 warning(
"Command line parameter -%c%s: the option '%c' has no meaning\n",
219 ch, value, value[0], (
const char *) key);
221 *((
int*) var) = l->code;
224 ListParameter::ListParameter(
char c,
const char * desc,
int & v,
OptionList * opt)
229 for (
OptionList * l = options; l->ch != 0; l++)
235 key.SetLength(key.Length() - 1);
238 SetParameter::SetParameter(
char c,
const char * desc,
int & v,
OptionList * opt)
243 for (
OptionList * l = options; l->ch != 0; l++)
248 key.SetLength(key.Length() - 1);
251 void SetParameter::Status()
254 int temp = * (
int *) var;
256 for (
OptionList * l = options; l->ch != 0; l++)
257 if ((l->code & temp) || (l->code == *(
int *) var))
260 fprintf(stderr,
"%*s : %*s (-%c{%s})\n", nameCol, description,
261 statusCol, l->description, ch, (
const char *) key);
263 fprintf(stderr,
"%*s & %*s\n", nameCol,
"",
264 statusCol, l->description);
270 void SetParameter::Translate(
const char * value)
274 for (
const char * chr = value; *chr != 0; chr++)
278 for (
OptionList * l = options; l->ch != 0; l++)
279 if (tolower(l->ch) == tolower(*chr))
281 *((
int*) var) |= l->code;
286 warning(
"Command line parameter -%c%s: the option '%c' has no meaning\n",
302 while (ptr->description != NULL)
304 if (ptr->type == LP_LEGACY_PARAMETERS)
306 if(ptr->type == LP_PHONEHOME_VERSION)
310 myNoPhoneHome =
false;
311 myVersion = ptr->description;
312 ptr->description =
"noPhoneHome";
313 ptr->value = &myNoPhoneHome;
314 ptr->type = LP_BOOL_PARAMETER;
315 index.Add(ptr->description, ptr);
319 if (ptr->value != NULL)
320 index.Add(ptr->description, ptr);
322 group_len = max(strlen(ptr->description), group_len);
327 while (ptr->description != NULL)
329 if(ptr->type == LP_PHONEHOME_VERSION)
333 myNoPhoneHome =
false;
334 myVersion = ptr->description;
335 ptr->description =
"noPhoneHome";
336 ptr->value = &myNoPhoneHome;
337 ptr->type = LP_BOOL_PARAMETER;
338 legacyIndex.Add(ptr->description, ptr);
342 if (ptr->value != NULL)
343 legacyIndex.Add(ptr->description, ptr);
351 void LongParameters::ExplainAmbiguity(
const char * cstr)
355 int p = value.FastFindChar(
':');
356 String stem = p == -1 ? value : value.Left(p);
359 for (
int i = 0; i < index.Length(); i++)
360 if (index[i].SlowCompareToStem(stem) == 0)
362 if (matches.Length() + index[i].Length() > 50)
368 matches.catprintf(
" --%s", (
const char *) index[i]);
371 warning(
"Ambiguous --%s matches%s\n",
372 (
const char *) value, (
const char *) matches);
375 void LongParameters::Translate(
const char * cstr)
379 int p = value.FastFindChar(
':');
380 int option = p == -1 ? index.FindStem(value) : index.FindStem(value.Left(p));
384 ExplainAmbiguity(cstr);
394 int alternate = p == -1 ? legacyIndex.FindFirstStem(value) :
395 legacyIndex.FindFirstStem(value.Left(p));
399 warning(
"Command line parameter --%s is undefined\n", (
const char *) value);
408 if (ptr->type == LP_BOOL_PARAMETER)
411 * (
bool *) ptr->value ^=
true;
413 *(
bool *) ptr->value = value.SubStr(p + 1).SlowCompare(
"ON") == 0;
418 for (
int i = -1; ptr[i].exclusive; i--) *(
bool *)ptr[i].value =
false;
419 for (
int i = 1; ptr[i].exclusive; i++) *(
bool *)ptr[i].value =
false;
422 else if (ptr->type == LP_INT_PARAMETER)
424 * (
int *) ptr->value = * (
int *) ptr->value ? 0 : 1;
426 *(
int *) ptr->value = value.SubStr(p + 1).SlowCompare(
"ON") == 0 ?
427 1 : value.SubStr(p + 1).AsInteger();
428 else if (ptr->type == LP_DOUBLE_PARAMETER)
431 * (
double *) ptr->value = value.SubStr(p + 1).AsDouble();
433 else if (ptr->type == LP_STRING_PARAMETER)
436 * (
String *) ptr->value = value.SubStr(p + 1);
440 bool LongParameters::TranslateExtras(
const char * cstr,
const char * extras)
442 if (strchr(cstr,
':') != NULL)
445 int option = index.FindStem(cstr);
461 option = legacyIndex.FindFirstStem(cstr);
470 if (ptr->type == LP_INT_PARAMETER && CheckInteger(extras))
472 *(
int *) ptr->value = atoi(extras);
476 else if (ptr->type == LP_DOUBLE_PARAMETER && CheckDouble(extras))
478 *(
double *) ptr->value = atof(extras);
482 else if (ptr->type == LP_STRING_PARAMETER)
484 *(
String *) ptr->value = extras;
492 void LongParameters::Status(
LongParameterList * ptr,
int & line_len,
bool & need_a_comma)
495 int line_start = group_len ? group_len + 5 : 0;
497 if (ptr->value == NULL)
499 fprintf(stderr,
"%s %*s :", need_a_comma ?
"\n" :
"", group_len + 2, ptr->description);
500 need_a_comma =
false;
501 line_len = line_start;
505 if (ptr->type == LP_BOOL_PARAMETER)
506 state = * (
bool *) ptr->value ?
" [ON]" :
"";
507 else if (ptr->type == LP_INT_PARAMETER)
508 if (((* (
int *) ptr->value == 1) && (ptr->exclusive)) || (* (
int *) ptr->value == 0))
509 state = * (
int *) ptr->value ?
" [ON]" :
"";
511 state =
" [", state += * (
int *) ptr->value, state +=
']';
512 else if (ptr->type == LP_DOUBLE_PARAMETER)
513 if (* (
double *) ptr->value != _NAN_)
515 double value = * (
double *) ptr->value;
518 if (value == 0.0 || value >= 0.01)
519 state.catprintf(
"%.*f", precision, value);
521 state.catprintf(
"%.1e", value);
526 else if (ptr->type == LP_STRING_PARAMETER)
527 state =
" [" + * (
String *) ptr->value +
"]";
529 int item_len = 3 + strlen(ptr->description) + need_a_comma + state.Length();
531 if (item_len + line_len > 78 && line_len > line_start)
533 line_len = line_start;
534 fprintf(stderr,
"%s\n%*s", need_a_comma ?
"," :
"", line_len,
"");
539 fprintf(stderr,
"%s --%s%s", need_a_comma ?
"," : (need_a_comma =
true,
""),
540 ptr->description, (
const char *) state);
543 line_len += item_len;
547 void LongParameters::Status()
549 if (description != NULL && description[0] != 0)
550 fprintf(stderr,
"\n%s\n", description);
552 bool need_a_comma =
false;
555 bool legacy_parameters =
false;
556 int legacy_count = 0;
559 if (ptr->type == LP_LEGACY_PARAMETERS)
560 legacy_parameters =
true;
561 else if (legacy_parameters ==
false)
562 Status(ptr, line_len, need_a_comma);
563 else if (ptr->touched)
565 if (legacy_count == 0)
567 fprintf(stderr,
"\n\nAdditional Options:\n %*s ", group_len + 3,
"");
568 line_len = group_len + 5;
569 need_a_comma =
false;
572 Status(ptr, line_len, need_a_comma);
576 fprintf(stderr,
"\n");
579 void LongParameters::addParamsToString(
String& params)
585 if(!params.IsEmpty())
587 params += PARAM_STR_SEP;
589 params += ptr->description;
596 if (count + 1 >= size)
597 error(
"Parameter list size should be increased");
599 p->SetWarningBuffer(warnings);
603 void ParameterList::Read(
int argc,
char ** argv,
int start)
605 MakeString(argc, argv, start);
606 for (
int i=start; i < argc; i++)
608 bool success =
false;
610 if (argv[i][0] ==
'-' && argv[i][1])
611 for (
int j=0; j<count; j++)
613 success = tolower(argv[i][1]) == pl[j]->ch;
617 if ((i+1 < argc) && pl[j]->TranslateExtras(argv[i]+2, argv[i+1]))
619 else if (argv[i][2] == 0 && (i+1 < argc) && (argv[i + 1][0] !=
'-'))
620 pl[j]->Translate(argv[++i]);
622 pl[j]->Translate(argv[i] + 2);
632 warning.printf(
"Command line parameter %s (#%d) ignored\n", argv[i], i);
637 if (warnings.Length())
639 ::warning(
"Problems encountered parsing command line:\n\n%s",
640 (
const char *) warnings);
644 HandlePhoneHome(argc, argv, start);
647 int ParameterList::ReadWithTrailer(
int argc,
char ** argv,
int start)
649 MakeString(argc, argv, start);
651 int last_success = start - 1;
654 for (
int i=start; i < argc; i++)
656 bool success =
false;
658 if (argv[i][0] ==
'-' && argv[i][1])
659 for (
int j=0; j<count; j++)
661 success = tolower(argv[i][1]) == pl[j]->ch;
665 if ((i+1 < argc) && pl[j]->TranslateExtras(argv[i]+2, argv[i+1]))
667 else if (argv[i][2] == 0 && (i+1 < argc) && (argv[i + 1][0] !=
'-'))
668 pl[j]->Translate(argv[i + 1]), split =
true;
670 pl[j]->Translate(argv[i] + 2);
676 for (last_success++; last_success < i; last_success++)
677 warnings.printf(
"Command line parameter %s (#%d) ignored\n",
678 argv[last_success], last_success);
688 if (warnings.Length())
690 ::warning(
"Problems encountered parsing command line:\n\n%s",
691 (
const char *) warnings);
695 HandlePhoneHome(argc, argv, start);
701 void ParameterList::Status()
703 for (
int i=0; i<count; i++)
706 fprintf(stderr,
"\n");
708 if (messages.Length())
709 fprintf(stderr,
"NOTES:\n%s\n", (
const char *) messages);
712 void ParameterList::MakeString(
int argc,
char ** argv,
int start)
716 for (
int i=start; i<argc; i++)
717 len += strlen(argv[i]) + 1;
719 string =
new char [len+1];
722 for (
int i=start; i<argc; i++)
724 strcat(
string, argv[i]);
730 void ParameterList::HandlePhoneHome(
int argc,
char ** argv,
int start)
734 for(
int i = 0; i < start; i++)
738 programName = argv[i];
743 programName += argv[i];
751 for (
int i=0; i<count; i++)
753 pl[i]->addParamsToString(params);
755 if(!pl[i]->myVersion.IsEmpty() && (!pl[i]->myNoPhoneHome))
759 version = pl[i]->myVersion;
763 if(!version.IsEmpty())
765 PhoneHome::checkVersion(programName.c_str(),
772 ParameterList::~ParameterList()
774 for (
int i = 0; i < count; i++)
780 bool Parameter::CheckInteger(
const char * value)
782 if (value[0] !=
'+' && value[0] !=
'-' &&
783 (value[0] <
'0' || value[0] >
'9'))
787 while (value[pos] != 0)
788 if (value[pos] <
'0' || value[pos] >
'9')
796 bool Parameter::CheckDouble(
const char * value)
798 if (value[0] !=
'+' && value[0] !=
'-' && value[0] !=
'.' &&
799 (value[0] <
'0' || value[0] >
'9'))
804 bool decimal = value[0] ==
'.';
806 for (
int pos = 1; value[pos] != 0; pos++)
808 if (value[pos] <
'0' || value[pos] >
'9')
810 if (!decimal && value[pos] ==
'.')
814 else if (value[pos] ==
'e' || value[pos] ==
'E')
816 return CheckInteger(value + pos + 1);
824 void ParameterList::Enforce(
bool & var,
bool value,
const char * format, ...)
834 va_start(ap, format);
835 buffer.vprintf(format, ap);
841 void ParameterList::Enforce(
int & var,
int value,
const char * format, ...)
851 va_start(ap, format);
852 buffer.vprintf(format, ap);
858 void ParameterList::Enforce(
double & var,
double value,
const char * format, ...)
868 va_start(ap, format);
869 buffer.vprintf(format, ap);
875 void ParameterList::Enforce(
String & var,
const char * value,
const char * format, ...)
877 if (var.SlowCompare(value) == 0)
884 va_start(ap, format);
885 buffer.vprintf(format, ap);
892 LongParamContainer::LongParamContainer()
896 add(NULL, NULL,
false, 0, 0);
900 LongParamContainer::~LongParamContainer()
905 void LongParamContainer::add(
const char * label,
void * val,
bool excl,
906 int paramType,
bool touch)
908 if(myEndIndex+1 < MAX_PARAM_ARRAY_SIZE)
911 myArray[myEndIndex].description = label;
912 myArray[myEndIndex].value = val;
913 myArray[myEndIndex].exclusive = excl;
914 myArray[myEndIndex].type = paramType;
915 myArray[myEndIndex].touched = touch;
919 myArray[myEndIndex].description = NULL;
920 myArray[myEndIndex].value = NULL;
921 myArray[myEndIndex].exclusive =
false;
922 myArray[myEndIndex].type = 0;
923 myArray[myEndIndex].touched = 0;
927 throw std::runtime_error(
"Tool Error: trying to add more parameters than allowed in LongParamContainer.\n");