src/core/config.c

Go to the documentation of this file.
00001 
00009 #include <stdio.h>
00010 #include <string.h>
00011 #include <stdlib.h>
00012 #include <ctype.h>
00013 #include <core/config.h>
00014 #include <misc/debug.h>
00015 #include <misc/result.h>
00016 #include <misc/generic_types.h>
00017 
00018 
00019 #define CONFIG_OPTION_DEFVALUE(name,                                        \
00020                                typename,                                    \
00021                                store_type,                                  \
00022                                parse_type,                                  \
00023                                defvalue,                                    \
00024                                validvalues,                                     \
00025                                num_validvalues)                             \
00026   defvalue,
00027 
00028 
00029 #define DEFVALUES                                                           \
00030 {                                                                           \
00031   FOREACH_RUNTIME_CONFIG_OPTION(CONFIG_OPTION_DEFVALUE)                     \
00032 }
00033 
00034 
00035 #define CONFIG_OPTION_VALID_VALUES_ENTRY(name,                              \
00036                                          typename,                          \
00037                                          store_type,                        \
00038                                          parse_type,                        \
00039                                          defvalue,                          \
00040                                          validvalues,                       \
00041                                          num_validvalues)                   \
00042   parse_type name[num_validvalues]; 
00043 
00044 
00045 #define CONFIG_OPTION_VALID_VALUES(name,                                    \
00046                                    typename,                                \
00047                                    store_type,                              \
00048                                    parse_type,                              \
00049                                    defvalue,                                \
00050                                    validvalues,                             \
00051                                    num_validvalues)                         \
00052   validvalues,
00053 
00054 
00055 #define VALIDVALUES                                                         \
00056 {                                                                           \
00057   FOREACH_RUNTIME_CONFIG_OPTION(CONFIG_OPTION_VALID_VALUES)                 \
00058 }
00059 
00060 
00061 #define CONFIG_OPTION_KEY(name,                                             \
00062                           typename,                                         \
00063                           store_type,                                       \
00064                           parse_type,                                       \
00065                           defvalue,                                         \
00066                           validvalues,                                      \
00067                           num_validvalues)                                  \
00068 {                                                                           \
00069   #name,                                                                    \
00070   txc_config_##typename##_data,                                             \
00071   &(txc_runtime_settings.name),                                             \
00072   &(valid_values.name),                                                     \
00073   num_validvalues                                                           \
00074 },
00075 
00076 
00077 txc_runtime_settings_t txc_runtime_settings = DEFVALUES;
00078 static char *txc_init_filename = "txc.ini";
00079 
00080 
00081 typedef enum {
00082         txc_config_integer_data, 
00083         txc_config_string_data, 
00084         txc_config_boolean_data 
00085 } option_valuetype_t;
00086 
00087 typedef enum {
00088         parse_result_pair,      /* Found (option, value) pair */ 
00089         parse_result_EOF,       /* End of file */ 
00090         parse_result_error,     /* Parsing error */
00091         parse_result_comment    /* Comment */
00092 } parse_result_t;
00093 
00094 
00095 typedef struct option_s option_t;
00096 
00097 struct option_s {
00098         char               *name;
00099         option_valuetype_t type;
00100         void               *value_ptr;
00101         void               *validvalues_ptr;
00102         int                num_validvalues;
00103 };
00104 
00105 static struct {
00106         FOREACH_RUNTIME_CONFIG_OPTION(CONFIG_OPTION_VALID_VALUES_ENTRY)
00107 } valid_values = VALIDVALUES;  
00108 
00109 static void 
00110 strtrim_whitespace(char **str)
00111 {
00112         char *p, *end;
00113         int len;
00114 
00115         p = *str;
00116         
00117         len = strlen(p);
00118         while ( *p && len) {
00119                 end = p + len-1;
00120                 if( ' ' == *end) {
00121                         *end = 0;
00122                 } else if ( '\t' == *end) {
00123                         *end = 0;
00124                 } else {
00125                         break;
00126                 }
00127                 len = strlen( p);
00128         }
00129 
00130         while ( *p && *p != 0 && len) {
00131                 if( ' ' == *p) {
00132                         *p = 0;
00133                 } else if ( '\t' == *p) {
00134                         *p = 0;
00135                 } else {
00136                         break;
00137                 }
00138                 p++;
00139                 len = strlen( p);
00140         }
00141         *str = p;
00142 
00143         return;
00144 }
00145 
00146 static 
00147 parse_result_t
00148 parse(FILE *fin, char *option, char *value) 
00149 {
00150         char buf1[1024];
00151         char buf2[1024];
00152         char *subtoken, *ret, *trimmed;
00153 
00154         ret = fgets(buf1, 1024, fin);
00155         if (ret == NULL) {
00156                 return parse_result_EOF;        
00157         }
00158         subtoken = strtok(buf1, "=");
00159         if (subtoken == NULL) {
00160                 return parse_result_error;
00161         }
00162         strcpy(buf2, subtoken);
00163         trimmed = buf2;
00164         strtrim_whitespace(&trimmed);
00165         if (trimmed[0] == '#') {
00166                 return parse_result_comment;
00167         }
00168         strcpy(option, trimmed);
00169 
00170         subtoken = strtok(NULL, "\n");
00171         if (subtoken == NULL) {
00172                 return parse_result_error;
00173         }
00174         strcpy(trimmed, subtoken);
00175         strtrim_whitespace(&trimmed);
00176         strcpy(value, trimmed);
00177 
00178         return parse_result_pair;
00179 }  
00180 
00181 
00182 static void 
00183 config_print()
00184 {
00185         int i;
00186 
00187         option_t options[] = {
00188                 FOREACH_RUNTIME_CONFIG_OPTION(CONFIG_OPTION_KEY)
00189         };
00190 
00191         fprintf(TXC_DEBUG_OUT, "Configuration parameters\n");
00192         fprintf(TXC_DEBUG_OUT, "========================\n");
00193         for (i=0; i < sizeof (options) / sizeof(option_t); i++) {
00194                 fprintf(TXC_DEBUG_OUT, "%s=", options[i].name);
00195                 switch(options[i].type) {
00196                         case txc_config_integer_data:
00197                                 fprintf(TXC_DEBUG_OUT, "%d\n", *((int *) options[i].value_ptr));
00198                                 break;
00199                         case txc_config_string_data:
00200                                 fprintf(TXC_DEBUG_OUT, "%s\n", *((char **) options[i].value_ptr));
00201                                 break;
00202                         case txc_config_boolean_data:
00203                                 fprintf(TXC_DEBUG_OUT, "%s\n", 
00204                                         *((txc_bool_t *) options[i].value_ptr) == TXC_BOOL_TRUE ?
00205                                         "enable": "disable");
00206                                 break;
00207                         default:
00208                                 TXC_INTERNALERROR("Not supported configuration parameter type");
00209                 } 
00210         }
00211 }
00212 
00213 
00214 static 
00215 void 
00216 option_set(option_t *option, char *value)
00217 {
00218         int j, value_is_valid;
00219         int int_value;
00220 
00221         switch (option->type) {
00222                 case txc_config_integer_data: 
00223                         if (option->num_validvalues != 2) {
00224                                 TXC_INTERNALERROR("config.h has wrong range definition");
00225                         }
00226                         int_value = atoi(value);
00227                         value_is_valid = 1;
00228                         if ((int_value < ((int *) option->validvalues_ptr)[0])
00229                             || (int_value > ((int *) option->validvalues_ptr)[1])) 
00230                         {
00231                             value_is_valid = 0;
00232                                 TXC_WARNING("Value given for parameter '%s' is out of range. Using default value.", 
00233                                             option->name);      
00234                         }
00235                         if (value_is_valid) {
00236                                 *((int *) option->value_ptr) = int_value;
00237                         }
00238                         break;
00239                 case txc_config_string_data: 
00240                         if (option->num_validvalues > 0) {
00241                                 value_is_valid = 0;
00242                                 for (j=0; j < option->num_validvalues; j++) {
00243                                         if (strcmp(value, ((char **) option->validvalues_ptr)[j]) == 0) {
00244                                                 value_is_valid = 1; 
00245                                         }
00246                                 } 
00247                         } else {
00248                                 value_is_valid = 1;
00249                         }
00250                         if (value_is_valid == 0) {
00251                                 TXC_WARNING("Value given for parameter '%s' is not recognized. Using default value.", 
00252                                             option->name);      
00253                         } else {
00254                                 char *bufp;
00255                                 bufp = (char *) malloc(strlen(value)+1);
00256                                 strcpy(bufp, value);
00257                                 *( (char **) option->value_ptr) = bufp;
00258                         }
00259                         break;
00260                 case txc_config_boolean_data: 
00261                         if (option->num_validvalues > 0) {
00262                                 value_is_valid = 0;
00263                                 for (j=0; j < option->num_validvalues; j++) {
00264                                         if (strcmp(value, ((char **) option->validvalues_ptr)[j]) == 0) {
00265                                                 value_is_valid = 1; 
00266                                         }
00267                                 } 
00268                         } else {
00269                                 value_is_valid = 1;
00270                         }
00271                         if (value_is_valid == 0) {
00272                                 TXC_WARNING("Value given for parameter '%s' is not recognized. Using default value.", 
00273                                             option->name);      
00274                         } else {
00275                                 if (strcmp(value, "enable") == 0) {
00276                                         *((txc_bool_t *) option->value_ptr) = TXC_BOOL_TRUE;
00277                                 } else {
00278                                         *((txc_bool_t *) option->value_ptr) = TXC_BOOL_FALSE;
00279                                 }
00280                         }
00281                         break;
00282                 default:
00283                         TXC_INTERNALERROR("Not supported configuration parameter type");
00284         }       
00285 }
00286 
00287 
00288 static 
00289 txc_result_t
00290 config_init_use_env()
00291 {
00292         int i, j;
00293         char buf_option[128];
00294         char *env_value;
00295         int len;
00296 
00297         option_t options[] = {
00298                 FOREACH_RUNTIME_CONFIG_OPTION(CONFIG_OPTION_KEY)
00299         };
00300 
00301         strcpy(buf_option, "TXC_");
00302 
00303         for (i=0; i < sizeof (options) / sizeof(option_t); i++) {
00304                 len = strlen(options[i].name);
00305                 for (j=0; j < len; j++) { 
00306                         buf_option[4+j] = (char) toupper(options[i].name[j]);
00307                 }
00308                 buf_option[4+len] = '\0';
00309                 if ((env_value = getenv(buf_option)) != NULL) {
00310                         option_set(&(options[i]), env_value);
00311                 }
00312         }
00313 
00314         return TXC_R_SUCCESS;
00315 }
00316 
00317 
00318 static 
00319 txc_result_t
00320 config_init_use_file(char *filename)
00321 {
00322         int i;
00323         int known_parameter;
00324         FILE *fin;
00325         char buf_option[128];
00326         char buf_value[128];
00327         int done;
00328 
00329         option_t options[] = {
00330                 FOREACH_RUNTIME_CONFIG_OPTION(CONFIG_OPTION_KEY)
00331         };
00332 
00333 
00334         if ((fin = fopen(filename, "r")) == NULL) {
00335                 return TXC_R_INVALIDFILE;
00336         } 
00337         done = 0;
00338 
00339         /* Parse each line of the configuration file */
00340         while (!done) {
00341                 switch(parse(fin, buf_option, buf_value)) {
00342                         case parse_result_EOF:
00343                                 done = 1;
00344                                 continue;
00345                         case parse_result_error: 
00346                                 TXC_ERROR("Error while parsing file %s.", txc_init_filename);
00347                                 TXC_ASSERT(0); /* never returns */
00348                         case parse_result_comment:
00349                                 continue;
00350                 }
00351                 known_parameter = 0;
00352                 for (i=0; i < sizeof (options) / sizeof(option_t); i++) {
00353                         if (strcmp(options[i].name, buf_option) == 0) {
00354                                 option_set(&options[i], buf_value); 
00355                                 known_parameter = 1;
00356                                 break;
00357                         }  
00358                 }               
00359                 if (known_parameter == 0) {
00360                         TXC_WARNING("Ignoring unknown parameter '%s'.", buf_option);
00361                 } 
00362         }
00363 
00364         return TXC_R_SUCCESS;
00365 }       
00366 
00367 txc_result_t
00368 txc_config_init ()
00369 {
00370         config_init_use_file(txc_init_filename);
00371         config_init_use_env();
00372 
00373         if (txc_runtime_settings.printconf == TXC_BOOL_TRUE) {
00374                 config_print();
00375         }       
00376                 
00377         return TXC_R_SUCCESS;   
00378 }
00379 
00380 
00381 txc_result_t 
00382 txc_config_set_option(char *option, char *value)
00383 {
00384         int i;
00385         int known_parameter;
00386 
00387         option_t options[] = {
00388                 FOREACH_RUNTIME_CONFIG_OPTION(CONFIG_OPTION_KEY)
00389         };
00390 
00391         known_parameter = 0;
00392         for (i=0; i < sizeof (options) / sizeof(option_t); i++) {
00393                 if (strcmp(options[i].name, option) == 0) {
00394                         option_set(&options[i], value); 
00395                         known_parameter = 1;
00396                         break;
00397                 }  
00398         }               
00399         if (known_parameter == 0) {
00400                 TXC_WARNING("Ignoring unknown parameter '%s'.", option);
00401         } 
00402 
00403         return TXC_R_SUCCESS;
00404 }

Generated on Wed Dec 9 20:32:39 2009 for xCalls by  doxygen 1.4.7