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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 101 - (show annotations) (download) (as text)
Sat Dec 10 04:22:07 2005 UTC (15 years, 4 months ago) by jds
File MIME type: text/x-csrc
File size: 45050 byte(s)
A little more progress killing compiler warnings.
1 /*
2 * Relation Output Routines
3 * by Tom Epperly
4 * Created: 2/8/90
5 * Version: $Revision: 1.16 $
6 * Version control file: $RCSfile: relation_io.c,v $
7 * Date last modified: $Date: 1998/04/10 23:25:47 $
8 * Last modified by: $Author: ballan $
9 *
10 * This file is part of the Ascend Language Interpreter.
11 *
12 * Copyright (C) 1990, 1993, 1994 Thomas Guthrie Epperly
13 * Copyright (C) 1998 Benjamin Allan and Vicente Rico-Ramirez
14 *
15 * The Ascend Language Interpreter is free software; you can redistribute
16 * it and/or modify it under the terms of the GNU General Public License as
17 * published by the Free Software Foundation; either version 2 of the
18 * License, or (at your option) any later version.
19 *
20 * The Ascend Language Interpreter is distributed in hope that it will be
21 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 * General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with the program; if not, write to the Free Software Foundation,
27 * Inc., 675 Mass Ave, Cambridge, MA 02139 USA. Check the file named
28 * COPYING.
29 *
30 */
31
32 #include <stdarg.h>
33 #include "utilities/ascConfig.h"
34 #include "utilities/ascMalloc.h"
35 #include "utilities/ascPanic.h"
36 #include "general/list.h"
37 #include "general/pool.h"
38 #include "general/dstring.h"
39 #include "general/pretty.h"
40 #include "compiler/compiler.h"
41 #include "compiler/fractions.h"
42 #include "compiler/dimen.h"
43 #include "compiler/functype.h"
44 #include "compiler/func.h"
45 #include "compiler/types.h"
46 #include "compiler/extfunc.h"
47 #include "compiler/extcall.h"
48 #include "compiler/instance_enum.h"
49 #include "compiler/mathinst.h"
50 #include "compiler/visitinst.h"
51 #include "compiler/parentchild.h"
52 #include "compiler/instquery.h"
53 #include "compiler/tmpnum.h"
54 #include "compiler/find.h"
55 #include "compiler/relation_type.h"
56 #include "compiler/relation.h"
57 #include "compiler/relation_util.h"
58 #include "compiler/relation_io.h"
59 #include "compiler/instance_io.h"
60
61 #ifndef lint
62 static CONST char RelationOutputRoutinesRCS[]="$Id: relation_io.c,v 1.16 1998/04/10 23:25:47 ballan Exp $";
63 #endif
64
65
66 static char g_shortbuf[256];
67 #define SB255 g_shortbuf
68
69 #ifdef ASC_NO_POOL
70 #define RELIO_USES_POOL FALSE
71 #else
72 #define RELIO_USES_POOL TRUE
73 #endif
74
75 /*
76 * stack entry for relation io conversion to infix.
77 */
78 struct rel_stack {
79 struct rel_stack *next;
80 unsigned long pos;
81 int first;
82 unsigned long lhs; /* used only for binary tokens with first = 2 */
83 };
84
85 /* default for other tokens. this will cause an array bounds read
86 * error if misused, which is nice if you assume purify.
87 */
88 #define NOLHS -1
89
90 /* worklist */
91 static struct rel_stack *g_rel_stack=NULL;
92
93 /* recycle spaces */
94 static pool_store_t g_rel_stack_pool = NULL;
95 /* global for our memory manager */
96 /* aim for 4096 chunks including malloc overhead */
97 #define RSP_LEN 2
98 #if (SIZEOF_VOID_P == 8)
99 #define RSP_WID 10
100 #else
101 #define RSP_WID 20
102 #endif
103 /* retune rpwid if the size of struct name changes */
104 #define RSP_ELT_SIZE (sizeof(struct rel_stack))
105 #define RSP_MORE_ELTS 1
106 /*
107 * Number of slots filled if more elements needed.
108 * So if the pool grows, it grows by RSP_MORE_ELTS*RSP_WID elements at a time.
109 */
110 #define RSP_MORE_BARS 5
111 /* This is the number of pool bar slots to add during expansion.
112 not all the slots will be filled immediately. */
113
114 /* This function is called at compiler startup time and destroy at shutdown. */
115 void RelationIO_init_pool(void) {
116 if (g_rel_stack_pool != NULL ) {
117 Asc_Panic(2, NULL, "ERROR: RelationIO_init_pool called twice.\n");
118 }
119 g_rel_stack_pool = pool_create_store(RSP_LEN, RSP_WID, RSP_ELT_SIZE,
120 RSP_MORE_ELTS, RSP_MORE_BARS);
121 if (g_rel_stack_pool == NULL) {
122 Asc_Panic(2, NULL,
123 "ERROR: RelationIO_init_pool unable to allocate pool.\n");
124 }
125 }
126
127 void RelationIO_destroy_pool(void) {
128 if (g_rel_stack_pool==NULL) return;
129 pool_clear_store(g_rel_stack_pool);
130 pool_destroy_store(g_rel_stack_pool);
131 g_rel_stack_pool = NULL;
132 }
133
134 void RelationIO_report_pool(void)
135 {
136 if (g_rel_stack_pool==NULL) {
137 FPRINTF(ASCERR,"rel_stacksPool is empty\n");
138 }
139 FPRINTF(ASCERR,"rel_stacksPool ");
140 pool_print_store(ASCERR,g_rel_stack_pool,0);
141 }
142
143 #if RELIO_USES_POOL
144 #define RSPMALLOC ((struct rel_stack *)(pool_get_element(g_rel_stack_pool)))
145 /* get a token. Token is the size of the struct struct rel_stack */
146 #define RSPFREE(p) (pool_free_element(g_rel_stack_pool,((void *)p)))
147 /* return a struct rel_stack */
148
149 #else
150
151 #define RSPMALLOC ascmalloc(sizeof(struct rel_stack ))
152 #define RSPFREE(p) ascfree(p)
153
154 #endif /* RELIO_USES_POOL */
155
156 static
157 void WriteOp(FILE *f, enum Expr_enum t)
158 {
159 switch(t){
160 case e_plus: PUTC('+',f); break;
161 case e_uminus:
162 case e_minus: PUTC('-',f); break;
163 case e_times: PUTC('*',f); break;
164 case e_divide: PUTC('/',f); break;
165 case e_power: PUTC('^',f); break;
166 case e_ipower: PUTC('^',f); break;
167 case e_equal: PUTC('=',f); break;
168 case e_notequal: FPRINTF(f,"<>"); break;
169 case e_less: PUTC('<',f); break;
170 case e_greater: PUTC('>',f); break;
171 case e_lesseq: FPRINTF(f,"<="); break;
172 case e_greatereq: FPRINTF(f,">="); break;
173 case e_maximize: FPRINTF(f,"MAXIMIZE"); break;
174 case e_minimize: FPRINTF(f,"MINIMIZE"); break;
175 default:
176 Asc_Panic(2, NULL, "Unknown term in WriteOp.\n");
177 break;
178 }
179 }
180
181 /* appends operator to dynamic symbol */
182 static void WriteOpDS(Asc_DString *dsPtr, enum Expr_enum t,
183 enum rel_lang_format lang)
184 {
185 (void)lang; /* future use for relational operators in other langs. */
186 assert(dsPtr!=NULL);
187 switch(t){
188 case e_plus:
189 Asc_DStringAppend(dsPtr,"+",1);
190 break;
191 case e_uminus:
192 case e_minus:
193 Asc_DStringAppend(dsPtr,"-",1);
194 break;
195 case e_times:
196 Asc_DStringAppend(dsPtr,"*",1);
197 break;
198 case e_divide:
199 Asc_DStringAppend(dsPtr,"/",1);
200 break;
201 case e_power:
202 Asc_DStringAppend(dsPtr,"^",1);
203 break;
204 case e_ipower:
205 Asc_DStringAppend(dsPtr,"^",1);
206 break;
207 case e_equal:
208 Asc_DStringAppend(dsPtr,"=",1);
209 break;
210 case e_notequal:
211 Asc_DStringAppend(dsPtr,"<>",2);
212 break;
213 case e_less:
214 Asc_DStringAppend(dsPtr,"<",1);
215 break;
216 case e_greater:
217 Asc_DStringAppend(dsPtr,">",1);
218 break;
219 case e_lesseq:
220 Asc_DStringAppend(dsPtr,"<=",2);
221 break;
222 case e_greatereq:
223 Asc_DStringAppend(dsPtr,">=",2);
224 break;
225 case e_maximize:
226 Asc_DStringAppend(dsPtr,"MAXIMIZE",8);
227 break;
228 case e_minimize:
229 Asc_DStringAppend(dsPtr,"MINIMIZE",8);
230 break;
231 default:
232 FPRINTF(ASCERR,"Unknown term in WriteOpDS.\n");
233 Asc_DStringAppend(dsPtr,"ERROR",5);
234 break;
235 }
236 }
237
238 char *RelationVarXName(CONST struct relation *r,
239 unsigned long varnum,
240 struct RXNameData *rd)
241 {
242 unsigned long i;
243 struct RXNameData myrd = {"x",NULL,""};
244 (void)r;
245
246 if (varnum < 1) {
247 return NULL;
248 }
249 if (rd == NULL) {
250 rd = &myrd;
251 } else {
252 assert(rd->prefix!=NULL);
253 assert(rd->suffix!=NULL);
254 }
255 if (rd->indices == NULL) {
256 i = varnum;
257 } else {
258 i = (unsigned long)(rd->indices[varnum]);
259 }
260 sprintf(SB255,"%.110s%lu%.110s",rd->prefix,i,rd->suffix);
261 return SB255;
262 }
263
264 static
265 void WriteTerm(FILE *f,
266 CONST struct relation *rel,
267 CONST struct relation_term *term,
268 CONST struct Instance *inst)
269 {
270 struct Instance *cur_var;
271 switch(RelationTermType(term)){
272 case e_var:
273 cur_var = RelationVariable(rel,TermVarNumber(term));
274 WriteInstanceName(f,cur_var,inst);
275 break;
276 case e_func:
277 FPRINTF(f,FuncName(TermFunc(term)));
278 break;
279 case e_int:
280 FPRINTF(f,"%ld",TermInteger(term));
281 break;
282 case e_zero:
283 FPRINTF(f,"%g",0.0);
284 break;
285 case e_real:
286 FPRINTF(f,"%g",TermReal(term));
287 break;
288 case e_plus:
289 case e_minus:
290 case e_times:
291 case e_divide:
292 case e_power:
293 case e_ipower:
294 WriteOp(f,RelationTermType(term));
295 break;
296 case e_uminus:
297 FPRINTF(f,"NEG");
298 break;
299 default:
300 Asc_Panic(2, NULL, "Unknown term type in WriteTerm.\n");
301 break;
302 }
303 }
304
305 /* write out a postfix term */
306 static
307 void WriteTermDS(Asc_DString *dsPtr,
308 CONST struct relation *rel,
309 CONST struct relation_term *term,
310 CONST struct Instance *inst)
311 {
312 struct Instance *cur_var;
313 switch(RelationTermType(term)){
314 case e_var:
315 cur_var = RelationVariable(rel,TermVarNumber(term));
316 WriteInstanceNameDS(dsPtr,cur_var,inst);
317 break;
318 case e_func:
319 Asc_DStringAppend(dsPtr,FuncName(TermFunc(term)),-1);
320 break;
321 case e_int:
322 sprintf(SB255,"%ld",TermInteger(term));
323 Asc_DStringAppend(dsPtr,SB255,-1);
324 break;
325 case e_zero:
326 Asc_DStringAppend(dsPtr,"0.0",3);
327 break;
328 case e_real:
329 sprintf(SB255,"(double) %.18g",TermReal(term));
330 Asc_DStringAppend(dsPtr,SB255,-1);
331 break;
332 case e_plus:
333 case e_minus:
334 case e_times:
335 case e_divide:
336 case e_power:
337 case e_ipower:
338 WriteOpDS(dsPtr,RelationTermType(term),relio_ascend);
339 break;
340 case e_uminus:
341 Asc_DStringAppend(dsPtr,"NEG",3);
342 break; /* what is this anyway? */
343 default:
344 FPRINTF(ASCERR,"Unknown term in WriteTermDS.\n");
345 Asc_DStringAppend(dsPtr,"ERROR",5);
346 break;
347 }
348 }
349
350 static
351 void WriteSidePF(FILE *f,
352 CONST struct relation *r,
353 int side,
354 CONST struct Instance *ref)
355 {
356 unsigned c,len;
357 CONST struct relation_term *term;
358 len = RelationLength(r,side);
359 for(c=1;c<=len;c++){
360 term = RelationTerm(r,c,side);
361 WriteTerm(f,r,term,ref);
362 if(c<len) PUTC(' ',f);
363 }
364 }
365
366 static
367 void WriteSidePFDS(Asc_DString *dsPtr,
368 CONST struct relation *r,
369 int side,
370 CONST struct Instance *ref)
371 {
372 unsigned c,len;
373 CONST struct relation_term *term;
374 len = RelationLength(r,side);
375 for(c=1;c<=len;c++){
376 term = RelationTerm(r,c,side);
377 WriteTermDS(dsPtr,r,term,ref);
378 if(c<len) Asc_DStringAppend(dsPtr," ",1);
379 }
380 }
381
382 void WriteRelationPostfix(FILE *f,
383 CONST struct Instance *relinst,
384 CONST struct Instance *ref)
385 {
386 CONST struct relation *r;
387 enum Expr_enum type;
388
389 r = GetInstanceRelation(relinst,&type);
390 if (type!=e_token) {
391 FPRINTF(ASCERR,"Invalid relation type in WriteRelationPostfix\n");
392 return;
393 }
394
395 switch(RelationRelop(r)){
396 case e_equal:
397 case e_notequal:
398 case e_less:
399 case e_greater:
400 case e_lesseq:
401 case e_greatereq:
402 WriteSidePF(f,r,1,ref);
403 PUTC(' ',f);
404 WriteSidePF(f,r,0,ref);
405 PUTC(' ',f);
406 WriteOp(f,RelationRelop(r));
407 break;
408 case e_maximize:
409 case e_minimize:
410 WriteOp(f,RelationRelop(r));
411 PUTC(' ',f);
412 WriteSidePF(f,r,1,ref);
413 break;
414 default:
415 FPRINTF(ASCERR,"Unexpected Relop in WriteRelationPostfix\n");
416 break;
417 }
418 }
419
420 char *WriteRelationPostfixString( CONST struct Instance *relinst,
421 CONST struct Instance *ref)
422 {
423 CONST struct relation *r;
424 enum Expr_enum type;
425 char *result;
426 static Asc_DString ds;
427 Asc_DString *dsPtr;
428
429 r = GetInstanceRelation(relinst,&type);
430 if (type!=e_token) {
431 FPRINTF(ASCERR,"Invalid relation type in WriteRelationPostfixString\n");
432 result=(char *)ascmalloc(60);
433 if (result==NULL) return result;
434 sprintf(result,"WriteRelationPostfixString called on non-token relation.");
435 return result;
436 }
437 dsPtr = &ds;
438 Asc_DStringInit(dsPtr);
439
440 switch(RelationRelop(r)){
441 case e_equal:
442 case e_notequal:
443 case e_less:
444 case e_greater:
445 case e_lesseq:
446 case e_greatereq:
447 WriteSidePFDS(dsPtr,r,1,ref);
448 Asc_DStringAppend(dsPtr," ",1);
449 WriteSidePFDS(dsPtr,r,0,ref);
450 Asc_DStringAppend(dsPtr," ",1);
451 WriteOpDS(dsPtr,RelationRelop(r),relio_ascend);
452 break;
453 case e_maximize:
454 case e_minimize:
455 WriteOpDS(dsPtr,RelationRelop(r),relio_ascend);
456 Asc_DStringAppend(dsPtr," ",1);
457 WriteSidePFDS(dsPtr,r,1,ref);
458 break;
459 default:
460 FPRINTF(ASCERR,"Unexpected Relop in WriteRelationPostfix\n");
461 break;
462 }
463 result = Asc_DStringResult(dsPtr);
464 Asc_DStringFree(dsPtr);
465 return result;
466 }
467
468 static
469 void ClearRelationStack(void)
470 {
471 struct rel_stack *next;
472 while(g_rel_stack!=NULL){
473 next = g_rel_stack->next;
474 RSPFREE(g_rel_stack);
475 g_rel_stack = next;
476 }
477 }
478
479 static
480 void PushRelation(unsigned long int pos, int first, unsigned long int lhs)
481 {
482 struct rel_stack *next;
483 next = g_rel_stack;
484 g_rel_stack = RSPMALLOC;
485 g_rel_stack->next = next;
486 g_rel_stack->pos = pos;
487 g_rel_stack->first = first;
488 g_rel_stack->lhs = lhs;
489 }
490
491 static
492 int NotEmptyStack(void)
493 {
494 return g_rel_stack!=NULL;
495 }
496
497 static
498 int FirstTop(void)
499 {
500 assert(g_rel_stack!=NULL);
501 return g_rel_stack->first;
502 }
503
504 static
505 int LHSTop(void)
506 {
507 assert(g_rel_stack!=NULL);
508 return g_rel_stack->lhs;
509 }
510
511 /*
512 * destroy top of stack and returns its pos value.
513 */
514 static
515 unsigned long PopRelation(void)
516 {
517 struct rel_stack *next;
518 unsigned long result;
519 assert(g_rel_stack!=NULL);
520 next = g_rel_stack->next;
521 result = g_rel_stack->pos;
522 RSPFREE((char *)g_rel_stack);
523 g_rel_stack = next;
524 return result;
525 }
526
527 /* Assumes relation array of the form [lhs tokens, rhstokens,postoken].
528 * Searches left starting from postoken given until it finds the pos
529 * preceding the ",". This pos is the top of the lhs tokens tree,
530 * if you think about things in tree terms. postoken is the top of
531 * the tree and is binary. lhs and rhs refer to left and right
532 * side of any binary operator.
533 * Calling this with an ill formed tree is likely to cause weird
534 * errors and overrun the array or underrun the result.
535 */
536 static
537 unsigned long LeftHandSide(CONST struct relation *r,
538 unsigned long int pos,
539 int side)
540 {
541 unsigned long depth=1;
542 CONST struct relation_term *term;
543 pos--;
544 while(depth){
545 term = RelationTerm(r,pos,side);
546 switch(RelationTermType(term)){
547 case e_int:
548 case e_zero:
549 case e_real:
550 case e_var:
551 depth--;
552 break;
553 case e_func:
554 case e_uminus:
555 break;
556 case e_plus:
557 case e_minus:
558 case e_times:
559 case e_divide:
560 case e_power:
561 case e_ipower:
562 depth++;
563 break;
564 default:
565 Asc_Panic(2, NULL,
566 "Don't know this type of relation type.\n"
567 "(%d) in function LeftHandSide\n",
568 RelationTermType(term));
569 break;
570 }
571 pos--;
572 }
573 return pos;
574 }
575
576 /* a little function to tell us about precedence */
577 static
578 unsigned Priority(enum Expr_enum t)
579 {
580 switch(t){
581 case e_zero:
582 case e_var:
583 case e_int:
584 case e_real:
585 case e_func:
586 return 0;
587
588 case e_plus:
589 case e_minus:
590 return 1;
591
592 case e_times:
593 case e_divide:
594 return 2;
595
596 case e_uminus:
597 return 3;
598
599 case e_power:
600 case e_ipower:
601 return 4;
602
603 default:
604 return 0; /* 0=good idea? */
605 }
606 /*NOTREACHED*/
607 }
608
609 int NeedParen(enum Expr_enum parent_op, enum Expr_enum child_op, int rhs)
610 {
611 unsigned parent_p,child_p;
612 switch(child_op){
613 case e_zero:
614 case e_var:
615 case e_int:
616 case e_real:
617 case e_func:
618 return 0;
619 default:
620 parent_p = Priority(parent_op);
621 child_p = Priority(child_op);
622 if (parent_p > child_p) return 1;
623 if (parent_p < child_p) return 0;
624 if ((parent_op == e_minus)&&rhs) return 1;
625 if ((parent_op == e_divide)&&rhs) return 1;
626 return 0;
627 }
628 }
629
630 static
631 void WriteSide(FILE *f,
632 CONST struct relation *r,
633 int side,
634 CONST struct Instance *ref)
635 {
636 unsigned long pos,lhs,oldlhs;
637 int first;
638 enum Expr_enum t;
639 CONST struct relation_term *term;
640 struct Instance *cur_var;
641 ClearRelationStack();
642 PushRelation(RelationLength(r,side),1,NOLHS);
643 while(NotEmptyStack()){
644 first = FirstTop(); /* check if this is the first visit */
645 oldlhs = LHSTop(); /* check for cached LHS position on binaries */
646 pos = PopRelation(); /* check the top */
647 term = RelationTerm(r,pos,side);
648 switch(t = RelationTermType(term)){
649 case e_var:
650 cur_var = RelationVariable(r,TermVarNumber(term));
651 WriteInstanceName(f,cur_var,ref);
652 break;
653 case e_int:
654 FPRINTF(f,"%ld",TermInteger(term));
655 break;
656 case e_zero:
657 FPRINTF(f,"0");
658 break;
659 case e_real:
660 FPRINTF(f,"%g",TermReal(term));
661 break;
662 case e_func:
663 if(first) {
664 FPRINTF(f,"%s(",FuncName(TermFunc(term)));
665 PushRelation(pos,0,NOLHS);
666 PushRelation(pos-1,1,NOLHS);
667 }
668 else{
669 PUTC(')',f);
670 }
671 break;
672 case e_plus:
673 case e_minus:
674 case e_times:
675 case e_divide:
676 case e_power:
677 case e_ipower:
678 switch(first){
679 case 1:
680 lhs = LeftHandSide(r,pos,side);
681 term = RelationTerm(r,lhs,side);
682 if (NeedParen(t,RelationTermType(term),0)) {
683 PUTC('(',f);
684 }
685 PushRelation(pos,2,lhs);
686 PushRelation(lhs,1,NOLHS);
687 break;
688 case 2:
689 term = RelationTerm(r,oldlhs,side);
690 if (NeedParen(t,RelationTermType(term),0)) {
691 PUTC(')',f);
692 }
693 PUTC(' ',f);
694 WriteOp(f,t);
695 PUTC(' ',f);
696 PushRelation(pos,0,NOLHS);
697 term = RelationTerm(r,pos-1,side);
698 if (NeedParen(t,RelationTermType(term),1))
699 PUTC('(',f);
700 PushRelation(pos-1,1,oldlhs);
701 break;
702 case 0:
703 term = RelationTerm(r,pos-1,side);
704 if (NeedParen(t,RelationTermType(term),1))
705 PUTC(')',f);
706 break;
707 }
708 break;
709 case e_uminus:
710 term = RelationTerm(r,pos-1,side);
711 if (first){
712 PUTC('-',f);
713 PushRelation(pos,0,NOLHS);
714 switch(RelationTermType(term)){
715 case e_power:
716 case e_ipower:
717 case e_zero:
718 case e_int:
719 case e_real:
720 case e_var:
721 case e_func:
722 case e_uminus:
723 break;
724 default:
725 PUTC('(',f);
726 break;
727 }
728 PushRelation(pos-1,1,NOLHS);
729 }
730 else{
731 switch(RelationTermType(term)){
732 case e_power:
733 case e_ipower:
734 case e_int:
735 case e_zero:
736 case e_real:
737 case e_var:
738 case e_func:
739 case e_uminus:
740 break;
741 default:
742 PUTC(')',f);
743 break;
744 }
745 }
746 break;
747 default:
748 Asc_Panic(2, NULL,
749 "Don't know this type of relation type: function WriteSide\n");
750 break;
751 }
752 }
753 }
754
755 /* write a side in infix */
756 static
757 void WriteSideDS(Asc_DString *dsPtr, CONST struct relation *r, int side,
758 CONST struct Instance *ref, WRSNameFunc func, void *userdata,
759 enum rel_lang_format lang)
760 {
761 unsigned long pos,lhs, oldlhs, rlen;
762 int first;
763 enum Expr_enum t;
764 CONST struct relation_term *term;
765 struct Instance *cur_var;
766 char *username;
767
768
769 ClearRelationStack();
770 rlen = RelationLength(r,side);
771 PushRelation(rlen,1,NOLHS);
772 while(NotEmptyStack()){
773 first = FirstTop(); /* check if this is the first visit */
774 oldlhs = LHSTop(); /* check if this is the first visit */
775 pos = PopRelation(); /* check the top */
776 term = RelationTerm(r,pos,side);
777 t = RelationTermType(term);
778 switch (t) {
779 case e_var:
780 if (func == NULL) {
781 cur_var = RelationVariable(r,TermVarNumber(term));
782 WriteInstanceNameDS(dsPtr,cur_var,ref);
783 } else {
784 username = (*func)(r,TermVarNumber(term),userdata);
785 Asc_DStringAppend(dsPtr,username,-1);
786 }
787 break;
788 case e_int:
789 if (lang == relio_C) {
790 if (pos == rlen /* don't check next term if at END */ ||
791 RelationTermType(RelationTerm(r,pos+1,side)) != e_ipower) {
792 /* don't want to provoke integer division, normally */
793 sprintf(SB255,"%ld.0",TermInteger(term));
794 } else {
795 /* ipow(expr,i) is the only legal way of seeing ipow )
796 * which in stack terms is [expr... , int , e_ipower]
797 */
798 sprintf(SB255,"%ld",TermInteger(term));
799 }
800 } else {
801 sprintf(SB255,"%ld",TermInteger(term));
802 }
803 Asc_DStringAppend(dsPtr,SB255,-1);
804 break;
805 case e_zero:
806 if (lang == relio_C) {
807 Asc_DStringAppend(dsPtr,"0.0",3);
808 /* don't want to provoke integer division */
809 } else {
810 Asc_DStringAppend(dsPtr,"0",1);
811 }
812 break;
813 case e_real:
814 if (lang == relio_C) {
815 sprintf(SB255,"(double) %.18g",TermReal(term));
816 } else {
817 sprintf(SB255,"%g",TermReal(term));
818 }
819 Asc_DStringAppend(dsPtr,SB255,-1);
820 break;
821 case e_func:
822 if(first) {
823 if (lang == relio_C) {
824 sprintf(SB255,"%s(",FuncCName(TermFunc(term)));
825 } else {
826 sprintf(SB255,"%s(",FuncName(TermFunc(term)));
827 }
828 Asc_DStringAppend(dsPtr,SB255,-1);
829 PushRelation(pos,0,NOLHS);
830 PushRelation(pos-1,1,NOLHS);
831 }
832 else{
833 Asc_DStringAppend(dsPtr,")",1);
834 }
835 break;
836 case e_power:
837 case e_ipower:
838 if (lang == relio_C) {
839 /* we assume the args to pow Always need () around them
840 * to keep , from confusing anything, so lhs not used.
841 */
842 switch(first) {
843 case 1:
844 /* seeing this binary token the first time */
845 if (t==e_power) {
846 Asc_DStringAppend(dsPtr,"pow((",5);
847 } else {
848 Asc_DStringAppend(dsPtr,"asc_ipow((",10);
849 }
850 PushRelation(pos,2,NOLHS);
851 lhs = LeftHandSide(r,pos,side);
852 PushRelation(lhs,1,NOLHS);
853 break;
854 case 2:
855 /* seeing this binary token the second time */
856 if (t==e_power) {
857 Asc_DStringAppend(dsPtr,") , (",5);
858 } else {
859 Asc_DStringAppend(dsPtr,") , ",4);
860 }
861 PushRelation(pos,0,NOLHS);
862 PushRelation(pos-1,1,NOLHS);
863 break;
864 case 0:
865 /* seeing binary token the third (last) time */
866 if (t==e_power) {
867 Asc_DStringAppend(dsPtr," ))",3);
868 } else {
869 Asc_DStringAppend(dsPtr,")",1);
870 }
871 break;
872 default: /* first */
873 Asc_Panic(2, "WriteSideDS", "Don't know this type of stack first");
874 break;
875 }
876 break;
877 }
878 /* else FALL THROUGH to usual binary operator treatment */
879 case e_plus:
880 case e_minus:
881 case e_times:
882 case e_divide:
883 switch(first){
884 case 1:
885 /* seeing this binary token the first time */
886 lhs = LeftHandSide(r,pos,side);
887 term = RelationTerm(r,lhs,side);
888 if (NeedParen(t,RelationTermType(term),0)) {
889 Asc_DStringAppend(dsPtr,"(",1);
890 }
891 PushRelation(pos,2,lhs);
892 PushRelation(lhs,1,NOLHS);
893 break;
894 case 2:
895 /* seeing this binary token the second time */
896 term = RelationTerm(r,oldlhs,side);
897 if (NeedParen(t,RelationTermType(term),0)) {
898 Asc_DStringAppend(dsPtr,")",1);
899 }
900 Asc_DStringAppend(dsPtr," ",1);
901 WriteOpDS(dsPtr,t,lang);
902 Asc_DStringAppend(dsPtr," ",1);
903 PushRelation(pos,0,NOLHS);
904 term = RelationTerm(r,pos-1,side);
905 if (NeedParen(t,RelationTermType(term),1)) {
906 Asc_DStringAppend(dsPtr,"(",1);
907 }
908 PushRelation(pos-1,1,NOLHS);
909 break;
910 case 0:
911 /* seeing binary token the third (last) time */
912 term = RelationTerm(r,pos-1,side);
913 if (NeedParen(t,RelationTermType(term),1))
914 Asc_DStringAppend(dsPtr,")",1);
915 break;
916 }
917 break;
918 case e_uminus:
919 term = RelationTerm(r,pos-1,side);
920 if (first){
921 Asc_DStringAppend(dsPtr,"-",1);
922 PushRelation(pos,0,NOLHS);
923 switch(RelationTermType(term)){
924 case e_power:
925 case e_ipower:
926 case e_zero:
927 case e_int:
928 case e_real:
929 case e_var:
930 case e_func:
931 case e_uminus:
932 break;
933 default:
934 Asc_DStringAppend(dsPtr,"(",1);
935 break;
936 }
937 PushRelation(pos-1,1,NOLHS);
938 }
939 else{
940 switch(RelationTermType(term)){
941 case e_power:
942 case e_ipower:
943 case e_int:
944 case e_zero:
945 case e_real:
946 case e_var:
947 case e_func:
948 case e_uminus:
949 break;
950 default:
951 Asc_DStringAppend(dsPtr,")",1);
952 break;
953 }
954 }
955 break;
956 default:
957 Asc_Panic(2, "WriteSideDS", "Don't know this type of relation token");
958 break;
959 }
960 }
961 }
962
963 static
964 void WriteTokenRelation(FILE *f,
965 CONST struct relation *r,
966 CONST struct Instance *ref)
967 {
968 switch(RelationRelop(r)){
969 case e_equal:
970 case e_notequal:
971 case e_less:
972 case e_greater:
973 case e_lesseq:
974 case e_greatereq:
975 WriteSide(f,r,1,ref);
976 PUTC(' ',f);
977 WriteOp(f,RelationRelop(r));
978 PUTC(' ',f);
979 WriteSide(f,r,0,ref);
980 break;
981 case e_maximize:
982 case e_minimize:
983 WriteOp(f,RelationRelop(r));
984 PUTC(' ',f);
985 WriteSide(f,r,1,ref);
986 break;
987 default:
988 FPRINTF(ASCERR,"Unexpected Relop in WriteTokenRelation\n");
989 break;
990 }
991 }
992
993 static
994 void WriteTokenRelationDS(Asc_DString *dsPtr,
995 CONST struct relation *r,
996 CONST struct Instance *ref,
997 WRSNameFunc func, void *userdata,
998 enum rel_lang_format lang)
999 {
1000 switch(RelationRelop(r)){
1001 case e_equal:
1002 case e_notequal:
1003 case e_less:
1004 case e_greater:
1005 case e_lesseq:
1006 case e_greatereq:
1007 if (lang == relio_C) {
1008 Asc_DStringAppend(dsPtr,"( ",2);
1009 }
1010 WriteSideDS(dsPtr,r,1,ref,func,userdata,lang);
1011 switch (lang) {
1012 case relio_ascend:
1013 Asc_DStringAppend(dsPtr," ",1);
1014 WriteOpDS(dsPtr,RelationRelop(r),lang);
1015 Asc_DStringAppend(dsPtr," ",1);
1016 break;
1017 case relio_C:
1018 Asc_DStringAppend(dsPtr," ) - ( ",7);
1019 break;
1020 default:
1021 Asc_Panic(2, NULL, "Unknown lang in WriteRelationString.\n");
1022 exit(2); /* NOTREACHED , shuts up gcc */
1023 }
1024 WriteSideDS(dsPtr,r,0,ref,func,userdata,lang);
1025 if (lang == relio_C) {
1026 Asc_DStringAppend(dsPtr," )",2);
1027 }
1028 break;
1029 case e_maximize:
1030 case e_minimize:
1031 /* max/min are lhs-only expression, so no operator in C case. */
1032 switch (lang) {
1033 case relio_ascend:
1034 WriteOpDS(dsPtr,RelationRelop(r),lang);
1035 Asc_DStringAppend(dsPtr," ",1);
1036 WriteSideDS(dsPtr,r,1,ref,func,userdata,lang);
1037 break;
1038 case relio_C:
1039 Asc_DStringAppend(dsPtr,"( ",2);
1040 WriteSideDS(dsPtr,r,1,ref,func,userdata,lang);
1041 Asc_DStringAppend(dsPtr," )",2);
1042 break;
1043 default:
1044 Asc_Panic(2, NULL, "Unknown lang in WriteRelationString.\n");
1045 exit(2); /* NOTREACHED , shuts up gcc */
1046 }
1047 break;
1048 default:
1049 FPRINTF(ASCERR,"Unexpected Relop in WriteTokenRelationDS\n");
1050 Asc_DStringAppend(dsPtr,"BADRELOPR ",9);
1051 break;
1052 }
1053 }
1054
1055 static
1056 void Infix_WriteSide(FILE *f,
1057 CONST struct relation *r,
1058 struct relation_term *term,
1059 CONST struct Instance *ref)
1060 {
1061 enum Expr_enum t;
1062 struct Instance *cur_var;
1063 int parens;
1064
1065 switch(t = RelationTermType(term)) {
1066 case e_var:
1067 cur_var = RelationVariable(r,TermVarNumber(term));
1068 WriteInstanceName(f,cur_var,ref);
1069 break;
1070 case e_int:
1071 FPRINTF(f,"%ld",TermInteger(term));
1072 break;
1073 case e_zero:
1074 FPRINTF(f,"0");
1075 break;
1076 case e_real:
1077 FPRINTF(f,"%g",TermReal(term));
1078 break;
1079 case e_func:
1080 FPRINTF(f,"%s(",FuncName(TermFunc(term)));
1081 Infix_WriteSide(f,r,TermFuncLeft(term),ref);
1082 FPRINTF(f,")");
1083 break;
1084 case e_uminus:
1085 FPRINTF(f,"-(");
1086 Infix_WriteSide(f,r,TermUniLeft(term),ref);
1087 FPRINTF(f,")");
1088 break;
1089 case e_plus:
1090 case e_minus:
1091 case e_times:
1092 case e_divide:
1093 case e_power:
1094 case e_ipower:
1095 parens = NeedParen(RelationTermType(term),
1096 RelationTermType(TermBinLeft(term)),0);
1097 if (parens) PUTC('(',f);
1098 Infix_WriteSide(f,r,TermBinLeft(term),ref);
1099 if (parens) PUTC(')',f);
1100 PUTC(' ',f);
1101 WriteOp(f,t);
1102 PUTC(' ',f);
1103 parens = NeedParen(RelationTermType(term),
1104 RelationTermType(TermBinRight(term)),1);
1105 if (parens) PUTC('(',f);
1106 Infix_WriteSide(f,r,TermBinRight(term),ref);
1107 if (parens) PUTC('(',f);
1108 break;
1109 default:
1110 FPRINTF(f,"***");
1111 break;
1112 }
1113 }
1114
1115 void Infix_WriteRelation(FILE *f,
1116 CONST struct Instance *relinst,
1117 CONST struct Instance *ref)
1118 {
1119 CONST struct relation *r;
1120 enum Expr_enum type;
1121
1122 r = GetInstanceRelation(relinst,&type);
1123 if (type!=e_token) {
1124 FPRINTF(ASCERR,"Invalid relation type in Infix_WriteRelation\n");
1125 return;
1126 }
1127 switch(RelationRelop(r)){
1128 case e_equal:
1129 case e_notequal:
1130 case e_less:
1131 case e_greater:
1132 case e_lesseq:
1133 case e_greatereq:
1134 Infix_WriteSide(f,r,Infix_LhsSide(r),ref);
1135 PUTC(' ',f);
1136 WriteOp(f,RelationRelop(r));
1137 PUTC(' ',f);
1138 Infix_WriteSide(f,r,Infix_RhsSide(r),ref);
1139 break;
1140 case e_maximize:
1141 case e_minimize:
1142 WriteOp(f,RelationRelop(r));
1143 PUTC(' ',f);
1144 Infix_WriteSide(f,r,Infix_LhsSide(r),ref);
1145 break;
1146 default:
1147 FPRINTF(ASCERR,"Unexpected Relop in Infix_WriteRelation\n");
1148 }
1149 }
1150
1151
1152 /*
1153 * KAA.
1154 * Just a dumb little note about writing out variable lists --
1155 * We need to check for the penultimate variable so that we
1156 * can know if we must write : "var, " or simply "var)".
1157 * One of doing this without having an if within the main loop
1158 * is to run from 1 to len-1, and then writing the last variable.
1159 * By running from 1 to len, if the length of the list is 0, we
1160 * automatically skip the loop. But by running from 1 to len-1,
1161 * we skip the loop, but have to then check that len was in fact
1162 * greater than 0, as gl_fetch(list,0) is not a pretty sight. Overall
1163 * we save len-1 ifs!! yaaaa!
1164 *
1165 * BAA
1166 * yah, that's it, optimize code way way way off the critical path
1167 * instead of doing things right. idiot.
1168 */
1169 static
1170 void WriteGlassBoxRelation(FILE *f,
1171 CONST struct relation *r,
1172 CONST struct Instance *ref)
1173 {
1174 struct ExternalFunc *efunc;
1175 CONST char *name;
1176 struct Instance *var;
1177 CONST struct gl_list_t *list;
1178 unsigned long len,c;
1179
1180 efunc = GlassBoxExtFunc(r);
1181 name = ExternalFuncName(efunc);
1182 FPRINTF(f,"%s(",name);
1183 if ((list = RelationVarList(r))) {
1184 len = gl_length(list);
1185 for (c=1;c<len;c++) { /* the < is intentional */
1186 var = (struct Instance *)gl_fetch(list,c);
1187 WriteInstanceName(f,var,ref);
1188 FPRINTF(f,", ");
1189 }
1190 if (len) { /* check length */
1191 var = (struct Instance *)gl_fetch(list,len);
1192 WriteInstanceName(f,var,ref);
1193 FPRINTF(f," ; %d)",GlassBoxRelIndex(r));
1194 }
1195 }
1196 else{
1197 FPRINTF(f," )");
1198 }
1199 WriteOp(f,RelationRelop(r));
1200 }
1201
1202 static void WriteGlassBoxRelationDS(Asc_DString *dsPtr,
1203 CONST struct relation *r,
1204 CONST struct Instance *ref)
1205 {
1206 struct ExternalFunc *efunc;
1207 CONST char *name;
1208 struct Instance *var;
1209 CONST struct gl_list_t *list;
1210 unsigned long len,c;
1211
1212 efunc = GlassBoxExtFunc(r);
1213 name = ExternalFuncName(efunc);
1214 Asc_DStringAppend(dsPtr,name,-1);
1215 Asc_DStringAppend(dsPtr,"(",1);
1216 if ((list = RelationVarList(r))) {
1217 len = gl_length(list);
1218 for (c=1;c<len;c++) { /* the < is intentional */
1219 var = (struct Instance *)gl_fetch(list,c);
1220 WriteInstanceNameDS(dsPtr,var,ref);
1221 Asc_DStringAppend(dsPtr,", ",2);
1222 }
1223 if (len) { /* check length */
1224 var = (struct Instance *)gl_fetch(list,len);
1225 WriteInstanceNameDS(dsPtr,var,ref);
1226 sprintf(SB255," ; %d)",GlassBoxRelIndex(r));
1227 Asc_DStringAppend(dsPtr,SB255,-1);
1228 }
1229 }
1230 else{
1231 Asc_DStringAppend(dsPtr," )",2);
1232 }
1233 WriteOpDS(dsPtr,RelationRelop(r),relio_ascend);
1234 }
1235
1236
1237 static
1238 void WriteBlackBoxRelation(FILE *f,
1239 CONST struct relation *r,
1240 CONST struct Instance *inst)
1241 {
1242 struct ExternalFunc *efunc;
1243 struct ExtCallNode *ext;
1244 struct gl_list_t *arglist;
1245 struct gl_list_t *branch;
1246 CONST struct Instance *arg;
1247 unsigned long len1,c1,len2,c2;
1248
1249 ext = BlackBoxExtCall(r);
1250 arglist = ExternalCallArgList(ext);
1251 len1 = gl_length(arglist);
1252 efunc = ExternalCallExtFunc(ext);
1253 FPRINTF(f," %s(",ExternalFuncName(efunc)); /* function name */
1254
1255 if (len1) {
1256 for (c1=1;c1<=len1;c1++) {
1257 branch = (struct gl_list_t *)gl_fetch(arglist,c1);
1258 if (branch) {
1259 len2 = gl_length(branch);
1260 for (c2=1;c2<len2;c2++) { /* < is intentional */
1261 arg = (struct Instance *)gl_fetch(branch,c2);
1262 WriteInstanceName(f,arg,inst);
1263 FPRINTF(f,", ");
1264 }
1265 if (len2) {
1266 arg = (struct Instance *)gl_fetch(branch,c2);
1267 WriteInstanceName(f,arg,inst);
1268 FPRINTF(f,"\n");
1269 }
1270 }
1271 if (c1==len1)
1272 FPRINTF(f,");\n");
1273 else
1274 FPRINTF(f,", ");
1275 }
1276 } else {
1277 FPRINTF(f,");\n ");
1278 }
1279 }
1280
1281 static
1282 void WriteBlackBoxRelationDS(Asc_DString *dsPtr,
1283 CONST struct relation *r,
1284 CONST struct Instance *inst)
1285 {
1286 struct ExternalFunc *efunc;
1287 struct ExtCallNode *ext;
1288 struct gl_list_t *arglist;
1289 struct gl_list_t *branch;
1290 CONST struct Instance *arg;
1291 unsigned long len1,c1,len2,c2;
1292
1293 ext = BlackBoxExtCall(r);
1294 arglist = ExternalCallArgList(ext);
1295 len1 = gl_length(arglist);
1296 efunc = ExternalCallExtFunc(ext);
1297 sprintf(SB255," %s(",ExternalFuncName(efunc)); /* function name */
1298 Asc_DStringAppend(dsPtr,SB255,-1);
1299
1300 if (len1) {
1301 for (c1=1;c1<=len1;c1++) {
1302 branch = (struct gl_list_t *)gl_fetch(arglist,c1);
1303 if (branch) {
1304 len2 = gl_length(branch);
1305 for (c2=1;c2<len2;c2++) { /* < is intentional */
1306 arg = (struct Instance *)gl_fetch(branch,c2);
1307 WriteInstanceNameDS(dsPtr,arg,inst);
1308 Asc_DStringAppend(dsPtr,", ",2);
1309 }
1310 if (len2) {
1311 arg = (struct Instance *)gl_fetch(branch,c2);
1312 WriteInstanceNameDS(dsPtr,arg,inst);
1313 Asc_DStringAppend(dsPtr,"\n",1);
1314 }
1315 }
1316 if (c1==len1)
1317 Asc_DStringAppend(dsPtr,");\n",3);
1318 else
1319 Asc_DStringAppend(dsPtr,", ",2);
1320 }
1321 } else {
1322 Asc_DStringAppend(dsPtr,");\n ",3);
1323 }
1324 }
1325
1326
1327 void WriteRelation(FILE *f, CONST struct Instance *relinst,
1328 CONST struct Instance *ref)
1329 {
1330 CONST struct relation *reln;
1331 enum Expr_enum reltype;
1332
1333 reln = GetInstanceRelation(relinst,&reltype);
1334 if (!reln) {
1335 FPRINTF(f,"NULL relation\n");
1336 return;
1337 }
1338 switch (reltype) {
1339 case e_token:
1340 WriteTokenRelation(f,reln,ref);
1341 return;
1342 case e_blackbox:
1343 WriteBlackBoxRelation(f,reln,ref);
1344 return;
1345 case e_glassbox:
1346 WriteGlassBoxRelation(f,reln,ref);
1347 return;
1348 default:
1349 FPRINTF(ASCERR,"Unknown relation type in WriteRelation\n");
1350 return;
1351 }
1352 }
1353
1354 char *WriteRelationString(CONST struct Instance *relinst,
1355 CONST struct Instance *ref,
1356 WRSNameFunc func, void *userdata,
1357 enum rel_lang_format lang,
1358 int *lenptr)
1359 {
1360 CONST struct relation *reln;
1361 enum Expr_enum reltype;
1362 static Asc_DString ds;
1363 Asc_DString *dsPtr;
1364 char *result;
1365
1366 reln = GetInstanceRelation(relinst,&reltype);
1367 if (!reln) {
1368 result = (char *) ascmalloc(15);
1369 if (result == NULL) return result;
1370 sprintf(result,"NULL relation\n");
1371 if (lenptr != NULL) {
1372 *lenptr = 14;
1373 }
1374 return result;
1375 }
1376
1377 dsPtr = &ds;
1378 Asc_DStringInit(dsPtr);
1379 switch (reltype) {
1380 case e_token:
1381 WriteTokenRelationDS(dsPtr,reln,ref,func,userdata,lang);
1382 break;
1383 case e_blackbox:
1384 WriteBlackBoxRelationDS(dsPtr,reln,ref);
1385 break;
1386 case e_glassbox:
1387 WriteGlassBoxRelationDS(dsPtr,reln,ref);
1388 break;
1389 default:
1390 FPRINTF(ASCERR,"Unknown relation type in WriteRelationString\n");
1391 if (lenptr != NULL) {
1392 *lenptr = -1;
1393 }
1394 return NULL;
1395 }
1396 if (lenptr != NULL) {
1397 *lenptr = Asc_DStringLength(dsPtr);
1398 }
1399 result = Asc_DStringResult(dsPtr);
1400 Asc_DStringFree(dsPtr);
1401 return result;
1402 }
1403
1404
1405 /*
1406 * some io to help in debugging relation manipulators.
1407 */
1408 static FILE *g_writfp = NULL;
1409 static void WriteIfRel(struct Instance *i)
1410 {
1411 struct Instance *p;
1412 char *string;
1413 struct RXNameData crd = {"x[",NULL,"]"};
1414 if (!i) {
1415 FPRINTF(ASCERR,"null child pointer in WriteIfRel\n");
1416 return;
1417 }
1418 if (InstanceKind(i)==REL_INST) {
1419 FPRINTF(g_writfp,"\n");
1420 WriteInstanceName(g_writfp,i,NULL);
1421 FPRINTF(g_writfp,"\n");
1422 p = InstanceParent(i,1);
1423 while (InstanceKind(p)!= MODEL_INST && InstanceKind(p) != SIM_INST) {
1424 p = InstanceParent(p,1);
1425 }
1426 FPRINTF(g_writfp,"INFIX\n");
1427 WriteRelation(g_writfp,i,p);
1428 FPRINTF(g_writfp,"\n");
1429 FFLUSH(g_writfp);
1430
1431 FPRINTF(g_writfp,"STRING-INFIX\n");
1432 string = WriteRelationString(i,p,NULL,NULL,relio_ascend,NULL);
1433 FPRINTF(g_writfp,"%s\n",(string==NULL)?"nullstring":string);
1434 if (string != NULL) {
1435 ascfree(string);
1436 }
1437 FFLUSH(g_writfp);
1438
1439 FPRINTF(g_writfp,"STRING-X-ASCEND\n");
1440 string = WriteRelationString(i,p,(WRSNameFunc)RelationVarXName,
1441 NULL,relio_ascend,NULL);
1442 FPRINTF(g_writfp,"%s\n",(string==NULL)?"nullstring":string);
1443 if (string != NULL) {
1444 ascfree(string);
1445 }
1446 FFLUSH(g_writfp);
1447
1448 FPRINTF(g_writfp,"STRING-C-pretty\n");
1449 string = WriteRelationString(i,p,(WRSNameFunc)RelationVarXName,
1450 (VOIDPTR)&crd,relio_C,NULL);
1451 print_long_string(g_writfp,string,60,8);
1452 FPRINTF(g_writfp,"STRING-C\n");
1453 FPRINTF(g_writfp,"%s\n",(string==NULL)?"nullstring":string);
1454 if (string != NULL) {
1455 ascfree(string);
1456 }
1457 FFLUSH(g_writfp);
1458
1459 FPRINTF(g_writfp,"POSTFIX\n");
1460 WriteRelationPostfix(g_writfp,i,p);
1461 FPRINTF(g_writfp,"\n");
1462 FFLUSH(g_writfp);
1463 }
1464 return;
1465 }
1466
1467 void WriteRelationsInTree(FILE *fp,struct Instance *i)
1468 {
1469 if (i==NULL || fp==NULL) return;
1470 g_writfp = fp;
1471 SlowVisitInstanceTree(i,WriteIfRel,0,0);
1472 }
1473
1474 void WriteRelationsInList(FILE *fp,struct gl_list_t *list)
1475 {
1476 if (list==NULL || fp==NULL) {
1477 return;
1478 }
1479 g_writfp = fp;
1480 gl_iterate(list,(void (*)(VOIDPTR))WriteIfRel);
1481 }
1482
1483
1484 /*
1485 *********************************************************************
1486 * Save Relation Code
1487 *
1488 * The below code is concerned with saving relations in a persistent
1489 * format. It writes out the code in a condensed format to allow
1490 * restoration to the original representation. A number of conversion
1491 * formats are provided. In particular, a token or opcode relation
1492 * may be saved as a glassbox relation, with the attendent loss of
1493 * information high level information.
1494 *
1495 * The grammar will follow later once it has stabilized.
1496 * In the mean time, the following keywords are used.
1497 * $KIND INTEGER - the reltype - e_token, e_opcode etc.
1498 * $RELOP INTEGER - the relational operator - e_maximize, e_equal etc.
1499 * $COUNT INTEGER - the number of variables.
1500 * $OPCODES INTEGER ':' (INTEGER)*
1501 * $VARIABLES ':' (INTEGER)* - global varindex
1502 * $CONSTANTS ':' (REAL)*
1503 *********************************************************************
1504 */
1505
1506 #undef LHS
1507 #undef RHS
1508 #define LHS 0
1509 #define RHS 1
1510 #define BREAKLINES 65
1511 static
1512 void SaveTokenRelnSide(FILE *fp,CONST struct relation *r,
1513 int side, struct gl_list_t *constants)
1514 {
1515 CONST struct relation_term *term;
1516 enum Expr_enum t;
1517 unsigned c,len;
1518 int count;
1519
1520 len = RelationLength(r,side);
1521 if (!len) return;
1522
1523 count = 16;
1524 FPRINTF(fp,"\t$OPCODES %d : ",side);
1525 for (c=1;c<=len;c++) {
1526 term = RelationTerm(r,c,side);
1527 t = RelationTermType(term);
1528 count += FPRINTF(fp," %d ",(int)t); /* the opcode is the enum */
1529 switch (t) {
1530 case e_var:
1531 count += FPRINTF(fp,"%lu",TermVarNumber(term));
1532 break;
1533 case e_func:
1534 count += FPRINTF(fp,"%d",(int)FuncId(TermFunc(term)));
1535 break;
1536 case e_int:
1537 case e_zero:
1538 case e_real:
1539 gl_append_ptr(constants,(VOIDPTR)term);
1540 count += FPRINTF(fp,"%lu",gl_length(constants));
1541 break;
1542 case e_uminus: /* DOUBLE CHECK -- KAA_DEBUG */
1543 case e_plus:
1544 case e_minus:
1545 case e_times:
1546 case e_divide:
1547 case e_power:
1548 case e_ipower:
1549 break;
1550 default:
1551 count += FPRINTF(fp,"%d",(int)e_nop);
1552 break;
1553 }
1554 if (count >= BREAKLINES) {
1555 PUTC('\n',fp); PUTC('\t',fp);
1556 count = 8;
1557 }
1558 }
1559 FPRINTF(fp,";\n"); /* terminate */
1560 }
1561
1562
1563 /*
1564 * We write out everybody as a floating point number. The
1565 * opcode will tell whether to coerce the double to a long
1566 * or vice verca.
1567 */
1568 static
1569 void SaveTokenConstants(FILE *fp, struct gl_list_t *constants)
1570 {
1571 CONST struct relation_term *term;
1572 unsigned long len,c;
1573
1574 len = gl_length(constants);
1575 if (!len) return;
1576
1577 FPRINTF(fp,"\t$CONSTANTS : ");
1578 for (c=1;c<=len;c++) {
1579 term = (CONST struct relation_term *)gl_fetch(constants,c);
1580 switch (RelationTermType(term)) {
1581 case e_zero:
1582 FPRINTF(fp,"%12.8e",0.0);
1583 break;
1584 case e_real:
1585 FPRINTF(fp,"%12.8e",TermReal(term));
1586 break;
1587 case e_int:
1588 FPRINTF(fp,"%12.8e",(double)TermInteger(term));
1589 break;
1590 default:
1591 Asc_Panic(2, NULL, "Illegal term in SaveTokenConstants\n");
1592 break;
1593 }
1594 PUTC(' ',fp);
1595 }
1596 FPRINTF(fp,";\n"); /* terminate */
1597 }
1598
1599 /*
1600 *********************************************************************
1601 * SaveRelationVariables
1602 *
1603 * This should be good for all types of relations, and the
1604 * conversions between those relations.
1605 *********************************************************************
1606 */
1607 void SaveRelationVariables(FILE *fp, CONST struct relation *r)
1608 {
1609 struct Instance *var;
1610 unsigned long len,c;
1611 int count;
1612 len = NumberVariables(r);
1613 if (!len) return;
1614
1615 count = 16;
1616 FPRINTF(fp,"\t$VARIABLES : ");
1617 for (c=1;c<=len;c++) {
1618 var = RelationVariable(r,c);
1619 count += FPRINTF(fp," %lu ",GetTmpNum(var));
1620 if (count >= BREAKLINES) {
1621 PUTC('\n',fp); PUTC('\t',fp);
1622 count = 8;
1623 }
1624 }
1625 FPRINTF(fp,";\n"); /* terminate */
1626 }
1627
1628 /*
1629 *********************************************************************
1630 * SaveTokenRelation
1631 *
1632 * Save a token relation in condensed opcode format.
1633 * Saving of dimensionality information is not done at the moment.
1634 *********************************************************************
1635 */
1636 void SaveTokenRelation(FILE *fp, CONST struct Instance *relinst)
1637 {
1638 CONST struct relation *reln;
1639 enum Expr_enum type;
1640 struct gl_list_t *constants = NULL;
1641
1642 reln = GetInstanceRelation(relinst,&type);
1643 if (type!=e_token) {
1644 FPRINTF(ASCERR,"Invalid relation type in SaveTokenRelation\n");
1645 return;
1646 }
1647 constants = gl_create(50L); /* overkill, but ... */
1648
1649 FPRINTF(fp,"$RELATION %lu {\n",GetTmpNum(relinst)); /* header */
1650 FPRINTF(fp,"\t$KIND %d, $RELOP %d, $COUNT %lu;\n",
1651 (int)type, (int)RelationRelop(reln), NumberVariables(reln));
1652 /*
1653 * Now write out the optional stuff.
1654 */
1655 SaveTokenRelnSide(fp,reln,LHS,constants);
1656 SaveTokenRelnSide(fp,reln,RHS,constants);
1657 SaveTokenConstants(fp,constants);
1658 SaveRelationVariables(fp,reln);
1659 FPRINTF(fp,"}\n\n"); /* the trailer */
1660
1661 gl_destroy(constants);
1662 }
1663
1664 /*
1665 *********************************************************************
1666 * SaveGlassBoxRelation
1667 *
1668 *********************************************************************
1669 */
1670 void SaveGlassBoxRelation(FILE *fp, CONST struct Instance *relinst)
1671 {
1672 CONST struct relation *reln;
1673 enum Expr_enum type;
1674 CONST char *tmp;
1675 int len;
1676
1677 reln = GetInstanceRelation(relinst,&type);
1678 len = GlassBoxNumberArgs(reln);
1679 if (len==0) return;
1680 if (NumberVariables(reln) != (unsigned long)len) {
1681 FPRINTF(ASCERR,"Corrupted arguements in glassbox relation\n");
1682 return;
1683 }
1684
1685 FPRINTF(fp,"$RELATION %lu {\n",GetTmpNum(relinst)); /* header */
1686 FPRINTF(fp,"\t$KIND %d, $RELOP %d, $COUNT %d;\n",
1687 (int)type, (int)RelationRelop(reln), len);
1688
1689 tmp = ExternalFuncName(GlassBoxExtFunc(reln));
1690 FPRINTF(fp,"\t$BASETYPE %s;\n",tmp); /* the funcname */
1691 FPRINTF(fp,"\t$INDEX %d\n",GlassBoxRelIndex(reln));
1692
1693 SaveRelationVariables(fp,reln);
1694 FPRINTF(fp,"}\n\n"); /* the trailer */
1695 }
1696
1697
1698 #ifdef THIS_IS_AN_UNUSED_FUNCTION
1699 /*
1700 * This function should be good enough to save token relations
1701 * and opcode relations to glassbox format. Blackbox relations
1702 * are not in order here.
1703 */
1704 static
1705 void Save__Reln2GlassBox(FILE *fp, CONST struct Instance *relinst,
1706 char *prefix, unsigned long index)
1707 {
1708 CONST struct relation *reln;
1709 enum Expr_enum type;
1710 unsigned long len;
1711
1712 reln = GetInstanceRelation(relinst,&type);
1713 assert(type!=e_blackbox);
1714 len = NumberVariables(reln);
1715 if (!len) return;
1716
1717 FPRINTF(fp,"$RELATION %lu {\n",GetTmpNum(relinst)); /* header */
1718 FPRINTF(fp,"\t$KIND %d, $RELOP %d, $COUNT %lu;\n",
1719 (int)type, (int)RelationRelop(reln), len);
1720 FPRINTF(fp,"\t$BASETYPE %s;\n",prefix); /* the funcname */
1721 FPRINTF(fp,"\t$INDEX %lu;\n",index);
1722
1723 SaveRelationVariables(fp,reln);
1724 FPRINTF(fp,"}\n\n"); /* the trailer */
1725 }
1726 #endif /* THIS_IS_AN_UNUSED_FUNCTION */
1727
1728
1729 /*
1730 *********************************************************************
1731 * SaveReln2GlassBox
1732 *
1733 * Save a relation and perform conversion to be able to restore it
1734 * as a glassbox.
1735 *********************************************************************
1736 */
1737 void SaveReln2GlassBox(FILE *fp, CONST struct Instance *relinst,
1738 char *prefix, unsigned long index_)
1739 {
1740 enum Expr_enum type;
1741
1742 type = GetInstanceRelationType(relinst);
1743 switch (type) {
1744 case e_token: /* token -> glassbox */
1745 case e_opcode: /* opcode -> glassbox */
1746 SaveReln2GlassBox(fp,relinst,prefix,index_);
1747 break;
1748 case e_glassbox:
1749 SaveGlassBoxRelation(fp,relinst); /* we will use the existing prefix */
1750 break;
1751 default:
1752 FPRINTF(ASCERR,"Relation type not supported in SaveGlassBox\n");
1753 break;
1754 }
1755 }
1756
1757 int ConversionIsValid(enum Expr_enum old, enum Expr_enum new)
1758 {
1759 if (new==old)
1760 return 1;
1761
1762 switch (old) {
1763 case e_token:
1764 if (new!=e_blackbox)
1765 return 1; /* we can handle all but blackboxes */
1766 return 0;
1767 case e_opcode: /* not fully supported yet */
1768 return 0;
1769 case e_glassbox:
1770 case e_blackbox:
1771 return 0;
1772 default:
1773 FPRINTF(ASCERR,"ConversionIsValid called with nonrelation type.\n");
1774 return 0;
1775 }
1776 }
1777
1778

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