1 /* 2 * The contents of this file are subject to the Mozilla Public 3 * License Version 1.1 (the "License"); you may not use this file 4 * except in compliance with the License. You may obtain a copy of 5 * the License at http://www.mozilla.org/MPL/ 6 * 7 * Software distributed under the License is distributed on an "AS 8 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or 9 * implied. See the License for the specific language governing 10 * rights and limitations under the License. 11 * 12 * The Original Code is MPEG4IP. 13 * 14 * The Initial Developer of the Original Code is Cisco Systems Inc. 15 * Portions created by Cisco Systems Inc. are 16 * Copyright (C) Cisco Systems Inc. 2000, 2001. All Rights Reserved. 17 * 18 * Contributor(s): 19 * Dave Mackie dmackie@cisco.com 20 * Bill May wmay@cisco.com 21 */ 22 23 #ifndef __CONFIG_SET_H__ 24 #define __CONFIG_SET_H__ 25 26 #include <mpeg4ip.h> 27 28 29 #ifndef CONFIG_SAFETY 30 #define CONFIG_SAFETY 1 31 #endif 32 33 typedef u_int32_t config_integer_t; 34 35 typedef u_int32_t config_index_t; 36 37 38 enum ConfigException { 39 CONFIG_ERR_INAME, 40 CONFIG_ERR_TYPE, 41 CONFIG_ERR_MEMORY, 42 }; 43 44 // TBD type specific exception info and printing utility 45 class CConfigException { 46 public: CConfigException(ConfigException e)47 CConfigException(ConfigException e) { 48 type = e; 49 } 50 ConfigException type; 51 }; 52 53 #define CONFIG_MAX_STRLEN 255 54 55 // TBD weld this in, and throw exception 56 57 typedef enum ConfigType { 58 CONFIG_TYPE_UNDEFINED, 59 CONFIG_TYPE_INTEGER, 60 CONFIG_TYPE_BOOL, 61 CONFIG_TYPE_STRING, 62 CONFIG_TYPE_FLOAT 63 } ConfigType; 64 65 union UConfigValue { UConfigValue(void)66 UConfigValue(void) { 67 m_svalue = NULL; 68 } UConfigValue(config_integer_t ivalue)69 UConfigValue(config_integer_t ivalue) { 70 m_ivalue = ivalue; 71 } UConfigValue(bool bvalue)72 UConfigValue(bool bvalue) { 73 m_bvalue = bvalue; 74 } UConfigValue(const char * svalue)75 UConfigValue(const char *svalue) { 76 m_svalue = svalue; 77 } UConfigValue(char * svalue)78 UConfigValue(char* svalue) { 79 m_svalue = svalue; 80 } UConfigValue(float fvalue)81 UConfigValue(float fvalue) { 82 m_fvalue = fvalue; 83 } 84 85 config_integer_t m_ivalue; 86 bool m_bvalue; 87 const char* m_svalue; 88 float m_fvalue; 89 }; 90 91 typedef struct SConfigVariable { 92 config_index_t *m_iName; 93 const char* m_sName; 94 ConfigType m_type; 95 UConfigValue m_defaultValue; 96 const char* m_helpString; 97 UConfigValue m_value; 98 } SConfigVarible; 99 100 101 102 struct SUnknownConfigVariable { 103 struct SUnknownConfigVariable *next; 104 SConfigVariable *value; 105 }; 106 107 class CConfigSet { 108 public: CConfigSet(const SConfigVariable * variables,config_index_t numVariables,const char * defaultFileName)109 CConfigSet(const SConfigVariable* variables, 110 config_index_t numVariables, 111 const char* defaultFileName) { 112 uint32_t size; 113 m_debug = false; 114 m_numVariables = numVariables; 115 size = sizeof(SConfigVariable) * numVariables; 116 m_variables = 117 (SConfigVariable*)malloc(size); 118 119 memcpy(m_variables, variables, size); 120 m_fileName = defaultFileName == NULL ? NULL : 121 strdup(defaultFileName); 122 SetToDefaults(); 123 m_unknown_head = NULL; 124 }; 125 ~CConfigSet()126 ~CConfigSet() { 127 CHECK_AND_FREE(m_fileName); 128 for (config_index_t i = 0; i < m_numVariables; i++) { 129 CleanUpConfig(&m_variables[i]); 130 } 131 free(m_variables); 132 m_variables = NULL; 133 SUnknownConfigVariable *ptr = m_unknown_head; 134 while (ptr != NULL) { 135 m_unknown_head = ptr->next; 136 CHECK_AND_FREE(ptr->value->m_sName); 137 CHECK_AND_FREE(ptr->value->m_value.m_svalue); 138 free(ptr->value); 139 free(ptr); 140 ptr = m_unknown_head; 141 } 142 } 143 InitializeIndexes(void)144 void InitializeIndexes(void) { 145 for (config_index_t ix = 0; ix < m_numVariables; ix++) { 146 *m_variables[ix].m_iName = ix; 147 } 148 } 149 AddConfigVariables(const SConfigVariable * vars,config_index_t numVariables)150 void AddConfigVariables (const SConfigVariable* vars, 151 config_index_t numVariables) { 152 config_index_t start = m_numVariables; 153 uint32_t size = sizeof(SConfigVariable) * 154 (m_numVariables + numVariables); 155 m_variables = (SConfigVariable*)realloc(m_variables, size); 156 memcpy(&m_variables[m_numVariables], vars, 157 numVariables * sizeof(SConfigVariable)); 158 m_numVariables += numVariables; 159 SetToDefaults(start); 160 } 161 GetFileName()162 const char* GetFileName() { 163 return m_fileName; 164 } 165 SetFileName(const char * name)166 void SetFileName(const char *name) { 167 CHECK_AND_FREE(m_fileName); 168 m_fileName = strdup(name); 169 }; 170 CheckIName(config_index_t iName)171 inline void CheckIName(config_index_t iName) { 172 if (iName >= m_numVariables) { 173 fprintf(stderr, 174 "config variable index failure - try %u max %u\n", 175 iName, m_numVariables); 176 fflush(stderr); 177 throw new CConfigException(CONFIG_ERR_INAME); 178 } 179 if (*m_variables[iName].m_iName != iName) { 180 fprintf(stderr, 181 "config variable index mismatch %u should %u\n", 182 iName, *m_variables[iName].m_iName); 183 fflush(stderr); 184 throw new CConfigException(CONFIG_ERR_INAME); 185 } 186 } 187 188 CheckIntegerType(config_index_t iName)189 inline void CheckIntegerType(config_index_t iName) { 190 if (m_variables[iName].m_type != CONFIG_TYPE_INTEGER) { 191 fprintf(stderr, 192 "config type mismatch on %s - shouldn't be integer\n", 193 m_variables[iName].m_sName); 194 fflush(stderr); 195 throw new CConfigException(CONFIG_ERR_TYPE); 196 } 197 } 198 CheckBoolType(config_index_t iName)199 inline void CheckBoolType(config_index_t iName) { 200 if (m_variables[iName].m_type != CONFIG_TYPE_BOOL) { 201 fprintf(stderr, 202 "config type mismatch on %s - shouldn't be bool\n", 203 m_variables[iName].m_sName); 204 fflush(stderr); 205 throw new CConfigException(CONFIG_ERR_TYPE); 206 } 207 } 208 CheckStringType(config_index_t iName)209 inline void CheckStringType(config_index_t iName) { 210 if (m_variables[iName].m_type != CONFIG_TYPE_STRING) { 211 fprintf(stderr, 212 "config type mismatch on %s - shouldn't be string\n", 213 m_variables[iName].m_sName); 214 fflush(stderr); 215 throw new CConfigException(CONFIG_ERR_TYPE); 216 } 217 } 218 CheckFloatType(config_index_t iName)219 inline void CheckFloatType(config_index_t iName) { 220 if (m_variables[iName].m_type != CONFIG_TYPE_FLOAT) { 221 fprintf(stderr, 222 "config type mismatch on %s - shouldn't be float\n", 223 m_variables[iName].m_sName); 224 fflush(stderr); 225 throw new CConfigException(CONFIG_ERR_TYPE); 226 } 227 } 228 IsDefault(const config_index_t iName)229 inline bool IsDefault (const config_index_t iName) { 230 #if CONFIG_SAFETY 231 CheckIName(iName); 232 #endif 233 return IsValueDefault(&m_variables[iName]); 234 }; 235 GetIntegerValue(const config_index_t iName)236 inline config_integer_t GetIntegerValue(const config_index_t iName) { 237 #if CONFIG_SAFETY 238 CheckIName(iName); 239 CheckIntegerType(iName); 240 #endif 241 return m_variables[iName].m_value.m_ivalue; 242 } 243 SetIntegerValue(const config_index_t iName,config_integer_t ivalue)244 inline void SetIntegerValue(const config_index_t iName, 245 config_integer_t ivalue) { 246 #if CONFIG_SAFETY 247 CheckIName(iName); 248 CheckIntegerType(iName); 249 #endif 250 m_variables[iName].m_value.m_ivalue = ivalue; 251 } 252 GetBoolValue(const config_index_t iName)253 inline bool GetBoolValue(const config_index_t iName) { 254 #if CONFIG_SAFETY 255 CheckIName(iName); 256 CheckBoolType(iName); 257 #endif 258 return m_variables[iName].m_value.m_bvalue;; 259 } 260 SetBoolValue(const config_index_t iName,bool bvalue)261 inline void SetBoolValue(const config_index_t iName, bool bvalue) { 262 #if CONFIG_SAFETY 263 CheckIName(iName); 264 CheckBoolType(iName); 265 #endif 266 m_variables[iName].m_value.m_bvalue = bvalue; 267 } 268 GetStringValue(const config_index_t iName)269 inline const char* GetStringValue(const config_index_t iName) { 270 #if CONFIG_SAFETY 271 CheckIName(iName); 272 CheckStringType(iName); 273 #endif 274 return m_variables[iName].m_value.m_svalue; 275 } 276 GetHelpValue(const config_index_t iName)277 inline const char* GetHelpValue(const config_index_t iName) { 278 #if CONFIG_SAFETY 279 CheckIName(iName); 280 #endif 281 return m_variables[iName].m_helpString; 282 }; 283 SetStringValue(const config_index_t iName,const char * svalue)284 inline void SetStringValue(const config_index_t iName, const char* svalue) { 285 #if CONFIG_SAFETY 286 CheckIName(iName); 287 CheckStringType(iName); 288 #endif 289 if (svalue == m_variables[iName].m_value.m_svalue) { 290 return; 291 } 292 CHECK_AND_FREE(m_variables[iName].m_value.m_svalue); 293 if (svalue == NULL) { 294 m_variables[iName].m_value.m_svalue = NULL; 295 } else { 296 m_variables[iName].m_value.m_svalue = strdup(svalue); 297 if (m_variables[iName].m_value.m_svalue == NULL) { 298 throw new CConfigException(CONFIG_ERR_MEMORY); 299 } 300 } 301 } 302 GetFloatValue(const config_index_t iName)303 inline float GetFloatValue(const config_index_t iName) { 304 #if CONFIG_SAFETY 305 CheckIName(iName); 306 CheckFloatType(iName); 307 #endif 308 return m_variables[iName].m_value.m_fvalue; 309 } 310 SetFloatValue(const config_index_t iName,float fvalue)311 inline void SetFloatValue(const config_index_t iName, float fvalue) { 312 #if CONFIG_SAFETY 313 CheckIName(iName); 314 CheckFloatType(iName); 315 #endif 316 m_variables[iName].m_value.m_fvalue = fvalue; 317 } 318 319 void SetToDefaults(int start = 0) { 320 for (config_index_t i = start; i < m_numVariables; i++) { 321 SetToDefault(&m_variables[i]); 322 } 323 } 324 SetToDefault(const config_index_t iName)325 void SetToDefault(const config_index_t iName) { 326 SetToDefault(&m_variables[iName]); 327 } 328 ProcessLine(char * line)329 void ProcessLine (char *line) { 330 // comment 331 SConfigVariable* var; 332 if (line[0] == '#') { 333 return; 334 } 335 char* s = line, *name; 336 while (*s != '\0') s++; 337 s--; 338 while (isspace(*s)) { 339 *s = '\0'; 340 s--; 341 } 342 s = name = line; 343 344 var = FindByName(strsep(&s, "=")); 345 if (var == NULL || s == NULL) { 346 if (s != NULL) { 347 SConfigVariable *svar; 348 svar = MALLOC_STRUCTURE(SConfigVariable); 349 memset(svar, 0, sizeof(*svar)); 350 svar->m_sName = strdup(name); 351 svar->m_type = CONFIG_TYPE_STRING; 352 if (!FromAscii(svar, s)) { 353 fprintf(stderr, "bad config value in line %s\n", s); 354 } 355 SUnknownConfigVariable *ptr; 356 ptr = MALLOC_STRUCTURE(SUnknownConfigVariable); 357 ptr->next = m_unknown_head; 358 ptr->value = svar; 359 m_unknown_head = ptr; 360 } 361 if (m_debug) { 362 fprintf(stderr, "bad config line %s\n", s); 363 } 364 return; 365 } 366 if (!FromAscii(var, s)) { 367 if (m_debug) { 368 fprintf(stderr, "bad config value in line %s\n", s); 369 } 370 } 371 } 372 SetVariableFromAscii(config_index_t ix,char * arg)373 void SetVariableFromAscii(config_index_t ix, char *arg) { 374 FromAscii(&m_variables[ix], arg); 375 }; 376 377 bool ReadFile(const char* fileName = NULL) { 378 if (fileName == NULL && m_fileName == NULL) 379 return false; 380 381 if (fileName != NULL) { 382 CHECK_AND_FREE(m_fileName); 383 m_fileName = strdup(fileName); 384 } 385 FILE* pFile = fopen(m_fileName, "r"); 386 if (pFile == NULL) { 387 if (m_debug) { 388 fprintf(stderr, "couldn't open file %s\n", fileName); 389 } 390 return false; 391 } 392 char line[256]; 393 while (fgets(line, sizeof(line), pFile)) { 394 ProcessLine(line); 395 } 396 fclose(pFile); 397 return true; 398 } 399 400 bool WriteToFile(const char* fileName = NULL, bool allValues = false) { 401 FILE* pFile; 402 config_index_t i; 403 SConfigVariable *var; 404 SUnknownConfigVariable *ptr; 405 if (fileName == NULL && m_fileName == NULL) { 406 return false; 407 } 408 if (fileName == NULL) { 409 fileName = m_fileName; 410 } 411 pFile = fopen(fileName, "w"); 412 if (pFile == NULL) { 413 if (m_debug) { 414 fprintf(stderr, "couldn't open file %s\n", fileName); 415 } 416 return false; 417 } 418 for (i = 0; i < m_numVariables; i++) { 419 var = &m_variables[i]; 420 if (allValues || !IsValueDefault(var)) { 421 fprintf(pFile, "%s=%s\n", var->m_sName, 422 ToAscii(var)); 423 } 424 } 425 ptr = m_unknown_head; 426 while (ptr != NULL) { 427 fprintf(pFile, "%s=%s\n", ptr->value->m_sName, 428 ToAscii(ptr->value)); 429 ptr = ptr->next; 430 } 431 fclose(pFile); 432 return true; 433 } 434 435 436 void SetDebug(bool debug = true) { 437 m_debug = debug; 438 } 439 #ifdef _WIN32 440 int ReadVariablesFromRegistry(const char *reg_name, 441 const char *config_section); 442 void WriteVariablesToRegistry(const char *reg_name, 443 const char *config_section); 444 #endif 445 public: FindIndexByName(const char * sName)446 config_index_t FindIndexByName(const char *sName) { 447 for (config_index_t i = 0; i < m_numVariables; i++) { 448 if (!strcasecmp(sName, m_variables[i].m_sName)) { 449 return i; 450 } 451 } 452 return UINT32_MAX; 453 } GetTypeFromIndex(config_index_t index)454 ConfigType GetTypeFromIndex (config_index_t index) { 455 if (index < m_numVariables) { 456 return m_variables[index].m_type; 457 } 458 return CONFIG_TYPE_UNDEFINED; 459 }; GetNameFromIndex(config_index_t index)460 const char *GetNameFromIndex (config_index_t index) { 461 if (index < m_numVariables) { 462 return m_variables[index].m_sName; 463 } 464 return NULL; 465 }; GetNumVariables(void)466 config_index_t GetNumVariables (void) { 467 return m_numVariables; 468 }; 469 void DisplayHelp(bool onlyHelp = false) { 470 config_index_t ix; 471 for (ix = 0; ix < m_numVariables; ix++) { 472 if (m_variables[ix].m_helpString) { 473 fprintf(stdout, "%s - %s\n", m_variables[ix].m_sName, 474 m_variables[ix].m_helpString); 475 } else if (onlyHelp == false) { 476 fprintf(stdout, "%s\n", m_variables[ix].m_sName); 477 } 478 } 479 }; Dump(void)480 void Dump (void) { 481 fprintf(stdout, "File - %s\n", GetFileName()); 482 config_index_t ix; 483 for (ix = 0; ix < m_numVariables; ix++) { 484 fprintf(stdout, "%s:\t%s\n", 485 m_variables[ix].m_sName, 486 ToAscii(&m_variables[ix])); 487 } 488 }; GetUnknownStringValue(const char * var_name)489 const char* GetUnknownStringValue (const char *var_name) { 490 SUnknownConfigVariable *svar = m_unknown_head; 491 while (svar != NULL) { 492 if (strcasecmp(var_name, svar->value->m_sName) == 0) { 493 return svar->value->m_value.m_svalue; 494 } 495 svar = svar->next; 496 } 497 config_index_t ix = FindIndexByName(var_name); 498 if (ix == UINT32_MAX) return NULL; 499 return m_variables[ix].m_value.m_svalue; 500 }; 501 502 protected: FindByName(const char * sName)503 SConfigVariable* FindByName(const char* sName) { 504 config_index_t ix = FindIndexByName(sName); 505 if (ix == UINT32_MAX) return NULL; 506 return &m_variables[ix]; 507 }; 508 509 protected: 510 SConfigVariable* m_variables; 511 config_index_t m_numVariables; 512 bool m_debug; 513 const char* m_fileName; 514 SUnknownConfigVariable *m_unknown_head; ToAscii(SConfigVariable * v)515 const char* ToAscii(SConfigVariable *v) { 516 static char sBuf[CONFIG_MAX_STRLEN+3]; 517 switch (v->m_type) { 518 case CONFIG_TYPE_INTEGER: 519 sprintf(sBuf, "%d", v->m_value.m_ivalue); 520 return sBuf; 521 case CONFIG_TYPE_BOOL: 522 sprintf(sBuf, "%d", v->m_value.m_bvalue); 523 return sBuf; 524 case CONFIG_TYPE_STRING: 525 if (v->m_value.m_svalue == NULL) { 526 sprintf(sBuf, "\"\""); 527 return sBuf; 528 } 529 if (strchr(v->m_value.m_svalue, ' ')) { 530 sBuf[0] = '"'; 531 strncpy(&sBuf[1], v->m_value.m_svalue, CONFIG_MAX_STRLEN); 532 strcpy(&sBuf[MIN(strlen(v->m_value.m_svalue), 533 CONFIG_MAX_STRLEN)+1], "\""); 534 } 535 return v->m_value.m_svalue; 536 case CONFIG_TYPE_FLOAT: 537 sprintf(sBuf, "%f", v->m_value.m_fvalue); 538 return sBuf; 539 case CONFIG_TYPE_UNDEFINED: 540 default: 541 return ""; 542 } 543 }; 544 FromAscii(SConfigVarible * v,const char * s)545 bool FromAscii(SConfigVarible *v, const char* s) { 546 switch (v->m_type) { 547 case CONFIG_TYPE_INTEGER: 548 return (sscanf(s, " %i ", &v->m_value.m_ivalue) == 1); 549 case CONFIG_TYPE_BOOL: 550 // OPTION could add "yes/no", "true/false" 551 if (sscanf(s, " %u ", &v->m_value.m_ivalue) != 1) { 552 return false; 553 } 554 v->m_value.m_bvalue = v->m_value.m_ivalue ? true : false; 555 return true; 556 case CONFIG_TYPE_STRING: 557 // N.B. assuming m_svalue has been alloc'ed 558 { 559 size_t len = strlen(s); 560 CHECK_AND_FREE(v->m_value.m_svalue); 561 if (*s == '"' && s[len] == '"') { 562 char *newvalue = strdup(s + 1); 563 newvalue[len - 1] = '\0'; 564 565 v->m_value.m_svalue = newvalue; 566 } else { 567 v->m_value.m_svalue = strdup(s); 568 } 569 if (v->m_value.m_svalue == NULL) { 570 throw new CConfigException(CONFIG_ERR_MEMORY); 571 } 572 return true; 573 } 574 case CONFIG_TYPE_FLOAT: 575 return (sscanf(s, " %f ", &v->m_value.m_fvalue) == 1); 576 case CONFIG_TYPE_UNDEFINED: 577 default: 578 return false; 579 } 580 }; 581 SetToDefault(SConfigVariable * v)582 void SetToDefault(SConfigVariable *v) { 583 switch (v->m_type) { 584 case CONFIG_TYPE_INTEGER: 585 v->m_value.m_ivalue = v->m_defaultValue.m_ivalue; 586 break; 587 case CONFIG_TYPE_BOOL: 588 v->m_value.m_bvalue = v->m_defaultValue.m_bvalue; 589 break; 590 case CONFIG_TYPE_STRING: 591 CHECK_AND_FREE(v->m_value.m_svalue); 592 if (v->m_defaultValue.m_svalue == NULL) { 593 v->m_value.m_svalue = NULL; 594 } else { 595 v->m_value.m_svalue = strdup(v->m_defaultValue.m_svalue); 596 if (v->m_value.m_svalue == NULL) { 597 throw new CConfigException(CONFIG_ERR_MEMORY); 598 } 599 } 600 break; 601 case CONFIG_TYPE_FLOAT: 602 v->m_value.m_fvalue = v->m_defaultValue.m_fvalue; 603 break; 604 case CONFIG_TYPE_UNDEFINED: 605 default: 606 break; 607 } 608 }; 609 IsValueDefault(SConfigVarible * v)610 bool IsValueDefault(SConfigVarible *v) { 611 switch (v->m_type) { 612 case CONFIG_TYPE_INTEGER: 613 return v->m_value.m_ivalue == v->m_defaultValue.m_ivalue; 614 case CONFIG_TYPE_BOOL: 615 return v->m_value.m_bvalue == v->m_defaultValue.m_bvalue; 616 case CONFIG_TYPE_STRING: 617 if (v->m_defaultValue.m_svalue == NULL && 618 v->m_value.m_svalue == NULL) 619 return true; 620 if (v->m_defaultValue.m_svalue == NULL) return false; 621 if (v->m_value.m_svalue == NULL) return false; 622 return (strcmp(v->m_value.m_svalue, 623 v->m_defaultValue.m_svalue) == 0); 624 case CONFIG_TYPE_FLOAT: 625 return v->m_value.m_fvalue == v->m_defaultValue.m_fvalue; 626 case CONFIG_TYPE_UNDEFINED: 627 default: 628 return false; 629 } 630 }; CleanUpConfig(SConfigVariable * v)631 void CleanUpConfig(SConfigVariable *v) { 632 if (v->m_type == CONFIG_TYPE_STRING) { 633 CHECK_AND_FREE(v->m_value.m_svalue); 634 } 635 }; 636 }; 637 638 // To define configuration variables - first DECLARE_CONFIG in a 639 // .h file. Then in either a C++ or h file, define a static array 640 // of configuration variables using CONFIG_BOOL, CONFIG_FLOAT, CONFIG_INT 641 // or CONFIG_STRING. You can include the .h anywhere you use the variable - 642 // in a .cpp, you must include the .h file with DECLARE_CONFIG_VARIABLES 643 // defined before the .h file. Note - if you're already including mp4live.h, 644 // you need to #define the DECLARE_CONFIG_VARIABLES after the include. 645 // 646 // Note - you want to add the config variables BEFORE the ReadFile 647 // call 648 649 #define CONFIG_BOOL(var, name, defval) \ 650 { &(var), (name), CONFIG_TYPE_BOOL, (defval), } 651 #define CONFIG_FLOAT(var, name, defval) \ 652 { &(var), (name), CONFIG_TYPE_FLOAT,(float) (defval), } 653 #define CONFIG_INT(var, name, defval) \ 654 { &(var), (name), CONFIG_TYPE_INTEGER,(config_integer_t) (defval), } 655 #define CONFIG_STRING(var, name, defval) \ 656 { &(var), (name), CONFIG_TYPE_STRING, (const char *)(defval), (const char *)NULL } 657 #define CONFIG_BOOL_HELP(var, name, defval, help) \ 658 { &(var), (name), CONFIG_TYPE_BOOL, (defval), (help), } 659 #define CONFIG_FLOAT_HELP(var, name, defval, help) \ 660 { &(var), (name), CONFIG_TYPE_FLOAT,(float) (defval), (help), } 661 #define CONFIG_INT_HELP(var, name, defval, help) \ 662 { &(var), (name), CONFIG_TYPE_INTEGER,(config_integer_t) (defval), (help), } 663 #define CONFIG_STRING_HELP(var, name, defval, help) \ 664 { &(var), (name), CONFIG_TYPE_STRING, (const char *)(defval), (help), (const char *)NULL, } 665 666 667 #endif /* __CONFIG_SET_H__ */ 668 669 #undef DECLARE_CONFIG 670 #ifdef DECLARE_CONFIG_VARIABLES 671 #define DECLARE_CONFIG(a) config_index_t (a); 672 #else 673 #define DECLARE_CONFIG(a) extern config_index_t (a); 674 #endif 675