/[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 710 - (show annotations) (download) (as text)
Thu Jun 29 08:53:37 2006 UTC (16 years, 7 months ago) by johnpye
File MIME type: text/x-csrc
File size: 12493 byte(s)
Added my so-called 'quick fix' to external relation processing.
Still need to pursue corruption of efunc->etype pointer, for some
reason.
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 was pre-loaded -- just update the info */
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)"
101 ,efunc, name, n_inputs, n_outputs, (int)efunc->etype
102 );
103 (void)AddExternalFunc(efunc,1);
104 }
105 return 0;
106 }
107
108
109 ExtBBoxInitFunc * GetInitFunc(struct ExternalFunc *efunc)
110 {
111 asc_assert(efunc!=NULL);
112 /* return (ExtBBoxInitFunc*)efunc->u.black.init; */
113 return efunc->u.black.initial;
114 }
115
116 ExtBBoxInitFunc * GetFinalFunc(struct ExternalFunc *efunc)
117 {
118 asc_assert(efunc!=NULL);
119 return efunc->u.black.final;
120 }
121
122 ExtBBoxFunc *GetValueFunc(struct ExternalFunc *efunc)
123 {
124 asc_assert(efunc!=NULL);
125 AssertMemory(efunc->etype);
126
127 CONSOLE_DEBUG("GETVALUEFUNC efunc = %p, type = %d",efunc,(int)efunc->etype);
128 asc_assert(efunc->etype == efunc_BlackBox);
129 /* return (ExtBBoxFunc *)efunc->value; */
130 return efunc->u.black.value;
131 }
132
133
134 ExtBBoxFunc *GetDerivFunc(struct ExternalFunc *efunc)
135 {
136 asc_assert(efunc!=NULL);
137 asc_assert(efunc->etype == efunc_BlackBox);
138 return efunc->u.black.deriv;
139 }
140
141 ExtBBoxFunc *GetDeriv2Func(struct ExternalFunc *efunc)
142 {
143 asc_assert(efunc!=NULL);
144 asc_assert(efunc->etype == efunc_BlackBox);
145 return efunc->u.black.deriv2;
146 }
147
148 /*------------------------------------------------------------------------------
149 GLASS BOX STUFF
150 */
151
152 int CreateUserFunctionGlassBox(CONST char *name,
153 ExtEvalFunc *init,
154 ExtEvalFunc **value,
155 ExtEvalFunc **deriv,
156 ExtEvalFunc **deriv2,
157 ExtEvalFunc *final,
158 CONST unsigned long n_inputs,
159 CONST unsigned long n_outputs,
160 CONST char *help)
161 {
162 struct ExternalFunc *efunc;
163 int isNew = 0;
164 if (name == NULL) {
165 return 1;
166 }
167 efunc = LookupExtFunc(name);
168 if (efunc != NULL) { /* name was pre-loaded -- just update the info */
169 isNew = 0;
170 } else {
171 isNew = 1;
172 efunc = ASC_NEW(struct ExternalFunc);
173 asc_assert(efunc!=NULL);
174 efunc->help = NULL;
175 efunc->name = ascstrdup(SCP(AddSymbol(name)));
176 /* add or find name in symbol table */
177 /* the main symtab owns the string */
178 }
179
180 efunc->etype = efunc_GlassBox;
181 efunc->n_inputs = n_inputs;
182 efunc->n_outputs = n_outputs;
183 efunc->u.glass.initial = init;
184 efunc->u.glass.value = value;
185 efunc->u.glass.deriv = deriv;
186 efunc->u.glass.deriv2 = deriv2;
187 efunc->u.glass.final = final;
188 if (help) {
189 if (efunc->help) ascfree((char *)efunc->help);
190 efunc->help = ascstrdup(help);
191 } else {
192 efunc->help = NULL;
193 }
194
195 if (isNew) {
196 (void)AddExternalFunc(efunc,1);
197 }
198 return 0;
199 }
200
201
202 /*
203 * GlassBox relations in particular register not just
204 * a single function but rather a pointer to a jump table
205 * of functions. There will be a jump table ptr for each
206 * of value, deriv, deriv2.
207 */
208
209 /*
210 * The following means:
211 * GetValue is a function that returning pointer to array[] of
212 * pointer to functions, which take args and return an int.
213 *
214 * int (*(*GetValueJumpTable(struct ExternalFunc *efunc))[])(args)
215 */
216
217 ExtEvalFunc **GetValueJumpTable(struct ExternalFunc *efunc)
218 {
219 asc_assert(efunc!=NULL);
220 asc_assert(efunc->etype == efunc_GlassBox);
221 return efunc->u.glass.value;
222 }
223
224 ExtEvalFunc **GetDerivJumpTable(struct ExternalFunc *efunc)
225 {
226 asc_assert(efunc!=NULL);
227 asc_assert(efunc->etype == efunc_GlassBox);
228 return efunc->u.glass.deriv;
229 }
230
231 ExtEvalFunc **GetDeriv2JumpTable(struct ExternalFunc *efunc)
232 {
233 asc_assert(efunc!=NULL);
234 asc_assert(efunc->etype == efunc_GlassBox);
235 return efunc->u.glass.deriv2;
236 }
237
238 /*------------------------------------------------------------------------------
239 EXTERNAL METHOD STUFF
240 */
241
242 int CreateUserFunctionMethod(CONST char *name,
243 /* ExtMethodInit *init, */
244 ExtMethodRun *run,
245 /* ExtMethodInitEvalFunc *final, */
246 CONST long n_args,
247 /* CONST unsigned long n_outputs, */
248 CONST char *help)
249 {
250 struct ExternalFunc *efunc;
251 int isNew = 1;
252 if (name == NULL) {
253 return 1;
254 }
255 efunc = LookupExtFunc(name);
256 if (efunc != NULL) {
257 isNew = 0;
258 /* name was pre-loaded -- just update the info. This may cause user
259 insanity if it wasn't a reload of the same thing. */
260 } else {
261 isNew = 1;
262 efunc = ASC_NEW(struct ExternalFunc);
263 asc_assert(efunc!=NULL);
264 efunc->help = NULL;
265 efunc->name = ascstrdup(SCP(AddSymbol(name)));
266 /* add or find name in symbol table, and copy because */
267 /* the main symtab owns the string */
268 }
269 efunc->etype = efunc_Method;
270 efunc->n_inputs = n_args;
271 efunc->n_outputs = 0;
272 efunc->u.method.run = run;
273 #if 0
274 efunc->u.method.initial = init;
275 efunc->u.method.final = final;
276 #endif
277 if (help) {
278 if (efunc->help) { ascfree((char *)efunc->help); }
279 efunc->help = ascstrdup(help);
280 } else {
281 efunc->help = NULL;
282 }
283
284 if (isNew ) {
285 (void)AddExternalFunc(efunc,1);
286 }
287 return 0;
288 }
289
290
291
292 ExtMethodRun *GetExtMethodRun(struct ExternalFunc *efunc)
293 {
294 asc_assert(efunc!=NULL);
295 asc_assert(efunc->etype == efunc_Method);
296 return efunc->u.method.run;
297 }
298
299 /*------------------------------------------------------------------------------
300 REGISTRATION AND LOOKUP FUNCTIONS
301 */
302
303 void DestroyExternalFunc(struct ExternalFunc *efunc){
304 struct ExternalFunc *tmp;
305 if(efunc){
306 CONSOLE_DEBUG("DESTROYING EFUNC at %p",efunc);
307 tmp = efunc;
308 if (tmp->name ) ascfree((char *)(tmp->name)); /* we own the string */
309 if (tmp->help) ascfree((char *)(tmp->help)); /* we own the string */
310 tmp->name = NULL;
311 tmp->help = NULL;
312 /* might want to set null pointers here depending on etype. */
313 tmp->etype = efunc_ERR;
314 ascfree((char *)tmp);
315 }
316 }
317
318 CONST char *ExternalFuncName(CONST struct ExternalFunc *efunc)
319 {
320 asc_assert(efunc!=NULL);
321 return efunc->name;
322 }
323
324 unsigned long NumberInputArgs(CONST struct ExternalFunc *efunc)
325 {
326 asc_assert(efunc!=NULL);
327 return efunc->n_inputs;
328 }
329
330 unsigned long NumberOutputArgs(CONST struct ExternalFunc *efunc)
331 {
332 asc_assert(efunc!=NULL);
333 return efunc->n_outputs;
334 }
335
336 /*------------------------------------------------------------------------------
337 EXTERNALFUNCLIBRARY TABLE-MANAGEMENT ROUTINES
338 */
339
340 void InitExternalFuncLibrary(void)
341 {
342 struct Table *result;
343 result = CreateTable(EXTFUNCHASHSIZE); /* this isn't destroyed at end. fix.*/
344 ExternalFuncLibrary = result;
345 }
346
347
348 int AddExternalFunc(struct ExternalFunc *efunc, int force){
349 struct ExternalFunc *found, *tmp;
350 char *name;
351
352 CONSOLE_DEBUG("efunc = %p",efunc);
353 asc_assert(efunc!=NULL);
354
355 name = (char *)efunc->name;
356 found = (struct ExternalFunc *)LookupTableData(ExternalFuncLibrary,name);
357 if(found){
358 /* function with this name already exists in the ExternalFuncLibrary */
359 if(!force){
360 CONSOLE_DEBUG("EFUNC found OK, not adding");
361 return 0;
362 }
363
364 /* force!=0, so we're requested to update the entry in the table */
365 CONSOLE_DEBUG("EFUNC found OK, update forced");
366 tmp = (struct ExternalFunc *)RemoveTableData(ExternalFuncLibrary,name);
367 DestroyExternalFunc(tmp);
368 AddTableData(ExternalFuncLibrary,(void *)efunc,name);
369 return 1;
370 }else{
371 /* need to add function to library */
372 CONSOLE_DEBUG("EFUNC not found, adding pointer %p for efunc to table under name '%s'.",efunc,name);
373 AddTableData(ExternalFuncLibrary,(void *)efunc,name);
374 return 1;
375 }
376 }
377
378
379 struct ExternalFunc *LookupExtFunc(CONST char *funcname)
380 {
381 struct ExternalFunc *found;
382 if (!funcname) {
383 return NULL;
384 }
385 found = (struct ExternalFunc *)LookupTableData(ExternalFuncLibrary,funcname);
386 if (found) {
387 CONSOLE_DEBUG("Found '%s' in ExternalFuncLibrary at %p",funcname,found);
388 return found;
389 } else {
390 return NULL; /* name not found */
391 }
392 }
393
394 struct ExternalFunc *RemoveExternalFunc(char *funcname)
395 {
396 struct ExternalFunc *found;
397 if (!funcname)
398 return NULL;
399 found = (struct ExternalFunc *)
400 RemoveTableData(ExternalFuncLibrary,funcname);
401 return found;
402 }
403
404
405 static
406 void ExternalFuncDestroyFunc(void *efunc)
407 {
408 struct ExternalFunc *local;
409 local = (struct ExternalFunc *)efunc;
410 if (local)
411 DestroyExternalFunc(local);
412 }
413
414 void DestroyExtFuncLibrary(void)
415 {
416 TableApplyAll(ExternalFuncLibrary,
417 (TableIteratorOne)ExternalFuncDestroyFunc);
418 DestroyTable(ExternalFuncLibrary,0);
419 ExternalFuncLibrary = NULL;
420 }
421
422 static
423 void PrintExtFuncLibraryFunc(void *efunc, void *fp)
424 {
425 struct ExternalFunc *local_efunc = (struct ExternalFunc *)efunc;
426
427 if (local_efunc!=NULL) {
428 FPRINTF(fp,"%s\n",ExternalFuncName(local_efunc));
429 if (local_efunc->help) {
430 FPRINTF(fp,"%s\n",local_efunc->help);
431 } else {
432 FPRINTF(fp,"No help information available for this function\n");
433 }
434 }
435 }
436
437 void PrintExtFuncLibrary(FILE *fp)
438 {
439 if (!fp) {
440 FPRINTF(ASCERR,"Invalid file handle in PrintExtFuncLibrary\n");
441 return;
442 }
443 TableApplyAllTwo(ExternalFuncLibrary, PrintExtFuncLibraryFunc,
444 (void *)fp);
445 }
446
447 static
448 void WriteExtFuncString(struct ExternalFunc *efunc, Asc_DString *dsPtr)
449 {
450 if (efunc!=NULL) {
451 Asc_DStringAppend(dsPtr,"{{",2);
452 Asc_DStringAppend(dsPtr,ExternalFuncName(efunc),-1);
453 Asc_DStringAppend(dsPtr,"} {",3);
454 if (efunc->help!=NULL) {
455 Asc_DStringAppend(dsPtr,efunc->help,-1);
456 } else {
457 Asc_DStringAppend(dsPtr,"No help available.",18);
458 }
459 Asc_DStringAppend(dsPtr,"}} ",3);
460 }
461 }
462
463 char *WriteExtFuncLibraryString(void)
464 {
465 char *result;
466 Asc_DString ds, *dsPtr;
467 dsPtr = &ds;
468 Asc_DStringInit(dsPtr);
469 TableApplyAllTwo(ExternalFuncLibrary,(TableIteratorTwo)WriteExtFuncString,
470 (void *) dsPtr);
471 result = Asc_DStringResult(dsPtr);
472 return result;
473 }
474
475 void
476 TraverseExtFuncLibrary(void (*func)(void *,void *), void *secondparam){
477 TableApplyAllTwo(ExternalFuncLibrary, func, secondparam);
478 }

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