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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1512 - (hide annotations) (download) (as text)
Wed Jun 27 13:45:17 2007 UTC (16 years, 3 months ago) by jpye
File MIME type: text/x-csrc
File size: 15429 byte(s)
Fixed handling of IDA not present. Commented out some debug stuff.
1 johnpye 862 /* 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 johnpye 1228 #include "importhandler.h"
28    
29 johnpye 862 #include <utilities/config.h>
30     #include <utilities/error.h>
31 johnpye 864 #include <utilities/ascDynaLoad.h>
32     #include <utilities/ascPanic.h>
33     #include <utilities/ascEnvVar.h>
34 johnpye 869 #include <general/table.h>
35 johnpye 862
36 johnpye 1228 #include <string.h>
37    
38 jpye 1512 /* #define SEARCH_DEBUG */
39 johnpye 912 /* #define IMPORTHANDLER_VERBOSE */
40    
41 johnpye 862 /*
42     Maximum number of importhandlers possible in one session. Hard to imagine
43     that you would want more than this.
44     */
45     #define IMPORTHANDLER_MAX 10
46    
47     /**
48     List of import handlers currently in effect. @TODO this shouldn't be a global,
49     but unfortunately such globals are 'The ASCEND Way'.
50     */
51     struct ImportHandler **importhandler_library=NULL;
52    
53 johnpye 869 /**
54     Table of registered pointers for use in passing GUI data out to external scripts.
55     */
56     struct Table *importhandler_sharedpointers=NULL;
57    
58 johnpye 1063 ASC_DLLSPEC int importhandler_add(struct ImportHandler *handler){
59 johnpye 862 int i;
60     if(handler==NULL){
61     ERROR_REPORTER_HERE(ASC_PROG_ERR,"Handler is NULL");
62     return 2;
63     }
64     if(importhandler_library == NULL){
65     importhandler_createlibrary();
66     }
67     for(i=0; i< IMPORTHANDLER_MAX; ++i){
68     if(importhandler_library[i] == NULL)break;
69     if(importhandler_library[i]->name == handler->name){
70 johnpye 931 ERROR_REPORTER_HERE(ASC_USER_NOTE,"Handler already loaded");
71 johnpye 862 return 0;
72     }
73     }
74     if(i==IMPORTHANDLER_MAX){
75     ERROR_REPORTER_HERE(ASC_PROG_ERR,"Too many import handlers register (IMPORTHANDLER_MAX=%d)",IMPORTHANDLER_MAX);
76     return 1;
77     }
78     importhandler_library[i] = handler;
79 johnpye 931 ERROR_REPORTER_HERE(ASC_USER_NOTE,"New import hander '%s' added",handler->name);
80 johnpye 862 return 0;
81     }
82    
83     /* Function to attempt import of an external script
84     @param partialname Name of the external script (without extension), relative to PATH.
85     @param defaultpath Default value of file search PATH. Is trumped by value of pathenvvar if present in environment.
86     @param pathenvvar Environment variable containing the user's preferred file search path value.
87     @return 0 on success
88     */
89     int importhandler_attemptimport(const char *partialname,const char *defaultpath, const char *pathenvvar){
90     ERROR_REPORTER_HERE(ASC_PROG_ERR,"%s not implemented",__FUNCTION__);
91     return 1;
92     }
93    
94     /*------------------------------------------------------------------------------
95     DEFAULT IMPORT HANDLER FOR DLL/SO FILES
96     */
97    
98     /**
99     Create a filename for an external library (DLL/SO) based on a
100     partial filename.
101    
102     @param partialname The partial filename (eg 'mylib')
103     @return Complete filename (eg 'libmylib.so' or 'mylib.dlll', etc)
104     */
105     char *importhandler_extlib_filename(const char *partialname){
106     char *buffer;
107     buffer = ASC_NEW_ARRAY(char,PATH_MAX);
108    
109     #if defined(ASC_SHLIBSUFFIX) && defined(ASC_SHLIBPREFIX)
110     /*
111     this is the preferred operation: SCons reports what the local system
112     uses as its shared library file extension.
113     */
114 johnpye 1228 snprintf(buffer,PATH_MAX,"%s%s%s",ASC_SHLIBPREFIX,partialname,ASC_SHLIBSUFFIX);
115 johnpye 862 #else
116 johnpye 1228 #ifdef __GNUC__
117     # warning "You should be using Use ASC_SHLIBPREFIX and ASC_SHLIBSUFFIX!"
118     #endif
119 johnpye 862 /**
120     @DEPRECATED
121    
122     If we don't have ASC_SHLIB-SUFFIX and -PREFIX then we can do some
123     system-specific stuff here, but it's not as general.
124     */
125     # ifdef __WIN32__
126 johnpye 866 snprintf(buffer,PATH_MAX,"%s.dll",partialname);
127 johnpye 862 # elif defined(linux)
128     snprintf(buffer,PATH_MAX,"lib%s.so",partialname); /* changed from .o to .so -- JP */
129     # elif defined(sun) || defined(solaris)
130     snprintf(buffer,PATH_MAX,"%s.so.1.0",partialname);
131     # elif defined(__hpux)
132     snprintf(buffer,PATH_MAX,"%s.sl",partialname);
133     # elif defined(_SGI_SOURCE)
134     snprintf(buffer,PATH_MAX,"%s.so",partialname);
135     # else
136     # error "Unknown system type (please define ASC_SHLIBSUFFIX and ASC_SHLIBPREFIX)"
137     # endif
138     #endif
139 johnpye 866
140 johnpye 862 return buffer;
141     }
142    
143     /**
144     Perform the actual importing of an external DLL/SO in to ASCEND. Can assume
145     that the file exists and is readable.
146    
147     @param fp Location of DLL/SO file
148 johnpye 864 @param initfunc Name of registration function, preferably NULL (so that ASCEND automatically determines it)
149     @param partialpath as specified in 'IMPORT' statement, for creation of auto_initfunc name
150 johnpye 862 @return 0 on success
151     */
152 johnpye 864 int importhandler_extlib_import(const struct FilePath *fp,const char *initfunc,const char *partialpath){
153    
154     struct FilePath *fp1;
155     char *stem;
156     char *path;
157     char auto_initfunc[PATH_MAX];
158     int result;
159    
160     path = ospath_str(fp);
161     if(path==NULL){
162     ERROR_REPORTER_HERE(ASC_PROG_ERR,"File path is NULL");
163     return 1;
164     }
165    
166     if(initfunc==NULL){
167     fp1 = ospath_new(partialpath);
168     stem = ospath_getbasefilename(fp1);
169     strncpy(auto_initfunc,stem,PATH_MAX);
170     ospath_free(fp1);
171     ASC_FREE(stem);
172    
173     strncat(auto_initfunc,"_register",PATH_MAX-strlen(auto_initfunc));
174 johnpye 895 /* CONSOLE_DEBUG("Created auto-initfunc name '%s'",auto_initfunc); */
175 johnpye 864 result = Asc_DynamicLoad(path,auto_initfunc);
176     }else{
177     result = Asc_DynamicLoad(path,initfunc);
178     }
179    
180     if(result){
181     CONSOLE_DEBUG("FAILED TO IMPORT '%s' (error %d)",partialpath,result);
182     }else{
183     if(initfunc==NULL){
184     CONSOLE_DEBUG("Successfully ran '%s' (automatically named) from dynamic package '%s'",auto_initfunc,path);
185     }else{
186     CONSOLE_DEBUG("Successfully ran '%s' from dynamic package '%s'",initfunc,path);
187     }
188     }
189    
190     ASC_FREE(path);
191 johnpye 866 return result;
192 johnpye 862 }
193    
194     /*------------------------------------------------------------------------------
195     LIST-BASED FUNCTIONS related to IMPORT handler 'library'
196     */
197    
198     int importhandler_createlibrary(){
199     int i;
200 johnpye 864 struct ImportHandler *extlib_handler;
201    
202 johnpye 862 if(importhandler_library!=NULL){
203 johnpye 865 /* ERROR_REPORTER_HERE(ASC_PROG_ERR,"Already created"); */
204     return 0;
205 johnpye 862 };
206     importhandler_library=ASC_NEW_ARRAY(struct ImportHandler *,IMPORTHANDLER_MAX);
207     for(i=0; i < IMPORTHANDLER_MAX; ++i){
208     importhandler_library[i] = NULL;
209     }
210 johnpye 897 /* CONSOLE_DEBUG("ImportHandler library created"); */
211 johnpye 864
212     extlib_handler = ASC_NEW(struct ImportHandler);
213     extlib_handler->name ="extlib";
214     extlib_handler->filenamefn = &importhandler_extlib_filename;
215     extlib_handler->importfn = &importhandler_extlib_import;
216     if(importhandler_add(extlib_handler)){
217     ERROR_REPORTER_HERE(ASC_PROG_ERR,"Failed to create 'extlib' import handler");
218     return 1;
219     }
220 johnpye 866
221 johnpye 862 return 0;
222     }
223    
224     int importhandler_remove(const char *name){
225 johnpye 1026 if(importhandler_library==NULL)return 2;
226 johnpye 1027 /* CONSOLE_DEBUG("Removing importhandler '%s'", name); */
227 johnpye 862 ERROR_REPORTER_HERE(ASC_PROG_ERR,"%s not implemented",__FUNCTION__);
228     return 1;
229     }
230    
231     struct ImportHandler *importhandler_lookup(const char *name){
232     ERROR_REPORTER_HERE(ASC_PROG_ERR,"%s not implemented",__FUNCTION__);
233     return NULL;
234     }
235    
236 johnpye 1026 /** @return 0 on success */
237 johnpye 862 int importhandler_destroylibrary(){
238 johnpye 1026 int i;
239     int err = 0;
240     CONSOLE_DEBUG("Destroying importhandler library...");
241     importhandler_printlibrary(stderr);
242 johnpye 1027 if(importhandler_library!=NULL){
243     for(i=IMPORTHANDLER_MAX - 1; i >= 0; --i){
244     if(importhandler_library[i]==NULL)continue;
245     err = err | importhandler_remove(importhandler_library[i]->name);
246     }
247 johnpye 1026 }
248     if(err)ERROR_REPORTER_HERE(ASC_PROG_WARNING,"Failed to destroy importhandler library");
249     return err;
250 johnpye 862 }
251    
252 johnpye 1026 /** @return 0 on success */
253 johnpye 862 int importhandler_printlibrary(FILE *fp){
254 johnpye 1026 int i;
255     if(importhandler_library==NULL){
256     fprintf(fp,"# importhandler_printlibrary: empty\n");
257     return 0;
258     }else{
259     fprintf(fp,"# importhandler_printlibrary: start\n");
260     for(i=0; i < IMPORTHANDLER_MAX && importhandler_library[i] != NULL; ++i){
261     fprintf(fp,"%s\n",importhandler_library[i]->name);
262     }
263     fprintf(fp,"# importhandler_printlibrary: end\n");
264     return 0;
265     }
266 johnpye 862 }
267    
268     int importhandler_printhandler(FILE *fp, struct ImportHandler *handler){
269     ERROR_REPORTER_HERE(ASC_PROG_ERR,"%s not implemented",__FUNCTION__);
270     CONSOLE_DEBUG("NOT IMPLEMENTED");
271     return 1;
272     }
273    
274 johnpye 864 /*------------------------------------------------------------------------------
275     PATH SEARCH ROUTINES
276     */
277 johnpye 862
278 johnpye 864 /**
279     A little structure to help with searching for import files
280    
281     @see test_importsearch
282     */
283     struct ImportHandlerSearch{
284     char *partialname; /**< for example 'myext' */
285     struct FilePath *relativedir; /**< for example 'path/to' */
286     struct FilePath *foundpath; /**< the complete filepath located, for example '/home/john/path/to/libmyext.so' */
287     struct ImportHandler *handler; /**< pointer to the import handler identified for this file */
288     };
289    
290     FilePathTestFn importhandler_search_test;
291    
292     /**
293     A FilePath 'test' function for passing to the ospath_searchpath_iterate function.
294 johnpye 866 This test function will return a match when an importable file having the
295 johnpye 864 required name is present in the fully resolved path.
296    
297     @param path the search path component
298     @param userdata will be an ImportHandlerSearch object
299     @return 1 if found
300     */
301     int importhandler_search_test(struct FilePath *path, void *userdata){
302     /* user data = the relative path, plus a place
303     to store the full path when found */
304     FILE *f;
305     char *filename;
306 johnpye 1281 #ifdef SEARCH_DEBUG
307     char *fullpath;
308     #endif
309 johnpye 864 struct ImportHandlerSearch *searchdata;
310     struct FilePath *fp, *fp1, *fp2;
311     int i;
312     ospath_stat_t buf;
313    
314     searchdata = (struct ImportHandlerSearch *)userdata;
315    
316 johnpye 1281 #ifdef SEARCH_DEBUG
317     char *pathcomponent;
318 johnpye 968 pathcomponent = ospath_str(path); //eg '/home/john'
319     CONSOLE_DEBUG("In directory '%s'...",pathcomponent);
320 johnpye 1281 ASC_FREE(pathcomponent);
321     #endif
322 johnpye 864
323     asc_assert(importhandler_library!=NULL);
324    
325     for(i=0; i<IMPORTHANDLER_MAX && importhandler_library[i]!=NULL; ++i){
326    
327     filename = (*(importhandler_library[i]->filenamefn))(searchdata->partialname); /* eg 'myext' -> 'libmyext.so' */
328     if(filename==NULL){
329     CONSOLE_DEBUG("Unable to create filename from partialname '%s'",searchdata->partialname);
330     continue;
331     }
332 johnpye 881 /* CONSOLE_DEBUG("Filename '%s'",filename); */
333 johnpye 864 fp = ospath_new_noclean(filename); /* eg 'libmyext.so' */
334     ASC_FREE(filename);
335     asc_assert(fp!=NULL);
336    
337 jpye 1332 #ifdef SEARCH_DEBUG
338 johnpye 1281 fullpath = ospath_str(searchdata->relativedir);
339 johnpye 968 CONSOLE_DEBUG("Relative dir is '%s'",fullpath);
340 johnpye 1281 ASC_FREE(fullpath);
341 jpye 1332 #endif
342 johnpye 864 fp1 = ospath_concat(path,searchdata->relativedir); /* eg '/home/john/path/to' */
343     asc_assert(fp1!=NULL);
344    
345 johnpye 1281
346     #ifdef SEARCH_DEBUG
347     fullpath = ospath_str(fp1);
348 johnpye 968 CONSOLE_DEBUG("Path is '%s'",fullpath);
349 johnpye 1281 ASC_FREE(fullpath);
350 johnpye 864
351 johnpye 1281 fullpath = ospath_str(fp);
352 johnpye 968 CONSOLE_DEBUG("Filename is '%s'",fullpath);
353 johnpye 1281 ASC_FREE(fullpath);
354     #endif
355 johnpye 865
356 johnpye 864 fp2 = ospath_concat(fp1,fp); /* eg '/home/john/path/to/libmyext.so' */
357     asc_assert(fp2!=NULL);
358     ospath_free(fp1);
359 johnpye 865 ospath_free(fp);
360 johnpye 864
361 johnpye 1281 #ifdef SEARCH_DEBUG
362     fullpath = ospath_str(fp2);
363 johnpye 968 CONSOLE_DEBUG("Checking for readable '%s'",fullpath);
364 johnpye 1281 ASC_FREE(fullpath);
365     #endif
366 johnpye 864
367     if(0==ospath_stat(fp2,&buf) && NULL!=(f = ospath_fopen(fp2,"r"))){
368     fclose(f);
369     searchdata->foundpath = fp2;
370     searchdata->handler = importhandler_library[i];
371     return 1; /* success */
372     }
373    
374     ospath_free(fp2);
375     }
376     return 0; /* failed */
377     }
378    
379     struct FilePath *importhandler_findinpath(const char *partialname
380     , char *defaultpath, char *envv, struct ImportHandler **handler
381     ){
382 johnpye 1281 struct FilePath *fp, *fp1; /* relative path */
383 johnpye 864 struct ImportHandlerSearch searchdata;
384 johnpye 1281 char *path, *filename;
385 johnpye 864 struct FilePath **sp;
386 johnpye 1281 int i;
387     ospath_stat_t buf;
388     FILE *f;
389 johnpye 864
390     fp1 = ospath_new_noclean(partialname); /* eg 'path/to/myext' */
391     if(fp1==NULL){
392     ERROR_REPORTER_HERE(ASC_USER_ERROR,"Invalid partial path '%s'",partialname);
393     return NULL;
394     }
395    
396     searchdata.partialname = ospath_getbasefilename(fp1);
397     if(searchdata.partialname==NULL){
398     CONSOLE_DEBUG("Not a filename");
399     ospath_free(fp1);
400     return NULL;
401     }
402    
403     searchdata.relativedir = ospath_getdir(fp1);
404     if(searchdata.relativedir ==NULL){
405     ERROR_REPORTER_HERE(ASC_PROG_ERR,"unable to retrieve file dir");
406     ospath_free(fp1);
407     ASC_FREE(searchdata.partialname);
408     return NULL;
409     }
410     ospath_free(fp1);
411    
412     searchdata.foundpath = NULL;
413     searchdata.handler = NULL;
414    
415 johnpye 1281 /* first, attempt to open without searching in path */
416 johnpye 864
417 johnpye 1281 for(i=0; i<IMPORTHANDLER_MAX && importhandler_library[i]!=NULL; ++i){
418    
419     filename = (*(importhandler_library[i]->filenamefn))(searchdata.partialname); /* eg 'myext' -> 'libmyext.so' */
420     if(filename==NULL){
421     CONSOLE_DEBUG("Unable to create filename from partialname '%s'",searchdata.partialname);
422     continue;
423     }
424    
425     fp = ospath_new(filename); /* eg 'libmyext.so' */
426     ASC_FREE(filename);
427     asc_assert(fp!=NULL);
428    
429     #ifdef SEARCH_DEBUG
430     path = ospath_str(searchdata.relativedir);
431     CONSOLE_DEBUG("Relative dir is '%s'",path);
432     ASC_FREE(path);
433    
434     path = ospath_str(fp);
435     CONSOLE_DEBUG("Filename is '%s'",path);
436     ASC_FREE(path);
437     #endif
438    
439     fp1 = ospath_concat(searchdata.relativedir,fp); /* eg '/home/john/path/to/libmyext.so' */
440     asc_assert(fp1!=NULL);
441     ospath_free(fp);
442    
443     #ifdef SEARCH_DEBUG
444     path = ospath_str(fp1);
445     CONSOLE_DEBUG("Checking for readable '%s'",path);
446     ASC_FREE(path);
447     #endif
448    
449     if(0==ospath_stat(fp1,&buf) && NULL!=(f = ospath_fopen(fp1,"r"))){
450     CONSOLE_DEBUG("FOUND!");
451     fclose(f);
452     ASC_FREE(searchdata.partialname);
453     ospath_free(searchdata.relativedir);
454     *handler = importhandler_library[i];
455     return fp1;
456 jpye 1332 }
457     #ifdef SEARCH_DEBUG
458     else{
459 johnpye 1281 CONSOLE_DEBUG("Not found");
460     }
461 jpye 1332 #endif
462 johnpye 1281
463     ospath_free(fp1);
464     }
465    
466     /*-----------------------*/
467    
468 johnpye 864 path=Asc_GetEnv(envv);
469     if(path==NULL){
470     CONSOLE_DEBUG("ENV VAR NOT FOUND, FALLING BACK TO DEFAULT SEARCH PATH = '%s'",defaultpath);
471     path=defaultpath;
472     }
473    
474 johnpye 895 /* CONSOLE_DEBUG("SEARCHPATH IS %s",path); */
475 johnpye 864 sp = ospath_searchpath_new(path);
476    
477     if(NULL==ospath_searchpath_iterate(sp,&importhandler_search_test,&searchdata)){
478     ospath_free(searchdata.relativedir);
479 johnpye 866 ASC_FREE(searchdata.partialname);
480 johnpye 864 ospath_searchpath_free(sp);
481     return NULL;
482     }
483    
484     ospath_searchpath_free(sp);
485     ASC_FREE(searchdata.partialname);
486     ospath_free(searchdata.relativedir);
487     *handler = searchdata.handler;
488     return searchdata.foundpath;
489     }
490 johnpye 869
491     /*------------------------------------------------------------------------------
492     SHARED POINTER TABLE
493     */
494    
495     int importhandler_createsharedpointertable(){
496     if(importhandler_sharedpointers==NULL){
497 johnpye 897 /* CONSOLE_DEBUG("CREATED SHARED POINTER TABLE"); */
498 johnpye 869 importhandler_sharedpointers = CreateTable(31);
499     }
500     return 0;
501     }
502    
503     int importhandler_setsharedpointer(const char *key, void *ptr){
504     importhandler_createsharedpointertable();
505     if(key==NULL){
506     ERROR_REPORTER_HERE(ASC_PROG_ERR,"key is NULL");
507     return 1;
508     }
509 johnpye 1027
510     /* woops! 'AddTableData' does *not* overwrite table entries! */
511     RemoveTableData(importhandler_sharedpointers,(char *)key);
512    
513 johnpye 869 AddTableData(importhandler_sharedpointers,ptr,key);
514 johnpye 912 #ifdef IMPORTHANDLER_VERBOSE
515 johnpye 900 CONSOLE_DEBUG("Set shared pointer '%s' to %p",key, ptr);
516 johnpye 912 #endif
517 johnpye 1027 asc_assert(importhandler_getsharedpointer(key)==ptr);
518 johnpye 869 return 0;
519     }
520    
521     void *importhandler_getsharedpointer(const char *key){
522     importhandler_createsharedpointertable();
523     if(key==NULL){
524     ERROR_REPORTER_HERE(ASC_PROG_ERR,"key is NULL");
525 johnpye 895 return NULL;
526 johnpye 869 }
527     return LookupTableData(importhandler_sharedpointers,key);
528     }

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