/[ascend]/trunk/base/generic/compiler/extfunc.c
ViewVC logotype

Contents of /trunk/base/generic/compiler/extfunc.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 752 - (show annotations) (download) (as text)
Wed Jul 12 02:50:54 2006 UTC (13 years, 6 months ago) by johnpye
File MIME type: text/x-csrc
File size: 12456 byte(s)
Fixed bug with instantiation of 'outvars'.
1 /*
2 ASCEND modelling environment
3 Copyright (C) 1990, 1993, 1994 Thomas Guthrie Epperly, Kirk Andre Abbott
4 Copyright (C) 2006 Carnegie Mellon University
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.
20 *//*
21 by Kirk Andre Abbott
22 Created: July 4, 1994.
23 Last in CVS: $Revision: 1.8 $ $Date: 1998/02/05 22:23:26 $ $Author: ballan $
24 */
25
26 #include <utilities/ascConfig.h>
27 #include <utilities/ascMalloc.h>
28 #include <utilities/ascPanic.h>
29 #include <general/hashpjw.h>
30 #include <general/list.h>
31 #include <general/table.h>
32 #include <general/dstring.h>
33 #include "compiler.h"
34 #include "symtab.h"
35 #include "instance_enum.h"
36 #include "instance_io.h"
37 #include "extfunc.h"
38 #include "extcall.h"
39 #include "atomvalue.h"
40
41 /*------------------------------------------------------------------------------
42 forward decls and typedefs etc
43 */
44
45 #define EXTFUNCHASHSIZE 31
46
47 static struct Table *ExternalFuncLibrary = NULL;
48
49 /*-----------------------------------------------------------------------------
50 BLACK BOX STUFF
51 */
52
53 int CreateUserFunctionBlackBox(CONST char *name,
54 ExtBBoxInitFunc *init,
55 ExtBBoxFunc *value,
56 ExtBBoxFunc *deriv,
57 ExtBBoxFunc *deriv2,
58 ExtBBoxInitFunc *final,
59 CONST unsigned long n_inputs,
60 CONST unsigned long n_outputs,
61 CONST char *help
62 ){
63 struct ExternalFunc *efunc;
64 int isNew = 0;
65 if(name == NULL){
66 return 1;
67 }
68 efunc = LookupExtFunc(name);
69 if(efunc != NULL){
70 /* CONSOLE_DEBUG("Found efunc at %p",efunc); */
71 /* name has already been seen, so now fill in the details */
72 isNew = 0;
73 }else{
74 isNew = 1;
75 efunc = ASC_NEW(struct ExternalFunc);
76 asc_assert(efunc!=NULL);
77 efunc->help = NULL;
78 efunc->name = ascstrdup(SCP(AddSymbol(name)));
79 /* CONSOLE_DEBUG("Created new efunc at %p",efunc); */
80 /* add or find name in symbol table */
81 /* the main symtab owns the string */
82 }
83
84 efunc->etype = efunc_BlackBox;
85 efunc->n_inputs = n_inputs;
86 efunc->n_outputs = n_outputs;
87 efunc->u.black.initial = init;
88 efunc->u.black.value = value;
89 efunc->u.black.deriv = deriv;
90 efunc->u.black.deriv2 = deriv2;
91 efunc->u.black.final = final;
92 if(help){
93 if (efunc->help) ascfree((char *)efunc->help);
94 efunc->help = ascstrdup(help);
95 }else{
96 efunc->help = NULL;
97 }
98
99 if(isNew){
100 CONSOLE_DEBUG("NEW BLACKBOX EFUNC %p ('%s', %lu inputs, %lu outputs, type=%d, value func=%p)"
101 ,efunc, name, n_inputs, n_outputs, (int)efunc->etype, value
102 );
103 (void)AddExternalFunc(efunc,1);
104 }
105 return 0;
106 }
107
108 ExtBBoxInitFunc * GetInitFunc(struct ExternalFunc *efunc){
109 asc_assert(efunc!=NULL);
110 /* return (ExtBBoxInitFunc*)efunc->u.black.init; */
111 return efunc->u.black.initial;
112 }
113
114 ExtBBoxInitFunc * GetFinalFunc(struct ExternalFunc *efunc){
115 asc_assert(efunc!=NULL);
116 return efunc->u.black.final;
117 }
118
119 ExtBBoxFunc *GetValueFunc(struct ExternalFunc *efunc){
120 asc_assert(efunc!=NULL);
121 AssertMemory(efunc->etype);
122
123 /* CONSOLE_DEBUG("GETVALUEFUNC efunc = %p, type = %d",efunc,(int)efunc->etype); */
124 asc_assert(efunc->etype == efunc_BlackBox);
125 /* return (ExtBBoxFunc *)efunc->value; */
126 return efunc->u.black.value;
127 }
128
129
130 ExtBBoxFunc *GetDerivFunc(struct ExternalFunc *efunc)
131 {
132 asc_assert(efunc!=NULL);
133 asc_assert(efunc->etype == efunc_BlackBox);
134 return efunc->u.black.deriv;
135 }
136
137 ExtBBoxFunc *GetDeriv2Func(struct ExternalFunc *efunc)
138 {
139 asc_assert(efunc!=NULL);
140 asc_assert(efunc->etype == efunc_BlackBox);
141 return efunc->u.black.deriv2;
142 }
143
144 /*------------------------------------------------------------------------------
145 GLASS BOX STUFF
146 */
147
148 int CreateUserFunctionGlassBox(CONST char *name,
149 ExtEvalFunc *init,
150 ExtEvalFunc **value,
151 ExtEvalFunc **deriv,
152 ExtEvalFunc **deriv2,
153 ExtEvalFunc *final,
154 CONST unsigned long n_inputs,
155 CONST unsigned long n_outputs,
156 CONST char *help)
157 {
158 struct ExternalFunc *efunc;
159 int isNew = 0;
160 if (name == NULL) {
161 return 1;
162 }
163 efunc = LookupExtFunc(name);
164 if (efunc != NULL) { /* name was pre-loaded -- just update the info */
165 isNew = 0;
166 } else {
167 isNew = 1;
168 efunc = ASC_NEW(struct ExternalFunc);
169 asc_assert(efunc!=NULL);
170 efunc->help = NULL;
171 efunc->name = ascstrdup(SCP(AddSymbol(name)));
172 /* add or find name in symbol table */
173 /* the main symtab owns the string */
174 }
175
176 efunc->etype = efunc_GlassBox;
177 efunc->n_inputs = n_inputs;
178 efunc->n_outputs = n_outputs;
179 efunc->u.glass.initial = init;
180 efunc->u.glass.value = value;
181 efunc->u.glass.deriv = deriv;
182 efunc->u.glass.deriv2 = deriv2;
183 efunc->u.glass.final = final;
184 if (help) {
185 if (efunc->help) ascfree((char *)efunc->help);
186 efunc->help = ascstrdup(help);
187 } else {
188 efunc->help = NULL;
189 }
190
191 if (isNew) {
192 (void)AddExternalFunc(efunc,1);
193 }
194 return 0;
195 }
196
197
198 /*
199 * GlassBox relations in particular register not just
200 * a single function but rather a pointer to a jump table
201 * of functions. There will be a jump table ptr for each
202 * of value, deriv, deriv2.
203 */
204
205 /*
206 * The following means:
207 * GetValue is a function that returning pointer to array[] of
208 * pointer to functions, which take args and return an int.
209 *
210 * int (*(*GetValueJumpTable(struct ExternalFunc *efunc))[])(args)
211 */
212
213 ExtEvalFunc **GetValueJumpTable(struct ExternalFunc *efunc)
214 {
215 asc_assert(efunc!=NULL);
216 asc_assert(efunc->etype == efunc_GlassBox);
217 return efunc->u.glass.value;
218 }
219
220 ExtEvalFunc **GetDerivJumpTable(struct ExternalFunc *efunc)
221 {
222 asc_assert(efunc!=NULL);
223 asc_assert(efunc->etype == efunc_GlassBox);
224 return efunc->u.glass.deriv;
225 }
226
227 ExtEvalFunc **GetDeriv2JumpTable(struct ExternalFunc *efunc)
228 {
229 asc_assert(efunc!=NULL);
230 asc_assert(efunc->etype == efunc_GlassBox);
231 return efunc->u.glass.deriv2;
232 }
233
234 /*------------------------------------------------------------------------------
235 EXTERNAL METHOD STUFF
236 */
237
238 int CreateUserFunctionMethod(CONST char *name,
239 /* ExtMethodInit *init, */
240 ExtMethodRun *run,
241 /* ExtMethodInitEvalFunc *final, */
242 CONST long n_args,
243 /* CONST unsigned long n_outputs, */
244 CONST char *help)
245 {
246 struct ExternalFunc *efunc;
247 int isNew = 1;
248 if (name == NULL) {
249 return 1;
250 }
251 efunc = LookupExtFunc(name);
252 if (efunc != NULL) {
253 isNew = 0;
254 /* name was pre-loaded -- just update the info. This may cause user
255 insanity if it wasn't a reload of the same thing. */
256 } else {
257 isNew = 1;
258 efunc = ASC_NEW(struct ExternalFunc);
259 asc_assert(efunc!=NULL);
260 efunc->help = NULL;
261 efunc->name = ascstrdup(SCP(AddSymbol(name)));
262 /* add or find name in symbol table, and copy because */
263 /* the main symtab owns the string */
264 }
265 efunc->etype = efunc_Method;
266 efunc->n_inputs = n_args;
267 efunc->n_outputs = 0;
268 efunc->u.method.run = run;
269 #if 0
270 efunc->u.method.initial = init;
271 efunc->u.method.final = final;
272 #endif
273 if (help) {
274 if (efunc->help) { ascfree((char *)efunc->help); }
275 efunc->help = ascstrdup(help);
276 } else {
277 efunc->help = NULL;
278 }
279
280 if (isNew ) {
281 (void)AddExternalFunc(efunc,1);
282 }
283 return 0;
284 }
285
286
287
288 ExtMethodRun *GetExtMethodRun(struct ExternalFunc *efunc)
289 {
290 asc_assert(efunc!=NULL);
291 asc_assert(efunc->etype == efunc_Method);
292 return efunc->u.method.run;
293 }
294
295 /*------------------------------------------------------------------------------
296 REGISTRATION AND LOOKUP FUNCTIONS
297 */
298
299 void DestroyExternalFunc(struct ExternalFunc *efunc){
300 struct ExternalFunc *tmp;
301 if(efunc){
302 /* CONSOLE_DEBUG("DESTROYING EFUNC at %p",efunc); */
303 tmp = efunc;
304 if (tmp->name ) ascfree((char *)(tmp->name)); /* we own the string */
305 if (tmp->help) ascfree((char *)(tmp->help)); /* we own the string */
306 tmp->name = NULL;
307 tmp->help = NULL;
308 /* might want to set null pointers here depending on etype. */
309 tmp->etype = efunc_ERR;
310 ascfree((char *)tmp);
311 }
312 }
313
314 CONST char *ExternalFuncName(CONST struct ExternalFunc *efunc)
315 {
316 asc_assert(efunc!=NULL);
317 return efunc->name;
318 }
319
320 unsigned long NumberInputArgs(CONST struct ExternalFunc *efunc)
321 {
322 asc_assert(efunc!=NULL);
323 return efunc->n_inputs;
324 }
325
326 unsigned long NumberOutputArgs(CONST struct ExternalFunc *efunc)
327 {
328 asc_assert(efunc!=NULL);
329 return efunc->n_outputs;
330 }
331
332 /*------------------------------------------------------------------------------
333 EXTERNALFUNCLIBRARY TABLE-MANAGEMENT ROUTINES
334 */
335
336 void InitExternalFuncLibrary(void)
337 {
338 struct Table *result;
339 result = CreateTable(EXTFUNCHASHSIZE); /* this isn't destroyed at end. fix.*/
340 ExternalFuncLibrary = result;
341 }
342
343
344 int AddExternalFunc(struct ExternalFunc *efunc, int force){
345 struct ExternalFunc *found, *tmp;
346 char *name;
347
348 /* CONSOLE_DEBUG("efunc = %p",efunc); */
349 asc_assert(efunc!=NULL);
350
351 name = (char *)efunc->name;
352 found = (struct ExternalFunc *)LookupTableData(ExternalFuncLibrary,name);
353 if(found){
354 /* function with this name already exists in the ExternalFuncLibrary */
355 if(!force){
356 CONSOLE_DEBUG("EFUNC found OK, not adding");
357 return 0;
358 }
359
360 /* force!=0, so we're requested to update the entry in the table */
361 CONSOLE_DEBUG("EFUNC found OK, update forced");
362 tmp = (struct ExternalFunc *)RemoveTableData(ExternalFuncLibrary,name);
363 DestroyExternalFunc(tmp);
364 AddTableData(ExternalFuncLibrary,(void *)efunc,name);
365 return 1;
366 }else{
367 /* need to add function to library */
368 CONSOLE_DEBUG("Adding external function '%s' (at %p).",name,efunc);
369 AddTableData(ExternalFuncLibrary,(void *)efunc,name);
370 return 1;
371 }
372 }
373
374
375 struct ExternalFunc *LookupExtFunc(CONST char *funcname)
376 {
377 struct ExternalFunc *found;
378 if (!funcname) {
379 return NULL;
380 }
381 found = (struct ExternalFunc *)LookupTableData(ExternalFuncLibrary,funcname);
382 if (found) {
383 /* CONSOLE_DEBUG("Found '%s' in ExternalFuncLibrary at %p",funcname,found); */
384 return found;
385 } else {
386 return NULL; /* name not found */
387 }
388 }
389
390 struct ExternalFunc *RemoveExternalFunc(char *funcname)
391 {
392 struct ExternalFunc *found;
393 if (!funcname)
394 return NULL;
395 found = (struct ExternalFunc *)
396 RemoveTableData(ExternalFuncLibrary,funcname);
397 return found;
398 }
399
400
401 static
402 void ExternalFuncDestroyFunc(void *efunc)
403 {
404 struct ExternalFunc *local;
405 local = (struct ExternalFunc *)efunc;
406 if (local)
407 DestroyExternalFunc(local);
408 }
409
410 void DestroyExtFuncLibrary(void)
411 {
412 TableApplyAll(ExternalFuncLibrary,
413 (TableIteratorOne)ExternalFuncDestroyFunc);
414 DestroyTable(ExternalFuncLibrary,0);
415 ExternalFuncLibrary = NULL;
416 }
417
418 static
419 void PrintExtFuncLibraryFunc(void *efunc, void *fp)
420 {
421 struct ExternalFunc *local_efunc = (struct ExternalFunc *)efunc;
422
423 if (local_efunc!=NULL) {
424 FPRINTF(fp,"%s\n",ExternalFuncName(local_efunc));
425 if (local_efunc->help) {
426 FPRINTF(fp,"%s\n",local_efunc->help);
427 } else {
428 FPRINTF(fp,"No help information available for this function\n");
429 }
430 }
431 }
432
433 void PrintExtFuncLibrary(FILE *fp)
434 {
435 if (!fp) {
436 FPRINTF(ASCERR,"Invalid file handle in PrintExtFuncLibrary\n");
437 return;
438 }
439 TableApplyAllTwo(ExternalFuncLibrary, PrintExtFuncLibraryFunc,
440 (void *)fp);
441 }
442
443 static
444 void WriteExtFuncString(struct ExternalFunc *efunc, Asc_DString *dsPtr)
445 {
446 if (efunc!=NULL) {
447 Asc_DStringAppend(dsPtr,"{{",2);
448 Asc_DStringAppend(dsPtr,ExternalFuncName(efunc),-1);
449 Asc_DStringAppend(dsPtr,"} {",3);
450 if (efunc->help!=NULL) {
451 Asc_DStringAppend(dsPtr,efunc->help,-1);
452 } else {
453 Asc_DStringAppend(dsPtr,"No help available.",18);
454 }
455 Asc_DStringAppend(dsPtr,"}} ",3);
456 }
457 }
458
459 char *WriteExtFuncLibraryString(void)
460 {
461 char *result;
462 Asc_DString ds, *dsPtr;
463 dsPtr = &ds;
464 Asc_DStringInit(dsPtr);
465 TableApplyAllTwo(ExternalFuncLibrary,(TableIteratorTwo)WriteExtFuncString,
466 (void *) dsPtr);
467 result = Asc_DStringResult(dsPtr);
468 return result;
469 }
470
471 void
472 TraverseExtFuncLibrary(void (*func)(void *,void *), void *secondparam){
473 TableApplyAllTwo(ExternalFuncLibrary, func, secondparam);
474 }

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