/[ascend]/branches/fprops-incomp/ascxx/library.cpp
ViewVC logotype

Contents of /branches/fprops-incomp/ascxx/library.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3484 - (show annotations) (download) (as text)
Tue Dec 7 01:47:45 2021 UTC (5 months, 2 weeks ago) by jpye
File MIME type: text/x-c++src
File size: 12249 byte(s)
increase message buffer size, use safe snprintf

1
2
3 #include <iostream>
4 #include <stdexcept>
5 #include <sstream>
6 using namespace std;
7
8 #undef NDEBUG
9
10 #include "config.h"
11
12 extern "C"{
13 #include <ascend/general/platform.h>
14
15 #include <ascend/general/list.h>
16 #include <ascend/compiler/ascCompiler.h>
17
18 /* #include <compiler/redirectFile.h> */
19 #include <ascend/compiler/prototype.h>
20 #include <ascend/compiler/dump.h>
21 #include <ascend/compiler/childio.h>
22 #include <ascend/compiler/type_desc.h>
23 #include <ascend/compiler/typedef.h>
24 #include <ascend/compiler/library.h>
25 #include <ascend/system/slv_types.h>
26 #include <ascend/system/system.h>
27 #include <ascend/utilities/ascEnvVar.h>
28 #include <ascend/compiler/symtab.h>
29 #include <ascend/general/table.h>
30 #include <ascend/compiler/instance_enum.h>
31 #include <ascend/compiler/notate.h>
32 #include <ascend/compiler/simlist.h>
33 #include <ascend/compiler/parser.h>
34 #include <ascend/utilities/error.h>
35 #include <ascend/general/env.h>
36 #include <ascend/compiler/importhandler.h>
37 }
38
39 #include "library.h"
40 #include "simulation.h"
41 #include "solver.h"
42
43 //#define ASCXX_LIBRARY_DEBUG
44 #ifdef ASCXX_LIBRARY_DEBUG
45 # define MSG CONSOLE_DEBUG
46 #else
47 # define MSG(ARGS...) ((void)0)
48 #endif
49
50 Library::Library(const char *defaultpath){
51 static int have_init;
52 if(!have_init){
53 MSG("Initialising ASCEND library...");
54
55 #ifdef REIMPLEMENT_STREAMS
56 Asc_RedirectCompilerDefault(); // Ensure that error message reach stderr
57 #endif
58 Asc_CompilerInit(1);
59 env_import_default(ASC_ENV_LIBRARY,getenv,Asc_GetEnv,Asc_PutEnv,DEFAULT_ASCENDLIBRARY,0,1);
60 env_import(ASC_ENV_SOLVERS,getenv,Asc_PutEnv,0);
61 Asc_ImportPathList(ASC_ENV_LIBRARY);
62 registerStandardSolvers();
63 }
64 have_init=1;
65 }
66
67 Library::~Library(){
68 //ERROR_REPORTER_NOLINE(ASC_PROG_WARNING,"DESTROYED LIBRARY!////////////////////////////////////////");
69 //DestroyLibrary();
70 // ... need to use some kind of reference counting before you can do that...
71 }
72
73 /**
74 Load an ASCEND model file into the Library. It will be parsed such that
75 its types will be visible to Library::findType.
76
77 @param filename Filename, will be searched for relative to ASCENDLIBRARY environment
78 variable, if necessary.
79 */
80 void
81 Library::load(const char *filename){
82
83 //std::cerr << "Loading '" << filename << "'" << std::endl;
84
85 int status;
86 struct module_t *m=Asc_RequireModule(filename,&status);
87 if(m!=NULL){
88 //std::cerr << "Loaded module '" << Asc_ModuleName(m) << "'" << std::endl;
89 }else{
90 std::cerr << "Error: unable to load module '" << filename << "'." << std::endl;
91 }
92
93 const char *msg = getLoadErrorMessage(status);
94
95 #define MSGLEN 4096
96 char msg1[MSGLEN];
97 snprintf(msg1,MSGLEN,msg,filename);
98
99 if(status<0 || status>0){
100 throw std::runtime_error(msg1);
101 #ifdef ASCXX_LIBRARY_DEBUG
102 }else{
103 MSG(msg1,Asc_ModuleName(m));
104 #endif
105 }
106
107 MSG("Beginning parse of %s",Asc_ModuleName(m));
108 error_reporter_tree_t *tree1 = error_reporter_tree_start(0);
109 status = zz_parse();
110 switch(status){
111 case 0: break;
112 case 1: ERROR_REPORTER_NOLINE(ASC_USER_ERROR,"Parsing of %s was aborted",Asc_ModuleName(m)); break;
113 case 2: ERROR_REPORTER_NOLINE(ASC_PROG_FATAL,"Out of memory when parsing %s",Asc_ModuleName(m)); break;
114 default: ERROR_REPORTER_NOLINE(ASC_PROG_ERROR,"Invalid return from zz_parse"); break;
115 }
116 status = error_reporter_tree_has_error(tree1);
117 if(!status){
118 error_reporter_tree_end_clear(tree1);
119 }else{
120 error_reporter_tree_end(tree1);
121 ERROR_REPORTER_NOLINE(ASC_USER_ERROR,"Error(s) when loading '%s'",filename);
122 stringstream ss;
123 ss << "Errors found in '" << filename << "'";
124 throw runtime_error(ss.str());
125 }
126
127 #ifdef ASCXX_LIBRARY_DEBUG
128 struct gl_list_t *l = Asc_TypeByModule(m);
129 MSG("%lu library entries loaded from %s",gl_length(l), filename);
130 #endif
131 }
132
133 /**
134 Load MODELs specified inside a text string into the Library. The string is
135 parsed and its types will then be visible to Library::findType.
136
137 @param str String containing the model, in the ASCEND modelling language.
138 @param nameprefix Name to be used to refer tothe string module when eg using
139 the Library::getModules methood.
140 */
141 void
142 Library::loadString(const char *str, const char *nameprefix){
143 int status;
144 struct module_t *m = Asc_OpenStringModule(str, &status, nameprefix);
145
146 const char *msg = getLoadErrorMessage(status);
147
148 char msg1[100];
149 sprintf(msg1,msg,nameprefix);
150
151 if(status<0 || status>0){
152 throw std::runtime_error(msg1);
153 }else{
154 std::cerr << "Note: Module " << Asc_ModuleName(m) << ": " << msg1 << std::endl;
155 }
156
157 MSG("Beginning parse of %s",Asc_ModuleName(m));
158 #ifdef LOADSTRING_ERROR_TREE
159 error_reporter_tree_t *tree1 = error_reporter_tree_start(0);
160 #endif
161 status = zz_parse();
162 switch(status){
163 case 0: break;
164 case 1: ERROR_REPORTER_NOLINE(ASC_USER_ERROR,"Parsing of %s was aborted",Asc_ModuleName(m)); break;
165 case 2: ERROR_REPORTER_NOLINE(ASC_PROG_FATAL,"Out of memory when parsing %s",Asc_ModuleName(m)); break;
166 default: ERROR_REPORTER_NOLINE(ASC_PROG_ERROR,"Invalid return from zz_parse"); break;
167 }
168 #ifdef LOADSTRING_ERROR_TREE
169 status = error_reporter_tree_has_error(tree1);
170 if(!status){
171 MSG("CLEARING TREE...");
172 error_reporter_tree_end_clear(tree1);
173 MSG("DONE CLEARING TREE...");
174 }else{
175 error_reporter_tree_end(tree1);
176 ERROR_REPORTER_NOLINE(ASC_USER_ERROR,"Error(s) when loading '%s'",nameprefix);
177 stringstream ss;
178 ss << "Errors found in '" << nameprefix << "'";
179 throw runtime_error(ss.str());
180 }
181 #endif
182
183 struct gl_list_t *l = Asc_TypeByModule(m);
184 MSG("%lu library entries loaded from %s",gl_length(l), nameprefix);
185 }
186
187 const char *
188 Library::getLoadErrorMessage(int status){
189 const char *msg = NULL;
190 switch(status){
191 case 5:
192 msg = "The module '%s' already exists. "; break;
193 case 4:
194 msg = "Caught an attempt to do a recursive require under '%s'."; break;
195 case 3:
196 msg = "A new module was created from '%s', overwriting a module's alias."; break;
197 case 2:
198 msg = "An existing module is being returned for '%s'." ; break;
199 case 1:
200 msg = "An new version of an existing module was created for '%s'."; break;
201 case 0:
202 msg = "Module for '%s' created OK."; break;
203 case -1:
204 msg = "File not found for '%s'. (-1)"; break;
205 case -2:
206 msg = "Unable to open '%s' for reading. (-2)";break;
207 case -3:
208 msg = "Insuffient memory to create module for '%s'. (-3)"; break;
209 case -4:
210 msg = "Bad input, null or zero length filename in '%s'. (-4)"; break;
211 default:
212 throw std::runtime_error("Invalid status code in library.cpp");
213 }
214 return msg;
215 }
216
217
218
219
220
221 /**
222 Return a vector of all the Modules which have been loaded into
223 the current library.
224 */
225 vector<Module>
226 Library::getModules(const int module_type){
227 if(module_type < 0 || module_type > 2){
228 throw std::runtime_error("Library::getModules: invalid module_type parameter");
229 }
230
231 vector<Module> v;
232 struct gl_list_t *l = Asc_ModuleList(module_type);
233 if(l==NULL){
234 MSG("list is empty");
235 return v;
236 }
237 for(int i=0, end=gl_length(l); i<end; ++i){
238 symchar *name = (symchar *)gl_fetch(l,i+1);
239 if(AscFindSymbol(name)==NULL){
240 throw runtime_error("Library::getModules: invalid symchar *");
241 }
242 //cerr << "GOT " << SCP( name ) << endl;
243 const module_t *m = Asc_GetModuleByName((const char *)name);
244 v.push_back(Module(m));
245 }
246 /*cerr << "LENGTH OF V IS " << v.size() << endl;
247 if(v.size()){
248 cerr << "MODULE 0's NAME IS " << v[0].getName() << endl;
249 }*/
250 return v;
251 }
252
253 /**
254 Output to stderr the names of the modules loaded into the current Library.
255 */
256 void
257 Library::listModules(const int module_type){
258 if(module_type < 0 || module_type > 2){
259 throw std::runtime_error("Library::listModules: invalid module_type parameter");
260 }
261
262 const char *type = NULL;
263 switch(module_type){
264 case 0: type = "defined types"; break;
265 case 1: type = "string definitions"; break;
266 case 2: type = "statements"; break;
267 }
268
269 vector<Module> v = getModules(module_type);
270 if(v.size()){
271 std::cerr << "Listing " << v.size() << " modules with " << type << std::endl;
272 for(vector<Module>::const_iterator i=v.begin(); i < v.end(); ++i){
273 cerr << " - " << i->getName() << endl;
274 vector<Type> tt = getModuleTypes(*i);
275 for(vector<Type>::const_iterator j = tt.begin(); j < tt.end(); ++j){
276 cerr << " * " << j->getName() << endl;
277 }
278 }
279 }else{
280 std::cerr << "Notice: No " << type << " found in module list." << std::endl;
281 }
282 }
283
284 Type &
285 Library::findType(const SymChar &sym){
286 TypeDescription *t = FindType(sym.getInternalType());
287 if(t==NULL){
288 stringstream ss;
289 ss << "Library::findType: type '" << sym << "' not found in library";
290 throw runtime_error(ss.str());
291 }/*else{
292 cerr << "Found something for type " << sym << endl;
293 }*/
294 Type *t2=new Type(t);
295 return *t2;
296 }
297
298 static int module_sort_cmp(const void *a, const void *b){
299 return strcmp((char *)a, (char *)b);
300 }
301
302 /**
303 This could be quite a bit more efficient if we could get a gl_list_t of TypeDescription rather than names
304 */
305 vector<Type>
306 Library::getModuleTypes(const Module &m){
307 //cerr << "GET MODULE TYPES\n" << endl;
308 vector<Type> v;
309 struct gl_list_t *l = Asc_TypeByModule(m.getInternalType());
310
311 gl_sort(l, &module_sort_cmp);
312
313 for(int i=0,end=gl_length(l); i<end; ++i){
314 char *name = (char *)gl_fetch(l,i+1);
315 MSG("Found type %s",name);
316 TypeDescription *t = FindType((const symchar *)name);
317 v.push_back(Type(t));
318 }
319 return v;
320 }
321
322 /**
323 This function is kinda fighting against the Table implementation of the external function library. What we really need is some kind of iterator on the Table struct, but it doesn't seem to be implemented. Instead there is a C-style equivalent of the STL 'bind1st' function which we can use, but it's not exported from the current extfunc.h so we need to add it.
324 */
325 vector<ExtMethod>
326 Library::getExtMethods(){
327 // Clear the vector
328 extmethod_vector = vector<ExtMethod>();
329
330 // Traverse the vector
331 TraverseExtFuncLibrary(Library::extMethodTraverse, (void *)this);
332
333 return extmethod_vector;
334 }
335
336 /**
337 This method exists only to allow the TraverseExtFuncLibrary function
338 to make callbacks to the Library class from C.
339
340 @NOTE there might be issues with C/C++ linking here?
341 */
342 void
343 Library::extMethodTraverse(void *a1, void *a2){
344 Library *self = (Library *)a2;
345 self->appendToExtMethodVector(a1);
346 }
347
348 void
349 Library::appendToExtMethodVector(void *a1){
350 struct ExternalFunc *e = (struct ExternalFunc *)a1;
351 extmethod_vector.push_back(ExtMethod(e));
352 }
353
354 /**
355 Clear the library: 'DESTROY TYPES'
356
357 @TODO do this more efficiently, don't destroy the whole ASCEND compiler.
358 */
359 void
360 Library::clear(){
361 /* Asc_CompilerDestroy();
362 cerr << "COMPLETED ASC_COMPILERDESTROY" << endl;
363 Asc_CompilerInit(1);
364 cerr << "... ASC_COMPILERINIT OK" << endl;
365 Asc_ImportPathList(PATHENVIRONMENTVAR);
366 registerStandardSolvers();
367 cerr << "... REGISTER_STANDARD_SOLVERS" << endl;
368 DefineFundamentalTypes();
369 cerr << "... DEFINED FUND TYPES" << endl;
370 \*SetUniversalProcedureList(NULL);
371 */
372
373 MSG("Displaying library modules and types...");
374 //listModules();
375
376 MSG("Destroying simulations...");
377 Asc_DestroySimulations();
378
379 MSG("Clearing library...");
380 DestroyNotesDatabase(LibraryNote());
381 SetUniversalProcedureList(NULL);
382 DestroyLibrary();
383 DestroyPrototype();
384 EmptyTrash();
385 Asc_DestroyModules((DestroyFunc)DestroyStatementList);
386 //importhandler_destroylibrary();
387 WriteChildMissing(NULL,NULL,NULL);
388 //Asc_CompilerInit(1)
389 DefineFundamentalTypes();
390 InitNotesDatabase(LibraryNote());
391 ERROR_REPORTER_NOLINE(ASC_PROG_WARNING,"LIBRARY CLEARED!");
392 }
393
394 AnnotationDatabase
395 Library::getAnnotationDatabase(){
396 return AnnotationDatabase(SCP(LibraryNote()));
397 }
398
399 vector<UnitsM>
400 Library::getUnits() const{
401 vector<UnitsM> v;
402 register unsigned long c;
403 const struct Units *p;
404 for(c = 0;c<UNITS_HASH_SIZE;c++) {
405 for(p = g_units_hash_table[c];p!=NULL;p = p->next){
406 v.push_back(UnitsM(p));
407 }
408 }
409 return v;
410 }
411
412 set<Type>
413 Library::getRealAtomTypes() const{
414 set<Type> s;
415 struct gl_list_t *l = DefinitionList();
416 if(!l){
417 throw runtime_error("No types found in library (perhaps no files have been loaded?)");
418 }
419
420 for(unsigned i = 1; i<=gl_length(l); ++i) {
421 Type t((const struct TypeDescription *)gl_fetch(l,i));
422 if(t.isRefinedReal()){
423 Dimensions d = t.getDimensions();
424 if(d.isWild() || d.isDimensionless())continue; // skip this one
425 // it's got some dimensions, add it to the list
426 s.insert(t);
427 }
428 }
429 gl_destroy(l);
430 return s;
431 }
432

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