core/globals.c

00001 
00012 #include <stdarg.h>
00013 #include "output.h"
00014 #include "globals.h"
00015 #include "module.h"
00016 
00017 static GLOBALVAR *global_varlist = NULL, *lastvar = NULL;
00018 
00019 static struct s_varmap {
00020     char *name;
00021     PROPERTYTYPE type;
00022     void *addr;
00023     PROPERTYACCESS access;
00024     char *init; /* this is not used yet */
00025 } map[] = {
00027     {"version.major", PT_int32, &global_version_major, PA_REFERENCE},
00028     {"version.minor", PT_int32, &global_version_minor, PA_REFERENCE},
00029     {"command_line", PT_char1024, &global_command_line, PA_REFERENCE},
00030     {"environment", PT_char1024, &global_environment, PA_REFERENCE},
00031     {"quiet", PT_int32, &global_quiet_mode, PA_REFERENCE},
00032     {"warn", PT_int32, &global_warn_mode, PA_REFERENCE},
00033     {"debugger", PT_int32, &global_debug_mode, PA_REFERENCE},
00034     {"debug", PT_int32, &global_debug_output, PA_REFERENCE},
00035     {"test", PT_int32, &global_debug_mode, PA_REFERENCE},
00036     {"verbose", PT_int32, &global_verbose_mode, PA_REFERENCE},
00037     {"iteration_limit", PT_int32, &global_iteration_limit, PA_REFERENCE},
00038     {"workdir", PT_char1024, &global_workdir, PA_REFERENCE},
00039     {"dumpfile", PT_char1024, &global_dumpfile, PA_REFERENCE},
00040     {"savefile", PT_char1024, &global_savefile, PA_REFERENCE},
00041     {"dumpall", PT_int32, &global_dumpall, PA_REFERENCE},
00042     {"runchecks", PT_int32, &global_runchecks, PA_REFERENCE},
00043     {"threadcount", PT_int32, &global_threadcount, PA_REFERENCE},
00044     {"profiler", PT_int32, &global_profiler, PA_REFERENCE},
00045     {"pauseatexit", PT_int32, &global_pauseatexit, PA_REFERENCE},
00046     {"testoutputfile", PT_char1024, &global_testoutputfile, PA_REFERENCE},
00047     {"xml_encoding", PT_int32, &global_xml_encoding, PA_REFERENCE},
00048     {"clock", PT_timestamp, &global_clock, PA_REFERENCE},
00049     {"starttime", PT_timestamp, &global_starttime, PA_REFERENCE},
00050     {"stoptime", PT_timestamp, &global_stoptime, PA_REFERENCE},
00051     {"double_format", PT_char32, &global_double_format, PA_REFERENCE},
00052     {"complex_format", PT_char256, &global_complex_format, PA_REFERENCE},
00053     {"object_format", PT_char32, &global_object_format, PA_REFERENCE},
00054     {"object_scan", PT_char32, &global_object_scan, PA_REFERENCE},
00055     {"object_tree_balance", PT_bool, &global_no_balance, PA_REFERENCE},
00056     {"kmlfile", PT_char1024, &global_kmlfile, PA_REFERENCE},
00057     {"modelname", PT_char1024, &global_modelname, PA_REFERENCE},
00058     {"execdir",PT_char1024, &global_execdir, PA_REFERENCE},
00059     /* add new global variables here */
00060 };
00061 
00065 STATUS global_init(void)
00066 {
00067     unsigned int i;
00068     for (i=0; i<sizeof(map)/sizeof(map[0]); i++)
00069     {
00070         struct s_varmap *p = &(map[i]);
00071         if (global_create(p->name,p->type,p->addr,PT_ACCESS,p->access,NULL)==NULL)
00072             output_error("global_init(): global variable '%s' registration failed", p->name);
00073     }
00074     return SUCCESS;
00075 }
00076 
00080 GLOBALVAR *global_find(char *name) 
00081 {
00082     GLOBALVAR *var;
00083     for (var=global_getnext(NULL); var!=NULL; var=global_getnext(var))
00084     {
00085         if (strcmp(var->name,name)==0)
00086             return var;
00087     }
00088     return NULL;
00089 }
00090 
00099 GLOBALVAR *global_getnext(GLOBALVAR *previous) 
00100 {
00101     return previous==NULL ? global_varlist : previous->next;
00102 }
00103 
00116 GLOBALVAR *global_create(char *name, ...)
00117 {
00118     va_list arg;
00119     PROPERTY *property = NULL, *lastprop = NULL;
00120     PROPERTYTYPE proptype;
00121 
00122     /* allocate the global var definition */
00123     GLOBALVAR *var = (GLOBALVAR*)malloc(sizeof(GLOBALVAR));
00124     if (var==NULL)
00125     {
00126         errno = ENOMEM;
00127         throw_exception("global_create(char *name='%s',...): unable to allocate memory for global variable", name);
00128         return NULL;
00129     }
00130     strncpy(var->name,name,sizeof(var->name));
00131     var->prop = NULL;
00132     var->next = NULL;
00133 
00134     /* read the property args */
00135     va_start(arg,name);
00136     while ((proptype=va_arg(arg,PROPERTYTYPE))!=0)
00137     {
00138         if (proptype>_PT_LAST)
00139         {
00140             if (property==NULL)
00141                 throw_exception("global_create(char *name='%s',...): property keyword not specified after an enumeration property definition", name);
00142             else if (proptype==PT_KEYWORD && property->ptype==PT_enumeration)
00143             {
00144                 char *keyword = va_arg(arg,char*);
00145                 long keyvalue = va_arg(arg,long);
00146                 KEYWORD *key = (KEYWORD*)malloc(sizeof(KEYWORD));
00147                 if (key==NULL) 
00148                     throw_exception("global_create(char *name='%s',...): property keyword could not be stored", name);
00149                 key->next = property->keywords;
00150                 strncpy(key->name,keyword,sizeof(key->name));
00151                 key->value = keyvalue;
00152                 property->keywords = key;
00153             }
00154             else if (proptype==PT_KEYWORD && property->ptype==PT_set)
00155             {
00156                 char *keyword = va_arg(arg,char*);
00157                 unsigned char keyvalue = va_arg(arg, int); /* uchars are promoted to int by GCC */
00158                 KEYWORD *key = (KEYWORD*)malloc(sizeof(KEYWORD));
00159                 if (keyvalue>63) 
00160                     throw_exception("global_create(char *name='%s',...): set '%s' keyword value '%d' may not exceed 64",name,keyword,keyvalue);
00161                 if (key==NULL) 
00162                     throw_exception("global_create(char *name='%s',...): property keyword could not be stored", name);
00163                 key->next = property->keywords;
00164                 strncpy(key->name,keyword,sizeof(key->name));
00165                 key->value = keyvalue;
00166                 property->keywords = key;
00167             }
00168             else if (proptype==PT_ACCESS)
00169             {
00170                 PROPERTYACCESS pa = va_arg(arg,PROPERTYACCESS); 
00171                 switch (pa) {
00172                 case PA_PUBLIC:
00173                 case PA_REFERENCE:
00174                 case PA_PROTECTED:
00175                 case PA_PRIVATE:
00176                     property->access = pa;
00177                     break;
00178                 default:
00179                     errno = EINVAL;
00180                     throw_exception("global_create(char *name='%s',...): unrecognized property access code (PROPERTYACCESS=%d)", name, pa);
00181                     break;
00182                 }
00183             }
00184             else if (proptype==PT_SIZE)
00185             {
00186                 property->size = va_arg(arg,unsigned long);
00187                 if (property->addr==0)
00188                 {
00189                     if (property->size>0)
00190                         property->addr = (PROPERTYADDR)malloc(property->size * property_size(property));
00191                     else
00192                         throw_exception("global_create(char *name='%s',...): property size must be greater than 0 to allocate memory", name);
00193                 }
00194             }
00195             else
00196                 throw_exception("global_create(char *name='%s',...): property extension code not recognized (PROPERTYTYPE=%d)", name, proptype);
00197         }
00198         else
00199         {
00200             DELEGATEDTYPE *delegation=(proptype==PT_delegated?va_arg(arg,DELEGATEDTYPE*):NULL);
00201             char unitspec[1024];
00202             if (strlen(name)>=sizeof(property->name))
00203                 throw_exception("global_create(char *name='%s',...): property name '%s' is too big to store", name, name);
00204             property = (PROPERTY*)malloc(sizeof(PROPERTY));
00205             if (property==NULL)
00206                 throw_exception("global_create(char *name='%s',...): property '%s' could not be stored", name, name);
00207             property->otype = 0;
00208             property->ptype = proptype;
00209             property->addr = va_arg(arg,PROPERTYADDR);
00210             property->size = 1;
00211             property->keywords = NULL;
00212             if (sscanf(name,"%[^[][%[A-Za-z0-9*/^]]",property->name,unitspec)==2)
00213             {
00214                 property->unit = unit_find(unitspec);
00215                 if (property->unit==NULL)
00216                     throw_exception("global_create(char *name='%s',...): property %s unit '%s' is not recognized",name, property->name,unitspec);
00217             }
00218             else
00219                 property->unit = NULL;
00220             property->delegation = delegation;
00221             property->next = NULL;
00222             if (var->prop==NULL)
00223                 var->prop = property;
00224 
00225             
00226             /* link map to oclass if not yet done */
00227             if (lastprop!=NULL)
00228                 lastprop->next = property;
00229             else
00230                 lastprop = property;
00231 
00232             /* save enum property in case keywords come up */
00233             if (property->ptype>_PT_LAST)
00234                 property = NULL;
00235         }
00236     }
00237     va_end(arg);
00238     
00239     if (lastvar==NULL) 
00240         /* first variable */
00241         global_varlist = lastvar = var;
00242     else
00243     {   /* not first */
00244         lastvar->next = var;
00245         lastvar = var;
00246     }
00247 
00248     return var;
00249 }
00250 
00260 STATUS global_setvar(char *def, ...) 
00261 {
00262     char name[32]="", value[1024]="";
00263     if (sscanf(def,"%[^=]=%[^\n]",name,value)<2)
00264     {
00265         va_list ptr;
00266         char *v;
00267         va_start(ptr,def);
00268         v = va_arg(ptr,char*);
00269         va_end(ptr);
00270         strncpy(value,v,sizeof(value));
00271         if (strcmp(value,v)!=0)
00272             output_error("global_setvar(char *name='%s',...): value is too long to store");
00273     }
00274     if (strcmp(name,"")!=0) /* something was defined */
00275     {
00276         GLOBALVAR *var = global_find(name);
00277         if (var==NULL)
00279             var = global_create(name,PT_char1024,NULL,PT_SIZE,1,PT_ACCESS,PA_PUBLIC,NULL);
00280         class_string_to_property(var->prop,(void*)var->prop->addr,value);
00281         return SUCCESS;
00282     }
00283     else
00284     {
00285         output_error("global variable definition '%s' not formatted correctedly", def);
00286         return FAILED;
00287     }
00288 }
00289 
00290 #if 0
00291 
00297 char *global_getvar(char *name) 
00298 {
00299     static char result[1024];
00300     GLOBALVAR *var = global_find(name);
00301     if (var==NULL)
00302         return NULL;
00303     if (class_property_to_string(var->prop,(void*)var->prop->addr,result,sizeof(result))>0)
00304         return result;
00305     else
00306         return NULL;
00307 }
00308 #endif
00309 
00316 char *global_getvar(char *name, char *buffer, int size){
00317     static char local_buff[1024];
00318     char temp[1024];
00319     int len = 0;
00320     GLOBALVAR *var = NULL;
00321     if(buffer == NULL){
00322         buffer = local_buff; /* might as well hook into the old func. -mh */
00323         size = 1024;
00324     }
00325     if(size < 1){
00326         return NULL; /* user error ... could force it, but that's asking for trouble. */
00327     }
00328     var = global_find(name);
00329     if(var == NULL)
00330         return NULL;
00331     len = class_property_to_string(var->prop, (void *)var->prop->addr, temp, sizeof(temp));
00332     if(len < size){ /* if we have enough space, copy to the supplied buffer */
00333         strncpy(buffer, temp, len+1);
00334         return buffer; /* wrote buffer, return ptr for printf funcs */
00335     }
00336     return NULL; /* NULL if insufficient buffer space */
00337 }
00338 
00339 void global_dump(void)
00340 {
00341     GLOBALVAR *var=NULL;
00342     while ((var=global_getnext(var))!=NULL)
00343     {
00344         char buffer[1024];
00345         if (class_property_to_string(var->prop, (void*)var->prop->addr,buffer,sizeof(buffer)))
00346             output_message("%s=%s;", var->name, buffer);
00347     }
00348 }
00349 

GridLAB-DTM Version 1.0
An open-source project initiated by the US Department of Energy