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

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