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

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