1 /*
2  * pred.c -- source for predicate detection, manipulation
3  *
4  * SOFTWARE RIGHTS
5  *
6  * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
7  * Set (PCCTS) -- PCCTS is in the public domain.  An individual or
8  * company may do whatever they wish with source code distributed with
9  * PCCTS or the code generated by PCCTS, including the incorporation of
10  * PCCTS, or its output, into commerical software.
11  *
12  * We encourage users to develop software with PCCTS.  However, we do ask
13  * that credit is given to us for developing PCCTS.  By "credit",
14  * we mean that if you incorporate our source code into one of your
15  * programs (commercial product, research project, or otherwise) that you
16  * acknowledge this fact somewhere in the documentation, research report,
17  * etc...  If you like PCCTS and have developed a nice tool with the
18  * output, please mention that you developed it using PCCTS.  In
19  * addition, we ask that this header remain intact in our source code.
20  * As long as these guidelines are kept, we expect to continue enhancing
21  * this system and expect to make other tools available as they are
22  * completed.
23  *
24  * ANTLR 1.33
25  * Terence Parr
26  * Parr Research Corporation
27  * with Purdue University and AHPCRC, University of Minnesota
28  * 1989-2001
29  */
30 
31 #include <stdio.h>
32 #include "pcctscfg.h"
33 #include "set.h"
34 #include "syn.h"
35 #include "hash.h"
36 #include "generic.h"
37 #include "dlgdef.h"
38 #include <ctype.h>
39 
40 #ifdef __USE_PROTOS
41 static void complete_context_sets(RuleRefNode *, Predicate *);
42 static void complete_context_trees(RuleRefNode *, Predicate *);
43 #else
44 static void complete_context_sets();
45 static void complete_context_trees();
46 #endif
47 
48 char *PRED_AND_LIST = "AND";
49 char *PRED_OR_LIST = "OR";
50 
51 /*
52  * In C mode, return the largest constant integer found as the
53  * sole argument to LATEXT(i).
54  *
55  * In C++ mode, return the largest constant integer found as the
56  * sole argument to LT(i) given that the char before is nonalpha.
57  */
58 
59 int
60 #ifdef __USE_PROTOS
predicateLookaheadDepth(ActionNode * a)61 predicateLookaheadDepth(ActionNode *a)
62 #else
63 predicateLookaheadDepth(a)
64 ActionNode *a;
65 #endif
66 {
67 	int     max_k=0;
68 
69     if (a->predEntry != NULL) {
70        MR_pred_depth(a->predEntry->pred,&max_k);
71        goto PREDENTRY_EXIT;
72     }
73 
74 	if ( GenCC )
75 	{
76 		/* scan for LT(i) */
77 		int k = 0;
78 		char *p = a->action;
79 		while ( p!=NULL )
80 		{
81 			p = strstr(p, "LT(");
82 			if ( p!=NULL )
83 			{
84 				if ( p>=a->action && !isalpha(*(p-1)) )
85 				{
86 					k = atoi(p+strlen("LT("));
87 					if ( k>max_k ) max_k=k;
88 				}
89 				p += strlen("LT(");
90 			}
91 		}
92 	}
93 	else {
94 		/* scan for LATEXT(i) */
95 		int k = 0;
96 		char *p = a->action;
97 		while ( p!=NULL )
98 		{
99 			p = strstr(p, "LATEXT(");
100 			if ( p!=NULL )
101 			{
102 				p += strlen("LATEXT(");
103 				k = atoi(p);
104 				if ( k>max_k ) max_k=k;
105 			}
106 		}
107 	}
108 
109 	if (max_k==0) {
110 		max_k = 1;	   /* MR33 Badly designed if didn't set max_k when CLL_k = 1 */
111 		if (CLL_k > 1) /* MR27 Don't warn if max(k,ck) == 1 */
112 		{
113 			if ( !a->frmwarned )
114 			{
115 				a->frmwarned = 1;
116 				warnFL(eMsg1("predicate: %s missing, bad, or with i=0; assuming i=1",
117 							 GenCC?"LT(i)":"LATEXT(i)"),
118 					   FileStr[a->file], a->line);
119 			}
120 		}
121 	}
122 
123 /* MR10 */    if ( max_k > CLL_k) {
124 /* MR10 */		if ( !a->frmwarned )
125 /* MR10 */        {
126 /* MR10 */			a->frmwarned = 1;
127 /* MR11 */ errFL(eMsgd2("predicate refers to lookahead token %d. Semantic lookahead is limited to max(k,ck)==%d",
128 /* MR10 */                        max_k,CLL_k),
129 /* MR10 */                        FileStr[a->file],a->line);
130 /* MR10 */          if (max_k >= OutputLL_k) {
131 /* MR10 */            if (!GenCC) {
132 /* MR10 */              errFL(eMsgd("    the lookahead buffer size in C mode is %d token(s) (including the one just recognized)",
133 /* MR10 */                        OutputLL_k),
134 /* MR10 */                        FileStr[a->file],a->line);
135 /* MR10 */            };
136 /* MR10 */          };
137 /* MR10 */        };
138 /* MR10 */        max_k= CLL_k;
139 /* MR10 */    };
140 
141 PREDENTRY_EXIT:
142 	return max_k;
143 }
144 
145 /* Find all predicates in a block of alternatives.  DO NOT find predicates
146  * behind the block because that predicate could depend on things set in
147  * one of the nonoptional blocks
148  */
149 
150 Predicate *
151 #ifdef __USE_PROTOS
find_in_aSubBlk(Junction * alt)152 find_in_aSubBlk( Junction *alt )
153 #else
154 find_in_aSubBlk( alt )
155 Junction *alt;
156 #endif
157 {
158 	Predicate *a, *head=NULL, *tail=NULL, *root=NULL;
159 	Junction *p = alt;
160 
161     if (MRhoisting) {
162       return MR_find_in_aSubBlk(alt);
163     };
164 	for (; p!=NULL; p=(Junction *)p->p2)
165 	{
166 		/* ignore empty alts */
167 		if ( p->p1->ntype != nJunction ||
168 			 ((Junction *)p->p1)->jtype != EndBlk )
169 		{
170 			a = find_predicates(p->p1);	/* get preds for this alt */
171 			if ( a==NULL ) continue;
172 
173 			/* make an OR list of predicates */
174 			if ( head==NULL )
175 			{
176 				root = new_pred();
177 				root->expr = PRED_OR_LIST;
178 				head = tail = a;
179 				root->down = head;
180 			}
181 			else {
182 				tail->right = a;
183 				a->left = tail;
184 				a->up = tail->up;
185 				tail = a;
186 			}
187 		}
188 	}
189 
190 	/* if just one pred, remove OR root */
191 	if ( root!=NULL && root->down->right == NULL )
192 	{
193 		Predicate *d = root->down;
194 		free( (char *) root);
195 		return d;
196 	}
197 
198 	return root;
199 }
200 
201 Predicate *
202 #ifdef __USE_PROTOS
find_in_aOptBlk(Junction * alt)203 find_in_aOptBlk( Junction *alt )
204 #else
205 find_in_aOptBlk( alt )
206 Junction *alt;
207 #endif
208 {
209 	return find_in_aSubBlk( alt );
210 }
211 
212 Predicate *
213 #ifdef __USE_PROTOS
find_in_aLoopBegin(Junction * alt)214 find_in_aLoopBegin( Junction *alt )
215 #else
216 find_in_aLoopBegin( alt )
217 Junction *alt;
218 #endif
219 {
220 	return find_in_aSubBlk( (Junction *) alt->p1 );	/* get preds in alts */
221 }
222 
223 Predicate *
224 #ifdef __USE_PROTOS
find_in_aPlusBlk(Junction * alt)225 find_in_aPlusBlk( Junction *alt )
226 #else
227 find_in_aPlusBlk( alt )
228 Junction *alt;
229 #endif
230 {
231 	require(alt!=NULL&&alt->p2!=NULL, "invalid aPlusBlk");
232 	return find_in_aSubBlk( alt );
233 }
234 
235 /* Look for a predicate;
236  *
237  * Do not pass anything but Junction nodes; no Actions, Tokens, RuleRefs.
238  * This means that a "hoisting distance" of zero is the only distance
239  * allowable.  Init actions are ignored.
240  *
241  * WARNING:
242  *		Assumes no (..)? block after predicate for the moment.
243  *		Does not check to see if pred is in production that can generate
244  *			a sequence contained in the set of ambiguous tuples.
245  *
246  * Return the predicate found if any.
247  */
248 
249 
250 Predicate *
251 #ifdef __USE_PROTOS
find_predicates(Node * alt)252 find_predicates( Node *alt )
253 #else
254 find_predicates( alt )
255 Node *alt;
256 #endif
257 {
258 #ifdef DBG_PRED
259 	Junction *j;
260 	RuleRefNode *r;
261 	TokNode *t;
262 #endif
263 	Predicate *pred;
264 
265 	if ( alt==NULL ) return NULL;
266 
267 #ifdef DBG_PRED
268 	switch ( alt->ntype )
269 	{
270 		case nJunction :
271 			j = (Junction *) alt;
272 			fprintf(stderr, "Junction(in %s)", j->rname);
273 			switch ( j->jtype )
274 			{
275 				case aSubBlk :
276 					fprintf(stderr,"aSubBlk\n");
277 					break;
278 				case aOptBlk :
279 					fprintf(stderr,"aOptBlk\n");
280 					break;
281 				case aLoopBegin :
282 					fprintf(stderr,"aLoopBeginBlk\n");
283 					break;
284 				case aLoopBlk :
285 					fprintf(stderr,"aLoopBlk\n");
286 					break;
287 				case aPlusBlk :
288 					fprintf(stderr,"aPlusBlk\n");
289 					break;
290 				case EndBlk :
291 					fprintf(stderr,"EndBlk\n");
292 					break;
293 				case RuleBlk :
294 					fprintf(stderr,"RuleBlk\n");
295 					break;
296 				case Generic :
297 					fprintf(stderr,"Generic\n");
298 					break;
299 				case EndRule :
300 					fprintf(stderr,"EndRule\n");
301 					break;
302 			}
303 			break;
304 		case nRuleRef :
305 			r = (RuleRefNode *) alt;
306 			fprintf(stderr, "RuleRef(in %s)\n", r->rname);
307 			break;
308 		case nToken :
309 			t = (TokNode *) alt;
310 			fprintf(stderr, "TokenNode(in %s)%s\n", t->rname, TokenString(t->token));
311 			break;
312 		case nAction :
313 			fprintf(stderr, "Action\n");
314 			break;
315 	}
316 #endif
317 
318 	switch ( alt->ntype )
319 	{
320 		case nJunction :
321 		{
322 			Predicate *a, *b;
323 			Junction *p = (Junction *) alt;
324 
325 			/* lock nodes */
326 			if ( p->jtype==aLoopBlk || p->jtype==RuleBlk ||
327 				 p->jtype==aPlusBlk || p->jtype==EndRule )
328 			{
329 				require(p->pred_lock!=NULL, "rJunc: lock array is NULL");
330 				if ( p->pred_lock[1] )
331 				{
332 					return NULL;
333 				}
334 				p->pred_lock[1] = TRUE;
335 			}
336 
337 			switch ( p->jtype )
338 			{
339 				case aSubBlk :
340 					a = find_in_aSubBlk(p);
341 					return a;	/* nothing is visible past this guy */
342 				case aOptBlk :
343 					a = find_in_aOptBlk(p);
344 					return a;
345 				case aLoopBegin :
346 					a = find_in_aLoopBegin(p);
347 					return a;
348 				case aLoopBlk :
349 					a = find_in_aSubBlk(p);
350 					p->pred_lock[1] = FALSE;
351 					return a;
352 				case aPlusBlk :
353 					a = find_in_aPlusBlk(p);
354 					p->pred_lock[1] = FALSE;
355 					return a;	/* nothing is visible past this guy */
356 				case RuleBlk :
357 					a = find_predicates(p->p1);
358 					p->pred_lock[1] = FALSE;
359 					return a;
360 				case Generic :
361 					a = find_predicates(p->p1);
362 					b = find_predicates(p->p2);
363 					if ( p->pred_lock!=NULL ) p->pred_lock[1] = FALSE;
364 					if ( a==NULL ) return b;
365 					if ( b==NULL ) return a;
366 					/* otherwise OR the two preds together */
367 					{
368 					fatal_internal("hit unknown situation during predicate hoisting");
369 					}
370 				case EndBlk :
371 				case EndRule :	/* Find no predicates after a rule ref */
372 					return NULL;
373 				default:
374 					fatal_internal("this cannot be printed\n");
375 					break;
376 			}
377 		}
378 		case nAction :
379 		{
380 			ActionNode *p = (ActionNode *) alt;
381             if ( p->noHoist) return NULL;                           /* MR12c */
382 			if ( p->init_action ) return find_predicates(p->next);
383 			if ( p->is_predicate )
384 			{
385 				Tree *t=NULL;
386 #ifdef DBG_PRED
387 				fprintf(stderr, "predicate: <<%s>>?\n", p->action);
388 #endif
389 				if ( p->guardpred!=NULL )
390 				{
391 					pred = predicate_dup(p->guardpred);
392                     MR_guardPred_plainSet(p,pred);                  /* MR12c */
393 				}
394 				else
395 				{
396 					pred = new_pred();
397 					pred->k = predicateLookaheadDepth(p);
398 					pred->source = p;
399 					pred->expr = p->action;
400 					if ( HoistPredicateContext && pred->k > 1 )
401 					{
402 						/* MR30 No need to use first_item_is_guess_block_extra
403 						   since we know this is an action, not a (...)* or
404 						   (...)+ block.
405 						*/
406 
407 						if ( first_item_is_guess_block((Junction *)p->next) )
408 						{
409                             warnFL("cannot compute context of predicate in front of (..)? block",
410                             FileStr[p->file], p->line);
411 						}
412 						else
413 						{
414 							ConstrainSearch = 0;
415 /* MR11 */                  if (p->ampersandPred != NULL) {
416 /* MR11 */  					TRAV(p,
417 /* MR11 */							 pred->k,
418 /* MR11 */  						 &(pred->completionTree), t);
419 /* MR11 */                  } else {
420     							TRAV(p->next,
421     								 pred->k,
422     								 &(pred->completionTree), t);
423                             };
424 							pred->tcontext = t;
425                             MR_check_pred_too_long(pred,pred->completionTree);
426 #ifdef DBG_PRED
427 							fprintf(stderr, "LL(%d) context:", pred->k);
428 							preorder(t);
429 							fprintf(stderr, "\n");
430 #endif
431 						}
432 					}
433 					else if ( HoistPredicateContext && pred->k == 1 )
434 					{
435 						pred->scontext[1] = empty;
436 						/* MR30 No need to use first_item_is_guess_block_extra
437 						   since we know this is an action.
438 						*/
439 						if ( first_item_is_guess_block((Junction *)p->next) )
440 						{
441                         warnFL("cannot compute context of predicate in front of (..)? block",
442                                              FileStr[p->file], p->line);
443 						}
444 						else
445 						{
446 							REACH((Junction *)p->next,
447 								  1,
448 								  &(pred->completionSet),
449 								  pred->scontext[1]);
450                             MR_check_pred_too_long(pred,pred->completionSet);
451 #ifdef DBG_PRED
452 							fprintf(stderr, "LL(1) context:");
453 							s_fprT(stderr, pred->scontext[1]);
454 							fprintf(stderr, "\n");
455 #endif
456 						}
457 					}
458 				}
459 				{
460 					Predicate  *d = find_predicates(p->next);
461                     Predicate  *root;
462 
463 /* Warning: Doesn't seem like the up pointers will all be set correctly;
464  * TJP: that's ok, we're not using them now.
465  */
466 					if ( d!=NULL )
467 					{
468 						root = new_pred();
469 						root->expr = PRED_AND_LIST;
470 						root->down = pred;
471 						pred->right = d;
472 						pred->up = root;
473 						d->left = pred;
474 						d->up = pred->up;
475 						return root;
476 					}
477 				}
478 				return pred;
479 			}
480 			return NULL;
481 		}
482 		case nRuleRef :
483 		{
484 			Predicate   *a;
485 			RuleRefNode *p = (RuleRefNode *) alt;
486 			Junction    *r;
487             Junction    *save_MR_RuleBlkWithHalt;
488 
489 			RuleEntry *q = (RuleEntry *) hash_get(Rname, p->text);
490 			if ( q == NULL )
491 			{
492 				warnFL( eMsg1("rule %s not defined",p->text), FileStr[p->file], p->line );
493 				return NULL;
494 			}
495 			r = RulePtr[q->rulenum];
496 			if ( r->pred_lock[1] )
497 			{
498 				/* infinite left-recursion; ignore 'cause LL sup 1 (k) analysis
499 				 * must have seen it earlier.
500 				 */
501 				return NULL;
502 			}
503 
504             /* MR10 There should only be one halt set at a time.        */
505             /* MR10 Life would have been easier with a global variable  */
506             /* MR10    (at least for this particular need)              */
507             /* MR10 Unset the old one and set the new one, later undo.  */
508 
509             require(r->end->halt == FALSE,"should only have one halt at a time");
510 
511 /* MR10 */  require(MR_RuleBlkWithHalt == NULL ||
512 /* MR10 */          (MR_RuleBlkWithHalt->jtype == RuleBlk && MR_RuleBlkWithHalt->end->halt == TRUE),
513 /* MR10 */             "RuleBlkWithHalt->end not RuleBlk or does not have halt set");
514 /* MR10 */  if (MR_RuleBlkWithHalt != NULL) {
515 /* MR10 */    MR_RuleBlkWithHalt->end->halt=FALSE;
516 /* MR10 */  };
517 
518 /***        fprintf(stderr,"\nSetting halt on junction #%d\n",r->end->seq);     ***/
519 
520             require(r->end->halt == FALSE,"rule->end->halt already set");
521 
522             save_MR_RuleBlkWithHalt=MR_RuleBlkWithHalt;
523 
524 /* MR10 */  MR_pointerStackPush(&MR_RuleBlkWithHaltStack,MR_RuleBlkWithHalt);
525 /* MR10 */  MR_pointerStackPush(&MR_PredRuleRefStack,p);
526 
527 			r->end->halt = TRUE;
528 /* MR10 */  MR_RuleBlkWithHalt=r;
529 
530 			a = find_predicates((Node *)r);
531 
532             require(r->end->halt == TRUE,"rule->end->halt not set");
533             r->end->halt = FALSE;
534 
535 /* MR10 */  MR_pointerStackPop(&MR_PredRuleRefStack);
536 /* MR10 */  MR_RuleBlkWithHalt=(Junction *) MR_pointerStackPop(&MR_RuleBlkWithHaltStack);
537 
538             require (MR_RuleBlkWithHalt==save_MR_RuleBlkWithHalt,
539                     "RuleBlkWithHaltStack not consistent");
540 
541 /* MR10 */  require(MR_RuleBlkWithHalt == NULL ||
542 /* MR10 */          (MR_RuleBlkWithHalt->jtype == RuleBlk && MR_RuleBlkWithHalt->end->halt == FALSE),
543 /* MR10 */             "RuleBlkWithHalt->end not RuleBlk or has no halt set");
544 /* MR10 */  if (MR_RuleBlkWithHalt != NULL) {
545 /* MR10 */    MR_RuleBlkWithHalt->end->halt=TRUE;
546 /* MR10 */  };
547 
548 /***        fprintf(stderr,"\nRestoring halt on junction #%d\n",r->end->seq);   ***/
549 
550 			if ( a==NULL ) return NULL;
551 
552 			/* attempt to compute the "local" FOLLOW just like in normal lookahead
553 			 * computation if needed
554 			 */
555 
556 			complete_context_sets(p,a);
557 			complete_context_trees(p,a);
558 
559 /* MR10 */  MR_cleanup_pred_trees(a);
560 
561 			return a;
562 		}
563 		case nToken :
564 			break;
565 	}
566 
567 	return NULL;
568 }
569 
570 #ifdef __USE_PROTOS
MR_find_predicates_and_supp(Node * alt)571 Predicate *MR_find_predicates_and_supp(Node *alt)
572 #else
573 Predicate *MR_find_predicates_and_supp(alt)
574   Node      *alt;
575 #endif
576 {
577     Predicate   *p;
578 
579     p=find_predicates(alt);
580     p=MR_suppressK(alt,p);
581     return p;
582 }
583 
584 Predicate *
585 #ifdef __USE_PROTOS
new_pred(void)586 new_pred( void )
587 #else
588 new_pred( )
589 #endif
590 {
591 	Predicate *p = (Predicate *) calloc(1,sizeof(Predicate)); /* MR10 */
592 	require(p!=NULL, "new_pred: cannot alloc predicate");
593     p->scontext[0]=empty;
594     p->scontext[1]=empty;
595     p->completionTree=empty;
596     p->completionSet=empty;
597     p->plainSet=empty;
598 	return p;
599 }
600 
601 static void
602 #ifdef __USE_PROTOS
complete_context_sets(RuleRefNode * p,Predicate * a)603 complete_context_sets( RuleRefNode *p, Predicate *a )
604 #else
605 complete_context_sets( p, a )
606 RuleRefNode *p;
607 Predicate *a;
608 #endif
609 {
610 	set rk2, b;
611 	int k2;
612 
613 #ifdef DBG_PRED
614 	fprintf(stderr, "enter complete_context_sets\n");
615 #endif
616 	for (; a!=NULL; a=a->right)
617 	{
618 		if ( a->expr == PRED_AND_LIST || a->expr == PRED_OR_LIST )
619 		{
620 			complete_context_sets(p,a->down);
621 			continue;
622 		}
623 		rk2 = b = empty;
624 		while ( !set_nil(a->completionSet) )
625 		{
626 			k2 = set_int(a->completionSet);
627 			set_rm(k2, a->completionSet);
628 
629             REACH(p->next, k2, &rk2, b);
630 			set_orin(&(a->scontext[1]), b);
631 			set_free(b);
632 		}
633 
634 		set_orin(&(a->completionSet), rk2);/* remember what we couldn't do */
635 		set_free(rk2);
636 #ifdef DBG_PRED
637 		fprintf(stderr, "LL(1) context for %s(addr 0x%x) after ruleref:", a->expr, a);
638 		s_fprT(stderr, a->scontext[1]);
639 		fprintf(stderr, "\n");
640 #endif
641 /*		complete_context_sets(p, a->down);*/
642 	}
643 #ifdef DBG_PRED
644 	fprintf(stderr, "exit complete_context_sets\n");
645 #endif
646 }
647 
648 static void
649 #ifdef __USE_PROTOS
complete_context_trees(RuleRefNode * p,Predicate * a)650 complete_context_trees( RuleRefNode *p, Predicate *a )
651 #else
652 complete_context_trees( p, a )
653 RuleRefNode *p;
654 Predicate *a;
655 #endif
656 {
657 	set rk2;
658 	int k2;
659 	Tree *u;
660 
661 #ifdef DBG_PRED
662 	fprintf(stderr, "enter complete_context_trees\n");
663 #endif
664 	for (; a!=NULL; a=a->right)
665 	{
666 		if ( a->expr == PRED_AND_LIST || a->expr == PRED_OR_LIST )
667 		{
668 			complete_context_trees(p, a->down);
669 			continue;
670 		}
671 		rk2 = empty;
672 
673 		/* any k left to do? if so, link onto tree */
674 		while ( !set_nil(a->completionTree) )
675 		{
676 			k2 = set_int(a->completionTree);
677 			set_rm(k2, a->completionTree);
678 			u = NULL;
679 
680             TRAV(p->next, k2, &rk2, u);
681 
682 			/* any subtrees missing k2 tokens, add u onto end */
683 			a->tcontext = tlink(a->tcontext, u, k2);
684             Tfree(u);   /* MR10 */
685 		}
686 		set_orin(&(a->completionTree), rk2);/* remember what we couldn't do */
687 		set_free(rk2);
688 #ifdef DBG_PRED
689 		fprintf(stderr, "LL(i<%d) context after ruleref:", LL_k);
690 		preorder(a->tcontext);
691 		fprintf(stderr, "\n");
692 #endif
693 /*		complete_context_trees(p, a->down);*/
694 	}
695 #ifdef DBG_PRED
696 	fprintf(stderr, "exit complete_context_trees\n");
697 #endif
698 }
699 
700 /* Walk a list of predicates and return the set of all tokens in scontext[1]'s */
701 set
702 #ifdef __USE_PROTOS
covered_set(Predicate * p)703 covered_set( Predicate *p )
704 #else
705 covered_set( p )
706 Predicate *p;
707 #endif
708 {
709 	set a;
710 
711 	a = empty;
712 	for (; p!=NULL; p=p->right)
713 	{
714 		if ( p->expr == PRED_AND_LIST || p->expr == PRED_OR_LIST )
715 		{
716 			set_orin(&a, covered_set(p->down));
717 			continue;
718 		}
719 		set_orin(&a, p->scontext[1]);
720 		set_orin(&a, covered_set(p->down));
721 	}
722 	return a;
723 }
724 
725 /* MR10 predicate_free()
726    MR10 Don't free the leaf nodes since they are part of the action node
727 */
728 
729 #ifdef __USE_PROTOS
predicate_free(Predicate * p)730 void predicate_free(Predicate *p)
731 #else
732 void predicate_free(p)
733   Predicate     *p;
734 #endif
735 {
736   if (p == NULL) return;
737   predicate_free(p->right);
738   predicate_free(p->down);
739   if (p->cloned ||
740       p->source == NULL ||
741       p->source->guardpred == NULL ||
742       p->expr == PRED_AND_LIST ||
743       p->expr == PRED_OR_LIST) {
744     set_free(p->scontext[1]);
745     set_free(p->completionSet);
746     set_free(p->completionTree);
747     set_free(p->plainSet);
748     Tfree(p->tcontext);
749     free( (char *) p);
750   } else {
751     p->right=NULL;
752     p->down=NULL;  /* MR13 *** debug */
753   };
754 }
755 
756 /* MR10 predicate_dup() */
757 
758 #ifdef __USE_PROTOS
predicate_dup_xxx(Predicate * p,int contextToo)759 Predicate * predicate_dup_xxx(Predicate *p,int contextToo)
760 #else
761 Predicate * predicate_dup_xxx(p,contextToo)
762   Predicate     *p;
763   int           contextToo;
764 #endif
765 {
766   Predicate     *q;
767 
768   if (p == NULL) return NULL;
769   q=new_pred();
770   q->down=predicate_dup(p->down);
771   q->right=predicate_dup(p->right);
772 
773   /*
774      don't replicate expr - it is read-only
775      and address comparison is used to look
776      for identical predicates.
777   */
778 
779   q->expr=p->expr;
780   q->k=p->k;
781   q->source=p->source;
782   q->cloned=1;
783   q->ampersandStyle=p->ampersandStyle;
784   q->inverted=p->inverted;
785   q->predEntry=p->predEntry;
786   q->plainSet=set_dup(p->plainSet);
787 
788   if (contextToo) {
789     q->tcontext=tdup(p->tcontext);
790     q->scontext[0]=set_dup(p->scontext[0]);
791     q->scontext[1]=set_dup(p->scontext[1]);
792     q->completionTree=set_dup(p->completionTree);
793     q->completionSet=set_dup(p->completionSet);
794   };
795 
796   /* don't need to dup "redundant" */
797 
798   return q;
799 
800 }
801 
802 #ifdef __USE_PROTOS
predicate_dup_without_context(Predicate * p)803 Predicate * predicate_dup_without_context(Predicate *p)
804 #else
805 Predicate * predicate_dup_without_context(p)
806   Predicate     *p;
807 #endif
808 {
809   return predicate_dup_xxx(p,0);
810 }
811 
812 #ifdef __USE_PROTOS
predicate_dup(Predicate * p)813 Predicate * predicate_dup(Predicate *p)
814 #else
815 Predicate * predicate_dup(p)
816   Predicate     *p;
817 #endif
818 {
819   return predicate_dup_xxx(p,1);
820 }
821 
822