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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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