/[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 1026 - (hide annotations) (download) (as text)
Wed Jan 3 12:03:08 2007 UTC (17 years, 2 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 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 johnpye 912 /* #define IMPORTHANDLER_VERBOSE */
37    
38 johnpye 862 /*
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 johnpye 869 /**
51     Table of registered pointers for use in passing GUI data out to external scripts.
52     */
53     struct Table *importhandler_sharedpointers=NULL;
54    
55 johnpye 862 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 johnpye 931 ERROR_REPORTER_HERE(ASC_USER_NOTE,"Handler already loaded");
68 johnpye 862 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 johnpye 931 ERROR_REPORTER_HERE(ASC_USER_NOTE,"New import hander '%s' added",handler->name);
77 johnpye 862 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 johnpye 866 snprintf(buffer,PATH_MAX,"%s.dll",partialname);
121 johnpye 862 # 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 johnpye 866
134 johnpye 862 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 johnpye 864 @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 johnpye 862 @return 0 on success
145     */
146 johnpye 864 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 johnpye 895 /* CONSOLE_DEBUG("Created auto-initfunc name '%s'",auto_initfunc); */
169 johnpye 864 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 johnpye 866 return result;
186 johnpye 862 }
187    
188     /*------------------------------------------------------------------------------
189     LIST-BASED FUNCTIONS related to IMPORT handler 'library'
190     */
191    
192     int importhandler_createlibrary(){
193     int i;
194 johnpye 864 struct ImportHandler *extlib_handler;
195    
196 johnpye 862 if(importhandler_library!=NULL){
197 johnpye 865 /* ERROR_REPORTER_HERE(ASC_PROG_ERR,"Already created"); */
198     return 0;
199 johnpye 862 };
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 johnpye 897 /* CONSOLE_DEBUG("ImportHandler library created"); */
205 johnpye 864
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 johnpye 866
215 johnpye 862 return 0;
216     }
217    
218     int importhandler_remove(const char *name){
219 johnpye 1026 if(importhandler_library==NULL)return 2;
220     CONSOLE_DEBUG("Removing importhandler '%s'", name);
221 johnpye 862 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 johnpye 1026 /** @return 0 on success */
231 johnpye 862 int importhandler_destroylibrary(){
232 johnpye 1026 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 johnpye 862 }
243    
244 johnpye 1026 /** @return 0 on success */
245 johnpye 862 int importhandler_printlibrary(FILE *fp){
246 johnpye 1026 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 johnpye 862 }
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 johnpye 864 /*------------------------------------------------------------------------------
267     PATH SEARCH ROUTINES
268     */
269 johnpye 862
270 johnpye 864 /**
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 johnpye 866 This test function will return a match when an importable file having the
287 johnpye 864 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 johnpye 1026 /* char *fullpath; */
299 johnpye 864 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 johnpye 968 /* char *pathcomponent;
307     pathcomponent = ospath_str(path); //eg '/home/john'
308     CONSOLE_DEBUG("In directory '%s'...",pathcomponent);
309     ASC_FREE(pathcomponent); */
310 johnpye 864
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 johnpye 881 /* CONSOLE_DEBUG("Filename '%s'",filename); */
321 johnpye 864 fp = ospath_new_noclean(filename); /* eg 'libmyext.so' */
322     ASC_FREE(filename);
323     asc_assert(fp!=NULL);
324    
325 johnpye 968 /* fullpath = ospath_str(searchdata->relativedir);
326     CONSOLE_DEBUG("Relative dir is '%s'",fullpath);
327     ASC_FREE(fullpath); */
328 johnpye 864
329     fp1 = ospath_concat(path,searchdata->relativedir); /* eg '/home/john/path/to' */
330     asc_assert(fp1!=NULL);
331    
332 johnpye 968 /*fullpath = ospath_str(fp1);
333     CONSOLE_DEBUG("Path is '%s'",fullpath);
334     ASC_FREE(fullpath);*/
335 johnpye 864
336 johnpye 968 /*fullpath = ospath_str(fp);
337     CONSOLE_DEBUG("Filename is '%s'",fullpath);
338     ASC_FREE(fullpath);*/
339 johnpye 865
340 johnpye 864 fp2 = ospath_concat(fp1,fp); /* eg '/home/john/path/to/libmyext.so' */
341     asc_assert(fp2!=NULL);
342     ospath_free(fp1);
343 johnpye 865 ospath_free(fp);
344 johnpye 864
345 johnpye 968 /* fullpath = ospath_str(fp2);
346     CONSOLE_DEBUG("Checking for readable '%s'",fullpath);
347     ASC_FREE(fullpath); */
348 johnpye 864
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 johnpye 895 /* CONSOLE_DEBUG("SEARCHPATH IS %s",path); */
403 johnpye 864 sp = ospath_searchpath_new(path);
404    
405     if(NULL==ospath_searchpath_iterate(sp,&importhandler_search_test,&searchdata)){
406     ospath_free(searchdata.relativedir);
407 johnpye 866 ASC_FREE(searchdata.partialname);
408 johnpye 864 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 johnpye 869
419     /*------------------------------------------------------------------------------
420     SHARED POINTER TABLE
421     */
422    
423     int importhandler_createsharedpointertable(){
424     if(importhandler_sharedpointers==NULL){
425 johnpye 897 /* CONSOLE_DEBUG("CREATED SHARED POINTER TABLE"); */
426 johnpye 869 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 johnpye 912 #ifdef IMPORTHANDLER_VERBOSE
439 johnpye 900 CONSOLE_DEBUG("Set shared pointer '%s' to %p",key, ptr);
440 johnpye 912 #endif
441 johnpye 869 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 johnpye 895 return NULL;
449 johnpye 869 }
450     return LookupTableData(importhandler_sharedpointers,key);
451     }

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