/[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 708 - (show annotations) (download) (as text)
Tue Jun 27 07:34:31 2006 UTC (17 years, 11 months ago) by johnpye
File MIME type: text/x-csrc
File size: 13522 byte(s)
Replaced some references to ascmalloc with ASC_NEW_ARRAY
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
40 /*------------------------------------------------------------------------------
41 forward decls and typedefs etc
42 */
43
44 #define EXTFUNCHASHSIZE 31
45
46 static struct Table *ExternalFuncLibrary = NULL;
47
48 /*-----------------------------------------------------------------------------
49 BLACK BOX STUFF
50 */
51
52 int CreateUserFunctionBlackBox(CONST char *name,
53 ExtBBoxInitFunc *init,
54 ExtBBoxFunc *value,
55 ExtBBoxFunc *deriv,
56 ExtBBoxFunc *deriv2,
57 ExtBBoxInitFunc *final,
58 CONST unsigned long n_inputs,
59 CONST unsigned long n_outputs,
60 CONST char *help)
61 {
62 struct ExternalFunc *efunc;
63 int isNew = 0;
64 if (name == NULL) {
65 return 1;
66 }
67 efunc = LookupExtFunc(name);
68 if (efunc != NULL) { /* name was pre-loaded -- just update the info */
69 isNew = 0;
70 } else {
71 isNew = 1;
72 efunc = ASC_NEW(struct ExternalFunc);
73 asc_assert(efunc!=NULL);
74 efunc->help = NULL;
75 efunc->name = ascstrdup(SCP(AddSymbol(name)));
76 /* add or find name in symbol table */
77 /* the main symtab owns the string */
78 }
79
80 efunc->etype = efunc_BlackBox;
81 efunc->n_inputs = n_inputs;
82 efunc->n_outputs = n_outputs;
83 efunc->u.black.initial = init;
84 efunc->u.black.value = value;
85 efunc->u.black.deriv = deriv;
86 efunc->u.black.deriv2 = deriv2;
87 efunc->u.black.final = final;
88 if (help) {
89 if (efunc->help) ascfree((char *)efunc->help);
90 efunc->help = ascstrdup(help);
91 } else {
92 efunc->help = NULL;
93 }
94
95 if (isNew) {
96 (void)AddExternalFunc(efunc,1);
97 }
98 return 0;
99 }
100
101 double blackbox_evaluate_residual(struct relation *r){
102 struct ExtCallNode *ext;
103 struct ExternalFunc *efunc;
104 int i,n;
105 char *tmp;
106 struct Instance *inst;
107 double *in;
108 double *out;
109
110 CONSOLE_DEBUG("...");
111
112 n = NumberVariables(r);
113
114 asc_assert(r!=NULL);
115 asc_assert(r->share!=NULL);
116 asc_assert(r->share->bbox.ext!=NULL);
117 ext = r->share->bbox.ext;
118 efunc = ext->efunc;
119 asc_assert(efunc!=NULL);
120 ERROR_REPORTER_HERE(ASC_PROG_NOTE,"ABOUT TO EVALUATE %s",efunc->name);
121
122 asc_assert(efunc->etype==efunc_BlackBox);
123
124 ExtBBoxFunc *valfnptr = efunc->u.black.value;
125 asc_assert(valfnptr!=NULL);
126
127 CONSOLE_DEBUG("vars=%d, inputs=%d, outputs=%d",n
128 ,NumberInputArgs(efunc)
129 ,NumberOutputArgs(efunc)
130 );
131
132 /* list all the variables associated with this black box */
133 for(i=1;i <= n; ++i){
134 inst = RelationVariable(r,i);
135 tmp = WriteInstanceNameString(inst, NULL);
136 if(i<=NumberInputArgs(efunc)){
137 CONSOLE_DEBUG("Input %d: '%s' (at %p)", i, tmp, inst);
138 }else{
139 CONSOLE_DEBUG("Output %d: '%s'", i-NumberInputArgs(efunc), tmp);
140 }
141 ASC_FREE(tmp);
142 }
143
144 /* allocate space for the evaluation inputs and outputs */
145 in = ASC_NEW_ARRAY(double,NumberInputArgs(efunc));
146 out = ASC_NEW_ARRAY_CLEAR(double,NumberOutputArgs(efunc));
147
148 /* pull the current input values and place them in our 'in' array */
149 for(i=0; i < NumberInputArgs(efunc); ++i){
150 inst = RelationVariable(r,i+1);
151 tmp = WriteInstanceNameString(inst,NULL);
152 if(!AtomAssigned(inst)){
153 CONSOLE_DEBUG("Var %d ('%s') has not been assigned yet!",i+1,tmp);
154 in[i]=-1;
155 }else{
156 in[i] = RealAtomValue(inst);
157 }
158 CONSOLE_DEBUG("Set var %d ('%s') to '%f'",i+1,tmp,in[i]);
159 ASC_FREE(tmp);
160 }
161
162 /* call the evaluation function */
163
164 /* push the current output values back into the instance hierarchy */
165
166 ERROR_REPORTER_HERE(ASC_PROG_WARNING,"Blackbox not implemented, returning -1");
167 return -1;
168 }
169
170
171 ExtBBoxInitFunc * GetInitFunc(struct ExternalFunc *efunc)
172 {
173 asc_assert(efunc!=NULL);
174 /* return (ExtBBoxInitFunc*)efunc->u.black.init; */
175 return efunc->u.black.initial;
176 }
177
178 ExtBBoxInitFunc * GetFinalFunc(struct ExternalFunc *efunc)
179 {
180 asc_assert(efunc!=NULL);
181 return efunc->u.black.final;
182 }
183
184 ExtBBoxFunc *GetValueFunc(struct ExternalFunc *efunc)
185 {
186 asc_assert(efunc!=NULL);
187 asc_assert(efunc->etype == efunc_BlackBox);
188 /* return (ExtBBoxFunc *)efunc->value; */
189 return efunc->u.black.value;
190 }
191
192
193 ExtBBoxFunc *GetDerivFunc(struct ExternalFunc *efunc)
194 {
195 asc_assert(efunc!=NULL);
196 asc_assert(efunc->etype == efunc_BlackBox);
197 return efunc->u.black.deriv;
198 }
199
200 ExtBBoxFunc *GetDeriv2Func(struct ExternalFunc *efunc)
201 {
202 asc_assert(efunc!=NULL);
203 asc_assert(efunc->etype == efunc_BlackBox);
204 return efunc->u.black.deriv2;
205 }
206
207 /*------------------------------------------------------------------------------
208 GLASS BOX STUFF
209 */
210
211 int CreateUserFunctionGlassBox(CONST char *name,
212 ExtEvalFunc *init,
213 ExtEvalFunc **value,
214 ExtEvalFunc **deriv,
215 ExtEvalFunc **deriv2,
216 ExtEvalFunc *final,
217 CONST unsigned long n_inputs,
218 CONST unsigned long n_outputs,
219 CONST char *help)
220 {
221 struct ExternalFunc *efunc;
222 int isNew = 0;
223 if (name == NULL) {
224 return 1;
225 }
226 efunc = LookupExtFunc(name);
227 if (efunc != NULL) { /* name was pre-loaded -- just update the info */
228 isNew = 0;
229 } else {
230 isNew = 1;
231 efunc = ASC_NEW(struct ExternalFunc);
232 asc_assert(efunc!=NULL);
233 efunc->help = NULL;
234 efunc->name = ascstrdup(SCP(AddSymbol(name)));
235 /* add or find name in symbol table */
236 /* the main symtab owns the string */
237 }
238
239 efunc->etype = efunc_GlassBox;
240 efunc->n_inputs = n_inputs;
241 efunc->n_outputs = n_outputs;
242 efunc->u.glass.initial = init;
243 efunc->u.glass.value = value;
244 efunc->u.glass.deriv = deriv;
245 efunc->u.glass.deriv2 = deriv2;
246 efunc->u.glass.final = final;
247 if (help) {
248 if (efunc->help) ascfree((char *)efunc->help);
249 efunc->help = ascstrdup(help);
250 } else {
251 efunc->help = NULL;
252 }
253
254 if (isNew) {
255 (void)AddExternalFunc(efunc,1);
256 }
257 return 0;
258 }
259
260
261 /*
262 * GlassBox relations in particular register not just
263 * a single function but rather a pointer to a jump table
264 * of functions. There will be a jump table ptr for each
265 * of value, deriv, deriv2.
266 */
267
268 /*
269 * The following means:
270 * GetValue is a function that returning pointer to array[] of
271 * pointer to functions, which take args and return an int.
272 *
273 * int (*(*GetValueJumpTable(struct ExternalFunc *efunc))[])(args)
274 */
275
276 ExtEvalFunc **GetValueJumpTable(struct ExternalFunc *efunc)
277 {
278 asc_assert(efunc!=NULL);
279 asc_assert(efunc->etype == efunc_GlassBox);
280 return efunc->u.glass.value;
281 }
282
283 ExtEvalFunc **GetDerivJumpTable(struct ExternalFunc *efunc)
284 {
285 asc_assert(efunc!=NULL);
286 asc_assert(efunc->etype == efunc_GlassBox);
287 return efunc->u.glass.deriv;
288 }
289
290 ExtEvalFunc **GetDeriv2JumpTable(struct ExternalFunc *efunc)
291 {
292 asc_assert(efunc!=NULL);
293 asc_assert(efunc->etype == efunc_GlassBox);
294 return efunc->u.glass.deriv2;
295 }
296
297 /*------------------------------------------------------------------------------
298 EXTERNAL METHOD STUFF
299 */
300
301 int CreateUserFunctionMethod(CONST char *name,
302 /* ExtMethodInit *init, */
303 ExtMethodRun *run,
304 /* ExtMethodInitEvalFunc *final, */
305 CONST long n_args,
306 /* CONST unsigned long n_outputs, */
307 CONST char *help)
308 {
309 struct ExternalFunc *efunc;
310 int isNew = 1;
311 if (name == NULL) {
312 return 1;
313 }
314 efunc = LookupExtFunc(name);
315 if (efunc != NULL) {
316 isNew = 0;
317 /* name was pre-loaded -- just update the info. This may cause user
318 insanity if it wasn't a reload of the same thing. */
319 } else {
320 isNew = 1;
321 efunc = ASC_NEW(struct ExternalFunc);
322 asc_assert(efunc!=NULL);
323 efunc->help = NULL;
324 efunc->name = ascstrdup(SCP(AddSymbol(name)));
325 /* add or find name in symbol table, and copy because */
326 /* the main symtab owns the string */
327 }
328 efunc->etype = efunc_Method;
329 efunc->n_inputs = n_args;
330 efunc->n_outputs = 0;
331 efunc->u.method.run = run;
332 #if 0
333 efunc->u.method.initial = init;
334 efunc->u.method.final = final;
335 #endif
336 if (help) {
337 if (efunc->help) { ascfree((char *)efunc->help); }
338 efunc->help = ascstrdup(help);
339 } else {
340 efunc->help = NULL;
341 }
342
343 if (isNew ) {
344 (void)AddExternalFunc(efunc,1);
345 }
346 return 0;
347 }
348
349
350
351 ExtMethodRun *GetExtMethodRun(struct ExternalFunc *efunc)
352 {
353 asc_assert(efunc!=NULL);
354 asc_assert(efunc->etype == efunc_Method);
355 return efunc->u.method.run;
356 }
357
358 /*------------------------------------------------------------------------------
359 REGISTRATION AND LOOKUP FUNCTIONS
360 */
361
362 void DestroyExternalFunc(struct ExternalFunc *efunc)
363 {
364 struct ExternalFunc *tmp;
365 if (efunc) {
366 tmp = efunc;
367 if (tmp->name ) ascfree((char *)(tmp->name)); /* we own the string */
368 if (tmp->help) ascfree((char *)(tmp->help)); /* we own the string */
369 tmp->name = NULL;
370 tmp->help = NULL;
371 /* might want to set null pointers here depending on etype. */
372 tmp->etype = efunc_ERR;
373 ascfree((char *)tmp);
374 }
375 }
376
377 CONST char *ExternalFuncName(CONST struct ExternalFunc *efunc)
378 {
379 asc_assert(efunc!=NULL);
380 return efunc->name;
381 }
382
383 unsigned long NumberInputArgs(CONST struct ExternalFunc *efunc)
384 {
385 asc_assert(efunc!=NULL);
386 return efunc->n_inputs;
387 }
388
389 unsigned long NumberOutputArgs(CONST struct ExternalFunc *efunc)
390 {
391 asc_assert(efunc!=NULL);
392 return efunc->n_outputs;
393 }
394
395 /*
396 * These are the table management routines.
397 */
398
399 void InitExternalFuncLibrary(void)
400 {
401 struct Table *result;
402 result = CreateTable(EXTFUNCHASHSIZE); /* this isn't destroyed at end. fix.*/
403 ExternalFuncLibrary = result;
404 }
405
406 int AddExternalFunc(struct ExternalFunc *efunc, int force)
407 {
408
409 struct ExternalFunc *found, *tmp;
410 char *name;
411
412 asc_assert(efunc!=NULL);
413 name = (char *)efunc->name;
414 found = (struct ExternalFunc *)LookupTableData(ExternalFuncLibrary,name);
415 if (found) { /* function name already exists */
416 if (force==0) {
417 return 0;
418 } else { /* need to update information */
419 tmp = (struct ExternalFunc *)RemoveTableData(ExternalFuncLibrary,name);
420 DestroyExternalFunc(tmp);
421 AddTableData(ExternalFuncLibrary,(void *)efunc,name);
422 return 1;
423 }
424 }
425 else{ /* need to add function to library */
426 AddTableData(ExternalFuncLibrary,(void *)efunc,name);
427 return 1;
428 }
429 }
430
431 struct ExternalFunc *LookupExtFunc(CONST char *funcname)
432 {
433 struct ExternalFunc *found;
434 if (!funcname) {
435 return NULL;
436 }
437 found = (struct ExternalFunc *)
438 LookupTableData(ExternalFuncLibrary,funcname);
439 if (found) {
440 return found;
441 } else {
442 return NULL; /* name not found */
443 }
444 }
445
446 struct ExternalFunc *RemoveExternalFunc(char *funcname)
447 {
448 struct ExternalFunc *found;
449 if (!funcname)
450 return NULL;
451 found = (struct ExternalFunc *)
452 RemoveTableData(ExternalFuncLibrary,funcname);
453 return found;
454 }
455
456
457 static
458 void ExternalFuncDestroyFunc(void *efunc)
459 {
460 struct ExternalFunc *local;
461 local = (struct ExternalFunc *)efunc;
462 if (local)
463 DestroyExternalFunc(local);
464 }
465
466 void DestroyExtFuncLibrary(void)
467 {
468 TableApplyAll(ExternalFuncLibrary,
469 (TableIteratorOne)ExternalFuncDestroyFunc);
470 DestroyTable(ExternalFuncLibrary,0);
471 ExternalFuncLibrary = NULL;
472 }
473
474 static
475 void PrintExtFuncLibraryFunc(void *efunc, void *fp)
476 {
477 struct ExternalFunc *local_efunc = (struct ExternalFunc *)efunc;
478
479 if (local_efunc!=NULL) {
480 FPRINTF(fp,"%s\n",ExternalFuncName(local_efunc));
481 if (local_efunc->help) {
482 FPRINTF(fp,"%s\n",local_efunc->help);
483 } else {
484 FPRINTF(fp,"No help information available for this function\n");
485 }
486 }
487 }
488
489 void PrintExtFuncLibrary(FILE *fp)
490 {
491 if (!fp) {
492 FPRINTF(ASCERR,"Invalid file handle in PrintExtFuncLibrary\n");
493 return;
494 }
495 TableApplyAllTwo(ExternalFuncLibrary, PrintExtFuncLibraryFunc,
496 (void *)fp);
497 }
498
499 static
500 void WriteExtFuncString(struct ExternalFunc *efunc, Asc_DString *dsPtr)
501 {
502 if (efunc!=NULL) {
503 Asc_DStringAppend(dsPtr,"{{",2);
504 Asc_DStringAppend(dsPtr,ExternalFuncName(efunc),-1);
505 Asc_DStringAppend(dsPtr,"} {",3);
506 if (efunc->help!=NULL) {
507 Asc_DStringAppend(dsPtr,efunc->help,-1);
508 } else {
509 Asc_DStringAppend(dsPtr,"No help available.",18);
510 }
511 Asc_DStringAppend(dsPtr,"}} ",3);
512 }
513 }
514
515 char *WriteExtFuncLibraryString(void)
516 {
517 char *result;
518 Asc_DString ds, *dsPtr;
519 dsPtr = &ds;
520 Asc_DStringInit(dsPtr);
521 TableApplyAllTwo(ExternalFuncLibrary,(TableIteratorTwo)WriteExtFuncString,
522 (void *) dsPtr);
523 result = Asc_DStringResult(dsPtr);
524 return result;
525 }
526
527 void
528 TraverseExtFuncLibrary(void (*func)(void *,void *), void *secondparam){
529 TableApplyAllTwo(ExternalFuncLibrary, func, secondparam);
530 }

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