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