/[ascend]/trunk/base/generic/compiler/importhandler.c
ViewVC logotype

Contents of /trunk/base/generic/compiler/importhandler.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1026 - (show annotations) (download) (as text)
Wed Jan 3 12:03:08 2007 UTC (16 years, 11 months ago) by johnpye
File MIME type: text/x-csrc
File size: 13655 byte(s)
Working on tracking down a segfault occuring when TestIDADENSE and TestExtFn test suites are run together.
Added comments about new solverparameter macros.
1 /* ASCEND modelling environment
2 Copyright (C) 2006 Carnegie Mellon University
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA.
18 *//**
19 @file
20 Handle the Import Handler library, which is a hash table of additional
21 handlers for external scripts in the IMPORT statement.
22 *//*
23 by John Pye
24 Created Sept 26, 2006
25 */
26
27 #include <utilities/ascConfig.h>
28 #include <utilities/config.h>
29 #include <utilities/error.h>
30 #include <utilities/ascDynaLoad.h>
31 #include <utilities/ascPanic.h>
32 #include <utilities/ascEnvVar.h>
33 #include <general/table.h>
34 #include "importhandler.h"
35
36 /* #define IMPORTHANDLER_VERBOSE */
37
38 /*
39 Maximum number of importhandlers possible in one session. Hard to imagine
40 that you would want more than this.
41 */
42 #define IMPORTHANDLER_MAX 10
43
44 /**
45 List of import handlers currently in effect. @TODO this shouldn't be a global,
46 but unfortunately such globals are 'The ASCEND Way'.
47 */
48 struct ImportHandler **importhandler_library=NULL;
49
50 /**
51 Table of registered pointers for use in passing GUI data out to external scripts.
52 */
53 struct Table *importhandler_sharedpointers=NULL;
54
55 ASC_DLLSPEC(int) importhandler_add(struct ImportHandler *handler){
56 int i;
57 if(handler==NULL){
58 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Handler is NULL");
59 return 2;
60 }
61 if(importhandler_library == NULL){
62 importhandler_createlibrary();
63 }
64 for(i=0; i< IMPORTHANDLER_MAX; ++i){
65 if(importhandler_library[i] == NULL)break;
66 if(importhandler_library[i]->name == handler->name){
67 ERROR_REPORTER_HERE(ASC_USER_NOTE,"Handler already loaded");
68 return 0;
69 }
70 }
71 if(i==IMPORTHANDLER_MAX){
72 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Too many import handlers register (IMPORTHANDLER_MAX=%d)",IMPORTHANDLER_MAX);
73 return 1;
74 }
75 importhandler_library[i] = handler;
76 ERROR_REPORTER_HERE(ASC_USER_NOTE,"New import hander '%s' added",handler->name);
77 return 0;
78 }
79
80 /* Function to attempt import of an external script
81 @param partialname Name of the external script (without extension), relative to PATH.
82 @param defaultpath Default value of file search PATH. Is trumped by value of pathenvvar if present in environment.
83 @param pathenvvar Environment variable containing the user's preferred file search path value.
84 @return 0 on success
85 */
86 int importhandler_attemptimport(const char *partialname,const char *defaultpath, const char *pathenvvar){
87 ERROR_REPORTER_HERE(ASC_PROG_ERR,"%s not implemented",__FUNCTION__);
88 return 1;
89 }
90
91 /*------------------------------------------------------------------------------
92 DEFAULT IMPORT HANDLER FOR DLL/SO FILES
93 */
94
95 /**
96 Create a filename for an external library (DLL/SO) based on a
97 partial filename.
98
99 @param partialname The partial filename (eg 'mylib')
100 @return Complete filename (eg 'libmylib.so' or 'mylib.dlll', etc)
101 */
102 char *importhandler_extlib_filename(const char *partialname){
103 char *buffer;
104 buffer = ASC_NEW_ARRAY(char,PATH_MAX);
105
106 #if defined(ASC_SHLIBSUFFIX) && defined(ASC_SHLIBPREFIX)
107 /*
108 this is the preferred operation: SCons reports what the local system
109 uses as its shared library file extension.
110 */
111 snprintf(buffer,PATH_MAX,"%s%s%s",ASC_SHLIBPREFIX,s1,ASC_SHLIBSUFFIX);
112 #else
113 /**
114 @DEPRECATED
115
116 If we don't have ASC_SHLIB-SUFFIX and -PREFIX then we can do some
117 system-specific stuff here, but it's not as general.
118 */
119 # ifdef __WIN32__
120 snprintf(buffer,PATH_MAX,"%s.dll",partialname);
121 # elif defined(linux)
122 snprintf(buffer,PATH_MAX,"lib%s.so",partialname); /* changed from .o to .so -- JP */
123 # elif defined(sun) || defined(solaris)
124 snprintf(buffer,PATH_MAX,"%s.so.1.0",partialname);
125 # elif defined(__hpux)
126 snprintf(buffer,PATH_MAX,"%s.sl",partialname);
127 # elif defined(_SGI_SOURCE)
128 snprintf(buffer,PATH_MAX,"%s.so",partialname);
129 # else
130 # error "Unknown system type (please define ASC_SHLIBSUFFIX and ASC_SHLIBPREFIX)"
131 # endif
132 #endif
133
134 return buffer;
135 }
136
137 /**
138 Perform the actual importing of an external DLL/SO in to ASCEND. Can assume
139 that the file exists and is readable.
140
141 @param fp Location of DLL/SO file
142 @param initfunc Name of registration function, preferably NULL (so that ASCEND automatically determines it)
143 @param partialpath as specified in 'IMPORT' statement, for creation of auto_initfunc name
144 @return 0 on success
145 */
146 int importhandler_extlib_import(const struct FilePath *fp,const char *initfunc,const char *partialpath){
147
148 struct FilePath *fp1;
149 char *stem;
150 char *path;
151 char auto_initfunc[PATH_MAX];
152 int result;
153
154 path = ospath_str(fp);
155 if(path==NULL){
156 ERROR_REPORTER_HERE(ASC_PROG_ERR,"File path is NULL");
157 return 1;
158 }
159
160 if(initfunc==NULL){
161 fp1 = ospath_new(partialpath);
162 stem = ospath_getbasefilename(fp1);
163 strncpy(auto_initfunc,stem,PATH_MAX);
164 ospath_free(fp1);
165 ASC_FREE(stem);
166
167 strncat(auto_initfunc,"_register",PATH_MAX-strlen(auto_initfunc));
168 /* CONSOLE_DEBUG("Created auto-initfunc name '%s'",auto_initfunc); */
169 result = Asc_DynamicLoad(path,auto_initfunc);
170 }else{
171 result = Asc_DynamicLoad(path,initfunc);
172 }
173
174 if(result){
175 CONSOLE_DEBUG("FAILED TO IMPORT '%s' (error %d)",partialpath,result);
176 }else{
177 if(initfunc==NULL){
178 CONSOLE_DEBUG("Successfully ran '%s' (automatically named) from dynamic package '%s'",auto_initfunc,path);
179 }else{
180 CONSOLE_DEBUG("Successfully ran '%s' from dynamic package '%s'",initfunc,path);
181 }
182 }
183
184 ASC_FREE(path);
185 return result;
186 }
187
188 /*------------------------------------------------------------------------------
189 LIST-BASED FUNCTIONS related to IMPORT handler 'library'
190 */
191
192 int importhandler_createlibrary(){
193 int i;
194 struct ImportHandler *extlib_handler;
195
196 if(importhandler_library!=NULL){
197 /* ERROR_REPORTER_HERE(ASC_PROG_ERR,"Already created"); */
198 return 0;
199 };
200 importhandler_library=ASC_NEW_ARRAY(struct ImportHandler *,IMPORTHANDLER_MAX);
201 for(i=0; i < IMPORTHANDLER_MAX; ++i){
202 importhandler_library[i] = NULL;
203 }
204 /* CONSOLE_DEBUG("ImportHandler library created"); */
205
206 extlib_handler = ASC_NEW(struct ImportHandler);
207 extlib_handler->name ="extlib";
208 extlib_handler->filenamefn = &importhandler_extlib_filename;
209 extlib_handler->importfn = &importhandler_extlib_import;
210 if(importhandler_add(extlib_handler)){
211 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Failed to create 'extlib' import handler");
212 return 1;
213 }
214
215 return 0;
216 }
217
218 int importhandler_remove(const char *name){
219 if(importhandler_library==NULL)return 2;
220 CONSOLE_DEBUG("Removing importhandler '%s'", name);
221 ERROR_REPORTER_HERE(ASC_PROG_ERR,"%s not implemented",__FUNCTION__);
222 return 1;
223 }
224
225 struct ImportHandler *importhandler_lookup(const char *name){
226 ERROR_REPORTER_HERE(ASC_PROG_ERR,"%s not implemented",__FUNCTION__);
227 return NULL;
228 }
229
230 /** @return 0 on success */
231 int importhandler_destroylibrary(){
232 int i;
233 int err = 0;
234 CONSOLE_DEBUG("Destroying importhandler library...");
235 importhandler_printlibrary(stderr);
236 for(i=IMPORTHANDLER_MAX - 1; i >= 0; --i){
237 if(importhandler_library[i]==NULL)continue;
238 err = err | importhandler_remove(importhandler_library[i]->name);
239 }
240 if(err)ERROR_REPORTER_HERE(ASC_PROG_WARNING,"Failed to destroy importhandler library");
241 return err;
242 }
243
244 /** @return 0 on success */
245 int importhandler_printlibrary(FILE *fp){
246 int i;
247 if(importhandler_library==NULL){
248 fprintf(fp,"# importhandler_printlibrary: empty\n");
249 return 0;
250 }else{
251 fprintf(fp,"# importhandler_printlibrary: start\n");
252 for(i=0; i < IMPORTHANDLER_MAX && importhandler_library[i] != NULL; ++i){
253 fprintf(fp,"%s\n",importhandler_library[i]->name);
254 }
255 fprintf(fp,"# importhandler_printlibrary: end\n");
256 return 0;
257 }
258 }
259
260 int importhandler_printhandler(FILE *fp, struct ImportHandler *handler){
261 ERROR_REPORTER_HERE(ASC_PROG_ERR,"%s not implemented",__FUNCTION__);
262 CONSOLE_DEBUG("NOT IMPLEMENTED");
263 return 1;
264 }
265
266 /*------------------------------------------------------------------------------
267 PATH SEARCH ROUTINES
268 */
269
270 /**
271 A little structure to help with searching for import files
272
273 @see test_importsearch
274 */
275 struct ImportHandlerSearch{
276 char *partialname; /**< for example 'myext' */
277 struct FilePath *relativedir; /**< for example 'path/to' */
278 struct FilePath *foundpath; /**< the complete filepath located, for example '/home/john/path/to/libmyext.so' */
279 struct ImportHandler *handler; /**< pointer to the import handler identified for this file */
280 };
281
282 FilePathTestFn importhandler_search_test;
283
284 /**
285 A FilePath 'test' function for passing to the ospath_searchpath_iterate function.
286 This test function will return a match when an importable file having the
287 required name is present in the fully resolved path.
288
289 @param path the search path component
290 @param userdata will be an ImportHandlerSearch object
291 @return 1 if found
292 */
293 int importhandler_search_test(struct FilePath *path, void *userdata){
294 /* user data = the relative path, plus a place
295 to store the full path when found */
296 FILE *f;
297 char *filename;
298 /* char *fullpath; */
299 struct ImportHandlerSearch *searchdata;
300 struct FilePath *fp, *fp1, *fp2;
301 int i;
302 ospath_stat_t buf;
303
304 searchdata = (struct ImportHandlerSearch *)userdata;
305
306 /* char *pathcomponent;
307 pathcomponent = ospath_str(path); //eg '/home/john'
308 CONSOLE_DEBUG("In directory '%s'...",pathcomponent);
309 ASC_FREE(pathcomponent); */
310
311 asc_assert(importhandler_library!=NULL);
312
313 for(i=0; i<IMPORTHANDLER_MAX && importhandler_library[i]!=NULL; ++i){
314
315 filename = (*(importhandler_library[i]->filenamefn))(searchdata->partialname); /* eg 'myext' -> 'libmyext.so' */
316 if(filename==NULL){
317 CONSOLE_DEBUG("Unable to create filename from partialname '%s'",searchdata->partialname);
318 continue;
319 }
320 /* CONSOLE_DEBUG("Filename '%s'",filename); */
321 fp = ospath_new_noclean(filename); /* eg 'libmyext.so' */
322 ASC_FREE(filename);
323 asc_assert(fp!=NULL);
324
325 /* fullpath = ospath_str(searchdata->relativedir);
326 CONSOLE_DEBUG("Relative dir is '%s'",fullpath);
327 ASC_FREE(fullpath); */
328
329 fp1 = ospath_concat(path,searchdata->relativedir); /* eg '/home/john/path/to' */
330 asc_assert(fp1!=NULL);
331
332 /*fullpath = ospath_str(fp1);
333 CONSOLE_DEBUG("Path is '%s'",fullpath);
334 ASC_FREE(fullpath);*/
335
336 /*fullpath = ospath_str(fp);
337 CONSOLE_DEBUG("Filename is '%s'",fullpath);
338 ASC_FREE(fullpath);*/
339
340 fp2 = ospath_concat(fp1,fp); /* eg '/home/john/path/to/libmyext.so' */
341 asc_assert(fp2!=NULL);
342 ospath_free(fp1);
343 ospath_free(fp);
344
345 /* fullpath = ospath_str(fp2);
346 CONSOLE_DEBUG("Checking for readable '%s'",fullpath);
347 ASC_FREE(fullpath); */
348
349 if(0==ospath_stat(fp2,&buf) && NULL!=(f = ospath_fopen(fp2,"r"))){
350 fclose(f);
351 searchdata->foundpath = fp2;
352 searchdata->handler = importhandler_library[i];
353 return 1; /* success */
354 }
355
356 ospath_free(fp2);
357 }
358 return 0; /* failed */
359 }
360
361 struct FilePath *importhandler_findinpath(const char *partialname
362 , char *defaultpath, char *envv, struct ImportHandler **handler
363 ){
364 struct FilePath *fp1; /* relative path */
365 struct ImportHandlerSearch searchdata;
366 char *path;
367 struct FilePath **sp;
368
369 fp1 = ospath_new_noclean(partialname); /* eg 'path/to/myext' */
370 if(fp1==NULL){
371 ERROR_REPORTER_HERE(ASC_USER_ERROR,"Invalid partial path '%s'",partialname);
372 return NULL;
373 }
374
375 searchdata.partialname = ospath_getbasefilename(fp1);
376 if(searchdata.partialname==NULL){
377 CONSOLE_DEBUG("Not a filename");
378 ospath_free(fp1);
379 return NULL;
380 }
381
382 searchdata.relativedir = ospath_getdir(fp1);
383 if(searchdata.relativedir ==NULL){
384 ERROR_REPORTER_HERE(ASC_PROG_ERR,"unable to retrieve file dir");
385 ospath_free(fp1);
386 ASC_FREE(searchdata.partialname);
387 return NULL;
388 }
389 ospath_free(fp1);
390
391 searchdata.foundpath = NULL;
392 searchdata.handler = NULL;
393
394 /** @TODO first, attempt to open without searching in path */
395
396 path=Asc_GetEnv(envv);
397 if(path==NULL){
398 CONSOLE_DEBUG("ENV VAR NOT FOUND, FALLING BACK TO DEFAULT SEARCH PATH = '%s'",defaultpath);
399 path=defaultpath;
400 }
401
402 /* CONSOLE_DEBUG("SEARCHPATH IS %s",path); */
403 sp = ospath_searchpath_new(path);
404
405 if(NULL==ospath_searchpath_iterate(sp,&importhandler_search_test,&searchdata)){
406 ospath_free(searchdata.relativedir);
407 ASC_FREE(searchdata.partialname);
408 ospath_searchpath_free(sp);
409 return NULL;
410 }
411
412 ospath_searchpath_free(sp);
413 ASC_FREE(searchdata.partialname);
414 ospath_free(searchdata.relativedir);
415 *handler = searchdata.handler;
416 return searchdata.foundpath;
417 }
418
419 /*------------------------------------------------------------------------------
420 SHARED POINTER TABLE
421 */
422
423 int importhandler_createsharedpointertable(){
424 if(importhandler_sharedpointers==NULL){
425 /* CONSOLE_DEBUG("CREATED SHARED POINTER TABLE"); */
426 importhandler_sharedpointers = CreateTable(31);
427 }
428 return 0;
429 }
430
431 int importhandler_setsharedpointer(const char *key, void *ptr){
432 importhandler_createsharedpointertable();
433 if(key==NULL){
434 ERROR_REPORTER_HERE(ASC_PROG_ERR,"key is NULL");
435 return 1;
436 }
437 AddTableData(importhandler_sharedpointers,ptr,key);
438 #ifdef IMPORTHANDLER_VERBOSE
439 CONSOLE_DEBUG("Set shared pointer '%s' to %p",key, ptr);
440 #endif
441 return 0;
442 }
443
444 void *importhandler_getsharedpointer(const char *key){
445 importhandler_createsharedpointertable();
446 if(key==NULL){
447 ERROR_REPORTER_HERE(ASC_PROG_ERR,"key is NULL");
448 return NULL;
449 }
450 return LookupTableData(importhandler_sharedpointers,key);
451 }

john.pye@anu.edu.au
ViewVC Help
Powered by ViewVC 1.1.22