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

Contents of /trunk/ascend/compiler/importhandler.c

Parent Directory Parent Directory | Revision Log Revision Log


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

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