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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1347 - (show annotations) (download) (as text)
Tue Mar 13 06:40:06 2007 UTC (13 years, 2 months ago) by jpye
File MIME type: text/x-csrc
File size: 45053 byte(s)
Added routine for outputting system as a DOT graph.
Changed an 'assert' to an 'asc_assert' in logrelation.c.
Changed logical relation in sequence.a4c (was causing a crash).
Added Simulation::write(FILE,char*) for outputting *stuff* from a simulation.
1 /*
2 * Logical Relation construction routines
3 * by Vicente Rico-Ramirez
4 * Version: $Revision: 1.18 $
5 * Version control file: $RCSfile: logrelation.c,v $
6 * Date last modified: $Date: 1998/02/20 02:10:24 $
7 * Last modified by: $Author: ballan $
8 *
9 * This file is part of the Ascend Language Interpreter.
10 *
11 * Copyright 1997, Carnegie Mellon University
12 *
13 *
14 * The Ascend Language Interpreter is free software; you can redistribute
15 * it and/or modify it under the terms of the GNU General Public License as
16 * published by the Free Software Foundation; either version 2 of the
17 * License, or (at your option) any later version.
18 *
19 * The Ascend Language Interpreter is distributed in hope that it will be
20 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with the program; if not, write to the Free Software Foundation,
26 * Inc., 675 Mass Ave, Cambridge, MA 02139 USA. Check the file named
27 * COPYING.
28 *
29 */
30
31 #include <stdarg.h>
32 #include <utilities/ascConfig.h>
33 #include <utilities/ascMalloc.h>
34 #include <utilities/ascPanic.h>
35 #include <general/pool.h>
36 #include <general/list.h>
37 #include <general/dstring.h>
38 #include <general/stack.h>
39
40 #include "functype.h"
41 #include "expr_types.h"
42 #include "name.h"
43 #include "exprs.h"
44 #include "sets.h"
45 #include "value_type.h"
46 #include "evaluate.h"
47 #include "forvars.h"
48 #include "find.h"
49 #include "logical_relation.h"
50 #include "relation_util.h"
51 #include "logrelation.h"
52 #include "logrel_util.h"
53 #include "rel_common.h"
54 #include "temp.h"
55 #include "instance_enum.h"
56 #include "instquery.h"
57 #include "mathinst.h"
58 #include "atomvalue.h"
59 #include "instance_io.h"
60
61
62 /*
63 * Some global and exported variables. */
64
65 /* boolean variables in the lofical relation */
66 struct gl_list_t *g_logrelation_bvar_list = NULL;
67 /* relations or logrelations in satisfied's exprssions */
68 struct gl_list_t *g_logrelation_satrel_list = NULL;
69
70
71 /*
72 * Simplification of Logical Equations not implemented yet
73 * We have to create
74 * the function SimplifyLogTermBuf (and subsidiary functions)
75 */
76 int g_simplify_logrelations = 0;
77
78 /*********************************************************************\
79 Section for creation and management of logical relation terms.
80 It is cheaper to create logical relation terms in arrays the size of
81 the union than individually because of operating system overhead.
82 Lookout, the tokens have unionized: next they'll want a raise.
83 \*********************************************************************/
84 /*
85 * The define POOL_ALLOCLOGTERM is for people who are pulling terms out
86 * of a pool and promise to return them immediately.
87 */
88
89 static pool_store_t g_logterm_pool = NULL;
90 /* A pool_store for 1 expression.
91 * Each time an expression is completed, it will be copied
92 * into an array which can be created already knowing
93 * its proper size. The array will be naturally in postfix.
94 */
95
96 #define POOL_ALLOCLOGTERM LOGA_TERM(pool_get_element(g_logterm_pool))
97 /* get a token. Token is the size of the LogRelTermUnion. */
98 #define POOL_LOGRESET pool_clear_store(g_logterm_pool)
99 /* reset the pool for next expression */
100
101 static struct {
102 long startcheck;
103 size_t len;
104 size_t cap;
105 struct logrel_term **buf;
106 unsigned long *termstack;
107 unsigned long termstackcap;
108 long endcheck;
109 } g_logterm_ptrs = {1234567890,0,0,NULL,NULL,0,987654321};
110
111 #define TPBUF_LOGRESET (g_logterm_ptrs.len=0)
112 /* forget about all the logical terms in the buffer */
113
114
115 /*
116 * The pool has a good growth mechanism and can handle tokens.
117 * Tradeoff: it is slower to copy the final token data into a
118 * fixed array from pool pointers than from a buffer monolith.
119 */
120 #define TPBUF_LOGINITSIZE 1000
121 /* initial token buffer capacity */
122 #define TPBUF_LOGGROW 1000
123 /* token buffer growth rate */
124
125 #define LOGRP_LEN 5
126 #if (SIZEOF_VOID_P == 8)
127 #define LOGRP_WID 41
128 #else
129 #define LOGRP_WID 63
130 #endif
131 /* retune rpwid if the size of tokens changes dramatically */
132 #define LOGRP_ELT_SIZE (sizeof(union LogRelTermUnion))
133 #define LOGRP_MORE_ELTS 5
134 /* Number of slots filled if more elements needed.
135 So if the pool grows, it grows by LOGRP_MORE_ELTS*LOGRP_WID elements
136 at a time. */
137 #define LOGRP_MORE_BARS 508
138 /* This is the number of pool bar slots to add during expansion.
139 not all the slots will be filled immediately. */
140
141 /* This function is called at compiler startup time and destroy at shutdown.
142 One could also recall these every time there is a delete all types. */
143 void InitLogRelInstantiator(void) {
144 if (g_logterm_pool != NULL || g_logterm_ptrs.buf != NULL) {
145 ASC_PANIC("ERROR: InitLogRelInstantiator called twice.\n");
146 }
147 g_logterm_pool =
148 pool_create_store(LOGRP_LEN, LOGRP_WID, LOGRP_ELT_SIZE, LOGRP_MORE_ELTS,
149 LOGRP_MORE_BARS);
150 if (g_logterm_pool == NULL) {
151 Asc_Panic(2, "InitLogRelInstantiator",
152 "ERROR: InitLogRelInstantiator unable to allocate pool.\n");
153 }
154 g_logterm_ptrs.buf = (struct logrel_term **)
155 ASC_NEW_ARRAY_CLEAR(union LogRelTermUnion *,TPBUF_LOGINITSIZE);
156 if (g_logterm_ptrs.buf == NULL) {
157 Asc_Panic(2, "InitLogRelInstantiator",
158 "ERROR: InitLogRelInstantiator unable to allocate memory.\n");
159 }
160 g_logterm_ptrs.len = 0;
161 g_logterm_ptrs.cap = TPBUF_LOGINITSIZE;
162 g_logterm_ptrs.termstackcap = 200;
163 g_logterm_ptrs.termstack = ASC_NEW_ARRAY(unsigned long,200);
164 if (g_logterm_ptrs.termstack == NULL) {
165 Asc_Panic(2, "InitLogRelInstantiator",
166 "ERROR: InitLogRelInstantiator unable to allocate memory.\n");
167 }
168 }
169
170 /* this function returns NULL when newcap is 0 or when
171 * it is unable to allocate the space requested.
172 */
173 static unsigned long *realloc_term_stack(unsigned long newcap){
174 if (!newcap) {
175 if (g_logterm_ptrs.termstackcap !=0) {
176 ascfree(g_logterm_ptrs.termstack);
177 g_logterm_ptrs.termstack = NULL;
178 g_logterm_ptrs.termstackcap = 0;
179 }
180 } else { /* less than means currently ok */
181 if (newcap >= g_logterm_ptrs.termstackcap) {
182 unsigned long *newbuf;
183 newbuf = (unsigned long *)
184 ascrealloc(g_logterm_ptrs.termstack,(sizeof(unsigned long)*newcap));
185 if (newbuf!=NULL) {
186 g_logterm_ptrs.termstack = newbuf;
187 g_logterm_ptrs.termstackcap = newcap;
188 } else {
189 FPRINTF(ASCERR,"Insufficient memory in logical relation processor\n");
190 return NULL;
191 }
192 }
193 }
194 return g_logterm_ptrs.termstack;
195 }
196
197 void DestroyLogRelInstantiator(void) {
198 assert(g_logterm_ptrs.buf!=NULL);
199 assert(g_logterm_pool!=NULL);
200 ascfree(g_logterm_ptrs.buf);
201 g_logterm_ptrs.buf = NULL;
202 g_logterm_ptrs.cap = g_logterm_ptrs.len = (size_t)0;
203 if (g_logterm_ptrs.termstackcap != 0) {
204 ascfree(g_logterm_ptrs.termstack);
205 g_logterm_ptrs.termstack = NULL;
206 g_logterm_ptrs.termstackcap = 0;
207 }
208 pool_destroy_store(g_logterm_pool);
209 g_logterm_pool = NULL;
210 }
211
212 void ReportLogRelInstantiator(FILE *f)
213 {
214 assert(g_logterm_pool!=NULL);
215 FPRINTF(f,"LogRelInstantiator ");
216 pool_print_store(f,g_logterm_pool,0);
217 FPRINTF(f,"LogRelInstantiator buffer capacity: %lu\n",
218 (unsigned long)g_logterm_ptrs.cap);
219 }
220
221 /* The slower expansion process. */
222 static void ExpandLogTermBuf(struct logrel_term *t) {
223 struct logrel_term **newbuf;
224 newbuf = (struct logrel_term **)ascrealloc(g_logterm_ptrs.buf,
225 (sizeof(struct logrel_term *)*(g_logterm_ptrs.cap+TPBUF_LOGGROW)));
226 if (newbuf!=NULL) {
227 g_logterm_ptrs.buf = newbuf;
228 g_logterm_ptrs.cap += TPBUF_LOGGROW;
229 g_logterm_ptrs.buf[g_logterm_ptrs.len] = t;
230 g_logterm_ptrs.len++;
231 } else {
232 FPRINTF(ASCERR,
233 "ERROR: LogicalRelation Instantiator unable to allocate memory.\n");
234 /* we have ignored the term pointer, but somebody else still has it: pool */
235 }
236 return;
237 }
238
239 /* Appends term to buffer. if buffer full and can't expand, forgets term.*/
240 static void AppendLogTermBuf(struct logrel_term *t) {
241 if (g_logterm_ptrs.len < g_logterm_ptrs.cap) {
242 g_logterm_ptrs.buf[g_logterm_ptrs.len++] = t;
243 } else {
244 ExpandLogTermBuf(t);
245 }
246 return;
247 }
248
249
250 struct logrel_side_temp {
251 unsigned long length;
252 union LogRelTermUnion *side;
253 };
254
255
256 /* forward declaration */
257 static struct logrel_term
258 *InfixArr_MakeLogSide(CONST struct logrel_side_temp *, int *);
259
260
261 /*
262 * returns 1 if converting buf is successful
263 * returns 0 if buf empty or insufficient memory.
264 * The structure tmp given is filled with an array of terms
265 * and its length. You must free the array if you decide you
266 * don't want it. We don't care how the structure is initialized.
267 */
268 static int ConvertLogTermBuf(struct logrel_side_temp *tmp)
269 {
270 union LogRelTermUnion *arr = NULL;
271 unsigned long len,c;
272
273 realloc_term_stack(0);
274 len = g_logterm_ptrs.len;
275 if (len < 1) return 0;
276 arr = ASC_NEW(union LogRelTermUnion);
277 if (arr==NULL) {
278 FPRINTF(ASCERR,"Create Logical Relation: Insufficient memory :-(.\n");
279 return 0;
280 }
281 for (c=0; c<len; c++) {
282 arr[c] = *(LOGUNION_TERM(g_logterm_ptrs.buf[c]));
283 }
284 tmp->side = arr;
285 tmp->length = len;
286 return 1;
287 }
288
289 /* usually we want to reset both simultaneously. reset our
290 pooling and buffering data. */
291 static
292 void DestroyLogTermList(void) {
293 POOL_LOGRESET;
294 TPBUF_LOGRESET;
295 }
296
297
298 /* create a term from the pool */
299 static struct logrel_term *CreateLogOpTerm(enum Expr_enum t)
300 {
301 struct logrel_term *term;
302 term = POOL_ALLOCLOGTERM;
303 assert(term!=NULL);
304 term->t = t;
305 if (t==e_not) {
306 LOGU_TERM(term)->left = NULL;
307 } else {
308 LOGB_TERM(term)->left = NULL;
309 LOGB_TERM(term)->right = NULL;
310 }
311 return term;
312 }
313
314 /* create a term from the pool */
315 static struct logrel_term *CreateBoolVarTerm(CONST struct Instance *i)
316 {
317 struct logrel_term *term;
318 unsigned long pos;
319 if (0 != (pos = gl_search(g_logrelation_bvar_list,i,(CmpFunc)CmpP))){
320 /* find boolean var if already on logical relations var list */
321 term = POOL_ALLOCLOGTERM;
322 assert(term!=NULL);
323 term->t = e_var;
324 LOGBV_TERM(term) -> varnum = pos;
325 }
326 else{
327 /* or add it to the var list */
328 gl_append_ptr(g_logrelation_bvar_list,(VOIDPTR)i);
329 term = POOL_ALLOCLOGTERM;
330 term->t = e_var;
331 LOGBV_TERM(term) -> varnum = gl_length(g_logrelation_bvar_list);
332 }
333 return term;
334 }
335
336
337 static struct logrel_term *CreateBooleanTerm( int val )
338 {
339 struct logrel_term *term;
340 term = POOL_ALLOCLOGTERM;
341 assert(term!=NULL);
342 term->t = e_boolean;
343 LOGBC_TERM(term) -> bvalue = val;
344 return term;
345 }
346
347 static struct logrel_term *CreateLogIntegerTerm( int val )
348 {
349 struct logrel_term *term;
350 term = POOL_ALLOCLOGTERM;
351 assert(term!=NULL);
352 term->t = e_int;
353 LOGI_TERM(term) -> ivalue = val;
354 return term;
355 }
356
357 /* create a term from the pool */
358 static struct logrel_term *CreateSatisfiedTerm(CONST struct Name *n,
359 struct Instance *inst,
360 double value,
361 CONST dim_type *dimensions)
362 {
363 struct logrel_term *term;
364 unsigned long pos;
365 if (0 != (pos = gl_search(g_logrelation_satrel_list,inst,(CmpFunc)CmpP))){
366 /* find log/relation if already on logical relations satrel list */
367 term = POOL_ALLOCLOGTERM;
368 assert(term!=NULL);
369 term->t = e_satisfied;
370 LOGS_TERM(term) ->ncond = n;
371 LOGS_TERM(term) ->relnum = pos;
372 LOGS_TERM(term) ->rtol = value;
373 LOGS_TERM(term) ->dim = dimensions;
374 }
375 else{
376 /* or add it to the satrel list */
377 gl_append_ptr(g_logrelation_satrel_list,(VOIDPTR)inst);
378 term = POOL_ALLOCLOGTERM;
379 term->t = e_satisfied;
380 LOGS_TERM(term) ->ncond = n;
381 LOGS_TERM(term) ->relnum = gl_length(g_logrelation_satrel_list);
382 LOGS_TERM(term) ->rtol = value;
383 LOGS_TERM(term) ->dim = dimensions;
384 }
385 return term;
386 }
387
388
389 /*
390 This function creates (and *must* create) the memory for the structure
391 and for the union that the stucuture points to. Too much code depends on
392 the pre-existence of a properly initialized union.
393 */
394 struct logrelation *CreateLogRelStructure(enum Expr_enum t)
395 {
396 struct logrelation *result;
397 result = ASC_NEW(struct logrelation);
398 asc_assert(result!=NULL);
399 memset((char *)&(result->token),0,sizeof(struct TokenLogRel));
400 result->logresidual = 0;
401 result->logiscond = 0;
402 result->lognominal = 1;
403 result->bvars = NULL;
404 result->satrels = NULL;
405 result->ref_count = 0;
406 result->relop = t;
407 return result;
408 }
409
410
411 /**************************************************************************\
412 Logical Relation processing and general logical relation check routines.
413 \**************************************************************************/
414
415 /*
416 * Here we give up if boolean vars are not well defined.
417 * At present e_var acceptable ARE:
418 * BOOLEAN_ATOM_INSTANCE
419 * Well defined boolean constants.
420 * Everything else is trash.
421 * CreateLogTermFromInst() and CheckLogExpr() must have matching semantics.
422 */
423 static
424 struct logrel_term *CreateLogTermFromInst(struct Instance *inst,
425 struct Instance *lrel,
426 enum logrelation_errors *err)
427 {
428 struct logrel_term *term;
429 switch(InstanceKind(inst)){
430 case BOOLEAN_ATOM_INST:
431 term = CreateBoolVarTerm(inst);
432 AddLogRel(inst,lrel);
433 return term;
434 case BOOLEAN_CONSTANT_INST:
435 if ( AtomAssigned(inst) ){
436 term = CreateBooleanTerm(GetBooleanAtomValue(inst));
437 return term;
438 }
439 else{
440 *err = boolean_value_undefined;
441 return NULL;
442 }
443 case BOOLEAN_INST:
444 *err = incorrect_boolean_linst_type;
445 return NULL;
446 case INTEGER_CONSTANT_INST:
447 case INTEGER_ATOM_INST:
448 case INTEGER_INST:
449 *err = incorrect_integer_linst_type;
450 return NULL;
451 case SYMBOL_ATOM_INST:
452 case SYMBOL_CONSTANT_INST:
453 case SYMBOL_INST:
454 *err = incorrect_symbol_linst_type;
455 return NULL;
456 case REAL_ATOM_INST:
457 case REAL_CONSTANT_INST:
458 case REAL_INST:
459 *err = incorrect_real_linst_type;
460 return NULL;
461 default:
462 *err = incorrect_linst_type;
463 return NULL;
464 }
465 }
466
467
468
469
470 /* nonrecursive, but may call recursive things. returns 1 if ok. 0 if not
471 * On a return of 1, newside->arr will be filled and should be deallocated
472 * if the user does not want it. a return of 0 means that newside data is
473 * invalid.
474 * This is the ONLY function that should call DestroyLogTermList.
475 */
476 static int ConvertLogExpr(CONST struct Expr *start,
477 CONST struct Expr *stop,
478 struct Instance *ref,
479 struct Instance *lrel,
480 enum logrelation_errors *err,
481 enum find_errors *ferr,
482 struct logrel_side_temp *newside)
483 {
484 struct gl_list_t *instances;
485 struct logrel_term *term;
486 struct Instance *inst;
487 CONST struct relation *rel;
488 CONST struct logrelation *logrel;
489 enum Expr_enum type;
490 int result;
491 symchar *str;
492 struct for_var_t *fvp;
493 if (newside==NULL) {
494 ASC_PANIC("newside == NULL");
495 }
496 while(start!=stop){
497 switch(ExprType(start)){
498 case e_and:
499 case e_or:
500 case e_not:
501 term = CreateLogOpTerm(ExprType(start));
502 AppendLogTermBuf(term);
503 break;
504 case e_var:
505 if (GetEvaluationForTable()!= NULL &&
506 (NULL != (str = SimpleNameIdPtr(ExprName(start)))) &&
507 (NULL != (fvp=FindForVar(GetEvaluationForTable(),str)))){
508 if (GetForKind(fvp)==f_integer){
509 term = CreateLogIntegerTerm(GetForInteger(fvp));
510 AppendLogTermBuf(term);
511 }
512 else{
513 *err = incorrect_linst_type;
514 DestroyLogTermList();
515 return 0;
516 }
517 }
518 else{
519 instances = FindInstances(ref,ExprName(start),ferr);
520 if (instances!=NULL){
521 if (gl_length(instances)==1){
522 inst = (struct Instance *)gl_fetch(instances,1);
523 gl_destroy(instances);
524 if ((term = CreateLogTermFromInst(inst,lrel,err))!=NULL){
525 AppendLogTermBuf(term);
526 }
527 else{
528 DestroyLogTermList();
529 return 0;
530 }
531 }
532 else{
533 *err=incorrect_logstructure;
534 gl_destroy(instances);
535 DestroyLogTermList();
536 return 0;
537 }
538 }
539 else{
540 *err = find_logerror;
541 DestroyLogTermList();
542 return 0;
543 }
544 }
545 break;
546 case e_boolean:
547 term = CreateBooleanTerm(ExprBValue(start));
548 AppendLogTermBuf(term);
549 break;
550 case e_satisfied:
551 instances = FindInstances(ref,SatisfiedExprName(start),ferr);
552 if (instances == NULL){
553 *err = find_logerror;
554 gl_destroy(instances);
555 DestroyLogTermList();
556 return 0;
557 }
558 else{
559 if (gl_length(instances)==1) {
560 inst = (struct Instance *)gl_fetch(instances,1);
561 gl_destroy(instances);
562 switch(InstanceKind(inst)){
563 case REL_INST:
564 rel = GetInstanceRelation(inst,&type);
565 if (!RelationIsCond(rel)){
566 *err = incorrect_linst_type;
567 DestroyLogTermList();
568 return 0;
569 }
570 break;
571 case LREL_INST:
572 logrel = GetInstanceLogRel(inst);
573 if (!LogRelIsCond(logrel)){
574 *err = incorrect_linst_type;
575 DestroyLogTermList();
576 return 0;
577 }
578 break;
579 default:
580 *err = incorrect_linst_type;
581 DestroyLogTermList();
582 return 0;
583 }
584 }
585 else {
586 gl_destroy(instances);
587 *err=incorrect_logstructure;
588 return 0;
589 }
590 }
591 term = CreateSatisfiedTerm(SatisfiedExprName(start),
592 inst,
593 SatisfiedExprRValue(start),
594 SatisfiedExprRDimensions(start));
595 AddLogRel(inst,lrel);
596 AppendLogTermBuf(term);
597 break;
598 default:
599 *err = incorrect_logstructure;
600 DestroyLogTermList();
601 return 0;
602 }
603 start = NextExpr(start);
604 }
605 result = ConvertLogTermBuf(newside);
606 DestroyLogTermList();
607 return result;
608 /* we do not check result here. that is the callers job */
609 }
610
611 static
612 CONST struct Expr *FindLogRHS(CONST struct Expr *ex)
613 {
614 CONST struct Expr *rhs = NULL,*previous=NULL;
615 unsigned depth=0;
616 while(ex!=NULL){
617 switch(ExprType(ex)){
618 case e_zero:
619 case e_var:
620 case e_int:
621 case e_real:
622 case e_boolean:
623 case e_set:
624 case e_symbol:
625 case e_card:
626 case e_choice:
627 case e_sum:
628 case e_prod:
629 case e_union:
630 case e_satisfied:
631 if ((++depth)==1) rhs = ex;
632 break;
633 /* binary operators */
634 case e_plus:
635 case e_minus:
636 case e_times:
637 case e_divide:
638 case e_power:
639 case e_ipower:
640 case e_or:
641 case e_and:
642 case e_in:
643 if ((--depth)==1) rhs = ex;
644 break;
645 case e_equal:
646 case e_notequal:
647 case e_boolean_eq:
648 case e_boolean_neq:
649 case e_less:
650 case e_greater:
651 case e_lesseq:
652 case e_greatereq:
653 if (NextExpr(ex)==NULL) {
654 return NextExpr(rhs);
655 } else {
656 return NULL;
657 }
658 case e_func:
659 case e_uminus:
660 case e_not:
661 if (depth==1) {
662 rhs = ex;
663 }
664 break;
665 case e_st:
666 ASC_PANIC("Such that expressions are not allowed.\n");
667 break;
668 case e_minimize:
669 case e_maximize:
670 Asc_Panic(2, NULL,
671 "Maximize and minimize are not allowed in expression.\n"
672 "They are only allowed in relations.\n");
673 break;
674 default:
675 ASC_PANIC("Unknown expression node type.\n");
676 break;
677 }
678 previous = ex;
679 ex = NextExpr(ex);
680 }
681 return NULL;
682 }
683
684 /*********************************************************************\
685 This code is to support the conversion from postfix to infix.
686 \*********************************************************************/
687
688 static void DoBreakPoint(void)
689 {
690 FPRINTF(ASCERR,"Something screwy with Infix_MakeLogSide\n");
691 return;
692 }
693
694 #define PopLogTermStack(stack) \
695 ((struct logrel_term *)gs_stack_pop((stack)))
696 #define PushLogTermStack(stack,term) \
697 (gs_stack_push((stack),(char*)(term)))
698
699 #if 0 /* defunct code. should be deleted? */
700 struct logrel_term *Infix_MakeLogSide(struct gl_list_t *term_list)
701 {
702 struct logrel_term *term = NULL;
703 struct logrel_term *left;
704 unsigned long len,count=1;
705 struct gs_stack_t *stack;
706 enum Expr_enum t;
707
708 len = gl_length(term_list);
709 stack = gs_stack_create(len);
710 while(count <= len) {
711 term = (struct logrel_term *)gl_fetch(term_list,count);
712 switch(t = LogRelTermType(term)) {
713 case e_boolean:
714 case e_var:
715 gs_stack_push(stack,(char *)term);
716 break;
717 case e_satisfied:
718 gs_stack_push(stack,(char *)term);
719 break;
720 case e_not:
721 left = LOGA_TERM(gs_stack_pop(stack));
722 LOGU_TERM(term)-> left = left;
723 gs_stack_push(stack,(char *)term);
724 break;
725 case e_and:
726 case e_or:
727 LOGB_TERM(term) -> right = LOGA_TERM(gs_stack_pop(stack));
728 LOGB_TERM(term) -> left = LOGA_TERM(gs_stack_pop(stack));
729 gs_stack_push(stack,(char *)term);
730 break;
731 default:
732 Asc_Panic(2, NULL,
733 "Dont know this type of logical relation term in MakeInfix\n");
734 break;
735 }
736 count++;
737 }
738 term = LOGA_TERM(gs_stack_pop(stack));
739 if (!gs_stack_empty(stack)) /* ensure that the stack is empty */
740 DoBreakPoint();
741 gs_stack_destroy(stack,0);
742 return term;
743 }
744 #endif
745
746 /*
747 * *err = 0 if ok, 1 otherwise. Sets up infix pointers.
748 */
749 static struct logrel_term
750 *InfixArr_MakeLogSide(CONST struct logrel_side_temp *tmp, int *err)
751 {
752 struct logrel_term *term = NULL;
753 struct logrel_term *left;
754 long len,count=0;
755 struct gs_stack_t *stack;
756 enum Expr_enum t;
757
758 *err = 0;
759 len = tmp->length;
760 stack = gs_stack_create(len);
761 while(count < len) {
762 term = LOGA_TERM(&(tmp->side[count])); /* aka tmp->side+count */
763 switch(t = LogRelTermType(term)) {
764 case e_boolean:
765 case e_var:
766 gs_stack_push(stack,(char *)term);
767 break;
768 case e_satisfied:
769 gs_stack_push(stack,(char *)term);
770 break;
771 case e_not:
772 left = LOGA_TERM(gs_stack_pop(stack));
773 LOGU_TERM(term)->left = left;
774 gs_stack_push(stack,(char *)term);
775 break;
776 case e_and:
777 case e_or:
778 LOGB_TERM(term)->right = LOGA_TERM(gs_stack_pop(stack));
779 LOGB_TERM(term)->left = LOGA_TERM(gs_stack_pop(stack));
780 gs_stack_push(stack,(char *)term);
781 break;
782 default:
783 Asc_Panic(2, NULL,
784 "Dont know this type of logical relation term in MakeInfix\n");
785 break;
786 }
787 count++;
788 }
789 term = LOGA_TERM(gs_stack_pop(stack));
790 if (!gs_stack_empty(stack)) {
791 /* ensure that the stack is empty */
792 FPRINTF(ASCERR,"stacksize %ld\n",stack->size);
793 DoBreakPoint();
794 *err = 1;
795 }
796 gs_stack_destroy(stack,0);
797 return term;
798 }
799
800 void DoInOrderLogRelVisit(struct logrel_term *term,
801 struct logrelation *r,
802 void (*func)(struct logrel_term *,
803 struct logrelation *))
804 {
805 if (term) {
806 switch(LogRelTermType(term)) {
807 case e_boolean:
808 case e_var:
809 (*func)(term,r);
810 break;
811 case e_satisfied:
812 (*func)(term,r);
813 break;
814 case e_not:
815 DoInOrderLogRelVisit(LOGU_TERM(term)->left,r,func);
816 (*func)(term,r);
817 break;
818 case e_and:
819 case e_or:
820 DoInOrderLogRelVisit(LOGB_TERM(term)->left,r,func);
821 (*func)(term,r);
822 DoInOrderLogRelVisit(LOGB_TERM(term)->right,r,func);
823 break;
824 default:
825 return;
826 }
827 }
828 }
829
830 #if 0
831 /* This is a recursive deallocation of a term tree.
832 It presupposes all terms are independently allocated,
833 which at present is true nowhere in the compiler.
834 It's a nice little function, though so we'll keep it in case,
835 but not compile it in the meantime.
836 Token of logrelations term lists are not independently allocated.
837 */
838 void DestroyLogTermTree(struct logrel_term *term)
839 {
840 if (term) {
841 switch(term->t) {
842 case e_and:
843 case e_or:
844 DestroyLogTermTree(LOGB_TERM(term)->left);
845 DestroyLogTermTree(LOGB_TERM(term)->right);
846 ascfree((char *)term);
847 term = NULL;
848 break;
849 case e_satisfied:
850 ascfree((char *)term);
851 term = NULL;
852 break;
853 case e_not:
854 DestroyLogTermTree(LOGU_TERM(term)->left);
855 break;
856 case e_boolean:
857 case e_var:
858 ascfree((char *)term);
859 term = NULL;
860 break;
861 default:
862 FPRINTF(ASCERR,"DestroyLogTermTree called with unexpected term type\n");
863 break;
864 }
865 }
866 }
867 #endif
868
869
870 /*********************************************************************\
871 Relation Processing for Instantiation.
872 \*********************************************************************/
873 static void DestroyLogTermSide(struct logrel_side_temp *);
874 void DestroyBVarList(struct gl_list_t *, struct Instance *);
875 void DestroySatRelList(struct gl_list_t *, struct Instance *);
876
877 struct logrelation *CreateLogicalRelation(struct Instance *reference,
878 struct Instance *lrelinst,
879 CONST struct Expr *ex,
880 enum logrelation_errors *err,
881 enum find_errors *ferr)
882 {
883 struct logrelation *result;
884 CONST struct Expr *rhs_ex,*last_ex;
885 int lhs,rhs;
886 enum Expr_enum type;
887 struct logrel_side_temp leftside,rightside;
888 assert(reference&&lrelinst&&ex&&err&&ferr);
889 g_logrelation_bvar_list = gl_create(20l);
890 g_logrelation_satrel_list = gl_create(2l);
891 *err = lokay;
892 *ferr = correct_instance;
893 last_ex = FindLastExpr(ex);
894 switch(ExprType(last_ex)){
895 case e_boolean_eq:
896 case e_boolean_neq:
897 type = ExprType(last_ex);
898 rhs_ex = FindLogRHS(ex);
899 if (rhs_ex!=NULL){
900 lhs = ConvertLogExpr(ex,rhs_ex,reference,lrelinst,err,ferr,&leftside);
901 if(!lhs) {
902 if (g_logrelation_bvar_list!=NULL) {
903 DestroyBVarList(g_logrelation_bvar_list,lrelinst);
904 }
905 g_logrelation_bvar_list = NULL;
906 if (g_logrelation_satrel_list!=NULL) {
907 DestroySatRelList(g_logrelation_satrel_list,lrelinst);
908 }
909 g_logrelation_satrel_list = NULL;
910 return NULL;
911 }
912 rhs = ConvertLogExpr(rhs_ex,last_ex,reference,lrelinst,err,
913 ferr,&rightside);
914 if(!rhs) {
915 DestroyLogTermSide(&leftside);
916 if (g_logrelation_bvar_list!=NULL) {
917 DestroyBVarList(g_logrelation_bvar_list,lrelinst);
918 }
919 g_logrelation_bvar_list = NULL;
920 if (g_logrelation_satrel_list!=NULL) {
921 DestroySatRelList(g_logrelation_satrel_list,lrelinst);
922 }
923 g_logrelation_satrel_list = NULL;
924 return NULL;
925 }
926 }
927 else{
928 *err = incorrect_logstructure;
929 FPRINTF(ASCERR,"Error finding logical relation operator.\n");
930 if (g_logrelation_bvar_list!=NULL) {
931 DestroyBVarList(g_logrelation_bvar_list,lrelinst);
932 }
933 g_logrelation_bvar_list = NULL;
934 if (g_logrelation_satrel_list!=NULL) {
935 DestroySatRelList(g_logrelation_satrel_list,lrelinst);
936 }
937 g_logrelation_satrel_list = NULL;
938 return NULL;
939 }
940 break;
941 default:
942 *err = incorrect_logstructure;
943 ERROR_REPORTER_NOLINE(ASC_USER_ERROR,"Expression missing logical relation operator.");
944 if (g_logrelation_bvar_list!=NULL) {
945 DestroyBVarList(g_logrelation_bvar_list,lrelinst);
946 }
947 g_logrelation_bvar_list = NULL;
948 if (g_logrelation_satrel_list!=NULL) {
949 DestroySatRelList(g_logrelation_satrel_list,lrelinst);
950 }
951 g_logrelation_satrel_list = NULL;
952 return NULL;
953 }
954 result = CreateLogRelStructure(type);
955 result->ref_count = 1;
956 if (lhs) {
957 int status;
958 result->token.lhs_len = leftside.length;
959 result->token.lhs = leftside.side;
960 result->token.lhs_term = InfixArr_MakeLogSide(&leftside,&status);
961 #ifndef NDEBUG
962 if (status) {
963 FPRINTF(ASCERR,"Anomaly in ");
964 WriteInstanceName(ASCERR,lrelinst,NULL);
965 FPRINTF(ASCERR," LHS.\n");
966 }
967 #endif
968 }
969 if (rhs) { /* sometimes true */
970 int status;
971 result->token.rhs_len = rightside.length;
972 result->token.rhs = rightside.side;
973 result->token.rhs_term = InfixArr_MakeLogSide(&rightside,&status);
974 #ifndef NDEBUG
975 if (status) {
976 FPRINTF(ASCERR,"Anomaly in ");
977 WriteInstanceName(ASCERR,lrelinst,NULL);
978 FPRINTF(ASCERR," RHS.\n");
979 }
980 #endif
981 }
982 result->bvars = g_logrelation_bvar_list;
983 result->satrels = g_logrelation_satrel_list;
984 g_logrelation_bvar_list = NULL;
985 g_logrelation_satrel_list = NULL;
986 return result;
987 }
988
989
990 /*
991 **************************************************************************
992 * Destroy Code.
993 *
994 * This takes care of destroying the parts of logical relations.
995 * It ensures that any variables that are
996 * incident upon the logical relations have their logrelation references
997 * removed. This is done using the RemoveLogRel function.
998 * It also ensures that all the relations or logrelations referenced
999 * (from SATISFIED operator) have their logrelation references
1000 * removed, using the RemoveLogRel function too.
1001 **************************************************************************
1002 */
1003
1004 static void DestroyLogTermSide(struct logrel_side_temp *temp)
1005 {
1006 if (temp!=NULL){
1007 if (temp->side !=NULL) ascfree(temp->side);
1008 }
1009 temp->side=NULL;
1010 temp->length=0L;
1011 }
1012
1013 void DestroyBVarList(struct gl_list_t *l, struct Instance *inst)
1014 {
1015 register struct Instance *ptr;
1016 register unsigned long c;
1017 for(c=gl_length(l);c>=1;c--)
1018 if (NULL != (ptr = (struct Instance *)gl_fetch(l,c)))
1019 RemoveLogRel(ptr,inst);
1020 gl_destroy(l);
1021 }
1022
1023 void DestroySatRelList(struct gl_list_t *l, struct Instance *inst)
1024 {
1025 register struct Instance *ptr;
1026 register unsigned long c;
1027 for(c=gl_length(l);c>=1;c--)
1028 if (NULL != (ptr = (struct Instance *)gl_fetch(l,c)))
1029 RemoveLogRel(ptr,inst);
1030 gl_destroy(l);
1031 }
1032
1033 void DestroyLogRelation(struct logrelation *lrel, struct Instance *lrelinst)
1034 {
1035 if (!lrel) return;
1036 assert(lrel->ref_count);
1037 if (--(lrel->ref_count)==0) {
1038 if (lrel->token.lhs!=NULL) ascfree(lrel->token.lhs);
1039 if (lrel->token.rhs!=NULL) ascfree(lrel->token.rhs);
1040 }
1041 if (lrel->bvars) DestroyBVarList(lrel->bvars,lrelinst);
1042 if (lrel->satrels) DestroySatRelList(lrel->satrels,lrelinst);
1043 ascfree((char *)lrel);
1044 }
1045
1046
1047 /*
1048 **************************************************************************
1049 * Variable Maintenance.
1050 *
1051 * Logical Relations need to keep a *unique* list of variables incident
1052 * upon them. However variables move around and also disappear,
1053 * in particular when being ARE_THE_SAME'd. This code does that variable
1054 * maintenance.
1055 *
1056 * This requires some explanation. There are a number of cases
1057 * to consider.
1058 *
1059 * 1) the old instance does not exist in the bvar list -- do nothing.
1060 *
1061 * 2) the old instance exists, but the new does not -- store the
1062 * the new instance in the slot where the old instance was and
1063 * return.
1064 *
1065 * 3) the old instance exists, *and* the new instance also exists in
1066 * the bvarlist. This can happen in the case when 2 variables
1067 * incident upon a logical relation are going to be ATS'ed (not wise
1068 * but possible.) We need to run down the entire list in the case
1069 * of logical relations. This is expensive and uses the
1070 * DeleteAndChange function.
1071 *
1072 * 4) the new instance is NULL, which can happen transiently during some
1073 * operations. This defaults to case 2).
1074 **************************************************************************
1075 */
1076
1077
1078 static
1079 void ChangeLogVarTermSide(union LogRelTermUnion *side,
1080 unsigned long int len,
1081 unsigned long int old,
1082 unsigned long int new)
1083 {
1084 register long c;
1085 register struct logrel_term *term;
1086 for(c=len-1;c>=0;c--){
1087 term = LOGA_TERM(&(side[c]));
1088 switch (term->t){
1089 case e_var:
1090 if (LOGBV_TERM(term)->varnum == old)
1091 LOGBV_TERM(term)->varnum = new;
1092 else
1093 if (LOGBV_TERM(term)->varnum > old) LOGBV_TERM(term)->varnum--;
1094 break;
1095 default:
1096 break;
1097 }
1098 }
1099 }
1100
1101
1102 static
1103 void ChangeLogSatTermSide(union LogRelTermUnion *side,
1104 unsigned long int len,
1105 unsigned long int old,
1106 unsigned long int new)
1107 {
1108 register long c;
1109 register struct logrel_term *term;
1110 for(c=len-1;c>=0;c--){
1111 term = LOGA_TERM(&(side[c]));
1112 switch (term->t){
1113 case e_satisfied:
1114 if (LOGS_TERM(term)->relnum == old)
1115 LOGS_TERM(term)->relnum = new;
1116 else
1117 if (LOGS_TERM(term)->relnum > old) LOGS_TERM(term)->relnum--;
1118 break;
1119 default:
1120 break;
1121 }
1122 }
1123 }
1124
1125
1126 static
1127 void LogDeleteAndChange(struct gl_list_t *relorvar, struct logrelation *lrel,
1128 unsigned long int pos1, unsigned long int pos2,
1129 int varflag)
1130 {
1131 if (pos1 < pos2) Swap(&pos1,&pos2);
1132 /* pos1 > pos2 now */
1133 gl_delete(relorvar,pos1,0);
1134 if (varflag) {
1135 if (lrel->token.rhs)
1136 ChangeLogVarTermSide(lrel->token.rhs,lrel->token.rhs_len,pos1,pos2);
1137 if (lrel->token.lhs)
1138 ChangeLogVarTermSide(lrel->token.lhs,lrel->token.lhs_len,pos1,pos2);
1139 }
1140 else {
1141 if (lrel->token.rhs)
1142 ChangeLogSatTermSide(lrel->token.rhs,lrel->token.rhs_len,pos1,pos2);
1143 if (lrel->token.lhs)
1144 ChangeLogSatTermSide(lrel->token.lhs,lrel->token.lhs_len,pos1,pos2);
1145 }
1146 }
1147
1148 void ModifyLogRelPointers(struct gl_list_t *relorvar,
1149 struct logrelation *lrel,
1150 CONST struct Instance *old,
1151 CONST struct Instance *new)
1152 {
1153 unsigned long pos,other;
1154 CONST struct Instance *inst;
1155 int varflag;
1156 assert(lrel!=NULL);
1157
1158 if (old==new) return;
1159
1160 if (new){
1161 if (0 != (pos = gl_search(relorvar,old,(CmpFunc)CmpP))) {
1162 if (0 != (other = gl_search(relorvar,new,(CmpFunc)CmpP))){
1163 gl_store(relorvar,pos,(VOIDPTR)new); /* case 3 */
1164 if (new == NULL) {
1165 inst = old;
1166 }
1167 else {
1168 inst = new;
1169 }
1170 switch (inst->t) {
1171 case BOOLEAN_ATOM_INST:
1172 varflag = 1;
1173 LogDeleteAndChange(relorvar,lrel,pos,other,varflag);
1174 break;
1175 case REL_INST:
1176 case LREL_INST:
1177 varflag = 0;
1178 LogDeleteAndChange(relorvar,lrel,pos,other,varflag);
1179 break;
1180 default:
1181 Asc_Panic(2, NULL,
1182 "Wrong instance type passed to ChangeLogRelPointers\n");
1183 break;
1184 }
1185 }
1186 else
1187 gl_store(relorvar,pos,(char *)new); /* case 2 */
1188 }
1189 else{ /* case 1 */
1190 FPRINTF(ASCERR,"Warning ModifiyLogRelPointers not found.\n");
1191 FPRINTF(ASCERR,"This shouldn't effect your usage at all.\n");
1192 }
1193 }
1194 else /* case 4 */
1195 if (0 != (pos = gl_search(relorvar,old,(CmpFunc)CmpP)))
1196 gl_store(relorvar,pos,(VOIDPTR)new);
1197 }
1198
1199
1200 /* forward declaration for recursing Check functions of logical relation */
1201 static int
1202 CheckLogExpr(CONST struct Instance *ref, CONST struct Expr *start,
1203 CONST struct Expr *stop, int list);
1204
1205
1206 /**********************************************************************\
1207 Here we check that vars are well defined, a precondition to FOR
1208 statements being executed.
1209 If lists of vars are acceptable (don't know why they would be)
1210 list should be passed in as 1, otherwise 0.
1211 At present e_var acceptable ARE:
1212 BOOLEAN_ATOM_INSTANCE
1213 Well defined Boolean constants.
1214 CreateLogTermFromInst() and CheckLogExpr() must have matching semantics.
1215
1216 Returns: 1 --> OK,
1217 0 --> BAD (undefined/unassigned) try again later
1218 -1 --> incurably BAD
1219 \**********************************************************************/
1220 static int CheckExprBVar(CONST struct Instance *ref, CONST struct Name *name,
1221 int list)
1222 {
1223 struct gl_list_t *instances;
1224 symchar *str;
1225 struct Instance *inst;
1226 struct for_var_t *fvp;
1227 enum find_errors err;
1228 if(NULL != (str = SimpleNameIdPtr(name))){
1229 if (TempExists(str)) {
1230 if (ValueKind(TempValue(str))==integer_value) {
1231 return 1;
1232 } else {
1233 return -1;
1234 }
1235 }
1236 if (GetEvaluationForTable() != NULL &&
1237 (NULL != (fvp=FindForVar(GetEvaluationForTable(),str))) ) {
1238 if (GetForKind(fvp)==f_integer) {
1239 return 1;
1240 } else {
1241 return -1;
1242 }
1243 }
1244 }
1245 instances = FindInstances(ref,name,&err); /* need noisy version of Find */
1246 if (instances == NULL){
1247 switch(err){
1248 case unmade_instance:
1249 case undefined_instance:
1250 return 0;
1251 default:
1252 return -1;
1253 }
1254 }
1255 else{
1256 if (gl_length(instances)==1) {
1257 inst = (struct Instance *)gl_fetch(instances,1);
1258 gl_destroy(instances);
1259 switch(InstanceKind(inst)){
1260 case BOOLEAN_ATOM_INST:
1261 return 1;
1262 case DUMMY_INST:
1263 return 1;
1264 case BOOLEAN_CONSTANT_INST:
1265 if (AtomAssigned(inst)) {
1266 return 1;
1267 }
1268 return 0;
1269 default: return -1; /* bogus var type found */
1270 }
1271 }
1272 else if (list){
1273 /* this part of the code is most peculiar, and semantics may not
1274 match it. We need to find out what is the semantics of list. */
1275 unsigned long c,len;
1276 len = gl_length(instances);
1277 for(c=1;c<=len;c++){
1278 inst = (struct Instance *)gl_fetch(instances,1);
1279 switch(InstanceKind(inst)){
1280 case BOOLEAN_ATOM_INST:
1281 break;
1282 case DUMMY_INST:
1283 break;
1284 case BOOLEAN_CONSTANT_INST:
1285 if (!AtomAssigned(inst)){
1286 gl_destroy(instances);
1287 return -1;
1288 }
1289 default:
1290 gl_destroy(instances);
1291 return 0;
1292 }
1293 }
1294 gl_destroy(instances);
1295 return 1;
1296 }
1297 else {
1298 gl_destroy(instances);
1299 return -1;
1300 }
1301 }
1302 }
1303
1304
1305 static int CheckExprSatisfied(CONST struct Instance *ref,
1306 CONST struct Name *name)
1307 {
1308 struct gl_list_t *instances;
1309 struct Instance *inst;
1310 enum find_errors err;
1311
1312 instances = FindInstances(ref,name,&err);
1313 if (instances == NULL){
1314 gl_destroy(instances);
1315 FPRINTF(ASCERR,
1316 "Name of an unmade instance (Relation) in Satisfied Expr \n");
1317 return 0;
1318 }
1319 else{
1320 if (gl_length(instances)==1) {
1321 inst = (struct Instance *)gl_fetch(instances,1);
1322 gl_destroy(instances);
1323 switch(InstanceKind(inst)){
1324 case REL_INST:
1325 return 1;
1326 case LREL_INST:
1327 return 1;
1328 case DUMMY_INST:
1329 return 1;
1330 default:
1331 FPRINTF(ASCERR,
1332 "Incorrect instance name (No Log/Relation)"
1333 " inside a Satisfied Expr\n");
1334 return 0;
1335 }
1336 }
1337 else {
1338 gl_destroy(instances);
1339 FPRINTF(ASCERR,
1340 "Error in Satisfied Expr Name assigned to more than one instance\n");
1341 return 0;
1342 }
1343 }
1344 }
1345
1346
1347 /**********************************************************************\
1348 CheckLogExpr(ref, start, stop, list)
1349 struct Instance *ref; context of the logical relation instance, ie
1350 parent. int list; boolean whether list of instances are acceptable
1351 struct Expr *start, *stop; pointers to the portion of relation this
1352 checks.
1353 \**********************************************************************/
1354 static int CheckLogExpr(CONST struct Instance *ref,
1355 CONST struct Expr *start,
1356 CONST struct Expr *stop,
1357 int list)
1358 {
1359 while (start!=stop){
1360 switch(ExprType(start)){
1361 case e_not:
1362 case e_and:
1363 case e_or:
1364 case e_boolean:
1365 break; /* automatically okay! */
1366 case e_satisfied:
1367 if(!CheckExprSatisfied(ref,SatisfiedExprName(start))) {
1368 return 0 ;
1369 }
1370 break;
1371 case e_var:
1372 switch(CheckExprBVar(ref,ExprName(start),list)){
1373 case 0:
1374 case -1:
1375 return 0;
1376 }
1377 break;
1378 default:
1379 return 0;
1380 }
1381 start = NextExpr(start);
1382 }
1383 return 1;
1384 }
1385
1386 /* see header. returns 1 if relation expression is fully instantiable
1387 ie all vars exist, and, if need be, properly initialized. */
1388 int CheckLogRel(CONST struct Instance *reference, CONST struct Expr *ex)
1389 {
1390 CONST struct Expr *last_ex,*rhs_ex;
1391 last_ex = FindLastExpr(ex);
1392 switch(ExprType(last_ex)){
1393 case e_boolean_eq:
1394 case e_boolean_neq:
1395 rhs_ex = FindLogRHS(ex);
1396 if (!CheckLogExpr(reference,rhs_ex,last_ex,0)) return 0;
1397 return CheckLogExpr(reference,ex,rhs_ex,0);
1398 default:
1399 return 0;
1400 }
1401 }
1402
1403
1404 /*
1405 * We can now just do a memcopy and the infix pointers
1406 * all adjust by the difference between the token
1407 * arrays that the gl_lists are hiding. Cool, eh?
1408 * Note, if any turkey ever tries to delete an individual
1409 * token from these gl_lists AND deallocate it,
1410 * they will get a severe headache.
1411 *
1412 * This is a full blown copy and not copy by reference.
1413 * You do not need to remake the infix pointers after
1414 * calling this function.
1415 */
1416 static union LogRelTermUnion
1417 *CopyLogRelSide(union LogRelTermUnion *old, unsigned long len)
1418 {
1419 struct logrel_term *term;
1420 union LogRelTermUnion *arr;
1421 unsigned long c;
1422 long int delta;
1423
1424 if (!old || !len) return NULL;
1425 arr = ASC_NEW_ARRAY(union LogRelTermUnion,len);
1426 if (arr==NULL) {
1427 FPRINTF(ASCERR,"Copy Logical Relation: Insufficient memory :-(.\n");
1428 return NULL;
1429 }
1430 memcpy( (VOIDPTR)arr, (VOIDPTR)old, len*sizeof(union LogRelTermUnion));
1431 /*
1432 * Difference in chars between old and arr ptrs. It should me a multiple
1433 * of sizeof(double) but may not be a multiple of sizeof(union LRTU).
1434 * Delta may easily be negative.
1435 * Normally, though arr > old.
1436 */
1437 delta = (char *)arr - (char *)old;
1438 #ifdef ADJLOGPTR
1439 #undef ADJLOGPTR
1440 #endif
1441 #define ADJLOGPTR(p) ( (p) = LOGA_TERM((char *)(p)+delta) )
1442 for (c=0;c<len;c++) {
1443 term = LOGA_TERM(&(arr[c]));
1444 switch (term->t) {
1445 /* unary terms */
1446 case e_not:
1447 ADJLOGPTR(LOGU_TERM(term)->left);
1448 break;
1449 /* binary terms */
1450 case e_and:
1451 case e_or:
1452 ADJLOGPTR(LOGB_TERM(term)->left);
1453 ADJLOGPTR(LOGB_TERM(term)->right);
1454 break;
1455 case e_boolean:
1456 case e_var: /* the var number will be correct */
1457 break;
1458 case e_satisfied:
1459 break;
1460 /* don't know how to deal with the following relation operators.
1461 they may be binary or unary, but InfixArr_MakeLogSide never set them. */
1462 case e_boolean_eq: case e_boolean_neq:
1463 default:
1464 ASC_PANIC("Unknown term type in CopyLogRelSide\n");
1465 break;
1466 }
1467 }
1468 #undef ADJLOGPTR
1469
1470 return arr;
1471 }
1472
1473
1474 /*
1475 * This function will always create a new instance list, from
1476 * the instance list provided. The instances will be copied
1477 * and made aware of the destination logrelation instance.
1478 */
1479 static
1480 struct gl_list_t *CopyLogRelInstList(struct Instance *dest_inst,
1481 struct gl_list_t *instlist)
1482 {
1483 struct Instance *inst;
1484 struct gl_list_t *newinstlist = NULL;
1485 unsigned long len,c,pos;
1486
1487 if (instlist) {
1488 len = gl_length(instlist);
1489 newinstlist = gl_create(len);
1490 for (c=1;c<=len;c++) {
1491 inst = (struct Instance *)gl_fetch(instlist,c);
1492 pos = gl_search(newinstlist,inst,(CmpFunc)CmpP);
1493 if (pos) {
1494 ASC_PANIC("Corrupted instance list in CopyLogRelation\n");
1495 }
1496 gl_append_ptr(newinstlist,(VOIDPTR)inst);
1497 AddLogRel(inst,dest_inst);
1498 }
1499 }
1500 else{ /* we will always return a newinstlist, even if empty */
1501 newinstlist = gl_create(1L);
1502 }
1503 return newinstlist;
1504 }
1505
1506
1507 static
1508 struct logrelation *CopyLogRelation(CONST struct Instance *src_inst,
1509 struct Instance *dest_inst,
1510 struct gl_list_t *varlist,
1511 struct gl_list_t *rellist)
1512 {
1513 CONST struct logrelation *src;
1514 struct logrelation *result;
1515 long int delta;
1516
1517 src = GetInstanceLogRel(src_inst);
1518 if (!src) return NULL;
1519
1520 result = CreateLogRelStructure(e_bol_token);
1521
1522 result->ref_count = 1;
1523
1524 result->token.lhs =
1525 CopyLogRelSide(src->token.lhs,src->token.lhs_len);
1526 if(result->token.lhs != NULL) {
1527 delta = LOGUNION_TERM(src->token.lhs_term) - src->token.lhs;
1528 result->token.lhs_term = LOGA_TERM(result->token.lhs+delta);
1529 result->token.lhs_len = src->token.lhs_len;
1530 } else {
1531 result->token.lhs_term = NULL;
1532 result->token.lhs_len = 0;
1533 }
1534
1535 result->token.rhs =
1536 CopyLogRelSide(src->token.rhs,src->token.rhs_len);
1537 if(result->token.rhs != NULL) {
1538 delta = LOGUNION_TERM(src->token.rhs_term) - src->token.rhs;
1539 result->token.rhs_term = LOGA_TERM(result->token.rhs+delta);
1540 result->token.rhs_len = src->token.rhs_len;
1541 } else {
1542 result->token.rhs_term = NULL;
1543 result->token.rhs_len = 0;
1544 }
1545
1546 result->bvars = CopyLogRelInstList(dest_inst,varlist);
1547 result->satrels = CopyLogRelInstList(dest_inst,rellist);
1548 result->logresidual = src->logresidual;
1549 result->lognominal = src->lognominal;
1550 return result;
1551 }
1552
1553
1554 struct logrelation *CopyLogRelByReference(CONST struct Instance *src_inst,
1555 struct Instance *dest_inst,
1556 struct gl_list_t *varlist,
1557 struct gl_list_t *rellist)
1558 {
1559 struct logrelation *src;
1560 struct logrelation *result;
1561 unsigned size;
1562
1563 src = (struct logrelation *)GetInstanceLogRel(src_inst);
1564 if (!src) return NULL;
1565
1566 result = CreateLogRelStructure(e_bol_token);
1567 size = sizeof(struct logrelation);
1568 ascbcopy(src,result,sizeof(struct logrelation));
1569 /* copy everything. */
1570 /*
1571 * We now have a verbatim copy. We now need to patch the public
1572 * stuff.
1573 */
1574 result->bvars = CopyLogRelInstList(dest_inst,varlist);
1575 result->satrels = CopyLogRelInstList(dest_inst,rellist);
1576 (src->ref_count)++;
1577 return result;
1578 }
1579
1580 struct logrelation *CopyLogRelToModify(CONST struct Instance *src_inst,
1581 struct Instance *dest_inst,
1582 struct gl_list_t *varlist,
1583 struct gl_list_t *rellist)
1584 {
1585 CONST struct logrelation *src;
1586 struct logrelation *result;
1587 src = GetInstanceLogRel(src_inst);
1588 if (!src) return NULL;
1589 result = CopyLogRelation(src_inst,dest_inst,varlist,rellist);
1590 return result;
1591 }
1592
1593

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