/[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 869 - (show annotations) (download) (as text)
Wed Oct 4 14:03:46 2006 UTC (18 years 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 /* 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 /*
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 /**
49 Table of registered pointers for use in passing GUI data out to external scripts.
50 */
51 struct Table *importhandler_sharedpointers=NULL;
52
53 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 ERROR_REPORTER_HERE(ASC_PROG_NOTE,"New import hander '%s' added",handler->name);
75 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 snprintf(buffer,PATH_MAX,"%s.dll",partialname);
119 # 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
132 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 @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 @return 0 on success
143 */
144 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 return result;
184 }
185
186 /*------------------------------------------------------------------------------
187 LIST-BASED FUNCTIONS related to IMPORT handler 'library'
188 */
189
190 int importhandler_createlibrary(){
191 int i;
192 struct ImportHandler *extlib_handler;
193
194 if(importhandler_library!=NULL){
195 /* ERROR_REPORTER_HERE(ASC_PROG_ERR,"Already created"); */
196 return 0;
197 };
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
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
213 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 /*------------------------------------------------------------------------------
245 PATH SEARCH ROUTINES
246 */
247
248 /**
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 This test function will return a match when an importable file having the
265 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 fullpath = ospath_str(fp);
315 CONSOLE_DEBUG("Filename is '%s'",fullpath);
316 ASC_FREE(fullpath);
317
318 fp2 = ospath_concat(fp1,fp); /* eg '/home/john/path/to/libmyext.so' */
319 asc_assert(fp2!=NULL);
320 ospath_free(fp1);
321 ospath_free(fp);
322
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 ASC_FREE(searchdata.partialname);
386 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
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