1 |
/* ASCEND modelling environment |
2 |
Copyright (C) 2006 Carnegie Mellon University |
3 |
Copyright (C) 1990, 1993, 1994 Thomas Guthrie Epperly, Kirk Andre Abbott |
4 |
|
5 |
This program is free software; you can redistribute it and/or modify |
6 |
it under the terms of the GNU General Public License as published by |
7 |
the Free Software Foundation; either version 2, or (at your option) |
8 |
any later version. |
9 |
|
10 |
This program is distributed in the hope that it will be useful, |
11 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 |
GNU General Public License for more details. |
14 |
|
15 |
You should have received a copy of the GNU General Public License |
16 |
along with this program; if not, write to the Free Software |
17 |
Foundation, Inc., 59 Temple Place - Suite 330, |
18 |
Boston, MA 02111-1307, USA. |
19 |
*//* |
20 |
by Kirk Andre Abbott |
21 |
Created: Jun 1, 1995. |
22 |
Last in CVS: $Revision: 1.9 $ $Date: 1998/02/24 21:44:42 $ $Author: ballan $ |
23 |
*/ |
24 |
|
25 |
#include <utilities/ascConfig.h> |
26 |
#include <utilities/ascMalloc.h> |
27 |
#include <utilities/error.h> |
28 |
#include "compiler.h" |
29 |
#include <general/list.h> |
30 |
#include "fractions.h" |
31 |
#include "dimen.h" |
32 |
#include "functype.h" |
33 |
#include "expr_types.h" |
34 |
#include "extinst.h" |
35 |
#include "mathinst.h" |
36 |
#include "extcall.h" |
37 |
|
38 |
struct ExtCallNode *CreateExtCall(struct ExternalFunc *efunc, |
39 |
struct gl_list_t *args, |
40 |
struct Instance *subject, |
41 |
struct Instance *data |
42 |
){ |
43 |
struct ExtCallNode *ext; |
44 |
struct Instance **hndl=NULL; |
45 |
unsigned long pos; |
46 |
int added=0; |
47 |
|
48 |
/* |
49 |
{ |
50 |
int i,j,m,n; |
51 |
struct gl_list_t *list1; |
52 |
struct Instance *inst; |
53 |
|
54 |
CONSOLE_DEBUG("..."); |
55 |
|
56 |
m = gl_length(args); |
57 |
for(i = 1; i <= m; ++i){ |
58 |
list1 = (struct gl_list_t *)gl_fetch(args,i); |
59 |
n = gl_length(list1); |
60 |
for(j=1;j<=n;++j){ |
61 |
char *tmp; |
62 |
inst = (struct Instance *)gl_fetch(list1,j); |
63 |
tmp = WriteInstanceNameString(inst, NULL); |
64 |
CONSOLE_DEBUG("list %d: argument[%d], type '%s', name '%s' at %p" |
65 |
, i, j, instance_typename(inst), tmp, inst |
66 |
); |
67 |
ASC_FREE(tmp); |
68 |
} |
69 |
} |
70 |
} |
71 |
*/ |
72 |
|
73 |
ext = ASC_NEW(struct ExtCallNode); |
74 |
/* CONSOLE_DEBUG("ASSIGNING efunc = %p TO ExtCallNode %p",efunc,ext); */ |
75 |
ext->efunc = efunc; |
76 |
ext->arglist = args; |
77 |
if(data){ |
78 |
hndl = AddVarToTable(data,&added); /** FIX FIX FIX **/ |
79 |
} |
80 |
ext->data = hndl; |
81 |
|
82 |
if(subject){ |
83 |
/* CONSOLE_DEBUG("subject at %p",subject); */ |
84 |
pos = GetSubjectIndex(args,subject); |
85 |
ext->subject = pos; |
86 |
/* CONSOLE_DEBUG("subject index is %d",pos); */ |
87 |
}else{ |
88 |
ext->subject = 0L; |
89 |
} |
90 |
|
91 |
ext->nodestamp = -1; |
92 |
return ext; |
93 |
} |
94 |
|
95 |
void DestroyExtCall(struct ExtCallNode *ext, struct Instance *relinst){ |
96 |
struct Instance *ptr; |
97 |
unsigned long len1, c1; |
98 |
unsigned long len2, c2; |
99 |
struct gl_list_t *arglist, *branch; |
100 |
|
101 |
if (!ext) return; |
102 |
arglist = ext->arglist; |
103 |
if (arglist) { |
104 |
len1 = gl_length(arglist); |
105 |
for (c1=1;c1<=len1;c1++) { |
106 |
branch = (struct gl_list_t *)gl_fetch(arglist,c1); |
107 |
len2 = gl_length(branch); |
108 |
for (c2=len2;c2>=1;c2--) { |
109 |
if ( (ptr = (struct Instance *)gl_fetch(branch,c2)) !=NULL) |
110 |
RemoveRelation(ptr,relinst); |
111 |
} |
112 |
gl_destroy(branch); |
113 |
} |
114 |
gl_destroy(arglist); |
115 |
arglist = NULL; |
116 |
} |
117 |
} |
118 |
|
119 |
struct Instance *GetSubjectInstance(struct gl_list_t *arglist, |
120 |
unsigned long varndx |
121 |
){ |
122 |
struct Instance *arg; |
123 |
struct gl_list_t *branch; |
124 |
unsigned long len1,c=1L,len2,count=0L; |
125 |
long safetycheck; |
126 |
|
127 |
if (arglist&&varndx) { |
128 |
len1 = gl_length(arglist); |
129 |
while(c<=len1){ |
130 |
branch = (struct gl_list_t *)gl_fetch(arglist,c); |
131 |
if (!branch) return NULL; |
132 |
len2 = gl_length(branch); |
133 |
count += len2; |
134 |
if (count>=varndx){ |
135 |
safetycheck = len2-count+varndx; |
136 |
if (safetycheck<=0){ |
137 |
ERROR_REPORTER_HERE(ASC_PROG_ERR,"Something really wrong"); |
138 |
return NULL; |
139 |
} |
140 |
arg = (struct Instance *)gl_fetch(branch,(unsigned long)safetycheck); |
141 |
return arg; |
142 |
} |
143 |
c++; |
144 |
} |
145 |
} |
146 |
return NULL; |
147 |
} |
148 |
|
149 |
unsigned long GetSubjectIndex(struct gl_list_t *arglist, struct Instance *subject){ |
150 |
unsigned long len1,c1,len2,c2; |
151 |
struct gl_list_t *branch; |
152 |
struct Instance *arg; |
153 |
unsigned long count=0L; |
154 |
|
155 |
if(arglist&&subject){ |
156 |
len1 = gl_length(arglist); |
157 |
for(c1=1;c1<=len1;c1++){ |
158 |
branch = (struct gl_list_t *)gl_fetch(arglist,c1); |
159 |
if(branch==NULL){ |
160 |
ERROR_REPORTER_HERE(ASC_PROG_ERR,"Found null branch"); |
161 |
return 0L; /* error */ |
162 |
} |
163 |
len2 = gl_length(branch); |
164 |
for(c2=1;c2<=len2;c2++){ |
165 |
count++; |
166 |
arg = (struct Instance *)gl_fetch(branch,c2); |
167 |
if (arg==subject){ |
168 |
/* CONSOLE_DEBUG("Subject index %lu",count);*/ |
169 |
return count; |
170 |
} |
171 |
} |
172 |
} |
173 |
ERROR_REPORTER_HERE(ASC_PROG_ERR,"Reached impossible place"); |
174 |
return 0L; /*NOTREACHED*/ |
175 |
} |
176 |
CONSOLE_DEBUG("No subject index found"); |
177 |
return 0L; |
178 |
} |
179 |
|
180 |
unsigned long CountNumberOfArgs(struct gl_list_t *arglist, |
181 |
unsigned long start, unsigned long end |
182 |
){ |
183 |
unsigned long c,count=0L; |
184 |
struct gl_list_t *branch; |
185 |
|
186 |
if(arglist){ |
187 |
assert(start<=end); |
188 |
for (c=start;c<=end;c++){ |
189 |
branch = (struct gl_list_t *)gl_fetch(arglist,c); |
190 |
if(branch==NULL){ |
191 |
ERROR_REPORTER_HERE(ASC_PROG_ERR,"Found null branch"); |
192 |
return 0L; /*error*/ |
193 |
} |
194 |
count += gl_length(branch); |
195 |
} |
196 |
return count; |
197 |
} |
198 |
return 0L; |
199 |
} |
200 |
|
201 |
struct gl_list_t *LinearizeArgList(struct gl_list_t *arglist, |
202 |
unsigned long start, unsigned long end |
203 |
){ |
204 |
struct gl_list_t *result,*branch; |
205 |
struct Instance *arg; |
206 |
unsigned long c1,len2,c2; |
207 |
|
208 |
if (arglist){ |
209 |
assert(start<=end); |
210 |
result = gl_create(20L); |
211 |
for(c1=start;c1<=end;c1++){ |
212 |
branch = (struct gl_list_t *)gl_fetch(arglist,c1); |
213 |
if (!branch){ |
214 |
gl_destroy(result); |
215 |
return NULL; |
216 |
} |
217 |
len2 = gl_length(branch); |
218 |
for(c2=1;c2<=len2;c2++){ |
219 |
arg = (struct Instance *)gl_fetch(branch,c2); |
220 |
gl_append_ptr(result,(VOIDPTR)arg); |
221 |
} |
222 |
} |
223 |
return result; |
224 |
} |
225 |
return NULL; |
226 |
} |
227 |
|
228 |
void DestroySpecialList(struct gl_list_t *list) |
229 |
{ |
230 |
unsigned long len,c; |
231 |
struct gl_list_t *branch,*tmp; |
232 |
if (list) { |
233 |
tmp = list; |
234 |
len = gl_length(tmp); |
235 |
for (c=1;c<=len;c++) { |
236 |
branch = (struct gl_list_t *)gl_fetch(tmp,c); |
237 |
if (branch != NULL) { |
238 |
gl_destroy(branch); |
239 |
} |
240 |
} |
241 |
gl_destroy(tmp); |
242 |
list = NULL; |
243 |
} |
244 |
} |
245 |
|
246 |
struct gl_list_t *CopySpecialList(struct gl_list_t *list){ |
247 |
unsigned long len1,c1,len2,c2; |
248 |
struct gl_list_t *result,*branch,*tmp; |
249 |
struct Instance *arg; |
250 |
if (list) { |
251 |
len1 = gl_length(list); |
252 |
result = gl_create(len1); |
253 |
for(c1=1;c1<=len1;c1++) { |
254 |
tmp = (struct gl_list_t *)gl_fetch(list,c1); |
255 |
if (tmp) { |
256 |
len2 = gl_length(tmp); |
257 |
branch = gl_create(len2); |
258 |
for (c2=1;c2<=len2;c2++) { |
259 |
arg = (struct Instance *)gl_fetch(tmp,c2); |
260 |
gl_append_ptr(branch,(VOIDPTR)arg); |
261 |
} |
262 |
} |
263 |
else{ |
264 |
DestroySpecialList(result); |
265 |
return NULL; |
266 |
} |
267 |
gl_append_ptr(result,(VOIDPTR)branch); |
268 |
} |
269 |
return result; |
270 |
} |
271 |
return NULL; |
272 |
} |
273 |
|
274 |
struct ExternalFunc *ExternalCallExtFuncF(struct ExtCallNode *ext){ |
275 |
return ext->efunc; |
276 |
} |
277 |
|
278 |
struct gl_list_t *ExternalCallArgListF(struct ExtCallNode *ext){ |
279 |
return ext->arglist; |
280 |
} |
281 |
|
282 |
struct Instance *ExternalCallDataInstance(struct ExtCallNode *ext){ |
283 |
struct Instance **hndl; |
284 |
hndl = ext->data; |
285 |
if(hndl!=NULL){ |
286 |
/* |
287 |
ExtCallNode::data is an array of pointers to Instance |
288 |
structures. We are here returning the first pointer from that array. |
289 |
*/ |
290 |
return *hndl; |
291 |
}else{ |
292 |
return NULL; |
293 |
} |
294 |
} |
295 |
|
296 |
int ExternalCallNodeStampF(struct ExtCallNode *ext){ |
297 |
return ext->nodestamp; |
298 |
} |
299 |
|
300 |
void SetExternalCallNodeStamp(struct ExtCallNode *ext, int nodestamp){ |
301 |
if (ext->nodestamp==-1) { |
302 |
ext->nodestamp = nodestamp; |
303 |
} |
304 |
} |
305 |
|
306 |
unsigned long ExternalCallVarIndexF(struct ExtCallNode *ext){ |
307 |
return ext->subject; |
308 |
} |
309 |
|
310 |
struct Instance *ExternalCallVarInstance(struct ExtCallNode *ext){ |
311 |
struct Instance *i; |
312 |
assert(ext->subject); |
313 |
i = GetSubjectInstance(ext->arglist,ext->subject); |
314 |
assert(i!=NULL); |
315 |
return i; |
316 |
} |
317 |
|