00001
00002
00003
00004 #include "TinkerKnobs.H"
00005
00006 #define TINKERKNOBS_DEBUG
00007
00008
00009 #include <stdio.h>
00010 #include <stdlib.h>
00011 #include <ctype.h>
00012 #include <string.h>
00013
00014 #define DEFAULT_KNOBTABLE_SIZE (64)
00015
00016 int
00017 knobs::Load (char *knobfile)
00018 {
00019 if (knobfile == NULL)
00020 return 0;
00021
00022 char commandline[200];
00023
00024 sprintf (commandline, "m4 %s", knobfile);
00025
00026 FILE *fp = popen (commandline, "r");
00027 if (fp == NULL)
00028 return 0;
00029
00030 curfname = knobfile;
00031 int numread = Load (fp);
00032 pclose (fp);
00033 curfname = NULL;
00034 return numread;
00035 }
00036
00037 int
00038 knobs::Load (FILE *kfp)
00039 {
00040 char line[200], param_name[140], param_type[10], param_string[200];
00041 knobnamelist *knltail;
00042 int numknobs = 0, numread, linenum = 0;
00043
00044 for (knltail = names; knltail != NULL && knltail->next != NULL;
00045 knltail = knltail->next) ;
00046
00047 while ((fgets (line, 199, kfp)) != NULL)
00048 {
00049 linenum++;
00050 if (line[0] == '#' || isspace(line[0]))
00051 continue;
00052
00053 numread = sscanf (line, "%s%s%s", param_name, param_type,
00054 param_string);
00055 if (numread != 3)
00056 {
00057 fprintf (stderr, "Error reading knob file %s, line %d.\n",
00058 curfname, linenum);
00059 return numknobs;
00060 }
00061
00062 if (strcmp (param_type, "integer") == 0)
00063 {
00064 int d = atoi (param_string);
00065 t->Set (param_name, d);
00066 }
00067 else if (strcmp (param_type, "boolean") == 0)
00068 {
00069 char d; int i;
00070
00071 for (i = 0; i < strlen (param_string); i++)
00072 param_string[i] = toupper (param_string[i]);
00073 if (strcmp (param_string, "TRUE") == 0 ||
00074 strcmp (param_string, "T") == 0 ||
00075 strcmp (param_string, "YES") == 0 ||
00076 strcmp (param_string, "Y") == 0)
00077 d = KNOB_TRUE;
00078 else if (strcmp (param_string, "FALSE") == 0 ||
00079 strcmp (param_string, "F") == 0 ||
00080 strcmp (param_string, "NO") == 0 ||
00081 strcmp (param_string, "N") == 0)
00082 d = KNOB_FALSE;
00083 else
00084 {
00085 fprintf (stderr, "Misspelled boolean in knob file %s, "
00086 "knob %s. Setting to false.\n", curfname,
00087 param_name);
00088 d = KNOB_FALSE;
00089 }
00090 t->Set (param_name, (char) d);
00091 }
00092 else if (strcmp (param_type, "string") == 0)
00093 {
00094 char *d = new char [strlen (param_string) + 1];
00095 strcpy (d, param_string);
00096 t->Set (param_name, d);
00097 }
00098 else if (strcmp (param_type, "float") == 0)
00099 {
00100 double d = atof (param_string);
00101 t->Set (param_name, d);
00102 }
00103 else
00104 {
00105 fprintf (stderr, "Unrecognized knob type %s for knob %s in knob "
00106 "file %s.\n", param_type, param_name, curfname);
00107 continue;
00108 }
00109
00110 numknobs++;
00111 if (names != NULL)
00112 {
00113 knobnamelist *knl;
00114
00115 for (knl = names; knl != NULL; knl = knl->next)
00116 if (strcmp (knl->name, param_name) == 0)
00117 break;
00118 if (knl == NULL)
00119 {
00120 knltail->next = new knobnamelist (param_name);
00121 knltail = knltail->next;
00122 }
00123 }
00124 else
00125 names = knltail = new knobnamelist (param_name);
00126
00127 }
00128
00129 fclose (kfp);
00130 return numknobs;
00131 }
00132
00133 int
00134 knobs::Save (char *knobfile = NULL)
00135 {
00136 if (knobfile == NULL)
00137 knobfile = customknobfile;
00138
00139 if (strcmp (knobfile, getenv ("TINKERKNOBS")) == 0)
00140 {
00141 fprintf (stderr, "Not allowed to overwrite common knob file.\n");
00142 return 0;
00143 }
00144
00145 FILE *fp = fopen (knobfile, "w");
00146 if (fp == NULL)
00147 return 0;
00148
00149 curfname = knobfile;
00150 int numsaved = Save (fp);
00151 fclose (fp);
00152 curfname = NULL;
00153 return numsaved;
00154 }
00155
00156 int
00157 knobs::Save (FILE *kfp)
00158 {
00159 char line[200], param_name[140], param_type[10], param_string[100];
00160 int numknobs = 0, putstatus, linenum = 1;
00161 knobnamelist *knl;
00162
00163 putstatus = fputs ("# Generated knob file\n", kfp);
00164 if (putstatus == EOF)
00165 {
00166 fprintf (stderr, "Error writing first line of %s.\n", curfname);
00167 return 0;
00168 }
00169
00170 for (knl = names; knl != NULL; knl = knl->next)
00171 {
00172 strcpy (param_name, knl->name);
00173 switch (t->TypeOf (param_name))
00174 {
00175 case THT_CHAR:
00176 strcpy (param_type, "boolean");
00177 if (t->LookupChar (param_name) == KNOB_TRUE)
00178 strcpy (param_string, "true");
00179 else
00180 strcpy (param_string, "false");
00181 break;
00182 case THT_INT:
00183 strcpy (param_type, "integer");
00184 sprintf (param_string, "%d", t->LookupInt (param_name));
00185 break;
00186 case THT_DOUBLE:
00187 strcpy (param_type, "float");
00188 sprintf (param_string, "%lf", t->LookupDouble (param_name));
00189 break;
00190 case THT_POINTER:
00191 strcpy (param_type, "string");
00192 strcpy (param_string, (char *) t->LookupPointer (param_name));
00193 break;
00194 default:
00195 fprintf (stderr, "Corrupted hashtable!\n");
00196 exit(1);
00197 }
00198
00199 sprintf (line, "%s\t%s\t%s\n", param_name, param_type, param_string);
00200 putstatus = fputs (line, kfp);
00201 if (putstatus == EOF)
00202 {
00203 fprintf (stderr, "Error writing knob %s to knob file %s.\n",
00204 param_name, curfname);
00205 return numknobs;
00206 }
00207
00208 numknobs++; linenum++;
00209 }
00210
00211 return numknobs;
00212 }
00213
00214 int
00215 knobs::Parse (int argc, char *argv[])
00216 {
00217 char *shortarg, *knob_name, *knob_type, *knob_value, *tmparg;
00218 int len, copyamount, numknobs = 0;
00219 knobnamelist *knltail;
00220
00221 for (knltail = names; knltail != NULL && knltail->next != NULL;
00222 knltail = knltail->next) ;
00223
00224
00225 for (int i = 1; i < argc; i++ )
00226 {
00227
00228
00229
00230
00231
00232 if (strncmp (argv[i], "-K", 2) != 0) continue;
00233 len = strlen (argv[i]);
00234
00235 if ( len < 3 )
00236 {
00237 fprintf (stderr, "Knobs::Parse: Knob string %s too short.\n",
00238 argv[i]);
00239 exit (-1);
00240 }
00241
00242
00243 shortarg = new char [len];
00244 if (argv[i][2] == '\'' || argv[i][2] == '\"')
00245 {
00246
00247 if (argv[i][len-1] != argv[i][2])
00248 {
00249 fprintf (stderr, "knobs::Parse: Badly formed knob string:\n"
00250 "%s\n", argv[i]);
00251 exit (-1);
00252 }
00253
00254 strncpy (shortarg, &(argv[i][3]), len - 3);
00255 shortarg[len - 3] = '\0';
00256 }
00257 else
00258 {
00259 strncpy (shortarg, &(argv[i][2]), len - 2);
00260 shortarg[len - 2] = '\0';
00261 }
00262
00263
00264 if ((knob_name = strtok (shortarg, " ")) == NULL)
00265 {
00266 fprintf (stderr, "knobs::Parse: Invalid knob string:\n"
00267 "%s\n", shortarg);
00268 exit (-1);
00269 }
00270 if ((knob_type = strtok ( NULL, " ")) == NULL)
00271 {
00272 fprintf (stderr, "knobs::Parse: Invalid knob string:\n"
00273 "%s\n", shortarg);
00274 exit (-1);
00275 }
00276 if ((knob_value = strtok (NULL, " ")) == NULL)
00277 {
00278 fprintf (stderr, "knobs::Parse: Invalid knob string:\n"
00279 "%s\n", shortarg);
00280 exit (-1);
00281 }
00282
00283
00284
00285 if (strcmp (knob_type, "boolean") == 0)
00286 {
00287 for (int j = 0; j < strlen (knob_value); j++)
00288 knob_value[j] = toupper (knob_value[j]);
00289 if (strcmp (knob_value, "YES") == 0 ||
00290 strcmp (knob_value, "Y") == 0 ||
00291 strcmp (knob_value, "T") == 0 ||
00292 strcmp (knob_value, "TRUE") == 0)
00293 t->Set (knob_name, KNOB_TRUE);
00294 else if (strcmp (knob_value, "NO") == 0 ||
00295 strcmp (knob_value, "N") == 0 ||
00296 strcmp (knob_value, "F") == 0 ||
00297 strcmp (knob_value, "FALSE") == 0)
00298 t->Set (knob_name, KNOB_FALSE);
00299 else
00300 {
00301 fprintf (stderr, "knobs::Parse: Invalid boolean value %s.\n",
00302 knob_value);
00303 exit (-1);
00304 }
00305 }
00306 else if (strcmp (knob_type, "integer") == 0)
00307 {
00308 int rc;
00309
00310 rc = atoi (knob_value);
00311 t->Set (knob_name, rc);
00312 }
00313 else if (strcmp (knob_type, "float") == 0)
00314 {
00315 double rc;
00316
00317 rc = atof (knob_value);
00318 t->Set (knob_name, rc);
00319 }
00320 else if (strcmp (knob_type, "string") == 0)
00321 {
00322 char *tempstring = new char [strlen (knob_value) + 1];
00323 strcpy (tempstring, knob_value);
00324 t->Set (knob_name, tempstring);
00325
00326 }
00327 else
00328 {
00329 fprintf (stderr, "knobs::Parse: Invalid knob type %s.\n", knob_type);
00330 exit (-1);
00331 }
00332
00333 numknobs++;
00334 if (names != NULL)
00335 {
00336 knobnamelist *knl;
00337
00338 for (knl = names; knl != NULL; knl = knl->next)
00339 if (strcmp (knl->name, knob_name) == 0)
00340 break;
00341 if (knl == NULL)
00342 {
00343 knltail->next = new knobnamelist (knob_name);
00344 knltail = knltail->next;
00345 }
00346 }
00347 else
00348 names = knltail = new knobnamelist (knob_name);
00349 }
00350
00351 return numknobs;
00352 }
00353
00354 #ifdef TINKERKNOBS_MAIN
00355
00356 int main()
00357 {
00358 knobs *k;
00359 char *string;
00360
00361 k = new knobs();
00362 k->SetDefaultPanel ("bill");
00363 k->Read ("favorite-Transformer", string);
00364 printf ("%s is cool.\n", string);
00365 k->Read ("favorite-Transformer", string);
00366 printf ("%s is fast.\n", string);
00367 k->Save ("MrKnobby.txt");
00368 delete k;
00369 return 0;
00370 }
00371
00372 #endif
00373