libStatGen Software  1
Parameters.cpp
00001 /*
00002  *  Copyright (C) 2010  Regents of the University of Michigan
00003  *
00004  *   This program is free software: you can redistribute it and/or modify
00005  *   it under the terms of the GNU General Public License as published by
00006  *   the Free Software Foundation, either version 3 of the License, or
00007  *   (at your option) any later version.
00008  *
00009  *   This program is distributed in the hope that it will be useful,
00010  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *   GNU General Public License for more details.
00013  *
00014  *   You should have received a copy of the GNU General Public License
00015  *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
00016  */
00017 
00018 #include "Parameters.h"
00019 #include "Constant.h"
00020 #include "MathConstant.h"
00021 #include "Error.h"
00022 #include "PhoneHome.h"
00023 
00024 #include <stdio.h>
00025 #include <ctype.h>
00026 #include <stdlib.h>
00027 #include <string.h>
00028 #include <stdexcept>
00029 
00030 int Parameter::nameCol = 30;
00031 int Parameter::statusCol = 15;
00032 
00033 Parameter::Parameter(char c, const char * desc, void * v)
00034 {
00035     ch = (char) tolower(c);
00036     description = new char [strlen(desc) + 1];
00037     strcpy(description, desc);
00038     var = v;
00039     warnings = NULL;
00040 
00041     myNoPhoneHome = true;
00042     myVersion.Clear();
00043 }
00044 
00045 bool Parameter::Read(int , char ** argv, int argn)
00046 {
00047     int   p = 0;
00048     char  c = (char) tolower(argv[argn][p]);
00049 
00050     if ((c == '-') || (c == '/'))
00051     {
00052         p++;
00053         c = (char) tolower(argv[argn][p]);
00054     }
00055 
00056     if (c == ch)
00057     {
00058         Translate(&(argv[argn][++p]));
00059         return true;
00060     }
00061     return false;
00062 }
00063 
00064 bool Parameter::TranslateExtras(const char * , const char *)
00065 {
00066     return false;
00067 }
00068 
00069 void Parameter::warning(const char * format, ...)
00070 {
00071     String buffer;
00072 
00073     va_list ap;
00074     va_start(ap, format);
00075     buffer.vprintf(format, ap);
00076     va_end(ap);
00077 
00078     if (warnings == NULL)
00079         ::warning(buffer);
00080     else
00081         (*warnings) += buffer;
00082 }
00083 
00084 void IntParameter::Translate(const char * value)
00085 {
00086     *(int *) var = atoi(value);
00087 }
00088 
00089 bool IntParameter::TranslateExtras(const char * value, const char * extras)
00090 {
00091     if (value[0] != 0 || !CheckInteger(extras))
00092         return false;
00093 
00094     Translate(extras);
00095 
00096     return true;
00097 }
00098 
00099 void IntParameter::Status()
00100 {
00101     fprintf(stderr, "%*s : %*d (-%c9999)\n", nameCol, description,
00102            statusCol, *(int *) var, ch);
00103 }
00104 
00105 void SwitchParameter::Translate(const char * value)
00106 {
00107     switch (*value)
00108     {
00109         case '+' :
00110             *(bool *) var = true;
00111             break;
00112         case '-' :
00113             *(bool *) var = false;
00114             break;
00115         case 0 :
00116             *(bool *) var = ! * (bool *) var;
00117             break;
00118         default :
00119             warning("Command line parameter -%c%s: the option '%c' has no meaning\n",
00120                     ch, value, value[0]);
00121     }
00122 }
00123 
00124 void SwitchParameter::Status()
00125 {
00126     fprintf(stderr, "%*s : %*s (-%c[+|-])\n", nameCol, description,
00127            statusCol, *(bool *) var == false ? "OFF" : "ON", ch);
00128 }
00129 
00130 DoubleParameter::DoubleParameter(char c, const char * desc, double & v)
00131         : Parameter(c, desc, &v)
00132 {
00133     precision = 2;
00134 }
00135 
00136 void DoubleParameter::Translate(const char * value)
00137 {
00138     if (value[0])
00139         *(double *) var = atof(value);
00140     else
00141         *(double *) var = _NAN_;
00142 }
00143 
00144 bool DoubleParameter::TranslateExtras(const char * value, const char * extras)
00145 {
00146     if (value[0] != 0 || !CheckDouble(extras))
00147         return false;
00148 
00149     Translate(extras);
00150 
00151     return true;
00152 }
00153 
00154 void DoubleParameter::Status()
00155 {
00156     double absolute_value = fabs(* (double *) var);
00157 
00158     if (*(double *) var == _NAN_)
00159         fprintf(stderr, "%*s : %*s (-%c99.999)\n", nameCol, description,
00160                statusCol, "NAN", ch);
00161     else if (absolute_value >= 0.00095)
00162         fprintf(stderr, "%*s : % *.*f (-%c99.999)\n", nameCol, description,
00163                 statusCol, precision, * (double *) var, ch);
00164     else if (absolute_value <= 1e-15)
00165         fprintf(stderr, "%*s : % *.0f (-%c99.999)\n", nameCol, description,
00166                statusCol, * (double *) var, ch);
00167     else
00168         fprintf(stderr, "%*s : %*.0e (-%c99.999)\n", nameCol, description,
00169                statusCol, *(double *) var, ch);
00170 }
00171 
00172 void StringParameter::Translate(const char * value)
00173 {
00174     String * s = (String *) var;
00175 
00176     *s = value;
00177 }
00178 
00179 bool StringParameter::TranslateExtras(const char * value, const char * extras)
00180 {
00181     if ((value[0] != 0) || ((!required) && (extras[0] == '-')))
00182         return false;
00183 
00184     String * s = (String *) var;
00185 
00186     *s = extras;
00187 
00188     return true;
00189 }
00190 
00191 void StringParameter::Status()
00192 {
00193     fprintf(stderr, "%*s : %*s (-%cname)\n", nameCol, description,
00194            statusCol, (const char *)(*(String *) var), ch);
00195 }
00196 
00197 void ListParameter::Status()
00198 {
00199     OptionList * l;
00200 
00201     for (l = options; l->ch != 0; l++)
00202         if (l->code == *((int *)var))
00203             break;
00204 
00205     fprintf(stderr, "%*s : %*s (-%c[%s])\n", nameCol, description,
00206            statusCol, l->description, ch, (const char *) key);
00207 }
00208 
00209 void ListParameter::Translate(const char * value)
00210 {
00211     OptionList * l;
00212 
00213     for (l = options; l->ch != 0; l++)
00214         if (tolower(l->ch) == tolower(value[0]))
00215             break;
00216 
00217     if (l->ch == 0 && tolower(value[0]) != 0)
00218         warning("Command line parameter -%c%s: the option '%c' has no meaning\n",
00219                 ch, value, value[0], (const char *) key);
00220 
00221     *((int*) var) = l->code;
00222 }
00223 
00224 ListParameter::ListParameter(char c, const char * desc, int & v, OptionList * opt)
00225         : Parameter(c, desc, &v)
00226 {
00227     options = opt;
00228 
00229     for (OptionList * l = options; l->ch != 0; l++)
00230     {
00231         key += l->ch;
00232         key += '|';
00233     }
00234 
00235     key.SetLength(key.Length() - 1);
00236 }
00237 
00238 SetParameter::SetParameter(char c, const char * desc, int & v, OptionList * opt)
00239         : Parameter(c, desc, &v)
00240 {
00241     options = opt;
00242 
00243     for (OptionList * l = options; l->ch != 0; l++)
00244     {
00245         key += l->ch;
00246         key += '|';
00247     }
00248     key.SetLength(key.Length() - 1);
00249 }
00250 
00251 void SetParameter::Status()
00252 {
00253     bool first = 0;
00254     int  temp = * (int *) var;
00255 
00256     for (OptionList * l = options; l->ch != 0; l++)
00257         if ((l->code & temp) || (l->code == *(int *) var))
00258         {
00259             if (!first)
00260                 fprintf(stderr, "%*s : %*s (-%c{%s})\n", nameCol, description,
00261                        statusCol, l->description, ch, (const char *) key);
00262             else
00263                 fprintf(stderr, "%*s & %*s\n", nameCol, "",
00264                        statusCol, l->description);
00265             first = true;
00266             temp &= ~l->code;
00267         }
00268 }
00269 
00270 void SetParameter::Translate(const char * value)
00271 {
00272     *(int*)var = 0;
00273 
00274     for (const char * chr = value; *chr != 0; chr++)
00275     {
00276         int valid = false;
00277 
00278         for (OptionList * l = options; l->ch != 0; l++)
00279             if (tolower(l->ch) == tolower(*chr))
00280             {
00281                 *((int*) var) |= l->code;
00282                 valid = true;
00283             }
00284 
00285         if (!valid)
00286             warning("Command line parameter -%c%s: the option '%c' has no meaning\n",
00287                     ch, value, *chr);
00288     }
00289 }
00290 
00291 LongParameters::LongParameters(const char * desc, LongParameterList * lst)
00292         : Parameter('-', desc, NULL)
00293 {
00294     list = lst;
00295 
00296     index.Clear();
00297     legacyIndex.Clear();
00298     group_len = 0;
00299 
00300     LongParameterList * ptr = list + 1;
00301 
00302     while (ptr->description != NULL)
00303     {
00304         if (ptr->type == LP_LEGACY_PARAMETERS)
00305             break;
00306         if(ptr->type == LP_PHONEHOME_VERSION)
00307         {
00308             // Phone home is turned on, so add
00309             // the parameter for the user to turn it off.
00310             myNoPhoneHome = false;
00311             myVersion = ptr->description;
00312             ptr->description = "noPhoneHome";
00313             ptr->value = &myNoPhoneHome;
00314             ptr->type = LP_BOOL_PARAMETER;
00315             index.Add(ptr->description, ptr);
00316         }
00317         else
00318         {
00319             if (ptr->value != NULL)
00320                 index.Add(ptr->description, ptr);
00321             else 
00322                 group_len = max(strlen(ptr->description), group_len);
00323         }
00324         ptr++;
00325     }
00326 
00327     while (ptr->description != NULL)
00328     {
00329         if(ptr->type == LP_PHONEHOME_VERSION)
00330         {
00331             // Phone home is turned on, so add
00332             // the parameter for the user to turn it off.
00333             myNoPhoneHome = false;
00334             myVersion = ptr->description;
00335             ptr->description = "noPhoneHome";
00336             ptr->value = &myNoPhoneHome;
00337             ptr->type = LP_BOOL_PARAMETER;
00338             legacyIndex.Add(ptr->description, ptr);
00339         }
00340         else
00341         {
00342             if (ptr->value != NULL)
00343                 legacyIndex.Add(ptr->description, ptr);
00344         }
00345         ptr++;
00346     }
00347 
00348     precision = 2;
00349 }
00350 
00351 void LongParameters::ExplainAmbiguity(const char * cstr)
00352 {
00353     String value(cstr);
00354 
00355     int p = value.FastFindChar(':');
00356     String stem = p == -1 ? value : value.Left(p);
00357     String matches;
00358 
00359     for (int i = 0; i < index.Length(); i++)
00360         if (index[i].SlowCompareToStem(stem) == 0)
00361         {
00362             if (matches.Length() + index[i].Length() > 50)
00363             {
00364                 matches += " ...";
00365                 break;
00366             }
00367 
00368             matches.catprintf(" --%s", (const char *) index[i]);
00369         }
00370 
00371     warning("Ambiguous --%s matches%s\n",
00372             (const char *) value, (const char *) matches);
00373 }
00374 
00375 void LongParameters::Translate(const char * cstr)
00376 {
00377     String value(cstr);
00378 
00379     int p = value.FastFindChar(':');
00380     int option = p == -1 ? index.FindStem(value) : index.FindStem(value.Left(p));
00381 
00382     if (option == -2)
00383     {
00384         ExplainAmbiguity(cstr);
00385         return;
00386     }
00387 
00388     LongParameterList * ptr;
00389 
00390     if (option >= 0)
00391         ptr = (LongParameterList *) index.Object(option);
00392     else
00393     {
00394         int alternate = p == -1 ? legacyIndex.FindFirstStem(value) :
00395                         legacyIndex.FindFirstStem(value.Left(p));
00396 
00397         if (alternate < 0)
00398         {
00399             warning("Command line parameter --%s is undefined\n", (const char *) value);
00400             return;
00401         }
00402 
00403         ptr = (LongParameterList *) legacyIndex.Object(alternate);
00404         ptr->touched = true;
00405     }
00406     ptr->touched = true;
00407 
00408     if (ptr->type == LP_BOOL_PARAMETER)
00409     {
00410         if (p == -1)
00411             * (bool *) ptr->value ^= true;
00412         else
00413             *(bool *) ptr->value = value.SubStr(p + 1).SlowCompare("ON") == 0;
00414 
00415         // In exclusive groups, only one option may be selected
00416         if (ptr->exclusive)
00417         {
00418             for (int i = -1; ptr[i].exclusive; i--) *(bool *)ptr[i].value = false;
00419             for (int i =  1; ptr[i].exclusive; i++) *(bool *)ptr[i].value = false;
00420         }
00421     }
00422     else if (ptr->type == LP_INT_PARAMETER)
00423         if (p == -1)
00424             * (int *) ptr->value = * (int *) ptr->value ? 0 : 1;
00425         else
00426             *(int *) ptr->value = value.SubStr(p + 1).SlowCompare("ON") == 0 ?
00427                                   1 : value.SubStr(p + 1).AsInteger();
00428     else if (ptr->type == LP_DOUBLE_PARAMETER)
00429     {
00430         if (p != -1)
00431             * (double *) ptr->value = value.SubStr(p + 1).AsDouble();
00432     }
00433     else if (ptr->type == LP_STRING_PARAMETER)
00434     {
00435         if (p != -1)
00436             * (String *) ptr->value = value.SubStr(p + 1);
00437     }
00438 }
00439 
00440 bool LongParameters::TranslateExtras(const char * cstr, const char * extras)
00441 {
00442     if (strchr(cstr, ':') != NULL)
00443         return false;
00444 
00445     int option = index.FindStem(cstr);
00446 
00447     if (option == -2)
00448     {
00449         // No need to explain ambiguity here ... will be handle by later call
00450         // to Translate()
00451         // ExplainAmbiguity(cstr);
00452         return false;
00453     }
00454 
00455     LongParameterList * ptr;
00456 
00457     if (option >= 0)
00458         ptr = (LongParameterList *) index.Object(option);
00459     else
00460     {
00461         option = legacyIndex.FindFirstStem(cstr);
00462 
00463         if (option < 0)
00464             return false;
00465 
00466         ptr = (LongParameterList *) legacyIndex.Object(option);
00467         ptr->touched = true;
00468     }
00469 
00470     if (ptr->type == LP_INT_PARAMETER && CheckInteger(extras))
00471     {
00472         *(int *) ptr->value = atoi(extras);
00473         ptr->touched = true;
00474         return true;
00475     }
00476     else if (ptr->type == LP_DOUBLE_PARAMETER && CheckDouble(extras))
00477     {
00478         *(double *) ptr->value = atof(extras);
00479         ptr->touched = true;
00480         return true;
00481     }
00482     else if (ptr->type == LP_STRING_PARAMETER)
00483     {
00484         *(String *) ptr->value = extras;
00485         ptr->touched = true;
00486         return true;
00487     }
00488 
00489     return false;
00490 }
00491 
00492 void LongParameters::Status(LongParameterList * ptr, int & line_len, bool & need_a_comma)
00493 {
00494     String state;
00495     int line_start = group_len ? group_len + 5 : 0;
00496 
00497     if (ptr->value == NULL)
00498     {
00499         fprintf(stderr, "%s %*s :", need_a_comma ? "\n" : "", group_len + 2, ptr->description);
00500         need_a_comma = false;
00501         line_len = line_start;
00502     }
00503     else
00504     {
00505         if (ptr->type == LP_BOOL_PARAMETER)
00506             state = * (bool *) ptr->value ? " [ON]" : "";
00507         else if (ptr->type == LP_INT_PARAMETER)
00508             if (((* (int *) ptr->value == 1) && (ptr->exclusive)) || (* (int *) ptr->value == 0))
00509                 state = * (int *) ptr->value ? " [ON]" : "";
00510             else
00511                 state = " [", state += * (int *) ptr->value, state += ']';
00512         else if (ptr->type == LP_DOUBLE_PARAMETER)
00513             if (* (double *) ptr->value != _NAN_)
00514             {
00515                 double value = * (double *) ptr->value;
00516 
00517                 state = " [";
00518                 if (value == 0.0 || value >= 0.01)
00519                     state.catprintf("%.*f", precision, value);
00520                 else
00521                     state.catprintf("%.1e", value);
00522                 state += ']';
00523             }
00524             else
00525                 state = "";
00526         else if (ptr->type == LP_STRING_PARAMETER)
00527             state = " [" + * (String *) ptr->value + "]";
00528 
00529         int item_len = 3 + strlen(ptr->description) + need_a_comma + state.Length();
00530 
00531         if (item_len + line_len > 78 && line_len > line_start)
00532         {
00533             line_len = line_start;
00534             fprintf(stderr, "%s\n%*s", need_a_comma ? "," : "", line_len,  "");
00535             need_a_comma = 0;
00536             item_len -= 1;
00537         }
00538 
00539         fprintf(stderr, "%s --%s%s", need_a_comma ? "," : (need_a_comma = true, ""),
00540                ptr->description, (const char *) state);
00541 
00542         need_a_comma = true;
00543         line_len += item_len;
00544     }
00545 }
00546 
00547 void LongParameters::Status()
00548 {
00549     if (description != NULL && description[0] != 0)
00550         fprintf(stderr, "\n%s\n", description);
00551 
00552     bool need_a_comma = false;
00553     int  line_len = 0;
00554 
00555     bool legacy_parameters = false;
00556     bool legacy_count = 0;
00557 
00558     for (LongParameterList * ptr = list + 1; ptr->description != NULL; ptr++)
00559         if (ptr->type == LP_LEGACY_PARAMETERS)
00560             legacy_parameters = true;
00561         else if (legacy_parameters == false)
00562             Status(ptr, line_len, need_a_comma);
00563         else if (ptr->touched)
00564         {
00565             if (legacy_count == 0)
00566             {
00567                 fprintf(stderr, "\n\nAdditional Options:\n %*s ", group_len + 3, "");
00568                 line_len = group_len + 5;
00569                 need_a_comma = false;
00570             }
00571 
00572             Status(ptr, line_len, need_a_comma);
00573             legacy_count++;
00574         }
00575 
00576     fprintf(stderr, "\n");
00577 }
00578 
00579 void LongParameters::addParamsToString(String& params)
00580 {
00581     for (LongParameterList * ptr = list + 1; ptr->description != NULL; ptr++)
00582     {
00583         if (ptr->touched)
00584         {
00585             if(!params.IsEmpty())
00586             {
00587                 params += PARAM_STR_SEP;
00588             }
00589             params += ptr->description;
00590         }
00591     }
00592 }
00593 
00594 void ParameterList::Add(Parameter * p)
00595 {
00596     if (count + 1 >= size)
00597         error("Parameter list size should be increased");
00598 
00599     p->SetWarningBuffer(warnings);
00600     pl[count++] = p;
00601 };
00602 
00603 void ParameterList::Read(int argc, char ** argv, int start)
00604 {
00605     MakeString(argc, argv, start);
00606     for (int i=start; i < argc; i++)
00607     {
00608         bool success = false;
00609 
00610         if (argv[i][0] == '-' && argv[i][1])
00611             for (int j=0; j<count; j++)
00612             {
00613                 success = tolower(argv[i][1]) == pl[j]->ch;
00614 
00615                 if (success)
00616                 {
00617                     if ((i+1 < argc) && pl[j]->TranslateExtras(argv[i]+2, argv[i+1]))
00618                         i++;
00619                     else if (argv[i][2] == 0 && (i+1 < argc) && (argv[i + 1][0] != '-'))
00620                         pl[j]->Translate(argv[++i]);
00621                     else
00622                         pl[j]->Translate(argv[i] + 2);
00623 
00624                     break;
00625                 }
00626             }
00627 
00628         if (!success)
00629         {
00630             String warning;
00631 
00632             warning.printf("Command line parameter %s (#%d) ignored\n", argv[i], i);
00633             warnings += warning;
00634         }
00635     }
00636 
00637     if (warnings.Length())
00638     {
00639         ::warning("Problems encountered parsing command line:\n\n%s",
00640                   (const char *) warnings);
00641         warnings.Clear();
00642     }
00643 
00644     HandlePhoneHome(argc, argv, start);
00645 }
00646 
00647 int ParameterList::ReadWithTrailer(int argc, char ** argv, int start)
00648 {
00649     MakeString(argc, argv, start);
00650 
00651     int last_success = start - 1;
00652     bool split = false;
00653 
00654     for (int i=start; i < argc; i++)
00655     {
00656         bool success = false;
00657 
00658         if (argv[i][0] == '-' && argv[i][1])
00659             for (int j=0; j<count; j++)
00660             {
00661                 success = tolower(argv[i][1]) == pl[j]->ch;
00662 
00663                 if (success)
00664                 {
00665                     if ((i+1 < argc) && pl[j]->TranslateExtras(argv[i]+2, argv[i+1]))
00666                         split = true;
00667                     else if (argv[i][2] == 0 && (i+1 < argc) && (argv[i + 1][0] != '-'))
00668                         pl[j]->Translate(argv[i + 1]), split = true;
00669                     else
00670                         pl[j]->Translate(argv[i] + 2);
00671                     break;
00672                 }
00673             }
00674 
00675         if (success)
00676             for (last_success++; last_success < i; last_success++)
00677                 warnings.printf("Command line parameter %s (#%d) ignored\n",
00678                                 argv[last_success], last_success);
00679 
00680         if (split)
00681         {
00682             split = false;
00683             last_success++;
00684             i++;
00685         }
00686     }
00687 
00688     if (warnings.Length())
00689     {
00690         ::warning("Problems encountered parsing command line:\n\n%s",
00691                   (const char *) warnings);
00692         warnings.Clear();
00693     }
00694 
00695     HandlePhoneHome(argc, argv, start);
00696 
00697     return last_success;
00698 };
00699 
00700 
00701 void ParameterList::Status()
00702 {
00703     for (int i=0; i<count; i++)
00704         pl[i]->Status();
00705 
00706     fprintf(stderr, "\n");
00707 
00708     if (messages.Length())
00709         fprintf(stderr, "NOTES:\n%s\n", (const char *) messages);
00710 }
00711 
00712 void ParameterList::MakeString(int argc, char ** argv, int start)
00713 {
00714     int len = 0;
00715 
00716     for (int i=start; i<argc; i++)
00717         len += strlen(argv[i]) + 1;
00718 
00719     string = new char [len+1];
00720     string[0] = 0;
00721 
00722     for (int i=start; i<argc; i++)
00723     {
00724         strcat(string, argv[i]);
00725         strcat(string, " ");
00726     }
00727 }
00728 
00729 
00730 void ParameterList::HandlePhoneHome(int argc, char ** argv, int start)
00731 {
00732     // Determine the tool name : args prior to start.
00733     String programName = "";
00734     for(int i = 0; i < start; i++)
00735     {
00736         if(i == 0)
00737         {
00738             programName = argv[i];
00739         }
00740         else
00741         {
00742             programName += ":";
00743             programName += argv[i];
00744         }
00745     }
00746 
00747     // Loop through and get the params
00748     String params = "";
00749     String version = "";
00750 
00751     for (int i=0; i<count; i++)
00752     {
00753         pl[i]->addParamsToString(params);
00754         // Check if phonehome is enabled.
00755         if(!pl[i]->myVersion.IsEmpty() && (!pl[i]->myNoPhoneHome))
00756         {
00757             // Version specified & phoneHome enabled, so
00758             // phonehome.
00759             version = pl[i]->myVersion;
00760         }
00761     }
00762     
00763     if(!version.IsEmpty())
00764     {
00765         PhoneHome::checkVersion(programName.c_str(), 
00766                                 version.c_str(),
00767                                 params.c_str());
00768     }
00769 }
00770 
00771 
00772 ParameterList::~ParameterList()
00773 {
00774     for (int i = 0; i < count; i++)
00775         delete pl[i];
00776     delete [] pl;
00777     delete [] string;
00778 };
00779 
00780 bool Parameter::CheckInteger(const char * value)
00781 {
00782     if (value[0] != '+' && value[0] != '-' &&
00783             (value[0] < '0' || value[0] > '9'))
00784         return false;
00785 
00786     int pos = 1;
00787     while (value[pos] != 0)
00788         if (value[pos] < '0' || value[pos] > '9')
00789             return false;
00790         else
00791             pos++;
00792 
00793     return true;
00794 }
00795 
00796 bool Parameter::CheckDouble(const char * value)
00797 {
00798     if (value[0] != '+' && value[0] != '-' && value[0] != '.' &&
00799             (value[0] < '0'  || value[0] > '9'))
00800     {
00801         return false;
00802     }
00803 
00804     bool decimal = value[0] == '.';
00805 
00806     for (int pos = 1; value[pos] != 0; pos++)
00807     {
00808         if (value[pos] < '0' || value[pos] > '9')
00809         {
00810             if (!decimal && value[pos] == '.')
00811             {
00812                 decimal = true;
00813             }
00814             else if (value[pos] == 'e' || value[pos] == 'E')
00815             {
00816                 return CheckInteger(value + pos + 1);
00817             }
00818         }
00819     }
00820 
00821     return true;
00822 }
00823 
00824 void ParameterList::Enforce(bool & var, bool value, const char * format, ...)
00825 {
00826     if (var == value)
00827         return;
00828 
00829     var = value;
00830 
00831     String buffer;
00832 
00833     va_list ap;
00834     va_start(ap, format);
00835     buffer.vprintf(format, ap);
00836     va_end(ap);
00837 
00838     messages += buffer;
00839 }
00840 
00841 void ParameterList::Enforce(int & var, int value, const char * format, ...)
00842 {
00843     if (var == value)
00844         return;
00845 
00846     var = value;
00847 
00848     String buffer;
00849 
00850     va_list ap;
00851     va_start(ap, format);
00852     buffer.vprintf(format, ap);
00853     va_end(ap);
00854 
00855     messages += buffer;
00856 }
00857 
00858 void ParameterList::Enforce(double & var, double value, const char * format, ...)
00859 {
00860     if (var == value)
00861         return;
00862 
00863     var = value;
00864 
00865     String buffer;
00866 
00867     va_list ap;
00868     va_start(ap, format);
00869     buffer.vprintf(format, ap);
00870     va_end(ap);
00871 
00872     messages += buffer;
00873 }
00874 
00875 void ParameterList::Enforce(String & var, const char * value, const char * format, ...)
00876 {
00877     if (var.SlowCompare(value) == 0)
00878         return;
00879 
00880     var = value;
00881 
00882     String buffer;
00883     va_list ap;
00884     va_start(ap, format);
00885     buffer.vprintf(format, ap);
00886     va_end(ap);
00887 
00888     messages += buffer;
00889 }
00890 
00891 
00892 LongParamContainer::LongParamContainer()
00893     : myEndIndex(0)
00894 {
00895     // Add the first (also adds ending) indicators.
00896     add(NULL, NULL, false, 0, 0);
00897 }
00898 
00899 
00900 LongParamContainer::~LongParamContainer()
00901 {
00902 }
00903 
00904 
00905 void LongParamContainer::add(const char * label, void * val, bool excl, 
00906                              int paramType, bool touch)
00907 {
00908     if(myEndIndex+1 < MAX_PARAM_ARRAY_SIZE)
00909     {
00910         // Overwrite the previous end record.
00911         myArray[myEndIndex].description = label;
00912         myArray[myEndIndex].value = val;
00913         myArray[myEndIndex].exclusive = excl;
00914         myArray[myEndIndex].type = paramType; 
00915         myArray[myEndIndex].touched = touch;
00916         ++myEndIndex;
00917 
00918         // Add a new empty entry to the end.
00919         myArray[myEndIndex].description = NULL;
00920         myArray[myEndIndex].value = NULL;
00921         myArray[myEndIndex].exclusive = false;
00922         myArray[myEndIndex].type = 0; 
00923         myArray[myEndIndex].touched = 0;
00924     }
00925     else
00926     {
00927         throw std::runtime_error("Tool Error: trying to add more parameters than allowed in LongParamContainer.\n");
00928     }
00929 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends