Beispiel #1
0
bool glxlink::set_target(char *name)
{
	char libname[1024];
	char path[1024];
	sprintf(libname,PREFIX "glx%s" DLEXT,name);
	if ( find_file(libname,NULL,X_OK,path,sizeof(path))!=NULL )
	{
		// load library
		handle = DLLOAD(path);
		if ( handle==NULL )
		{
			output_error("unable to load '%s' for target '%s': %s", path,name,DLERR);
			return false;
		}

		// attach functions
		settag = (bool(*)(glxlink*,char*,char*))DLSYM(handle,"glx_settag");
		init = (bool(*)(glxlink*))DLSYM(handle,"glx_init");
		sync = (TIMESTAMP(*)(glxlink*,TIMESTAMP))DLSYM(handle,"glx_sync");
		term = (bool(*)(glxlink*))DLSYM(handle,"glx_term");

		// call create routine
		bool (*create)(glxlink*,CALLBACKS*) = (bool(*)(glxlink*,CALLBACKS*))DLSYM(handle,"glx_create");
		if ( create!=NULL && create(this,module_callbacks()) )
		{
			strcpy(target,name);
			return true;
		}
		else
		{
			output_error("library '%s' for target '%s' does not define/export glx_create properly", path,name);
			return false;
		}
	}
	else
	{
		output_error("library '%s' for target '%s' not found", libname, name);
		return false;
	}
}
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;
}