1 |
/* |
2 |
* Logical Relation Output Routines |
3 |
* by Vicente Rico-Ramirez |
4 |
* Version: $Revision: 1.13 $ |
5 |
* Version control file: $RCSfile: logrel_io.c,v $ |
6 |
* Date last modified: $Date: 1997/10/28 19:20:39 $ |
7 |
* Last modified by: $Author: mthomas $ |
8 |
* |
9 |
* This file is part of the Ascend Language Interpreter. |
10 |
* |
11 |
* The Ascend Language Interpreter is free software; you can redistribute |
12 |
* it and/or modify it under the terms of the GNU General Public License as |
13 |
* published by the Free Software Foundation; either version 2 of the |
14 |
* License, or (at your option) any later version. |
15 |
* |
16 |
* The Ascend Language Interpreter is distributed in hope that it will be |
17 |
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of |
18 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
19 |
* General Public License for more details. |
20 |
* |
21 |
* You should have received a copy of the GNU General Public License |
22 |
* along with the program; if not, write to the Free Software Foundation, |
23 |
* Inc., 675 Mass Ave, Cambridge, MA 02139 USA. Check the file named |
24 |
* COPYING. |
25 |
* |
26 |
*/ |
27 |
|
28 |
#include <stdarg.h> |
29 |
#include <ascend/general/platform.h> |
30 |
#include <ascend/general/ascMalloc.h> |
31 |
#include <ascend/general/panic.h> |
32 |
#include <ascend/general/list.h> |
33 |
#include <ascend/general/dstring.h> |
34 |
|
35 |
|
36 |
|
37 |
#include "functype.h" |
38 |
#include "expr_types.h" |
39 |
#include "find.h" |
40 |
#include "instance_enum.h" |
41 |
#include "instance_io.h" |
42 |
#include "logical_relation.h" |
43 |
#include "logrelation.h" |
44 |
#include "logrel_util.h" |
45 |
#include "logrel_io.h" |
46 |
#include "instquery.h" |
47 |
#include "parentchild.h" |
48 |
#include "mathinst.h" |
49 |
#include "visitinst.h" |
50 |
#include "tmpnum.h" |
51 |
|
52 |
|
53 |
static char g_log_shortbuf[256]; |
54 |
#define SBL255 g_log_shortbuf |
55 |
|
56 |
/* Logical Operators */ |
57 |
static |
58 |
void WriteLogOp(FILE *f, enum Expr_enum t) |
59 |
{ |
60 |
switch(t){ |
61 |
case e_and: FPRINTF(f,"AND"); break; |
62 |
case e_not: FPRINTF(f,"NOT"); break; |
63 |
case e_or: FPRINTF(f,"OR"); break; |
64 |
case e_boolean_eq: FPRINTF(f,"=="); break; |
65 |
case e_boolean_neq: FPRINTF(f,"!="); break; |
66 |
default: |
67 |
ASC_PANIC("Unknown term in WriteLogOp.\n");/*NOTREACHED*/ |
68 |
} |
69 |
} |
70 |
|
71 |
/* appends operators to dynamic symbol */ |
72 |
static void WriteLogOpDS(Asc_DString *dsPtr, enum Expr_enum t) |
73 |
{ |
74 |
assert(dsPtr!=NULL); |
75 |
switch(t){ |
76 |
case e_and: |
77 |
Asc_DStringAppend(dsPtr,"AND",3); |
78 |
break; |
79 |
case e_not: |
80 |
Asc_DStringAppend(dsPtr,"NOT",3); |
81 |
break; |
82 |
case e_or: |
83 |
Asc_DStringAppend(dsPtr,"OR",2); |
84 |
break; |
85 |
case e_boolean_eq: |
86 |
Asc_DStringAppend(dsPtr,"==",2); |
87 |
break; |
88 |
case e_boolean_neq: |
89 |
Asc_DStringAppend(dsPtr,"!=",2); |
90 |
break; |
91 |
default: |
92 |
FPRINTF(ASCERR,"Unknown term in WriteLogOpDS.\n"); |
93 |
Asc_DStringAppend(dsPtr,"ERROR",5); |
94 |
break; |
95 |
} |
96 |
} |
97 |
|
98 |
|
99 |
static |
100 |
void WriteLogTerm(FILE *f, |
101 |
CONST struct logrelation *lrel, |
102 |
CONST struct logrel_term *term, |
103 |
CONST struct Instance *inst) |
104 |
{ |
105 |
struct Instance *cur_var; |
106 |
struct Instance *rel; |
107 |
int bvalue; |
108 |
|
109 |
switch(LogRelTermType(term)){ |
110 |
case e_var: |
111 |
cur_var = LogRelBoolVar(lrel,LogTermBoolVarNumber(term)); |
112 |
WriteInstanceName(f,cur_var,inst); |
113 |
break; |
114 |
case e_satisfied: |
115 |
FPRINTF(f,"SATISFIED("); |
116 |
rel = LogRelRelation(lrel,LogTermSatRelNumber(term)); |
117 |
WriteInstanceName(f,rel,inst); |
118 |
if (LogTermSatTolerance(term) != DBL_MAX) { |
119 |
FPRINTF(f,","); |
120 |
FPRINTF(f,"%g",LogTermSatTolerance(term)); |
121 |
} |
122 |
FPRINTF(f,")"); |
123 |
break; |
124 |
case e_int: |
125 |
FPRINTF(f,"%d",LogTermInteger(term)); |
126 |
break; |
127 |
case e_boolean: |
128 |
bvalue = LogTermBoolean(term); |
129 |
if (bvalue){ |
130 |
FPRINTF(f,"TRUE"); |
131 |
} |
132 |
else { |
133 |
FPRINTF(f,"FALSE"); |
134 |
} |
135 |
break; |
136 |
case e_and: |
137 |
case e_or: |
138 |
WriteLogOp(f,LogRelTermType(term)); |
139 |
break; |
140 |
case e_not: FPRINTF(f,"NOT"); break; |
141 |
default: |
142 |
ASC_PANIC("Unknown term type in WriteLogTerm.\n");/*NOTREACHED*/ |
143 |
} |
144 |
} |
145 |
|
146 |
static |
147 |
void WriteLogTermDS(Asc_DString *dsPtr, |
148 |
CONST struct logrelation *lrel, |
149 |
CONST struct logrel_term *term, |
150 |
CONST struct Instance *inst) |
151 |
{ |
152 |
struct Instance *cur_var; |
153 |
struct Instance *rel; |
154 |
int bvalue; |
155 |
switch(LogRelTermType(term)){ |
156 |
case e_var: |
157 |
cur_var = LogRelBoolVar(lrel,LogTermBoolVarNumber(term)); |
158 |
WriteInstanceNameDS(dsPtr,cur_var,inst); |
159 |
break; |
160 |
case e_satisfied: |
161 |
Asc_DStringAppend(dsPtr,"SATISFIED(",10); |
162 |
rel = LogRelRelation(lrel,LogTermSatRelNumber(term)); |
163 |
WriteInstanceNameDS(dsPtr,rel,inst); |
164 |
if (LogTermSatTolerance(term) != DBL_MAX) { |
165 |
Asc_DStringAppend(dsPtr,",",1); |
166 |
sprintf(SBL255,"%g",LogTermSatTolerance(term)); |
167 |
Asc_DStringAppend(dsPtr,SBL255,-1); |
168 |
} |
169 |
Asc_DStringAppend(dsPtr,")",1); |
170 |
break; |
171 |
case e_int: |
172 |
sprintf(SBL255,"%d",LogTermInteger(term)); |
173 |
Asc_DStringAppend(dsPtr,SBL255,-1); |
174 |
break; |
175 |
case e_boolean: |
176 |
bvalue = LogTermBoolean(term); |
177 |
if (bvalue){ |
178 |
Asc_DStringAppend(dsPtr,"TRUE",4); |
179 |
} |
180 |
else { |
181 |
Asc_DStringAppend(dsPtr,"FALSE",5); |
182 |
} |
183 |
break; |
184 |
case e_and: |
185 |
case e_or: |
186 |
WriteLogOpDS(dsPtr,LogRelTermType(term)); |
187 |
break; |
188 |
case e_not: |
189 |
Asc_DStringAppend(dsPtr,"NOT",3); |
190 |
break; |
191 |
default: |
192 |
FPRINTF(ASCERR,"Unknown term in WriteLogTermDS.\n"); |
193 |
Asc_DStringAppend(dsPtr,"ERROR",5); |
194 |
break; |
195 |
} |
196 |
} |
197 |
|
198 |
static |
199 |
void WriteLogSidePostfix(FILE *f, |
200 |
CONST struct logrelation *lr, |
201 |
int side, |
202 |
CONST struct Instance *ref) |
203 |
{ |
204 |
unsigned c,len; |
205 |
CONST struct logrel_term *term; |
206 |
len = LogRelLength(lr,side); |
207 |
for(c=1;c<=len;c++){ |
208 |
term = LogRelTerm(lr,c,side); |
209 |
WriteLogTerm(f,lr,term,ref); |
210 |
if(c<len) PUTC(' ',f); |
211 |
} |
212 |
} |
213 |
|
214 |
static |
215 |
void WriteLogSidePostfixDS(Asc_DString *dsPtr, |
216 |
CONST struct logrelation *lr, |
217 |
int side, |
218 |
CONST struct Instance *ref) |
219 |
{ |
220 |
unsigned c,len; |
221 |
CONST struct logrel_term *term; |
222 |
len = LogRelLength(lr,side); |
223 |
for(c=1;c<=len;c++){ |
224 |
term = LogRelTerm(lr,c,side); |
225 |
WriteLogTermDS(dsPtr,lr,term,ref); |
226 |
if(c<len) Asc_DStringAppend(dsPtr," ",1); |
227 |
} |
228 |
} |
229 |
|
230 |
void WriteLogRelPostfix(FILE *f, |
231 |
CONST struct Instance *lrelinst, |
232 |
CONST struct Instance *ref) |
233 |
{ |
234 |
CONST struct logrelation *lr; |
235 |
|
236 |
lr = GetInstanceLogRel(lrelinst); |
237 |
switch(LogRelRelop(lr)){ |
238 |
case e_boolean_eq: |
239 |
case e_boolean_neq: |
240 |
WriteLogSidePostfix(f,lr,1,ref); |
241 |
PUTC(' ',f); |
242 |
WriteLogSidePostfix(f,lr,0,ref); |
243 |
PUTC(' ',f); |
244 |
WriteLogOp(f,LogRelRelop(lr)); |
245 |
break; |
246 |
default: |
247 |
FPRINTF(ASCERR,"Unexpected boolean Relop in WriteLogRelPostfix\n"); |
248 |
break; |
249 |
} |
250 |
} |
251 |
|
252 |
char *WriteLogRelPostfixToString( CONST struct Instance *lrelinst, |
253 |
CONST struct Instance *ref) |
254 |
{ |
255 |
CONST struct logrelation *lr; |
256 |
char *result; |
257 |
static Asc_DString ds; |
258 |
Asc_DString *dsPtr; |
259 |
|
260 |
lr = GetInstanceLogRel(lrelinst); |
261 |
dsPtr = &ds; |
262 |
Asc_DStringInit(dsPtr); |
263 |
|
264 |
switch(LogRelRelop(lr)){ |
265 |
case e_boolean_eq: |
266 |
case e_boolean_neq: |
267 |
WriteLogSidePostfixDS(dsPtr,lr,1,ref); |
268 |
Asc_DStringAppend(dsPtr," ",1); |
269 |
WriteLogSidePostfixDS(dsPtr,lr,0,ref); |
270 |
Asc_DStringAppend(dsPtr," ",1); |
271 |
WriteLogOpDS(dsPtr,LogRelRelop(lr)); |
272 |
break; |
273 |
default: |
274 |
FPRINTF(ASCERR,"Unexpected boolean Relop in WriteLogRelPostfixToString\n"); |
275 |
break; |
276 |
} |
277 |
result = Asc_DStringResult(dsPtr); |
278 |
Asc_DStringFree(dsPtr); |
279 |
return result; |
280 |
} |
281 |
|
282 |
struct logrel_stack { |
283 |
struct logrel_stack *next; |
284 |
unsigned long pos; |
285 |
int first; |
286 |
}; |
287 |
|
288 |
static struct logrel_stack *g_logrel_stack=NULL; |
289 |
|
290 |
static |
291 |
void ClearLogRelStack(void) |
292 |
{ |
293 |
struct logrel_stack *next; |
294 |
while(g_logrel_stack!=NULL){ |
295 |
next =g_logrel_stack->next; |
296 |
ascfree((char *)g_logrel_stack); |
297 |
g_logrel_stack = next; |
298 |
} |
299 |
} |
300 |
|
301 |
static |
302 |
void PushLogRel(unsigned long int pos, int first) |
303 |
{ |
304 |
struct logrel_stack *next; |
305 |
next = g_logrel_stack; |
306 |
g_logrel_stack = ASC_NEW(struct logrel_stack); |
307 |
g_logrel_stack->next = next; |
308 |
g_logrel_stack->pos = pos; |
309 |
g_logrel_stack->first = first; |
310 |
} |
311 |
|
312 |
static |
313 |
int LogRelNotEmptyStack(void) |
314 |
{ |
315 |
return g_logrel_stack!=NULL; |
316 |
} |
317 |
|
318 |
static |
319 |
int LogrelFirstTop(void) |
320 |
{ |
321 |
assert(g_logrel_stack!=NULL); |
322 |
return g_logrel_stack->first; |
323 |
} |
324 |
|
325 |
static |
326 |
unsigned long PopLogRel(void) |
327 |
{ |
328 |
struct logrel_stack *next; |
329 |
unsigned long result; |
330 |
assert(g_logrel_stack!=NULL); |
331 |
next = g_logrel_stack->next; |
332 |
result = g_logrel_stack->pos; |
333 |
ascfree((char *)g_logrel_stack); |
334 |
g_logrel_stack = next; |
335 |
return result; |
336 |
} |
337 |
|
338 |
static |
339 |
unsigned long LogRelLeftHandSide(CONST struct logrelation *lr, |
340 |
unsigned long int pos, |
341 |
int side) |
342 |
{ |
343 |
unsigned long depth=1; |
344 |
CONST struct logrel_term *term; |
345 |
pos--; |
346 |
while(depth){ |
347 |
term = LogRelTerm(lr,pos,side); |
348 |
switch(LogRelTermType(term)){ |
349 |
case e_int: |
350 |
case e_boolean: |
351 |
case e_satisfied: |
352 |
case e_var: |
353 |
depth--; |
354 |
break; |
355 |
case e_not: |
356 |
break; |
357 |
case e_and: |
358 |
case e_or: |
359 |
depth++; |
360 |
break; |
361 |
default: |
362 |
Asc_Panic(2, NULL, |
363 |
"Don't know this type of logical relation type.\n" |
364 |
"(%d) in function LogRelLeftHandSide\n", |
365 |
LogRelTermType(term)); |
366 |
} |
367 |
pos--; |
368 |
} |
369 |
return pos; |
370 |
} |
371 |
|
372 |
/* a little function to tell us about precedence */ |
373 |
static |
374 |
unsigned LogPriority(enum Expr_enum t) |
375 |
{ |
376 |
switch(t){ |
377 |
case e_var: |
378 |
case e_int: |
379 |
case e_satisfied: |
380 |
return 0; |
381 |
|
382 |
case e_and: |
383 |
return 1; |
384 |
|
385 |
case e_or: |
386 |
return 2; |
387 |
|
388 |
case e_not: |
389 |
return 3; |
390 |
|
391 |
default: |
392 |
return 0; /* 0=good idea? */ |
393 |
} |
394 |
/*NOTREACHED*/ |
395 |
} |
396 |
|
397 |
int LogExprNeedParentheses(enum Expr_enum parent_op, enum Expr_enum child_op, int rhs) |
398 |
{ |
399 |
unsigned parent_p,child_p; |
400 |
switch(child_op){ |
401 |
case e_var: |
402 |
case e_int: |
403 |
case e_boolean: |
404 |
case e_satisfied: |
405 |
return 0; |
406 |
default: |
407 |
parent_p = LogPriority(parent_op); |
408 |
child_p = LogPriority(child_op); |
409 |
if (parent_p > child_p) return 1; |
410 |
if (parent_p < child_p) return 0; |
411 |
if ((parent_op == e_not)&&rhs) return 1; |
412 |
return 0; |
413 |
} |
414 |
} |
415 |
|
416 |
static |
417 |
void WriteLogSide(FILE *f, |
418 |
CONST struct logrelation *lr, |
419 |
int side, |
420 |
CONST struct Instance *ref) |
421 |
{ |
422 |
unsigned long pos,lhs; |
423 |
int first; |
424 |
enum Expr_enum t; |
425 |
CONST struct logrel_term *term; |
426 |
struct Instance *cur_var; |
427 |
struct Instance *rel; |
428 |
int bvalue; |
429 |
ClearLogRelStack(); |
430 |
PushLogRel(LogRelLength(lr,side),1); |
431 |
while(LogRelNotEmptyStack()){ |
432 |
first = LogrelFirstTop(); /* check if this is the first visit */ |
433 |
pos = PopLogRel(); /* check the top */ |
434 |
term = LogRelTerm(lr,pos,side); |
435 |
switch(t = LogRelTermType(term)){ |
436 |
case e_var: |
437 |
cur_var = LogRelBoolVar(lr,LogTermBoolVarNumber(term)); |
438 |
WriteInstanceName(f,cur_var,ref); |
439 |
break; |
440 |
case e_int: |
441 |
FPRINTF(f,"%d",LogTermInteger(term)); |
442 |
break; |
443 |
case e_boolean: |
444 |
bvalue = LogTermBoolean(term); |
445 |
if (bvalue){ |
446 |
FPRINTF(f,"TRUE"); |
447 |
} |
448 |
else { |
449 |
FPRINTF(f,"FALSE"); |
450 |
} |
451 |
break; |
452 |
case e_satisfied: |
453 |
if(first) { |
454 |
FPRINTF(f,"SATISFIED("); |
455 |
rel = LogRelRelation(lr,LogTermSatRelNumber(term)); |
456 |
WriteInstanceName(f,rel,ref); |
457 |
if (LogTermSatTolerance(term) != DBL_MAX) { |
458 |
FPRINTF(f,","); |
459 |
FPRINTF(f,"%g",LogTermSatTolerance(term)); |
460 |
} |
461 |
FPRINTF(f,")"); |
462 |
} |
463 |
else{ |
464 |
PUTC(')',f); |
465 |
} |
466 |
break; |
467 |
case e_and: |
468 |
case e_or: |
469 |
switch(first){ |
470 |
case 1: |
471 |
PushLogRel(pos,2); |
472 |
lhs = LogRelLeftHandSide(lr,pos,side); |
473 |
term = LogRelTerm(lr,lhs,side); |
474 |
if (LogExprNeedParentheses(t,LogRelTermType(term),0)) |
475 |
PUTC('(',f); |
476 |
PushLogRel(lhs,1); |
477 |
break; |
478 |
case 2: |
479 |
term = LogRelTerm(lr,LogRelLeftHandSide(lr,pos,side),side); |
480 |
if (LogExprNeedParentheses(t,LogRelTermType(term),0)) |
481 |
PUTC(')',f); |
482 |
PUTC(' ',f); |
483 |
WriteLogOp(f,t); |
484 |
PUTC(' ',f); |
485 |
PushLogRel(pos,0); |
486 |
term = LogRelTerm(lr,pos-1,side); |
487 |
if (LogExprNeedParentheses(t,LogRelTermType(term),1)) |
488 |
PUTC('(',f); |
489 |
PushLogRel(pos-1,1); |
490 |
break; |
491 |
case 0: |
492 |
term = LogRelTerm(lr,pos-1,side); |
493 |
if (LogExprNeedParentheses(t,LogRelTermType(term),1)) |
494 |
PUTC(')',f); |
495 |
break; |
496 |
} |
497 |
break; |
498 |
case e_not: |
499 |
if (first){ |
500 |
FPRINTF(f,"NOT"); |
501 |
PushLogRel(pos,0); |
502 |
PUTC('(',f); |
503 |
PushLogRel(pos-1,1); |
504 |
} |
505 |
else{ |
506 |
PUTC(')',f); |
507 |
} |
508 |
break; |
509 |
default: |
510 |
Asc_Panic(2, NULL, |
511 |
"Don't know this type of logical relation type.\n" |
512 |
"function WriteLogSide\n");; |
513 |
} |
514 |
} |
515 |
} |
516 |
|
517 |
static |
518 |
void WriteLogSideDS(Asc_DString *dsPtr, CONST struct logrelation *lr, int side, |
519 |
CONST struct Instance *ref) |
520 |
{ |
521 |
unsigned long pos,lhs; |
522 |
int first; |
523 |
enum Expr_enum t; |
524 |
CONST struct logrel_term *term; |
525 |
struct Instance *cur_var; |
526 |
struct Instance *rel; |
527 |
int bvalue; |
528 |
ClearLogRelStack(); |
529 |
PushLogRel(LogRelLength(lr,side),1); |
530 |
while(LogRelNotEmptyStack()){ |
531 |
first = LogrelFirstTop(); /* check if this is the first visit */ |
532 |
pos = PopLogRel(); /* check the top */ |
533 |
term = LogRelTerm(lr,pos,side); |
534 |
switch(t = LogRelTermType(term)){ |
535 |
case e_var: |
536 |
cur_var = LogRelBoolVar(lr,LogTermBoolVarNumber(term)); |
537 |
WriteInstanceNameDS(dsPtr,cur_var,ref); |
538 |
break; |
539 |
case e_int: |
540 |
sprintf(SBL255,"%d",LogTermInteger(term)); |
541 |
Asc_DStringAppend(dsPtr,SBL255,-1); |
542 |
break; |
543 |
case e_boolean: |
544 |
bvalue = LogTermBoolean(term); |
545 |
if (bvalue){ |
546 |
Asc_DStringAppend(dsPtr,"TRUE",4); |
547 |
} |
548 |
else { |
549 |
Asc_DStringAppend(dsPtr,"FALSE",5); |
550 |
} |
551 |
break; |
552 |
case e_satisfied: |
553 |
if(first) { |
554 |
Asc_DStringAppend(dsPtr,"SATISFIED(",10); |
555 |
rel = LogRelRelation(lr,LogTermSatRelNumber(term)); |
556 |
WriteInstanceNameDS(dsPtr,rel,ref); |
557 |
if (LogTermSatTolerance(term) != DBL_MAX) { |
558 |
Asc_DStringAppend(dsPtr,",",1); |
559 |
sprintf(SBL255,"%g",LogTermSatTolerance(term)); |
560 |
Asc_DStringAppend(dsPtr,SBL255,-1); |
561 |
} |
562 |
Asc_DStringAppend(dsPtr,")",1); |
563 |
} |
564 |
else{ |
565 |
Asc_DStringAppend(dsPtr,")",1); |
566 |
} |
567 |
break; |
568 |
case e_and: |
569 |
case e_or: |
570 |
switch(first){ |
571 |
case 1: |
572 |
PushLogRel(pos,2); |
573 |
lhs = LogRelLeftHandSide(lr,pos,side); |
574 |
term = LogRelTerm(lr,lhs,side); |
575 |
if (LogExprNeedParentheses(t,LogRelTermType(term),0)) |
576 |
Asc_DStringAppend(dsPtr,"(",1); |
577 |
PushLogRel(lhs,1); |
578 |
break; |
579 |
case 2: |
580 |
term = LogRelTerm(lr,LogRelLeftHandSide(lr,pos,side),side); |
581 |
if (LogExprNeedParentheses(t,LogRelTermType(term),0)) { |
582 |
Asc_DStringAppend(dsPtr,")",1); |
583 |
} |
584 |
Asc_DStringAppend(dsPtr," ",1); |
585 |
WriteLogOpDS(dsPtr,t); |
586 |
Asc_DStringAppend(dsPtr," ",1); |
587 |
PushLogRel(pos,0); |
588 |
term = LogRelTerm(lr,pos-1,side); |
589 |
if (LogExprNeedParentheses(t,LogRelTermType(term),1)) { |
590 |
Asc_DStringAppend(dsPtr,"(",1); |
591 |
} |
592 |
PushLogRel(pos-1,1); |
593 |
break; |
594 |
case 0: |
595 |
term = LogRelTerm(lr,pos-1,side); |
596 |
if (LogExprNeedParentheses(t,LogRelTermType(term),1)) |
597 |
Asc_DStringAppend(dsPtr,")",1); |
598 |
break; |
599 |
} |
600 |
break; |
601 |
case e_not: |
602 |
if (first){ |
603 |
Asc_DStringAppend(dsPtr,"NOT",3); |
604 |
PushLogRel(pos,0); |
605 |
Asc_DStringAppend(dsPtr,"(",1); |
606 |
PushLogRel(pos-1,1); |
607 |
} |
608 |
else{ |
609 |
Asc_DStringAppend(dsPtr,")",1); |
610 |
} |
611 |
break; |
612 |
default: |
613 |
Asc_Panic(2, NULL, |
614 |
"Don't know this type of logical relation type.\n" |
615 |
"function WriteLogSide\n"); |
616 |
} |
617 |
} |
618 |
} |
619 |
|
620 |
static |
621 |
void WriteLogicalRelation(FILE *f, |
622 |
CONST struct logrelation *lr, |
623 |
CONST struct Instance *ref) |
624 |
{ |
625 |
switch(LogRelRelop(lr)){ |
626 |
case e_boolean_eq: |
627 |
case e_boolean_neq: |
628 |
WriteLogSide(f,lr,1,ref); |
629 |
PUTC(' ',f); |
630 |
WriteLogOp(f,LogRelRelop(lr)); |
631 |
PUTC(' ',f); |
632 |
WriteLogSide(f,lr,0,ref); |
633 |
break; |
634 |
default: |
635 |
FPRINTF(ASCERR,"Unexpected Relop in WriteLogicalRelation\n"); |
636 |
break; |
637 |
} |
638 |
} |
639 |
|
640 |
static |
641 |
void WriteLogRelDS(Asc_DString *dsPtr, |
642 |
CONST struct logrelation *lr, |
643 |
CONST struct Instance *ref) |
644 |
{ |
645 |
switch(LogRelRelop(lr)){ |
646 |
case e_boolean_eq: |
647 |
case e_boolean_neq: |
648 |
WriteLogSideDS(dsPtr,lr,1,ref); |
649 |
Asc_DStringAppend(dsPtr," ",1); |
650 |
WriteLogOpDS(dsPtr,LogRelRelop(lr)); |
651 |
Asc_DStringAppend(dsPtr," ",1); |
652 |
WriteLogSideDS(dsPtr,lr,0,ref); |
653 |
break; |
654 |
default: |
655 |
FPRINTF(ASCERR,"Unexpected Relop in WriteLogRelDS\n"); |
656 |
Asc_DStringAppend(dsPtr,"BADRELOPR ",9); |
657 |
break; |
658 |
} |
659 |
} |
660 |
|
661 |
static |
662 |
void WriteLogSideInfix(FILE *f, |
663 |
CONST struct logrelation *lr, |
664 |
struct logrel_term *term, |
665 |
CONST struct Instance *ref) |
666 |
{ |
667 |
enum Expr_enum t; |
668 |
struct Instance *cur_var; |
669 |
struct Instance *rel; |
670 |
int bvalue; |
671 |
int parens; |
672 |
|
673 |
switch(t = LogRelTermType(term)) { |
674 |
case e_var: |
675 |
cur_var = LogRelBoolVar(lr,LogTermBoolVarNumber(term)); |
676 |
WriteInstanceName(f,cur_var,ref); |
677 |
break; |
678 |
case e_int: |
679 |
FPRINTF(f,"%d",LogTermInteger(term)); |
680 |
break; |
681 |
case e_boolean: |
682 |
bvalue = LogTermBoolean(term); |
683 |
if (bvalue){ |
684 |
FPRINTF(f,"TRUE"); |
685 |
} |
686 |
else { |
687 |
FPRINTF(f,"FALSE"); |
688 |
} |
689 |
break; |
690 |
case e_satisfied: |
691 |
FPRINTF(f,"SATISFIED("); |
692 |
rel = LogRelRelation(lr,LogTermSatRelNumber(term)); |
693 |
WriteInstanceName(f,rel,ref); |
694 |
if (LogTermSatTolerance(term) != DBL_MAX) { |
695 |
FPRINTF(f,","); |
696 |
FPRINTF(f,"%g",LogTermSatTolerance(term)); |
697 |
} |
698 |
FPRINTF(f,")"); |
699 |
break; |
700 |
case e_not: |
701 |
FPRINTF(f,"NOT("); |
702 |
WriteLogSideInfix(f,lr,LogTermUniLeft(term),ref); |
703 |
FPRINTF(f,")"); |
704 |
break; |
705 |
case e_and: |
706 |
case e_or: |
707 |
parens = LogExprNeedParentheses(LogRelTermType(term), |
708 |
LogRelTermType(LogTermBinLeft(term)),0); |
709 |
if (parens) PUTC('(',f); |
710 |
WriteLogSideInfix(f,lr,LogTermBinLeft(term),ref); |
711 |
if (parens) PUTC(')',f); |
712 |
PUTC(' ',f); |
713 |
WriteLogOp(f,t); |
714 |
PUTC(' ',f); |
715 |
parens = LogExprNeedParentheses(LogRelTermType(term), |
716 |
LogRelTermType(LogTermBinRight(term)),1); |
717 |
if (parens) PUTC('(',f); |
718 |
WriteLogSideInfix(f,lr,LogTermBinRight(term),ref); |
719 |
if (parens) PUTC(')',f); |
720 |
break; |
721 |
default: |
722 |
FPRINTF(f,"***"); |
723 |
break; |
724 |
} |
725 |
} |
726 |
|
727 |
void WriteLogRelInfix(FILE *f, |
728 |
CONST struct Instance *lrelinst, |
729 |
CONST struct Instance *ref) |
730 |
{ |
731 |
CONST struct logrelation *lr; |
732 |
|
733 |
lr = GetInstanceLogRel(lrelinst); |
734 |
switch(LogRelRelop(lr)){ |
735 |
case e_boolean_eq: |
736 |
case e_boolean_neq: |
737 |
WriteLogSideInfix(f,lr,Infix_Log_LhsSide(lr),ref); |
738 |
PUTC(' ',f); |
739 |
WriteLogOp(f,LogRelRelop(lr)); |
740 |
PUTC(' ',f); |
741 |
WriteLogSideInfix(f,lr,Infix_Log_RhsSide(lr),ref); |
742 |
break; |
743 |
default: |
744 |
FPRINTF(ASCERR,"Unexpected Relop in WriteLogRelInfix\n"); |
745 |
} |
746 |
} |
747 |
|
748 |
|
749 |
|
750 |
void WriteLogRel(FILE *f, CONST struct Instance *lrelinst, |
751 |
CONST struct Instance *ref) |
752 |
{ |
753 |
CONST struct logrelation *lreln; |
754 |
|
755 |
lreln = GetInstanceLogRel(lrelinst); |
756 |
if (!lreln) { |
757 |
FPRINTF(f,"NULL logical relation\n"); |
758 |
return; |
759 |
} |
760 |
WriteLogicalRelation(f,lreln,ref); |
761 |
return; |
762 |
} |
763 |
|
764 |
char *WriteLogRelToString(CONST struct Instance *lrelinst, |
765 |
CONST struct Instance *ref) |
766 |
{ |
767 |
CONST struct logrelation *lreln; |
768 |
static Asc_DString ds; |
769 |
Asc_DString *dsPtr; |
770 |
char *result; |
771 |
|
772 |
lreln = GetInstanceLogRel(lrelinst); |
773 |
if (!lreln) { |
774 |
result = ASC_NEW_ARRAY(char,15); |
775 |
if (result == NULL) return result; |
776 |
sprintf(result,"NULL logical relation\n"); |
777 |
return result; |
778 |
} |
779 |
|
780 |
dsPtr = &ds; |
781 |
Asc_DStringInit(dsPtr); |
782 |
WriteLogRelDS(dsPtr,lreln,ref); |
783 |
result = Asc_DStringResult(dsPtr); |
784 |
Asc_DStringFree(dsPtr); |
785 |
return result; |
786 |
} |
787 |
|
788 |
|
789 |
/* |
790 |
* some io to help in debugging logical relation manipulators. |
791 |
*/ |
792 |
static FILE *g_logwritfp = NULL; |
793 |
static void WriteIfLogRel(struct Instance *i) |
794 |
{ |
795 |
struct Instance *p; |
796 |
if (!i) { |
797 |
FPRINTF(ASCERR,"null child pointer in WriteIfLogRel\n"); |
798 |
return; |
799 |
} |
800 |
if (InstanceKind(i)==LREL_INST) { |
801 |
FPRINTF(g_logwritfp,"\n"); |
802 |
WriteInstanceName(g_logwritfp,i,NULL); |
803 |
FPRINTF(g_logwritfp,"\n"); |
804 |
p = InstanceParent(i,1); |
805 |
while (InstanceKind(p)!= MODEL_INST && InstanceKind(p) != SIM_INST) { |
806 |
p = InstanceParent(p,1); |
807 |
} |
808 |
WriteLogRel(g_logwritfp,i,p); |
809 |
FPRINTF(g_logwritfp,"\n"); |
810 |
FPRINTF(g_logwritfp,"\n"); |
811 |
WriteLogRelPostfix(g_logwritfp,i,p); |
812 |
FPRINTF(g_logwritfp,"\n"); |
813 |
} |
814 |
return; |
815 |
} |
816 |
|
817 |
void WriteLogRelationsInTree(FILE *fp,struct Instance *i) |
818 |
{ |
819 |
if (i==NULL || fp==NULL) return; |
820 |
g_logwritfp = fp; |
821 |
SlowVisitInstanceTree(i,WriteIfLogRel,0,0); |
822 |
} |
823 |
|
824 |
|
825 |
/* |
826 |
********************************************************************* |
827 |
* Save Logical Relation Code |
828 |
* |
829 |
* The below code is concerned with saving relations in a persistent |
830 |
* format. It writes out the code in a condensed format to allow |
831 |
* restoration to the original representation. |
832 |
* |
833 |
* The grammar will follow later once it has stabilized. |
834 |
* In the mean time, the following keywords are used. |
835 |
* $LRELOP INTEGER - the relational operator - e_boolean_eq etc. |
836 |
* $LOPCODES INTEGER ':' (INTEGER *) |
837 |
* $LCOUNT INTEGER - the number of variables. |
838 |
* $BVARIABLES ':' (INTEGER)* - global varindex |
839 |
* $BCONSTANTS ':' (BOOLEAN)* |
840 |
********************************************************************* |
841 |
*/ |
842 |
|
843 |
#undef LogLHS |
844 |
#undef LogRHS |
845 |
#define LogLHS 0 |
846 |
#define LogRHS 1 |
847 |
#define LBREAKLINES 65 |
848 |
#define SATID 23 |
849 |
static |
850 |
void SaveLogRelSide(FILE *fp,CONST struct logrelation *lr, |
851 |
int side, struct gl_list_t *constants) |
852 |
{ |
853 |
CONST struct logrel_term *term; |
854 |
struct Instance *rel; |
855 |
enum Expr_enum t; |
856 |
unsigned c,len; |
857 |
int count; |
858 |
|
859 |
len = LogRelLength(lr,side); |
860 |
if (!len) return; |
861 |
|
862 |
count = 16; |
863 |
FPRINTF(fp,"\t$LOPCODES %d : ",side); |
864 |
for (c=1;c<=len;c++) { |
865 |
term = LogRelTerm(lr,c,side); |
866 |
t = LogRelTermType(term); |
867 |
count += FPRINTF(fp," %d ",(int)t); |
868 |
switch (t) { |
869 |
case e_var: |
870 |
count += FPRINTF(fp,"%lu",LogTermBoolVarNumber(term)); |
871 |
break; |
872 |
case e_satisfied: |
873 |
count += FPRINTF(fp,"%d",SATID); |
874 |
rel = LogRelRelation(lr,LogTermSatRelNumber(term)); |
875 |
count += FPRINTF(fp," %lu ",GetTmpNum(rel)); |
876 |
if (LogTermSatTolerance(term) != DBL_MAX) { |
877 |
count += FPRINTF(fp,"%12.8e",LogTermSatTolerance(term)); |
878 |
} |
879 |
break; |
880 |
case e_int: |
881 |
case e_boolean: |
882 |
gl_append_ptr(constants,(VOIDPTR)term); |
883 |
count += FPRINTF(fp,"%lu",gl_length(constants)); |
884 |
break; |
885 |
case e_not: |
886 |
case e_and: |
887 |
case e_or: |
888 |
break; |
889 |
default: |
890 |
count += FPRINTF(fp,"%d",(int)e_nop); |
891 |
break; |
892 |
} |
893 |
if (count >= LBREAKLINES) { |
894 |
PUTC('\n',fp); PUTC('\t',fp); |
895 |
count = 8; |
896 |
} |
897 |
} |
898 |
FPRINTF(fp,";\n"); |
899 |
} |
900 |
|
901 |
|
902 |
static |
903 |
void SaveTokenLogConstants(FILE *fp, struct gl_list_t *constants) |
904 |
{ |
905 |
CONST struct logrel_term *term; |
906 |
unsigned long len,c; |
907 |
|
908 |
len = gl_length(constants); |
909 |
if (!len) return; |
910 |
|
911 |
FPRINTF(fp,"\t$BCONSTANTS : "); |
912 |
for (c=1;c<=len;c++) { |
913 |
term = (CONST struct logrel_term *)gl_fetch(constants,c); |
914 |
switch (LogRelTermType(term)) { |
915 |
case e_boolean: |
916 |
FPRINTF(fp,"%d",LogTermBoolean(term)); |
917 |
break; |
918 |
case e_int: |
919 |
FPRINTF(fp,"%d",LogTermInteger(term)); |
920 |
break; |
921 |
default: |
922 |
ASC_PANIC("Illegal term in SaveTokenLogConstants\n"); |
923 |
} |
924 |
PUTC(' ',fp); |
925 |
} |
926 |
FPRINTF(fp,";\n"); |
927 |
} |
928 |
|
929 |
/* |
930 |
********************************************************************* |
931 |
* Save Logical Relation Boolean Variables |
932 |
********************************************************************* |
933 |
*/ |
934 |
void SaveLogRelBoolVars(FILE *fp, CONST struct logrelation *lr) |
935 |
{ |
936 |
struct Instance *bvar; |
937 |
unsigned long len,c; |
938 |
int count; |
939 |
len = NumberBoolVars(lr); |
940 |
if (!len) return; |
941 |
|
942 |
count = 16; |
943 |
FPRINTF(fp,"\t$BVARIABLES : "); |
944 |
for (c=1;c<=len;c++) { |
945 |
bvar = LogRelBoolVar(lr,c); |
946 |
count += FPRINTF(fp," %lu ",GetTmpNum(bvar)); |
947 |
if (count >= LBREAKLINES) { |
948 |
PUTC('\n',fp); PUTC('\t',fp); |
949 |
count = 8; |
950 |
} |
951 |
} |
952 |
FPRINTF(fp,";\n"); |
953 |
} |
954 |
|
955 |
/* |
956 |
********************************************************************* |
957 |
* SaveLogRel |
958 |
* Save a logical relation in condensed opcode format. |
959 |
********************************************************************* |
960 |
*/ |
961 |
void SaveLogRel(FILE *fp, CONST struct Instance *lrelinst) |
962 |
{ |
963 |
CONST struct logrelation *lreln; |
964 |
struct gl_list_t *constants = NULL; |
965 |
|
966 |
lreln = GetInstanceLogRel(lrelinst); |
967 |
constants = gl_create(50L); |
968 |
|
969 |
FPRINTF(fp,"$LOGRELATION %lu {\n",GetTmpNum(lrelinst)); |
970 |
FPRINTF(fp,"\t$COUNT %lu;\n",NumberBoolVars(lreln)); |
971 |
|
972 |
SaveLogRelSide(fp,lreln,LogLHS,constants); |
973 |
SaveLogRelSide(fp,lreln,LogRHS,constants); |
974 |
SaveTokenLogConstants(fp,constants); |
975 |
SaveLogRelBoolVars(fp,lreln); |
976 |
FPRINTF(fp,"}\n\n"); |
977 |
|
978 |
gl_destroy(constants); |
979 |
} |
980 |
|
981 |
|