00001
00013 #include <stdarg.h>
00014 #include "output.h"
00015 #include "globals.h"
00016 #include "module.h"
00017
00018 static GLOBALVAR *global_varlist = NULL, *lastvar = NULL;
00019
00020 static KEYWORD df_keys[] = {
00021 {"ISO", DF_ISO, df_keys+1},
00022 {"US", DF_US, df_keys+2},
00023 {"EURO", DF_EURO, NULL},
00024 };
00025
00026 static struct s_varmap {
00027 char *name;
00028 PROPERTYTYPE type;
00029 void *addr;
00030 PROPERTYACCESS access;
00031 KEYWORD *keys;
00032 void (*callback)(char *name);
00033 } map[] = {
00035 {"version.major", PT_int32, &global_version_major, PA_REFERENCE},
00036 {"version.minor", PT_int32, &global_version_minor, PA_REFERENCE},
00037 {"command_line", PT_char1024, &global_command_line, PA_REFERENCE},
00038 {"environment", PT_char1024, &global_environment, PA_REFERENCE},
00039 {"quiet", PT_int32, &global_quiet_mode, PA_PUBLIC},
00040 {"warn", PT_int32, &global_warn_mode, PA_PUBLIC},
00041 {"debugger", PT_int32, &global_debug_mode, PA_PUBLIC},
00042 {"gdb", PT_int32, &global_gdb, PA_PUBLIC},
00043 {"debug", PT_int32, &global_debug_output, PA_PUBLIC},
00044 {"test", PT_int32, &global_debug_mode, PA_PUBLIC},
00045 {"verbose", PT_int32, &global_verbose_mode, PA_PUBLIC},
00046 {"iteration_limit", PT_int32, &global_iteration_limit, PA_PUBLIC},
00047 {"workdir", PT_char1024, &global_workdir, PA_REFERENCE},
00048 {"dumpfile", PT_char1024, &global_dumpfile, PA_PUBLIC},
00049 {"savefile", PT_char1024, &global_savefile, PA_PUBLIC},
00050 {"dumpall", PT_int32, &global_dumpall, PA_PUBLIC},
00051 {"runchecks", PT_int32, &global_runchecks, PA_PUBLIC},
00052 {"threadcount", PT_int32, &global_threadcount, PA_PUBLIC},
00053 {"profiler", PT_int32, &global_profiler, PA_PUBLIC},
00054 {"pauseatexit", PT_int32, &global_pauseatexit, PA_PUBLIC},
00055 {"testoutputfile", PT_char1024, &global_testoutputfile, PA_PUBLIC},
00056 {"xml_encoding", PT_int32, &global_xml_encoding, PA_PUBLIC},
00057 {"clock", PT_timestamp, &global_clock, PA_PUBLIC},
00058 {"starttime", PT_timestamp, &global_starttime, PA_PUBLIC},
00059 {"stoptime", PT_timestamp, &global_stoptime, PA_PUBLIC},
00060 {"double_format", PT_char32, &global_double_format, PA_PUBLIC},
00061 {"complex_format", PT_char256, &global_complex_format, PA_PUBLIC},
00062 {"object_format", PT_char32, &global_object_format, PA_PUBLIC},
00063 {"object_scan", PT_char32, &global_object_scan, PA_PUBLIC},
00064 {"object_tree_balance", PT_bool, &global_no_balance, PA_PUBLIC},
00065 {"kmlfile", PT_char1024, &global_kmlfile, PA_PUBLIC},
00066 {"modelname", PT_char1024, &global_modelname, PA_REFERENCE},
00067 {"execdir",PT_char1024, &global_execdir, PA_REFERENCE},
00068 {"strictnames", PT_bool, &global_strictnames, PA_PUBLIC},
00069 {"website", PT_char1024, &global_urlbase, PA_PUBLIC},
00070 {"urlbase", PT_char1024, &global_urlbase, PA_PUBLIC},
00071 {"randomseed", PT_int32, &global_randomseed, PA_PUBLIC,NULL,(void(*)(char*))random_init},
00072 {"include", PT_char1024, &global_include, PA_REFERENCE},
00073 {"trace", PT_char1024, &global_trace, PA_PUBLIC},
00074 {"gdb_window", PT_int32, &global_gdb_window, PA_PUBLIC},
00075 {"tmp", PT_char1024, &global_tmp, PA_PUBLIC},
00076 {"force_compile", PT_int32, &global_force_compile, PA_PUBLIC},
00077 {"nolocks", PT_int32, &global_nolocks, PA_PUBLIC},
00078 {"skipsafe", PT_int32, &global_skipsafe, PA_PUBLIC},
00079 {"dateformat", PT_enumeration, &global_dateformat, PA_PUBLIC, df_keys},
00080 {"minimum_timestep", PT_int32, &global_minimum_timestep, PA_PUBLIC},
00081 {"platform",PT_char8, global_platform, PA_REFERENCE},
00082 {"suppress_repeat_messages",PT_int32, &global_suppress_repeat_messages, PA_PUBLIC},
00083 {"maximum_synctime",PT_int32, &global_maximum_synctime, PA_PUBLIC},
00084 {"run_realtime",PT_int32, &global_run_realtime, PA_PUBLIC},
00085 {"no_deprecate",PT_int16, &global_suppress_deprecated_messages, PA_PUBLIC},
00086 #ifdef _DEBUG
00087 {"sync_dumpfile",PT_char1024, &global_sync_dumpfile, PA_PUBLIC},
00088 #endif
00089 {"streaming_io",PT_int32, &global_streaming_io_enabled, PA_PROTECTED},
00090 {"compileonly",PT_int32, &global_compileonly, PA_PROTECTED},
00091 {"relax_naming_rules",PT_int32,&global_relax_naming_rules, PA_PUBLIC}
00092
00093 };
00094
00098 STATUS global_init(void)
00099 {
00100 unsigned int i;
00101 for (i = 0; i < sizeof(map) / sizeof(map[0]); i++){
00102 struct s_varmap *p = &(map[i]);
00103 GLOBALVAR *var = global_create(p->name, p->type, p->addr, PT_ACCESS, p->access, NULL);
00104 if(var == NULL){
00105 output_error("global_init(): global variable '%s' registration failed", p->name);
00106
00107
00108
00109
00110
00111
00112 } else {
00113 var->prop->keywords = p->keys;
00114 var->callback = p->callback;
00115 }
00116 }
00117 return SUCCESS;
00118 }
00119
00123 GLOBALVAR *global_find(char *name)
00124 {
00125 GLOBALVAR *var = NULL;
00126 for(var = global_getnext(NULL); var != NULL; var = global_getnext(var)){
00127 if(strcmp(var->name, name) == 0){
00128 return var;
00129 }
00130 }
00131 return NULL;
00132 }
00133
00142 GLOBALVAR *global_getnext(GLOBALVAR *previous){
00143 if(previous == NULL){
00144 return global_varlist;
00145 } else {
00146 return previous->next;
00147 }
00148 }
00149
00162 GLOBALVAR *global_create(char *name, ...){
00163 va_list arg;
00164 PROPERTY *prop = NULL, *lastprop = NULL;
00165 PROPERTYTYPE proptype;
00166 GLOBALVAR *var = NULL;
00167
00168
00169 if(global_find(name) != NULL){
00170 errno = EINVAL;
00171 output_error("tried to create global variable '%s' a second time", name);
00172
00173
00174
00175
00176
00177 return NULL;
00178 }
00179
00180
00181 var = (GLOBALVAR *)malloc(sizeof(GLOBALVAR));
00182 memset(var,0,sizeof(GLOBALVAR));
00183
00184 if(var == NULL){
00185 errno = ENOMEM;
00186 throw_exception("global_create(char *name='%s',...): unable to allocate memory for global variable", name);
00187
00188
00189
00190 return NULL;
00191 }
00192
00193 strncpy(var->name, name, sizeof(var->name));
00194 var->prop = NULL;
00195 var->next = NULL;
00196
00197
00198 va_start(arg, name);
00199
00200 while ((proptype = va_arg(arg,PROPERTYTYPE)) != 0){
00201 if(proptype > _PT_LAST){
00202 if(prop == NULL){
00203 throw_exception("global_create(char *name='%s',...): property keyword not specified after an enumeration property definition", name);
00204 } else if(proptype == PT_KEYWORD && prop->ptype == PT_enumeration) {
00205 char *keyword = va_arg(arg, char *);
00206 long keyvalue = va_arg(arg, long);
00207 KEYWORD *key = (KEYWORD *)malloc(sizeof(KEYWORD));
00208 if(key == NULL){
00209 throw_exception("global_create(char *name='%s',...): property keyword could not be stored", name);
00210
00211
00212
00213 }
00214 key->next = prop->keywords;
00215 strncpy(key->name, keyword, sizeof(key->name));
00216 key->value = keyvalue;
00217 prop->keywords = key;
00218 } else if(proptype == PT_KEYWORD && prop->ptype == PT_set){
00219 char *keyword = va_arg(arg, char *);
00220 unsigned int64 keyvalue = va_arg(arg, int64);
00221 KEYWORD *key = (KEYWORD *)malloc(sizeof(KEYWORD));
00222 if(key == NULL){
00223 throw_exception("global_create(char *name='%s',...): property keyword could not be stored", name);
00224
00225
00226
00227 }
00228 key->next = prop->keywords;
00229 strncpy(key->name, keyword, sizeof(key->name));
00230 key->value = keyvalue;
00231 prop->keywords = key;
00232 } else if(proptype == PT_ACCESS){
00233 PROPERTYACCESS pa = va_arg(arg, PROPERTYACCESS);
00234 switch (pa){
00235 case PA_PUBLIC:
00236 case PA_REFERENCE:
00237 case PA_PROTECTED:
00238 case PA_PRIVATE:
00239 prop->access = pa;
00240 break;
00241 default:
00242 errno = EINVAL;
00243 throw_exception("global_create(char *name='%s',...): unrecognized property access code (PROPERTYACCESS=%d)", name, pa);
00244
00245
00246
00247 break;
00248 }
00249 } else if(proptype == PT_SIZE){
00250 prop->size = va_arg(arg, unsigned long);
00251 if(prop->addr == 0){
00252 if (prop->size > 0){
00253 prop->addr = (PROPERTYADDR)malloc(prop->size * property_size(prop));
00254 } else {
00255 throw_exception("global_create(char *name='%s',...): property size must be greater than 0 to allocate memory", name);
00256
00257
00258
00259 }
00260 }
00261 } else if(proptype == PT_UNITS){
00262 char *unitspec = va_arg(arg, char *);
00263 if((prop->unit = unit_find(unitspec)) == NULL){
00264 output_warning("global_create(char *name='%s',...): property %s unit '%s' is not recognized",name, prop->name,unitspec);
00265
00266
00267
00268
00269 }
00270 } else if (proptype == PT_DESCRIPTION) {
00271 prop->description = va_arg(arg,char*);
00272 } else if (proptype == PT_DEPRECATED) {
00273 prop->flags |= PF_DEPRECATED;
00274 } else {
00275 throw_exception("global_create(char *name='%s',...): property extension code not recognized (PROPERTYTYPE=%d)", name, proptype);
00276
00277
00278
00279 }
00280 } else {
00281
00282 PROPERTYADDR addr = va_arg(arg,PROPERTYADDR);
00283 if(strlen(name) >= sizeof(prop->name)){
00284 throw_exception("global_create(char *name='%s',...): property name '%s' is too big to store", name, name);
00285
00286
00287
00288
00289 }
00290 prop = property_malloc(proptype,NULL,name,addr,NULL);
00291 if (prop==NULL)
00292 throw_exception("global_create(char *name='%s',...): property '%s' could not be stored", name, name);
00293 if (var->prop==NULL)
00294 var->prop = prop;
00295
00296
00297 if (lastprop!=NULL)
00298 lastprop->next = prop;
00299 else
00300 lastprop = prop;
00301
00302
00303 if (prop->ptype>_PT_LAST)
00304 prop = NULL;
00305 }
00306 }
00307 va_end(arg);
00308
00309 if (lastvar==NULL)
00310
00311 global_varlist = lastvar = var;
00312 else
00313 {
00314 lastvar->next = var;
00315 lastvar = var;
00316 }
00317
00318 return var;
00319 }
00320
00330 STATUS global_setvar(char *def, ...)
00331 {
00332 char name[66]="", value[1024]="";
00333 if (sscanf(def,"%[^=]=%[^\r\n]",name,value)<2)
00334 {
00335 va_list ptr;
00336 char *v;
00337 va_start(ptr,def);
00338 v = va_arg(ptr,char*);
00339 va_end(ptr);
00340 if (v!=NULL)
00341 {
00342 strncpy(value,v,sizeof(value));
00343 if (strcmp(value,v)!=0)
00344 output_error("global_setvar(char *name='%s',...): value is too long to store");
00345
00346
00347
00348
00349 }
00350 }
00351 if (strcmp(name,"")!=0)
00352 {
00353 GLOBALVAR *var = global_find(name);
00354 if (var==NULL)
00355 {
00356 if (global_strictnames)
00357 {
00358 output_error("strict naming prevents implicit creation of %s", name);
00359
00360
00361
00362
00363
00364
00365 return FAILED;
00366 }
00367
00369 var = global_create(name,PT_char1024,NULL,PT_SIZE,1,PT_ACCESS,PA_PUBLIC,NULL);
00370 }
00371 if (class_string_to_property(var->prop,(void*)var->prop->addr,value)==0){
00372 output_error("global_setvar(): unable to set %s to %s",name,value);
00373
00374
00375
00376
00377
00378 return FAILED;
00379
00380 }
00381 else if (var->callback)
00382 var->callback(var->name);
00383
00384 return SUCCESS;
00385 }
00386 else
00387 {
00388 output_error("global variable definition '%s' not formatted correctedly", def);
00389
00390
00391
00392
00393 return FAILED;
00394 }
00395 }
00396
00403 char *global_getvar(char *name, char *buffer, int size){
00404 static char local_buff[1024];
00405 char temp[1024];
00406 int len = 0;
00407 GLOBALVAR *var = NULL;
00408 if(buffer == NULL){
00409 buffer = local_buff;
00410 size = 1024;
00411 }
00412 if(size < 1){
00413 return NULL;
00414 }
00415 var = global_find(name);
00416 if(var == NULL)
00417 return NULL;
00418 len = class_property_to_string(var->prop, (void *)var->prop->addr, temp, sizeof(temp));
00419 if(len < size){
00420 strncpy(buffer, temp, len+1);
00421 return buffer;
00422 }
00423 return NULL;
00424 }
00425
00426 void global_dump(void)
00427 {
00428 GLOBALVAR *var=NULL;
00429 while ((var=global_getnext(var))!=NULL)
00430 {
00431 char buffer[1024];
00432 if (class_property_to_string(var->prop, (void*)var->prop->addr,buffer,sizeof(buffer)))
00433 output_message("%s=%s;", var->name, buffer);
00434 }
00435 }
00436