int kml_document(FILE *fp) { CLASS *oclass, *openclass=NULL; MODULE *mod; char buffer[1024]; time_t now = time(NULL); kml_write("%s"," <Document>\n"); kml_write(" <name>%s</name>\n", global_modelname); kml_write(" <description>GridLAB-D results for %s</description>\n", convert_from_timestamp(global_clock,buffer,sizeof(buffer))?buffer:"unknown date/time"); /* for each module */ for (mod=module_get_first(); mod!=NULL; mod=mod->next) { if (mod->kmldump) mod->kmldump(kml_write,NULL); /* dump styles */ } /* scan each class in the model */ for (oclass=class_get_first_class(); oclass!=NULL; oclass=oclass->next) { OBJECT *obj; /* scan each object in the model */ for (obj=object_get_first(); obj!=NULL; obj=obj->next) { int has_location = !(isnan(obj->latitude) || isnan(obj->longitude)); MODULE *mod; /* class does not match current object */ if (obj->oclass!=oclass) continue; /* first instance of this class needs folder */ else if (openclass==NULL) { kml_write(" <Folder><name>Class %s</name>\n", oclass->name); kml_write(" <description>Module %s",oclass->module->name); if (oclass->module->minor!=0 || oclass->module->major!=0) kml_write(" (V%d.%02d)",oclass->module->major,oclass->module->minor); kml_write("</description>\n",oclass->module->name); openclass=oclass; } /* module overrides KML output */ mod = (MODULE*)(obj->oclass->module); if (mod->kmldump!=NULL) (*(mod->kmldump))(kml_write,obj); else if (has_location) { /* basic KML output of published variables */ PROPERTY *prop; kml_write(" <Placemark>\n"); if (obj->name) kml_write(" <name>%s</name>\n", obj->name); else kml_write(" <name>%s %d</name>\n", obj->oclass->name, obj->id); kml_write(" <description>\n"); kml_write(" <![CDATA[\n"); kml_write(" <TABLE><TR>\n"); for (prop=oclass->pmap;prop!=NULL && prop->oclass==oclass; prop=prop->next) { char *value = object_property_to_string(obj,prop->name, buffer, 1023); if (value!=NULL) kml_write("<TR><TH ALIGN=LEFT>%s</TH><TD ALIGN=RIGHT>%s</TD></TR>", prop->name, value); } kml_write(" </TR></TABLE>\n"); kml_write(" ]]>\n"); kml_write(" </description>\n"); kml_write(" <Point>\n"); kml_write(" <coordinates>%f,%f</coordinates>\n",obj->longitude,obj->latitude); kml_write(" </Point>\n"); kml_write(" </Placemark>\n"); } } /* close folder if any */ if (openclass!=NULL) { kml_write(" </Folder>\n"); openclass=NULL; } } kml_write(" </Document>\n"); return 0; }
/** Load and process the command-line arguments @return a STATUS value Arguments are processed immediately as they are seen. This means that models are loaded when they are encountered, and in relation to the other flags. Thus @code gridlabd --warn model1 --warn model2 @endcode will load \p model1 with warnings on, and \p model2 with warnings off. **/ STATUS cmdarg_load(int argc, /**< the number of arguments in \p argv */ char *argv[]) /**< a list pointers to the argument string */ { int test_mod_num = 1; unsigned int pos=0; int i; char *pd1, *pd2; /* capture the execdir */ strcpy(global_execname,argv[0]); strcpy(global_execdir,argv[0]); pd1 = strrchr(global_execdir,'/'); pd2 = strrchr(global_execdir,'\\'); if (pd1>pd2) *pd1='\0'; else if (pd2>pd1) *pd2='\0'; /* capture the command line */ for (i=0; i<argc; i++) { if (pos<sizeof(global_command_line)-strlen(argv[i])) pos += sprintf(global_command_line+pos,"%s%s",pos>0?" ":"",argv[i]); } while (argv++,--argc>0) { if (strcmp(*argv,"--copyright")==0) legal_notice(); else if (strcmp(*argv,"-w")==0 || strcmp(*argv,"--warn")==0) global_warn_mode=!global_warn_mode; else if (strcmp(*argv,"--bothstdout")==0) output_both_stdout(); else if (strcmp(*argv,"-c")==0 || strcmp(*argv,"--check")==0) global_runchecks=!global_runchecks; else if (strcmp(*argv,"--debug")==0) global_debug_output=!global_debug_output; else if (strcmp(*argv,"--debugger")==0){ global_debug_mode=1; global_debug_output=!global_debug_output; } else if (strcmp(*argv,"--dumpall")==0) global_dumpall=!global_dumpall; else if (strcmp(*argv,"-q")==0 || strcmp(*argv,"--quiet")==0) global_quiet_mode=!global_quiet_mode; else if (strcmp(*argv,"-v")==0 || strcmp(*argv,"--verbose")==0){ global_verbose_mode=!global_verbose_mode; } else if (strcmp(*argv,"--profile")==0) global_profiler=!global_profiler; else if (strcmp(*argv,"--pause")==0) global_pauseatexit=!global_pauseatexit; else if (strcmp(*argv,"--compile")==0) global_compileonly = !global_compileonly; else if (strcmp(*argv,"--license")==0) legal_license(); else if (strcmp(*argv,"--server_portnum")==0 || strcmp(*argv,"-P")==0) { if (argc-1>0) global_server_portnum = (argc--,atoi(*++argv)); else { output_fatal("missing server port number"); /* TROUBLESHOOT The <b>-P</b> or <b>--server_portnum</b> command line directive was not followed by a valid number. The correct syntax is <b>-P <i>number</i></b> or <b>--server_portnum <i>number</i></b>. */ } } else if (strcmp(*argv, "-V")==0 ||strcmp(*argv, "--version")==0) { char *buildinfo = strstr(BUILD,":"); int build = buildinfo ? atoi(strstr(BUILD,":")+1) : 0; output_message("Revision major: %d", REV_MAJOR); output_message("Revision minor: %d", REV_MINOR); output_message("Patch number : %d", REV_PATCH); output_message("Branch name : %s", BRANCH); if (build>0) output_message("Build number : %d", build); else output_message("Build number : %s", #ifdef WIN32 #ifdef _DEBUG #ifdef _M_X64 "WIN64-DEBUG" #else "WIN32-DEBUG" #endif #else #ifdef _M_X64 "WIN64-RELEASE" #else "WIN32-RELEASE" #endif #endif #else "DEV" #endif ); } else if (strcmp(*argv,"--dsttest")==0) timestamp_test(); else if (strcmp(*argv,"--randtest")==0) random_test(); else if (strcmp(*argv,"--unitstest")==0) unit_test(); else if (strcmp(*argv,"--scheduletest")==0) schedule_test(); else if (strcmp(*argv,"--loadshapetest")==0) loadshape_test(); else if (strcmp(*argv,"--endusetest")==0) enduse_test(); else if (strcmp(*argv,"--xmlstrict")==0) global_xmlstrict = !global_xmlstrict; else if (strcmp(*argv,"--globaldump")==0) { global_dump(); exit(0); } else if (strcmp(*argv,"--relax")==0) global_strictnames = FALSE; else if (strncmp(*argv,"--pidfile",9)==0) { char *filename = strchr(*argv,'='); if (filename==NULL) strcpy(global_pidfile,"gridlabd.pid"); else strcpy(global_pidfile,filename+1); } else if (strncmp(*argv,"--kml",5)==0) { char *filename = strchr(*argv,'='); if (filename) strcpy(global_kmlfile,filename+1); else strcpy(global_kmlfile,"gridlabd.kml"); } else if (strcmp(*argv, "--avlbalance") == 0){ global_no_balance = !global_no_balance; } else if (strcmp(*argv,"--testall")==0){ FILE *fd = NULL; if(*++argv != NULL) fd = fopen(*argv,"r"); else { output_fatal("no filename for testall"); /* TROUBLESHOOT The --testall parameter was found on the command line, but if was not followed by a filename containing the test description file. */ return FAILED; } argc--; global_test_mode=TRUE; if(fd == NULL) { output_fatal("incorrect module list file name"); /* TROUBLESHOOT The --testall parameter was found on the command line, but if was not followed by a valid filename containing the test description file. */ return FAILED; } if(load_module_list(fd,&test_mod_num) == FAILED) return FAILED; } else if (strcmp(*argv,"--modhelp")==0) { if(argc-1 > 0){ MODULE *mod = NULL; CLASS *oclass = NULL; argv++; argc--; if(strchr(argv[0], ':') == 0){ // no class mod = module_load(argv[0],0,NULL); } else { GLOBALVAR *var=NULL; char *cname; cname = strchr(argv[0], ':')+1; mod = module_load(strtok(argv[0],":"),0,NULL); oclass = class_get_class_from_classname(cname); if(oclass == NULL){ output_fatal("Unable to find class '%s' in module '%s'", cname, argv[0]); /* TROUBLESHOOT The <b>--modhelp</b> parameter was found on the command line, but if was followed by a class specification that isn't valid. Verify that the class exists in the module you specified. */ return FAILED; } /* dump module globals */ printf("module %s {\n", mod->name); while ((var=global_getnext(var))!=NULL) { PROPERTY *prop = var->prop; char *proptype = class_get_property_typename(prop->ptype); if (strncmp(var->prop->name,mod->name,strlen(mod->name))!=0) continue; if (proptype!=NULL){ if(prop->unit != NULL) { printf("\t%s %s[%s];", proptype, strrchr(prop->name,':')+1, prop->unit->name); } else if (prop->ptype==PT_set || prop->ptype==PT_enumeration) { KEYWORD *key; printf("\t%s {", proptype); for (key=prop->keywords; key!=NULL; key=key->next) printf("%s=%"FMT_INT64"u%s", key->name, (int64)key->value, key->next==NULL?"":", "); printf("} %s;", strrchr(prop->name,':')+1); } else { printf("\t%s %s;", proptype, strrchr(prop->name,':')+1); } if (prop->description!=NULL) printf(" // %s%s",prop->flags&PF_DEPRECATED?"(DEPRECATED) ":"",prop->description); printf("\n"); } } printf("}\n"); } if(mod == NULL){ output_fatal("module %s is not found",*argv); /* TROUBLESHOOT The <b>--modhelp</b> parameter was found on the command line, but if was followed by a module specification that isn't valid. Verify that the module exists in GridLAB-D's <b>lib</b> folder. */ return FAILED; } if(oclass != NULL) { print_class(oclass); } else { CLASS *oclass; pntree *ctree; /* lexographically sort all elements from class_get_first_class & oclass->next */ oclass=class_get_first_class(); ctree = (pntree *)malloc(sizeof(pntree)); if(ctree == NULL){ throw_exception("--modhelp: malloc failure"); /* TROUBLESHOOT The memory allocation needed for module help to function has failed. Try freeing up system memory and try again. */ } ctree->name = oclass->name; ctree->oclass = oclass; ctree->left = ctree->right = 0; for(; oclass != NULL; oclass = oclass->next){ modhelp_alpha(&ctree, oclass); //print_class(oclass); } /* flatten tree */ print_modhelp_tree(ctree); } } } else if (strcmp(*argv,"--modtest")==0) { if (argc-1>0) { MODULE *mod = module_load(argv[1],0,NULL); if (mod==NULL) output_fatal("module %s is not found",argv[1]); /* TROUBLESHOOT The <b>--modtest</b> parameter was found on the command line, but if was followed by a module specification that isn't valid. Verify that the module exists in GridLAB-D's <b>lib</b> folder. */ else { argv++;argc--; if (mod->test==NULL) output_fatal("module %s does not implement a test routine", argv[0]); /* TROUBLESHOOT The <b>--modtest</b> parameter was found on the command line, but if was followed by a specification for a module that doesn't implement any test procedures. See the <b>--libinfo</b> command line parameter for information on which procedures the module supports. */ else { output_test("*** modtest of %s beginning ***", argv[0]); mod->test(0,NULL); output_test("*** modtest of %s ended ***", argv[0]); } } } else { output_fatal("definition is missing"); /* TROUBLESHOOT The <b>--modtest</b> parameter was found on the command line, but if was not followed by a module specification. The correct syntax is <b>gridlabd --modtest <i>module_name</i></b>. */ return FAILED; } } else if (strcmp(*argv,"--test")==0){ global_test_mode=TRUE; global_strictnames = FALSE; output_debug("disabling strict naming for tests"); if (argc-1>0) { char mod_test[100]; sprintf(mod_test,"mod_test%d=%s",test_mod_num++,*++argv); if (global_setvar(mod_test)==SUCCESS) argc--; } else { output_fatal("test module name is missing"); /* TROUBLESHOOT The <b>--test</b> parameter was found on the command line, but if was not followed by a module specification that is valid. The correct syntax is <b>gridlabd --test <i>module_name</i></b>. */ return FAILED; } } else if (strcmp(*argv,"-D")==0 || strcmp(*argv,"--define")==0) { if (argc-1>0) { bool namestate = global_strictnames; global_strictnames = FALSE; if (global_setvar(*++argv,NULL)==SUCCESS){ argc--; } global_strictnames = namestate; } else { output_fatal("definition is missing"); /* TROUBLESHOOT The <b>-D</b> or <b>--define</b> command line parameters was given, but it was not followed by a variable definition. The correct syntax <b>-D </i>variable</i>=<i>value</i></b> or <b>--define </i>variable</i>=<i>value</i></b> */ return FAILED; } } else if (strcmp(*argv,"--globals")==0) { char *list[65536]; int i, n=0; GLOBALVAR *var = NULL; /* load the list into the array */ while ((var=global_getnext(var))!=NULL) { if (n<sizeof(list)/sizeof(list[0])) list[n++] = var->prop->name; else { output_fatal("--globals has insufficient buffer space to sort globals list"); return FAILED; } } /* sort the array */ qsort(list,n,sizeof(list[0]),compare); /* output sorted array */ for (i=0; i<n; i++) { char buffer[1024]; var = global_find(list[i]); printf("%s=%s;",var->prop->name,global_getvar(var->prop->name,buffer,sizeof(buffer))?buffer:"(error)"); if (var->prop->description || var->prop->flags&PF_DEPRECATED) printf(" // %s%s", (var->prop->flags&PF_DEPRECATED)?"DEPRECATED ":"", var->prop->description?var->prop->description:""); printf("\n"); } } else if (strcmp(*argv,"--redirect")==0) { if (argc-1>0) { char buffer[1024]; char *p; strcpy(buffer,*++argv); argc--; if (strcmp(buffer,"all")==0) { if (output_redirect("output",NULL)==NULL || output_redirect("error",NULL)==NULL || output_redirect("warning",NULL)==NULL || output_redirect("debug",NULL)==NULL || output_redirect("verbose",NULL)==NULL || output_redirect("profile",NULL)==NULL || output_redirect("progress",NULL)==NULL) { output_fatal("redirection of all failed"); /* TROUBLESHOOT An attempt to close all standard stream from the command line using <b>--redirect all</b> has failed. One of the streams cannot be closed. Try redirecting each stream separately until the problem stream is identified and the correct the problem with that stream. */ return FAILED; } } else if ((p=strchr(buffer,':'))!=NULL) { *p++='\0'; if (output_redirect(buffer,p)==NULL) { output_fatal("redirection of %s to '%s' failed: %s",buffer,p, strerror(errno)); /* TROUBLESHOOT An attempt to redirect a standard stream from the command line using <b>--redirect <i>stream</i>:<i>destination</i></b> has failed. The message should provide an indication of why the attempt failed. The remedy will depend on the nature of the problem. */ return FAILED; } } else if (output_redirect(buffer,NULL)==NULL) { output_fatal("default redirection of %s failed: %s",buffer, strerror(errno)); /* TROUBLESHOOT An attempt to close a standard stream from the command line using <b>--redirect <i>stream</i></b> has failed. The message should provide an indication of why the attempt failed. The remedy will depend on the nature of the problem. */ return FAILED; } } else { output_fatal("redirection is missing"); /* TROUBLESHOOT A <b>--redirect</b> directive on the command line is missing its redirection specification. The correct syntax is <b>--redirect <i>stream</i>[:<i>destination</i>]</b>. */ return FAILED; } } else if (strcmp(*argv,"-L")==0 || strcmp(*argv,"--libinfo")==0) { if (argc-1>0) { argc--; module_libinfo(*++argv); exit(0); } else { output_fatal("missing library name"); /* TROUBLESHOOT The <b>-L</b> or <b>--libinfo</b> command line directive was not followed by a module name. The correct syntax is <b>-L <i>module_name</i></b> or <b>--libinfo <i>module_name</i></b>. */ return FAILED; } } else if (strcmp(*argv,"-T")==0 || strcmp(*argv,"--threadcount")==0) { if (argc-1>0) global_threadcount = (argc--,atoi(*++argv)); else { output_fatal("missing thread count"); /* TROUBLESHOOT The <b>-T</b> or <b>--threadcount</b> command line directive was not followed by a valid number. The correct syntax is <b>-T <i>number</i></b> or <b>--threadcount <i>number</i></b>. */ return FAILED; } } else if (strcmp(*argv,"-o")==0 || strcmp(*argv,"--output")==0) { if (argc-1>0) strcpy(global_savefile,(argc--,*++argv)); else { output_fatal("missing output file"); /* TROUBLESHOOT The <b>-o</b> or <b>--output</b> command line directive was not followed by a valid filename. The correct syntax is <b>-o <i>file</i></b> or <b>--output <i>file</i></b>. */ return FAILED; } } else if (strcmp(*argv,"-e")==0 || strcmp(*argv,"--environment")==0) { if (argc-1>0) strcpy(global_environment,(argc--,*++argv)); else { output_fatal("environment not specified"); /* TROUBLESHOOT The <b>-e</b> or <b>--environment</b> command line directive was not followed by a valid environment specification. The correct syntax is <b>-e <i>keyword</i></b> or <b>--environment <i>keyword</i></b>. */ return FAILED; } } else if (strcmp(*argv,"--xmlencoding")==0) { if (argc-1>0) { global_xml_encoding = atoi(*++argv); argc--; } else { output_fatal("xml encoding not specified"); /* TROUBLESHOOT The <b>--xmlencoding</b> command line directive was not followed by a encoding specification. The correct syntax is <b>--xmlencoding <i>keyword</i></b>. */ return FAILED; } } else if (strcmp(*argv,"--xsd")==0) { if (argc-1>0) { argc--; exit(output_xsd(*++argv)); } else { MODULE *mod; for (mod=module_get_first(); mod!=NULL; mod=mod->next) output_xsd(mod->name); return SUCCESS; } } else if (strcmp(*argv,"--xsl")==0) { if (argc-1>0) { char fname[1024]; char *p_arg = *++argv; char n_args=1; char **p_args; argc--; while (*p_arg++!='\0') if (*p_arg==',') n_args++; p_args = (char**)malloc(sizeof(char*)*n_args); p_arg = strtok(*argv,","); n_args=0; while (p_arg!=NULL) { p_args[n_args++] = p_arg; p_arg = strtok(NULL,","); } sprintf(fname,"gridlabd-%d_%d.xsl",global_version_major,global_version_minor); exit(output_xsl(fname,n_args,p_args)); } else { output_fatal("module list not specified"); /* TROUBLESHOOT The <b>--xsl</b> command line directive was not followed by a validlist of modules. The correct syntax is <b>--xsl <i>module1</i>[,<i>module2</i>[,...]]</b>. */ return FAILED; } } else if (strcmp(*argv,"--stream")==0) global_streaming_io_enabled = !global_streaming_io_enabled; else if (strcmp(*argv,"--server")==0) strcpy(global_environment,"server"); else if (strcmp(*argv,"-h")==0 || strcmp(*argv,"--help")==0) { printf("Syntax: gridlabd [OPTIONS ...] <file> ... \nOptions:\n" " --avlbalance toggles AVL tree balancing\n" " -c|--check toggles module checks after model loads\n" " -D|--define <def> defines a macro value\n" " --debug toggles debug output (prints internal messages)\n" " --debugger toggles debugger mode (generates internal messages)\n" " --dumpall toggles module data dump after run completes\n" " -e|--environment <name> specifies user environment (default none)\n" " --license print license information\n" " -L|--libinfo <module> print module library information\n" " -o|--output <file> specifies model should be output after run\n" " --profile toggles profilers\n" " -q|--quiet toggles quiet mode (suppresses startup banner)\n" " --test toggles test mode (activate testing procedures)\n" " -T|--threadcount <n> specifies the number of processor threads to use\n" " -v|--verbose toggles verbose mode (active verbose messages)\n" " -V|--version prints the GridlabD version information\n" " -w|--warn toggles warning mode (generates warning messages)\n" " --xmlencoding <num> set the XML encoding (8, 16, or 32)\n" " --xmlstrict toggles XML encoding to be strict\n" " --xsd <module>[:<object>] prints the xsd of an object\n" " --xsl <modlist> prints the xsl for the modules listed\n" ); exit(0); } else if (**argv!='-') { if (global_test_mode) output_warning("file '%s' ignored in test mode", *argv); /* TROUBLESHOOT This warning is caused by an attempt to read an input file in self-test mode. The use of self-test model precludes reading model files. Try running the system in normal more or leaving off the model file name. */ else { if (!loadall(*argv)) return FAILED; /* preserve name of first model only */ if (strcmp(global_modelname,"")==0) strcpy(global_modelname,*argv); } } else { int n = module_cmdargs(argc,argv); if (n==0) { output_error("command line option '%s' is not recognized",*argv); /* TROUBLESHOOT The command line option given is not valid where it was found. Check the command line for correct syntax and order of options. */ return FAILED; } } } /*debug_traverse_tree(NULL);*/ /* for checking the name tree & getting a test file. -mh */ return SUCCESS; }
MODULE *module_load(const char *file, /**< module filename, searches \p PATH */ int argc, /**< count of arguments in \p argv */ char *argv[]) /**< arguments passed from the command line */ { /* check for already loaded */ MODULE *mod = module_find((char *)file); char buffer[FILENAME_MAX+1]; char *fmod; bool isforeign = false; char pathname[1024]; char *tpath = NULL; #ifdef WIN32 char from='/', to='\\'; #else char from='\\', to='/'; #endif char *p = NULL; void *hLib = NULL; LIBINIT init = NULL; int *pMajor = NULL, *pMinor = NULL; CLASS *previous = NULL; CLASS *c; #ifdef NEVER /* this shouldn't ever be necessary but sometimes for debugging purposes it is helpful */ /* if LD_LIBRARY_PATH is not set, default to current directory */ if (getenv("LD_LIBRARY_PATH")==NULL) { putenv("LD_LIBRARY_PATH=."); output_verbose("Setting default LD_LIBRARY_DEFAULT to current directory"); } #endif if (mod!=NULL) { output_verbose("%s(%d): module '%s' already loaded", __FILE__, __LINE__, file); return mod; } else { output_verbose("%s(%d): module '%s' not yet loaded", __FILE__, __LINE__, file); } /* check for foreign modules */ strcpy(buffer,file); fmod = strtok(buffer,"::"); if (fmod!=NULL && strcmp(fmod, file) != 0) { char *modname = strtok(NULL,"::"); MODULE *parent_mod = module_find(fmod); if(parent_mod == NULL) parent_mod = module_load(fmod, 0, NULL); previous = class_get_last_class(); if(parent_mod != NULL && parent_mod->subload != NULL) { /* if we've defined a subload routine and already loaded the parent module*/ MODULE *child_mod; if(module_find(fmod) == NULL) module_load(fmod, 0, NULL); child_mod = parent_mod->subload(modname, &mod, (previous ? &(previous->next) : &previous), argc, argv); if(child_mod == NULL) { /* failure */ output_error("module_load(file='%s::%s'): subload failed", fmod, modname); return NULL; } if (mod != NULL) { /* if we want to register another module */ last_module->next = mod; last_module = mod; mod->oclass = previous ? previous->next : class_get_first_class(); } return last_module; } else { struct { char *name; LOADER loader; } fmap[] = { {"matlab",NULL}, {"java",load_java_module}, {"python",load_python_module}, {NULL,NULL} /* DO NOT DELETE THIS TERMINATOR ENTRY */ }, *p; for (p=fmap; p->name!=NULL; p++) { if (strcmp(p->name, fmod)==0) { static char *args[1]; isforeign = true; if (p->loader!=NULL) /* use external loader */ return p->loader(modname,argc,argv); /* use a module with command args */ argv = args; argc=1; argv[0] = modname; file=buffer; break; } } if (p==NULL) { output_error("module_load(file='%s',...): foreign module type %s not recognized or supported", fmod); return NULL; } } } /* create a new module entry */ mod = (MODULE *)malloc(sizeof(MODULE)); if (mod==NULL) { output_verbose("%s(%d): module '%s' memory allocation failed", __FILE__, __LINE__, file); errno=ENOMEM; return NULL; } else output_verbose("%s(%d): module '%s' memory allocated", __FILE__, __LINE__, file); /* locate the module */ snprintf(pathname, 1024, "%s" DLEXT, file); tpath = find_file(pathname, NULL, X_OK|R_OK); if(tpath == NULL) { output_verbose("unable to locate %s in GLPATH, using library loader instead", pathname); tpath=pathname; } else { #ifndef WIN32 /* if the path is a relative path */ struct stat buf; if (tpath[0]!='/' && stat(tpath,&buf)==0) { char buffer[1024]; /* add ./ to the beginning of the path */ sprintf(buffer,"./%s", tpath); strcpy(tpath,buffer); } #endif output_verbose("full path to library '%s' is '%s'", file, tpath); } /* convert path delims based on OS preference */ for (p=strchr(tpath,from); p!=NULL; p=strchr(p,from)) *p=to; /* ok, let's do it */ hLib = DLLOAD(tpath); if (hLib==NULL) { #if defined WIN32 && ! defined MINGW output_error("%s(%d): module '%s' load failed - %s (error code %d)", __FILE__, __LINE__, file, strerror(errno), GetLastError()); #else output_error("%s(%d): module '%s' load failed - %s", __FILE__, __LINE__, file, dlerror()); output_debug("%s(%d): path to module is '%s'", __FILE__, __LINE__, tpath); #endif dlload_error(pathname); errno = ENOENT; free(mod); return NULL; } else output_verbose("%s(%d): module '%s' loaded ok", __FILE__, __LINE__, file); /* get the initialization function */ init = (LIBINIT)DLSYM(hLib,"init"); if (init==NULL) { output_error("%s(%d): module '%s' does not export init()", __FILE__, __LINE__, file); dlload_error(pathname); errno = ENOEXEC; free(mod); return NULL; } else output_verbose("%s(%d): module '%s' exports init()", __FILE__, __LINE__, file); /* connect the module's exported data & functions */ mod->hLib = (void*)hLib; pMajor = (int*)DLSYM(hLib, "major"); pMinor = (int*)DLSYM(hLib, "minor"); mod->major = pMajor?*pMajor:0; mod->minor = pMinor?*pMinor:0; mod->import_file = (int(*)(char*))DLSYM(hLib,"import_file"); mod->export_file = (int(*)(char*))DLSYM(hLib,"export_file"); mod->setvar = (int(*)(char*,char*))DLSYM(hLib,"setvar"); mod->getvar = (void*(*)(char*,char*,unsigned int))DLSYM(hLib,"getvar"); mod->check = (int(*)())DLSYM(hLib,"check"); #ifndef _NO_CPPUNIT mod->module_test = (int(*)(TEST_CALLBACKS*,int,char*[]))DLSYM(hLib,"module_test"); #endif mod->cmdargs = (int(*)(int,char**))DLSYM(hLib,"cmdargs"); mod->kmldump = (int(*)(FILE*,OBJECT*))DLSYM(hLib,"kmldump"); mod->subload = (MODULE *(*)(char *, MODULE **, CLASS **, int, char **))DLSYM(hLib, "subload"); mod->test = (void(*)(int,char*[]))DLSYM(hLib,"test"); mod->globals = NULL; strcpy(mod->name,file); mod->next = NULL; /* call the initialization function */ mod->oclass = (*init)(&callbacks,(void*)mod,argc,argv); if (mod->oclass==NULL) return NULL; /* connect intrinsic functions */ for (c=mod->oclass; c!=NULL; c=c->next) { char fname[1024]; struct { FUNCTIONADDR *func; char *name; int optional; } map[] = { {&c->create,"create",FALSE}, {&c->init,"init",TRUE}, {&c->sync,"sync",TRUE}, {&c->commit,"commit",TRUE}, {&c->notify,"notify",TRUE}, {&c->isa,"isa",TRUE}, {&c->plc,"plc",TRUE}, {&c->recalc,"recalc",TRUE}, }; int i; for (i=0; i<sizeof(map)/sizeof(map[0]); i++) { snprintf(fname, 1024,"%s_%s",map[i].name,isforeign?fmod:c->name); if ((*(map[i].func) = (FUNCTIONADDR)DLSYM(hLib,fname))==NULL && !map[i].optional) { output_fatal("intrinsic %s is not defined in class %s", fname,file); /* TROUBLESHOOT A required intrinsic function was not found. Please review and modify the class definition. */ errno=EINVAL; return NULL; } else if(!map[i].optional) output_verbose("%s(%d): module '%s' intrinsic %s found", __FILE__, __LINE__, file, fname); } } /* attach to list of known modules */ if (first_module==NULL) first_module = mod; else last_module->next = mod; last_module = mod; return last_module; }