core/module.c

00001 
00317 
00319 
00321 
00336 
00348 
00384 #ifdef WIN32
00385 #include <io.h>
00386 #else
00387 #include <unistd.h>
00388 #endif
00389 #include <math.h>
00390 
00391 #ifdef HAVE_CONFIG_H
00392 #include "config.h"
00393 #endif
00394 
00395 /* The following hack is required to stringize LIBEXT as passed in from
00396  * Makefile and used by snprintf below to construct the library name. */
00397 #define _STR(x) #x
00398 #define STR(x) _STR(x)
00399 
00400 #ifdef WIN32
00401 #define WIN32_LEAN_AND_MEAN     // Exclude rarely-used stuff from Windows headers
00402 #define _WIN32_WINNT 0x0400
00403 #include <windows.h>
00404 #define LIBPREFIX
00405 #ifndef LIBEXT
00406 #define LIBEXT .dll
00407 #endif
00408 #define DLLOAD(P) LoadLibrary(P)
00409 #define DLSYM(H,S) GetProcAddress((HINSTANCE)H,S)
00410 #define snprintf _snprintf
00411 #else /* ANSI */
00412 #include "dlfcn.h"
00413 #define LIBPREFIX "lib"
00414 #ifndef LIBEXT
00415 #define LIBEXT .so
00416 #else
00417 #endif
00418 #define DLLOAD(P) dlopen(P,RTLD_LAZY)
00419 #define DLSYM(H,S) dlsym(H,S)
00420 #endif
00421 
00422 #if !defined(HAVE_CONFIG_H) || defined(HAVE_MALLOC_H)
00423 #include <malloc.h>
00424 #endif
00425 
00426 #include <errno.h>
00427 #include "globals.h"
00428 #include "output.h"
00429 #include "module.h"
00430 #include "find.h"
00431 #include "random.h"
00432 #include "test_callbacks.h"
00433 #include "exception.h"
00434 #include "unit.h"
00435 #include "lock.h"
00436 
00437 #include "matlab.h"
00438 
00439 int get_exe_path(char *buf, int len, void *mod){    /* void for GetModuleFileName, a windows func */
00440     int rv = 0, i = 0;
00441     if(buf == NULL)
00442         return 0;
00443     if(len < 1)
00444         return 0;
00445 #ifdef WIN32
00446     rv = GetModuleFileName((HMODULE) mod, buf, len);
00447     if(rv){
00448         for(i = rv; ((buf[i] != '/') && (buf[i] != '\\') && (i >= 0)); --i){
00449             buf[i] = 0;
00450             --rv;
00451         }
00452     }
00453 #else /* POSIX */
00454     if(mod == NULL){ /* "/bin/gridlabd"?*/
00455         ;
00456     } else {
00457         ;
00458     }
00459 #endif
00460     return rv;
00461 }
00462 
00463 int module_get_exe_path(char *buf, int len){
00464     return get_exe_path(buf, len, NULL);
00465 }
00466 
00467 int module_get_path(char *buf, int len, MODULE *mod){
00468     return get_exe_path(buf, len, mod->hLib);
00469 }
00470 
00471 void dlload_error(const char *filename)
00472 {
00473 #ifdef WIN32
00474     LPTSTR error;
00475     LPTSTR end;
00476     DWORD result = FormatMessage(
00477                 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
00478                 NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
00479                 (LPTSTR) &error, 0, NULL);
00480     if (!result)
00481         error = TEXT("[FormatMessage failed]");
00482     else for (end = error + strlen(error) - 1; end >= error && isspace(*end); end--)
00483         *end = 0;
00484 #else
00485     char *error = dlerror();
00486 #endif
00487     output_debug("%s: %s (LD_LIBRARY_PATH=%s)", filename, error,getenv("LD_LIBRARY_PATH"));
00488 #ifdef WIN32
00489     if (result)
00490         LocalFree(error);
00491 #endif
00492 }
00493 
00494 /* these are the core functions available to loadable modules
00495  * the structure is defined in object.h */
00496 int64 lock_count;
00497 int64 lock_spin;
00498 static CALLBACKS callbacks = {
00499     &global_clock,
00500     output_verbose,
00501     output_message,
00502     output_warning,
00503     output_error,
00504     output_debug,
00505     output_test,
00506     class_register,
00507     object_create_single,
00508     object_create_array,
00509     class_define_map,
00510     class_define_function,
00511     class_define_enumeration_member,
00512     class_define_set_member,
00513     object_set_dependent,
00514     object_set_parent,
00515     object_set_rank,
00516     {object_get_property, object_set_value_by_addr,object_get_value_by_addr, object_set_value_by_name,object_get_value_by_name,object_get_reference,object_get_unit},
00517     find_objects,
00518     find_next,
00519     malloc,
00520     free,
00521     aggregate_mkgroup,
00522     aggregate_value,
00523     module_getvar_addr,
00524     {random_uniform, random_normal, random_bernoulli, random_pareto, random_lognormal, random_sampled, random_exponential, random_type, random_value},
00525     object_isa,
00526     class_register_type,
00527     class_define_type,
00528     {mkdatetime,strdatetime,timestamp_to_days,timestamp_to_hours,timestamp_to_minutes,timestamp_to_seconds,local_datetime,convert_to_timestamp},
00529     unit_convert, unit_convert_ex,
00530     {create_exception_handler,delete_exception_handler,throw_exception,exception_msg},
00531     {global_create, global_setvar, global_getvar, global_find},
00532 #ifndef NOLOCKS
00533     &lock_count, &lock_spin,
00534 #endif
00535     {find_file},
00536     {object_get_complex, object_get_int16, object_get_int32, object_get_int64, object_get_double, object_get_string, object_get_object},
00537     {object_get_complex_by_name, object_get_int16_by_name, object_get_int32_by_name, object_get_int64_by_name,
00538         object_get_double_by_name, object_get_string_by_name},
00539     {class_string_to_property, class_property_to_string,},
00540     module_find,
00541     object_find_name,
00542     object_get_oflags,
00543 };
00544 
00545 MODULE *first_module = NULL;
00546 MODULE *last_module = NULL;
00547 
00555 typedef MODULE *(*LOADER)(const char *, int, char *[]);
00556 MODULE *module_load(const char *file, 
00557                                int argc, 
00558                                char *argv[]) 
00559 {
00560     /* check for already loaded */
00561     MODULE *mod = module_find((char *)file);
00562     char buffer[FILENAME_MAX+1];
00563     char *fmod;
00564     bool isforeign = false;
00565     char pathname[1024];
00566     char *tpath = NULL;
00567 #ifdef WIN32
00568     char from='/', to='\\';
00569 #else
00570     char from='\\', to='/';
00571 #endif
00572     char *p = NULL;
00573     void *hLib = NULL;
00574     LIBINIT init = NULL;
00575     int *pMajor = NULL, *pMinor = NULL;
00576     CLASS *previous = NULL;
00577     CLASS *c;
00578 
00579     if (mod!=NULL)
00580     {
00581         output_verbose("%s(%d): module '%s' already loaded", __FILE__, __LINE__, file);
00582         return mod;
00583     }
00584     else
00585     {
00586         output_verbose("%s(%d): module '%s' not yet loaded", __FILE__, __LINE__, file);
00587     }
00588 
00589     /* check for foreign modules */
00590     strcpy(buffer,file);
00591     fmod = strtok(buffer,"::");
00592     if (fmod!=NULL && strcmp(fmod, file) != 0)
00593     {
00594         char *modname = strtok(NULL,"::");
00595         MODULE *parent_mod = module_find(fmod);
00596         if(parent_mod == NULL)
00597             parent_mod = module_load(fmod, 0, NULL);
00598         previous = class_get_last_class();
00599         if(parent_mod != NULL && parent_mod->subload != NULL)
00600         {   /* if we've defined a subload routine and already loaded the parent module*/
00601             MODULE *child_mod;
00602             if(module_find(fmod) == NULL)
00603                 module_load(fmod, 0, NULL);
00604             child_mod = parent_mod->subload(modname, &mod, (previous ? &(previous->next) : &previous), argc, argv);
00605             if(child_mod == NULL)
00606             {   /* failure */
00607                 output_error("module_load(file='%s::%s'): subload failed", fmod, modname);
00608                 return NULL;
00609             }
00610             if (mod != NULL)
00611             {   /* if we want to register another module */
00612                 last_module->next = mod;
00613                 last_module = mod;
00614                 mod->oclass = previous ? previous->next : class_get_first_class();
00615             }
00616             return last_module;
00617         } else {
00618             struct {
00619                 char *name;
00620                 LOADER loader;
00621             } fmap[] = {
00622                 {"matlab",NULL},
00623                 {"java",load_java_module},
00624                 {"python",load_python_module},
00625                 {NULL,NULL} /* DO NOT DELETE THIS TERMINATOR ENTRY */
00626             }, *p;
00627             for (p=fmap; p->name!=NULL; p++)
00628             {
00629                 if (strcmp(p->name, fmod)==0)
00630                 {
00631                     static char *args[1];
00632                     isforeign = true;
00633                     if (p->loader!=NULL)
00634                         /* use external loader */
00635                         return p->loader(modname,argc,argv);
00636 
00637                     /* use a module with command args */
00638                     argv = args;
00639                     argc=1;
00640                     argv[0] = modname;
00641                     file=buffer;
00642                     break;
00643                 }
00644             }
00645             if (p==NULL)
00646             {
00647                 output_error("module_load(file='%s',...): foreign module type %s not recognized or supported", fmod);
00648                 return NULL;
00649             }
00650         }
00651     }
00652 
00653     /* create a new module entry */
00654     mod = (MODULE *)malloc(sizeof(MODULE));
00655     if (mod==NULL)
00656     {
00657         output_verbose("%s(%d): module '%s' memory allocation failed", __FILE__, __LINE__, file);
00658         errno=ENOMEM;
00659         return NULL;
00660     }
00661     else
00662         output_verbose("%s(%d): module '%s' memory allocated", __FILE__, __LINE__, file);
00663 
00664     /* locate the module */
00665     snprintf(pathname, 1024, LIBPREFIX "%s" STR(LIBEXT), file);
00666     tpath = find_file(pathname, NULL, X_OK|R_OK);
00667     if(tpath == NULL) 
00668     {
00669         output_verbose("unable to locate %s in GLPATH, using library loader instead", pathname);
00670         tpath=pathname;
00671     }
00672     else
00673         output_verbose("full path to library '%s' is '%s'", file, tpath);
00674 
00675     /* convert path delims based on OS preference */
00676     for (p=strchr(tpath,from); p!=NULL; p=strchr(p,from))
00677         *p=to;
00678 
00679     /* ok, let's do it */
00680     hLib = DLLOAD(tpath);
00681     if (hLib==NULL)
00682     {
00683 #ifdef WIN32
00684         output_verbose("%s(%d): module '%s' load failed - %s (error code %d)", __FILE__, __LINE__, file, strerror(errno), GetLastError());
00685 #else
00686         output_verbose("%s(%d): module '%s' load failed - %s", __FILE__, __LINE__, file, dlerror());
00687 #endif
00688         dlload_error(pathname);
00689         errno = ENOENT;
00690         free(mod);
00691         return NULL;
00692     }
00693     else
00694         output_verbose("%s(%d): module '%s' loaded ok", __FILE__, __LINE__, file);
00695 
00696     /* get the initialization function */
00697     init = (LIBINIT)DLSYM(hLib,"init");
00698     if (init==NULL)
00699     {
00700         output_verbose("%s(%d): module '%s' does not export init()", __FILE__, __LINE__, file);
00701         dlload_error(pathname);
00702         errno = ENOEXEC;
00703         free(mod);
00704         return NULL;
00705     }
00706     else
00707         output_verbose("%s(%d): module '%s' exports init()", __FILE__, __LINE__, file);
00708 
00709     /* connect the module's exported data & functions */
00710     mod->hLib = (void*)hLib;
00711     pMajor = (int*)DLSYM(hLib, "major");
00712     pMinor = (int*)DLSYM(hLib, "minor");
00713     mod->major = pMajor?*pMajor:0;
00714     mod->minor = pMinor?*pMinor:0;
00715     mod->import_file = (int(*)(char*))DLSYM(hLib,"import_file");
00716     mod->export_file = (int(*)(char*))DLSYM(hLib,"export_file");
00717     mod->setvar = (int(*)(char*,char*))DLSYM(hLib,"setvar");
00718     mod->getvar = (void*(*)(char*,char*,unsigned int))DLSYM(hLib,"getvar");
00719     mod->check = (int(*)())DLSYM(hLib,"check");
00720 #ifndef _NO_CPPUNIT
00721     mod->module_test = (int(*)(TEST_CALLBACKS*,int,char*[]))DLSYM(hLib,"module_test");
00722 #endif
00723     mod->cmdargs = (int(*)(int,char**))DLSYM(hLib,"cmdargs");
00724     mod->kmldump = (int(*)(FILE*,OBJECT*))DLSYM(hLib,"kmldump");
00725     mod->subload = (MODULE *(*)(char *, MODULE **, CLASS **, int, char **))DLSYM(hLib, "subload");
00726     mod->globals = NULL;
00727     strcpy(mod->name,file);
00728     mod->next = NULL;
00729 
00730     /* call the initialization function */
00731     previous = class_get_last_class();
00732     if ((*init)(&callbacks,(void*)mod,argc,argv)!=NULL)
00733         mod->oclass = previous ? previous->next : class_get_first_class();
00734     else
00735         mod->oclass = NULL;
00736 
00737     /* connect intrinsic functions */
00738     for (c=mod->oclass; c!=NULL; c=c->next) {
00739         char fname[1024];
00740         struct {
00741             FUNCTIONADDR *func;
00742             char *name;
00743             int optional;
00744         } map[] = {
00745             {&c->create,"create",FALSE},
00746             {&c->init,"init",TRUE},
00747             {&c->sync,"sync",FALSE},
00748             {&c->notify,"notify",TRUE},
00749             {&c->isa,"isa",TRUE},
00750             {&c->plc,"plc",TRUE},
00751             {&c->recalc,"recalc",TRUE},
00752         };
00753         int i;
00754         for (i=0; i<sizeof(map)/sizeof(map[0]); i++)
00755         {
00756             snprintf(fname, 1024,"%s_%s",map[i].name,isforeign?fmod:c->name);
00757             if ((*(map[i].func) = (FUNCTIONADDR)DLSYM(hLib,fname))==NULL && !map[i].optional)
00758             {
00759                 output_fatal("intrinsic %s is not defined in %s", fname,file);
00760                 errno=EINVAL;
00761                 return NULL;
00762             }
00763             else
00764                 if(!map[i].optional)
00765                     output_verbose("%s(%d): module '%s' instrinsic %s found", __FILE__, __LINE__, file, fname);
00766         }
00767     }
00768 
00769     /* attach to list of known modules */
00770     if (first_module==NULL)
00771         first_module = mod;
00772     else
00773         last_module->next = mod;
00774     last_module = mod;
00775     return last_module;
00776 }
00777 
00778 int module_setvar(MODULE *mod, char *varname, char *value)
00779 {
00780     char modvarname[1024];
00781     sprintf(modvarname,"%s::%s",mod->name,varname);
00782     return global_setvar(modvarname,value)==SUCCESS;
00783 }
00784 
00785 void* module_getvar(MODULE *mod, char *varname, char *value, unsigned int size)
00786 {
00787     char modvarname[1024];
00788     sprintf(modvarname,"%s::%s",mod->name,varname);
00789     return global_getvar(modvarname,value,size);
00790 }
00791 
00792 double* module_getvar_addr(MODULE *mod, char *varname)
00793 {
00794     char modvarname[1024];
00795     GLOBALVAR *var;
00796     sprintf(modvarname,"%s::%s",mod->name,varname);
00797     var = global_find(modvarname);
00798     if (var!=NULL && var->prop->ptype==PT_double)
00799         return var->prop->addr;
00800     else
00801         return NULL;
00802 }
00803 
00804 int module_saveall(FILE *fp)
00805 {
00806     MODULE *mod;
00807     int count=0;
00808     CLASS *oclass = NULL;
00809     char32 varname;
00810     count += fprintf(fp,"\n########################################################\n");
00811     count += fprintf(fp,"# modules\n");
00812     for (mod=first_module; mod!=NULL; mod=mod->next)
00813     {
00814         varname[0] = '\0';
00815         oclass = NULL;
00816 
00817         count += fprintf(fp,"module %s {\n",mod->name);
00818         if (mod->major>0 || mod->minor>0)
00819             count += fprintf(fp,"\tmajor %d;\n\tminor %d;\n",mod->major,mod->minor);
00820         for (oclass=mod->oclass; oclass!=NULL ; oclass=oclass->next)
00821         {
00822             if (oclass->module==mod)
00823                 count += fprintf(fp,"\tclass %s;\n",oclass->name);
00824         }
00825 
00826         while (module_getvar(mod,varname,NULL,0))
00827         {
00828             char32 value;
00829             if (module_getvar(mod,varname,value,sizeof(value)))
00830                 count += fprintf(fp,"\t%s %s;\n",varname,value);
00831         }
00832         count += fprintf(fp,"}\n");
00833     }
00834     return count;
00835 }
00836 
00837 int module_saveall_xml(FILE *fp){
00838     MODULE *mod;
00839     int count = 0;
00840     char32 varname = "";
00841     char32 value = "";
00842 
00843     for (mod = first_module; mod != NULL; mod = mod->next){
00844         count += fprintf(fp, "\t<module type=\"%s\" ", mod->name);
00845         if (mod->major > 0){
00846             count += fprintf(fp, "major=\"%d\" minor=\"%d\">\n", mod->major, mod->minor);
00847         } else {
00848             count += fprintf(fp, ">\n");
00849         }
00850         module_saveobj_xml(fp, mod);    /* insert objects w/in module tag */
00851         count += fprintf(fp,"\t</module>\n");
00852     }
00853     return count;
00854 }
00855 
00856 #ifdef WIN32
00857 #define isnan _isnan  /* map isnan to appropriate function under Windows */
00858 #endif
00859 
00860 int module_saveobj_xml(FILE *fp, MODULE *mod){ 
00861     unsigned count = 0;
00862     char buffer[1024];
00863     PROPERTY *prop = NULL;
00864     OBJECT *obj;
00865     CLASS *oclass=NULL;
00866 
00867     for(obj = object_get_first(); obj != NULL; obj = obj->next){
00868         char32 oname = "(unidentified)";
00869         if(obj->oclass->module != mod){
00870             continue;
00871         }
00872         
00873         if(obj->name != NULL){
00874             strcpy(oname, obj->name);
00875         } else {
00876             sprintf(oname, "%s:%i", obj->oclass->name, obj->id);
00877         }
00878         if ((oclass == NULL) || (obj->oclass->type != oclass->type))
00879             oclass = obj->oclass;
00880         count += fprintf(fp,"\t\t<object type=\"%s\" id=\"%i\" name=\"%s\">\n", obj->oclass->name, obj->id, oname);
00881 
00882         /* dump internal properties */
00883         if (obj->parent!=NULL){
00884             if(obj->parent->name != NULL){
00885                 strcpy(oname, obj->parent->name);
00886             } else {
00887                 sprintf(oname, "%s:%i", obj->parent->oclass->name, obj->parent->id);
00888             }
00889             count += fprintf(fp,"\t\t\t<parent>%s</parent>\n", oname);
00890         } else {
00891             count += fprintf(fp,"\t\t\t<parent>root</parent>\n");
00892         }
00893         count += fprintf(fp,"\t\t\t<rank>%d</rank>\n", obj->rank);
00894         count += fprintf(fp,"\t\t\t<clock>\n", obj->clock);
00895         count += fprintf(fp,"\t\t\t\t <timestamp>%s</timestamp>\n", convert_from_timestamp(obj->clock,buffer,sizeof(buffer))>0?buffer:"(invalid)");
00896         count += fprintf(fp,"\t\t\t</clock>\n");
00897         /* why do latitude/longitude have 2 values?  I currently only store as float in the schema... -dc */
00898         if (!isnan(obj->latitude))
00899             count += fprintf(fp,"\t\t\t<latitude>%s</latitude>\n", convert_from_latitude(obj->latitude,buffer,sizeof(buffer))?buffer:"(invalid)");
00900         else
00901             count += fprintf(fp, "\t\t\t<latitude>NONE</latitude>\n");
00902         if (!isnan(obj->longitude))
00903             count += fprintf(fp,"\t\t\t<longitude>%s</longitude>\n",convert_from_longitude(obj->longitude,buffer,sizeof(buffer))?buffer:"(invalid)");
00904         else
00905             count += fprintf(fp,"\t\t\t<longitude>NONE</longitude>\n");
00906 
00907         for (prop=oclass->pmap;prop!=NULL && prop->otype==oclass->type;prop=prop->next)
00908         {
00909             char *value = NULL;
00910             if((prop->access != PA_PUBLIC) && (prop->access != PA_REFERENCE))
00911                 continue;
00912             value = object_property_to_string(obj,prop->name);
00913             if (value!=NULL){
00914                 count += fprintf(fp, "\t\t\t<%s>%s</%s>\n", prop->name, value, prop->name);
00915             }
00916         }
00917         count += fprintf(fp,"\t\t</object>\n");
00918     }
00919 
00920     return count;
00921 }
00922 
00923 MODULE *module_get_first(void)
00924 {
00925     return first_module;
00926 }
00927 
00928 int module_saveall_xml_old(FILE *fp);
00929 
00930 int module_saveall_xml_old(FILE *fp)
00931 {
00932     MODULE *mod;
00933     int count=0;
00934     count += fprintf(fp,"\t<modules>\n");
00935     for (mod=first_module; mod!=NULL; mod=mod->next)
00936     {
00937         CLASS *oclass;
00938         char32 varname="";
00939         count += fprintf(fp,"\t\t<module> \n");
00940         count += fprintf(fp,"\t\t\t<name>%s</name>\n",mod->name);
00941         if(mod->major > 0)
00942             count += fprintf(fp,"\t\t\t<major>%d</major>\n",mod->major );
00943         if(mod->minor > 0)
00944             count += fprintf(fp,"\t\t\t<minor>%d</minor>\n",mod->minor);
00945         count += fprintf(fp,"\t\t\t<classes>\n");
00946         for (oclass=mod->oclass; oclass!=NULL ; oclass=oclass->next)
00947         {
00948             if (oclass->module==mod){
00949                 count += fprintf(fp, "\t\t\t\t<class> \n");
00950                 count += fprintf(fp, "\t\t\t\t\t<classname>%s</classname>\n", oclass->name);
00951                 count += fprintf(fp, "\t\t\t\t\t<module name=\"%s\" />\n", mod->name);
00952                 count += fprintf(fp, "\t\t\t\t</class>\n");
00953             }
00954         }
00955         count += fprintf(fp,"\t\t\t</classes>\n");
00956         count += fprintf(fp,"\t\t\t<properties>\n");
00957         while (module_getvar(mod,varname,NULL,0))
00958         {
00959             char32 value;
00960             if (module_getvar(mod,varname,value,sizeof(value)))
00961             {   /* TODO: support other types (ticket #46) */
00962                 count += fprintf(fp,"\t\t\t\t<property> \n");
00963                 count += fprintf(fp,"\t\t\t\t\t <type>double</type>\n", varname);
00964                 count += fprintf(fp,"\t\t\t\t\t <name>%s</name>\n", value);
00965                 count += fprintf(fp,"\t\t\t\t</property> \n");
00966             }
00967         }
00968         count += fprintf(fp,"\t\t\t</properties>\n");
00969         count += fprintf(fp,"\t\t</module>\n");
00970     }
00971     count += fprintf(fp,"\t</modules>\n");
00972     return count;
00973 }
00974 
00975 MODULE *module_find(char *modname)
00976 {
00977     MODULE *mod = NULL;
00978     for (mod=first_module; mod!=NULL; mod=mod->next)
00979     {
00980         if (strcmp(mod->name,modname)==0)
00981             break;
00982     }
00983     return mod;
00984 
00985 }
00986 
00987 int module_import(MODULE *mod, char *filename)
00988 {
00989     if (mod->import_file == NULL)
00990     {
00991         errno = ENOENT;
00992         return 0;
00993     }
00994     return (*mod->import_file)(filename);
00995 }
00996 
00997 int module_save(MODULE *mod, char *filename)
00998 {
00999     if (mod->export_file == NULL)
01000     {
01001         errno = ENOENT;
01002         return 0;
01003     }
01004     return (*mod->export_file)(filename);
01005 }
01006 
01007 int module_dumpall(void)
01008 {
01009     MODULE *mod;
01010     int count=0;
01011     for (mod=first_module; mod!=NULL; mod=mod->next)
01012     {
01013         if (mod->export_file!=NULL)
01014             count += module_save(mod,NULL);
01015     }
01016     return count;
01017 }
01018 
01019 int module_checkall(void)
01020 {
01021     MODULE *mod;
01022     int count=0;
01023     for (mod=first_module; mod!=NULL; mod=mod->next)
01024             count += module_check(mod);
01025     return count;
01026 }
01027 
01028 int module_check(MODULE *mod)
01029 {
01030     if (mod->check==NULL)
01031         return 0;
01032     return (*mod->check)();
01033 }
01034 
01035 void module_libinfo(char *module_name)
01036 {
01037     MODULE *mod = module_load(module_name,0,NULL);
01038     if (mod!=NULL)
01039     {
01040         CLASS *c;
01041         PROPERTY *p;
01042         output_raw("Module name....... %s\n", mod->name);
01043         output_raw("Major version..... %d\n", mod->major);
01044         output_raw("Minor version..... %d\n", mod->minor);
01045         output_raw("Classes........... ");
01046         for (c=mod->oclass; c!=NULL; c=c->next)
01047             output_raw("%s%s", c->name, c->next!=NULL?", ":"");
01048         output_raw("\n");
01049         output_raw("Implementations... ");
01050         if (mod->cmdargs!=NULL) output_raw("cmdargs ");
01051         if (mod->getvar!=NULL) output_raw("getvar ");
01052         if (mod->setvar!=NULL) output_raw("setvar ");
01053         if (mod->import_file!=NULL) output_raw("import_file ");
01054         if (mod->export_file!=NULL) output_raw("export_file ");
01055         if (mod->check!=NULL) output_raw("check ");
01056         if (mod->kmldump!=NULL) output_raw("kmldump ");
01057 #ifndef _NO_CPPUNIT
01058         if (mod->module_test!=NULL) output_raw("module_test ");
01059 #endif
01060         output_raw("\nGlobals........... ");
01061         for (p=mod->globals; p!=NULL; p=p->next)
01062             output_raw("%s ", p->name);
01063         output_raw("\n");
01064     }
01065     else
01066         output_error("Module %s load failed", module_name);
01067 }
01068 
01069 int module_cmdargs(int argc, char **argv)
01070 {
01071     MODULE *mod;
01072     for (mod=first_module; mod!=NULL; mod=mod->next)
01073     {
01074         if (mod!=NULL && mod->cmdargs!=NULL)
01075             return (*(mod->cmdargs))(argc,argv);
01076     }
01077     return 0;
01078 }
01079 

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