C:/Users/Dennis/src/lang/Life_start/Life/life-1.02/source/copy.c

Go to the documentation of this file.
00001 /* Copyright 1991 Digital Equipment Corporation.
00002 ** All Rights Reserved.
00003 *****************************************************************/
00004 /*      $Id: copy.c,v 1.2 1994/12/08 23:21:30 duchier Exp $      */
00005 
00006 #ifndef lint
00007 static char vcid[] = "$Id: copy.c,v 1.2 1994/12/08 23:21:30 duchier Exp $";
00008 #endif /* lint */
00009 
00010 #include "extern.h"
00011 #include "memory.h"
00012 #include "parser.h"
00013 #include "trees.h"
00014 #include "login.h"
00015 #include "copy.h"
00016 /* #include <malloc.h> 11.9 */
00017 
00018 jmp_buf env; /* To jump back to main() when copy(..) overflows */
00019 
00020 /****************************************************************************/
00021 
00022 /* New translation routines for Wild_Life                     */
00023 /* These routines work for any size structure.                */
00024 /* They are based on a hash table with buckets and timestamp. */
00025 /* This allows fast clearing of the table and fast insertion  */
00026 /* and lookup.                                                */
00027 
00028 /* Size of hash table; must be a power of 2 */
00029 /* A big hash table means it is sparse and therefore fast */
00030 #define HASHSIZE 2048
00031 
00032 /* Total number of buckets in initial hash table; */
00033 /* this is dynamically increased if necessary.    */
00034 #define NUMBUCKETS 1024
00035 
00036 /* Simple hash function */
00037 #define HASH(A) (((long) A + ((long) A >> 3)) & (HASHSIZE-1))
00038 
00039 /* Tail of hash bucket */
00040 #define HASHEND (-1)
00041 
00042 struct hashbucket {
00043    ptr_psi_term old_value;
00044    ptr_psi_term new_value;
00045    long info;
00046    long next;
00047 };
00048 
00049 struct hashentry {
00050    long timestamp;
00051    long bucketindex;
00052 };
00053 
00054 static struct hashentry hashtable[HASHSIZE];
00055 static struct hashbucket *hashbuckets; /* Array of buckets */
00056 static long hashtime; /* Currently valid timestamp */
00057 static long hashfree; /* Index into array of buckets */
00058 static long numbuckets; /* Total number of buckets; initially=NUMBUCKETS */
00059 
00060 
00061 /* #define HASHSTATS 1000 20.8 */
00062 /* long hashstats[HASHSTATS]; 20.8 */
00063 
00064 
00065 /******** INIT_COPY()
00066   Execute once upon startup of Wild_Life.
00067 */
00068 void init_copy()
00069 {
00070   long i;
00071 
00072   /* for(i=0; i<HASHSTATS; i++) hashstats[i]=0; 20.8 */
00073 
00074   for(i=0; i<HASHSIZE; i++) hashtable[i].timestamp = 0;
00075   hashtime = 0;
00076   numbuckets = NUMBUCKETS;
00077   hashbuckets = (struct hashbucket *)
00078     malloc(NUMBUCKETS * sizeof(struct hashbucket));
00079 }
00080 
00081 
00082 /******** CLEAR_COPY()
00083   Erase the hash table.
00084   This must be done as a prelude to any copying operation.
00085 */
00086 void clear_copy()
00087 {
00088   hashtime++;
00089   hashfree=0;
00090 }
00091 
00092 
00093 /******** INSERT_TRANSLATION(a,b,info)
00094   Add the translation of address A to address B in the translation table.
00095   Also add an info field.
00096 */
00097 /* static */ void insert_translation(a,b,info)
00098 ptr_psi_term a;
00099 ptr_psi_term b;
00100 long info;
00101 {
00102   long index;
00103   long lastbucket;
00104   
00105   /* Ensure there are free buckets by doubling their number if necessary */
00106   if (hashfree >= numbuckets) {
00107     numbuckets *= 2;
00108     hashbuckets = (struct hashbucket *) 
00109       realloc((void *) hashbuckets, numbuckets * sizeof(struct hashbucket));
00110     /* *** Do error handling here *** */
00111     Traceline("doubled the number of hashbuckets to %d\n", numbuckets);
00112   }
00113 
00114   /* Add a bucket to the beginning of the list */
00115   index = HASH(a);
00116   if (hashtable[index].timestamp == hashtime)
00117     lastbucket = hashtable[index].bucketindex;
00118   else {
00119     lastbucket = HASHEND;
00120     hashtable[index].timestamp = hashtime;
00121   }
00122   hashtable[index].bucketindex = hashfree;
00123   hashbuckets[hashfree].old_value = a;
00124   hashbuckets[hashfree].new_value = b;
00125   hashbuckets[hashfree].info = info;
00126   hashbuckets[hashfree].next = lastbucket;
00127   hashfree++;
00128 }
00129 
00130 
00131 /******** TRANSLATE(a,info)
00132   Get the translation of address A and the info field stored with it.
00133   Return NULL if none is found.
00134 */
00135 /* static */ ptr_psi_term translate(a,infoptr)   /*  RM: Jan 27 1993  */
00136 ptr_psi_term a;
00137 long **infoptr;
00138 {
00139   long index;
00140   /* long i; 20.8 */
00141   long bucket;
00142 
00143   index = HASH(a);
00144   if (hashtable[index].timestamp != hashtime) return NULL;
00145   bucket = hashtable[index].bucketindex;
00146   /* i=0; 20.8 */
00147   while (bucket != HASHEND && hashbuckets[bucket].old_value != a) {
00148     /* i++; 20.8 */
00149     bucket = hashbuckets[bucket].next;
00150   }
00151   /* hashstats[i]++; 20.8 */
00152   if (bucket != HASHEND) {
00153     *infoptr = &hashbuckets[bucket].info;
00154     return (hashbuckets[bucket].new_value);
00155   }
00156   else
00157     return NULL;
00158 }
00159 
00160 
00161 /****************************************************************************/
00162 
00163 
00164 /******** COPY_TREE(t)
00165   Return a pointer to a copy of the binary tree t.
00166   Structure sharing between trees is not preserved by this routine,
00167   this is not a problem seeing that coreferences in the nodes will ensure
00168   coherence.
00169 */
00170 
00171 /* TRUE means: heap_flag==TRUE & only copy to heap those objects not */
00172 /* already on heap, i.e. incremental copy to heap.                   */
00173 long to_heap;
00174 
00175 /* TRUE iff R is on the heap */
00176 #define ONHEAP(R) ((GENERIC)R>=heap_pointer)
00177 
00178 /* Allocate a new record on the heap or stack if necessary: */
00179 #define NEW(A,TYPE) (heap_flag==HEAP \
00180                     ? (to_heap \
00181                       ? (ONHEAP(A) \
00182                         ? A \
00183                         : HEAP_ALLOC(TYPE) \
00184                         ) \
00185                       : HEAP_ALLOC(TYPE) \
00186                       ) \
00187                     : STACK_ALLOC(TYPE) \
00188                     )
00189 
00190 /* TRUE iff to_heap is TRUE & work is done, i.e. the term is on the heap. */
00191 #define HEAPDONE(R) (to_heap && ONHEAP(R))
00192 
00193 
00194 ptr_psi_term copy(); /* Forward declarations */
00195 void mark_quote_c();
00196 
00197 static ptr_node copy_tree(t, copy_flag, heap_flag)
00198 ptr_node t;
00199 long copy_flag, heap_flag;
00200 {
00201   ptr_node r;
00202   ptr_psi_term t1,t2;
00203 
00204   /* if (t) {   RM: Dec 15 1992  this test is useless */
00205   
00206   if (HEAPDONE(t)) return t;
00207   r=NEW(t,node);
00208   r->key = t->key;
00209   r->left  = (t->left)  ? copy_tree(t->left,copy_flag,heap_flag)  : NULL;
00210   t1 = (ptr_psi_term)(t->data);
00211   t2 = copy(t1,copy_flag,heap_flag);
00212   r->data = (GENERIC) t2;
00213   r->right = (t->right) ? copy_tree(t->right,copy_flag,heap_flag) : NULL;
00214 
00215   /* } else r=NULL; */
00216 
00217   return r;
00218 }
00219 
00220 
00221 
00222 /******** COPY(t)
00223   This is the workhorse of the interpreter (alas!).
00224   All copy-related routines are non-interruptible by the garbage collector.
00225   
00226   Make a copy in the STACK or in the HEAP of psi_term t, which is located in
00227   the HEAP.  A copy is done whenever invoking a rule, so it had better be fast.
00228   This routine uses hash tables with buckets and partial inlining for speed.
00229 
00230   The following three versions of copy all rename their variables and return
00231   a completely dereferenced object:
00232 
00233   u=exact_copy(t,hf)  u is an exact copy of t.
00234   u=quote_copy(t,hf)  u is a copy of t that is recursively marked evaluated.
00235   u=eval_copy(t,hf)   u is a copy of t that is recursively marked unevaluated.
00236 
00237   This version of copy is an incremental copy to the heap.  It copies only
00238   those parts of a psi_term that are on the stack, leaving the others
00239   unchanged:
00240 
00241   u=inc_heap_copy(t)  u is an exact copy of t, on the heap.  This is like
00242                       hf==HEAP, except that objects already on the heap are
00243                       untouched.  Relies on no pointers from heap to stack.
00244 
00245   hf = heap_flag.  hf = HEAP or STACK means allocate in the HEAP or STACK.
00246   Marking eval/uneval is done by modifying the STATUS field of the copied
00247   psi_term.
00248   In eval_copy, a term's status is set to 0 if the term or any subterm needs
00249   evaluation.
00250   Terms are dereferenced when copying them to the heap.
00251 */
00252 
00253 #define EXACT_FLAG 0
00254 #define QUOTE_FLAG 1
00255 #define EVAL_FLAG  2
00256 /* See mark_quote_c: */ /* 15.9 */
00257 #define QUOTE_STUB 3
00258 
00259 ptr_psi_term exact_copy(t, heap_flag)
00260 ptr_psi_term t;
00261 long heap_flag;
00262 { to_heap=FALSE; return (copy(t, EXACT_FLAG, heap_flag)); }
00263 
00264 ptr_psi_term quote_copy(t, heap_flag)
00265 ptr_psi_term t;
00266 long heap_flag;
00267 { to_heap=FALSE; return (copy(t, QUOTE_FLAG, heap_flag)); }
00268 
00269 ptr_psi_term eval_copy(t, heap_flag)
00270 ptr_psi_term t;
00271 long heap_flag;
00272 { to_heap=FALSE; return (copy(t, EVAL_FLAG, heap_flag)); }
00273 
00274 /* There is a bug in inc_heap_copy */
00275 ptr_psi_term inc_heap_copy(t)
00276 ptr_psi_term t;
00277 { to_heap=TRUE; return (copy(t, EXACT_FLAG, TRUE)); }
00278 
00279 static long curr_status;
00280 
00281 
00282 
00283 ptr_psi_term copy(t, copy_flag, heap_flag)
00284      ptr_psi_term t;
00285      long copy_flag,heap_flag;
00286 {
00287   ptr_psi_term u;
00288   long old_status;
00289   long local_copy_flag;
00290   long *infoptr;
00291 
00292   
00293   if (u=t) {    
00294     deref_ptr(t); /* Always dereference when copying */
00295     
00296     if (HEAPDONE(t)) return t;
00297     u = translate(t,&infoptr);
00298     
00299     if (u && *infoptr!=QUOTE_STUB) { /* 24.8 */
00300       /* If it was eval-copied before, then quote it now. */
00301       if (*infoptr==EVAL_FLAG && copy_flag==QUOTE_FLAG) { /* 24.8 25.8 */
00302         mark_quote_c(t,heap_flag);
00303         *infoptr=QUOTE_FLAG; /* I.e. don't touch this term any more */
00304       }
00305       if (copy_flag==EVAL_FLAG) { /* PVR 14.2.94 */
00306         /* If any subterm has zero curr_status (i.e., if u->status==0),
00307            then so does the whole term: */
00308         old_status=curr_status;
00309         curr_status=u->status;
00310         if (curr_status) curr_status=old_status;
00311       }
00312     }
00313     else {
00314       if (heap_pointer-stack_pointer < COPY_THRESHOLD) {
00315         Errorline("psi-term too large -- get a bigger Life!\n");
00316         abort_life(TRUE);
00317         longjmp(env,FALSE); /* Back to main loop */ /*  RM: Feb 15 1993  */
00318       }
00319       if (copy_flag==EVAL_FLAG && !t->type->evaluate_args) /* 24.8 25.8 */
00320         local_copy_flag=QUOTE_FLAG; /* All arguments will be quoted 24.8 */
00321       else /* 24.8 */
00322         local_copy_flag=copy_flag;
00323       if (copy_flag==EVAL_FLAG) {
00324         old_status = curr_status;
00325         curr_status = 4;
00326       }
00327       if (u) { /* 15.9 */
00328         *infoptr=QUOTE_FLAG;
00329         local_copy_flag=QUOTE_FLAG;
00330         copy_flag=QUOTE_FLAG;
00331       }
00332       else {
00333         u=NEW(t,psi_term);
00334         insert_translation(t,u,local_copy_flag); /* 24.8 */
00335       }
00336       *u = *t;
00337       u->resid=NULL; /* 24.8 Don't copy residuations */
00338 #ifdef TS
00339       u->time_stamp=global_time_stamp; /* 9.6 */
00340 #endif
00341       
00342       if (t->attr_list)
00343         u->attr_list=copy_tree(t->attr_list, local_copy_flag, heap_flag);
00344       
00345       if (copy_flag==EVAL_FLAG) {
00346         switch(t->type->type) {
00347         case type:
00348           if (t->type->properties)
00349             curr_status=0;
00350           break;
00351           
00352         case function:
00353           curr_status=0;
00354           break;
00355 
00356         case global: /*  RM: Feb  8 1993  */
00357           curr_status=0;
00358           break;
00359 
00360         default:
00361           break;
00362         }
00363         u->status=curr_status;
00364         u->flags=curr_status?QUOTED_TRUE:FALSE; /* 14.9 */
00365         /* If any subterm has zero curr_status,
00366            then so does the whole term: */
00367         if (curr_status) curr_status=old_status;
00368       } else if (copy_flag==QUOTE_FLAG) {
00369         u->status=4;
00370         u->flags=QUOTED_TRUE; /* 14.9 */
00371       }
00372       /* else copy_flag==EXACT_FLAG & u->status=t->status */
00373       
00374       if (heap_flag==HEAP) {
00375         if (t->type==cut) u->value=NULL;
00376       } else {
00377         if (t->type==cut) {
00378           u->value=(GENERIC)choice_stack;
00379           Traceline("current choice point is %x\n",choice_stack);
00380         }
00381       }
00382     }
00383   }
00384 
00385   return u;
00386 }
00387 
00388 
00389 
00390 /****************************************************************************/
00391 
00392 
00393 /******** DISTINCT_TREE(t)
00394   Return an exact copy of an attribute tree.
00395   This is used by APPLY in order to build the calling psi-term which is used
00396   for matching.
00397 */
00398 ptr_node distinct_tree(t)
00399 ptr_node t;
00400 {
00401   ptr_node n;
00402   
00403   n=NULL;
00404   if (t) {
00405     n=STACK_ALLOC(node);
00406     n->key=t->key;
00407     n->data=t->data;
00408     n->left=distinct_tree(t->left);
00409     n->right=distinct_tree(t->right);
00410   }
00411 
00412   return n;
00413 }
00414 
00415 
00416 /******** DISTINCT_COPY(t)
00417   Make a distinct copy of T and T's attribute tree, which are identical to T,
00418   only located elsewhere in memory. This is used by apply to build the calling
00419   psi-term which is used for matching.  Note that this routine is not
00420   recursive, i.e. it only copies the main functor & the attribute tree.
00421 */
00422 ptr_psi_term distinct_copy(t)
00423 ptr_psi_term t;
00424 {
00425   ptr_psi_term res;
00426 
00427   res=STACK_ALLOC(psi_term);
00428   *res= *t;
00429 #ifdef TS
00430   res->time_stamp=global_time_stamp; /* 9.6 */
00431 #endif
00432   /* res->coref=distinct_copy(t->coref); */
00433   res->attr_list=distinct_tree(t->attr_list);
00434 
00435   return res;
00436 }
00437 
00438 
00439 /****************************************************************************/
00440 
00441 /* The new mark_quote to be used from copy. */
00442 
00443 extern void mark_quote_tree_c(); /* A forward declaration */
00444 
00445 /* Meaning of the info field in the translation table: */
00446 /* With u=translate(t,&infoptr): */
00447 /* If infoptr==QUOTE_FLAG then the whole subgraph from u is quoted. */
00448 /* If infoptr==EVAL_FLAG then anything is possible. */
00449 /* If infoptr==QUOTE_STUB then the term does not exist yet, e.g., there  */
00450 /* is a cycle in the term & copy(...) has not created it yet, for  */
00451 /* example X:s(L,t(X),R), where non_strict(t), in which R does not */
00452 /* exist when the call to mark_quote_c is done.  When the term is  */
00453 /* later created, it must be created as quoted. */
00454 
00455 /* Mark a psi-term u (which is a copy of t) as completely evaluated. */
00456 /* Only t is given as the argument. */
00457 /* Assumes the psi-term is a copy of another psi-term t, which is made through */
00458 /* eval_copy.  Therefore the copy is accessible through the translation table. */
00459 /* Assumes all translation table entries already exist. */
00460 /* The infoptr field is updated so that each subgraph is only traversed once. */
00461 /* This routine is called only from the main copy routine. */
00462 void mark_quote_c(t,heap_flag)
00463 ptr_psi_term t;
00464 long heap_flag;
00465 {
00466   ptr_list l;
00467   long *infoptr;
00468   ptr_psi_term u;
00469 
00470   if (t) {
00471     deref_ptr(t);
00472     u=translate(t,&infoptr);
00473     /* assert(u!=NULL); 15.9 */
00474     if (u) {
00475       if (*infoptr==EVAL_FLAG) {
00476         *infoptr=QUOTE_FLAG;
00477         u->status=4;
00478         u->flags=QUOTED_TRUE; /* 14.9 */
00479         mark_quote_tree_c(t->attr_list,heap_flag);
00480       }
00481     }
00482     else { /* u does not exist yet */ /* 15.9 */
00483       /* Create a stub & mark it as to-be-quoted. */
00484       u=NEW(t,psi_term);
00485       insert_translation(t,u,QUOTE_STUB);
00486     }
00487   }
00488 }
00489 
00490 void mark_quote_tree_c(n,heap_flag)
00491 ptr_node n;
00492 long heap_flag;
00493 {
00494   if (n) {
00495     mark_quote_tree_c(n->left,heap_flag);
00496     mark_quote_c((ptr_psi_term) (n->data),heap_flag);
00497     mark_quote_tree_c(n->right,heap_flag);
00498   }
00499 }
00500 
00501 /****************************************************************************/
00502 
00503 /* A (possibly) correct mark_eval and its companion mark_quote. */
00504 
00505 /* The translation table is used to record whether a subgraph has already */
00506 /* been quoted or not. */
00507 
00508 /* Forward declarations */
00509 void mark_eval_new();
00510 void mark_quote_new();
00511 void mark_eval_tree_new();
00512 void mark_quote_tree_new();
00513 
00514 static long mark_nonstrict_flag;
00515 
00516 /* Mark a psi-term as to be evaluated (i.e. strict), except for arguments   */
00517 /* of a nonstrict term, which are marked quoted.  Set status correctly and  */
00518 /* propagate zero status upwards.  Avoid doing superfluous work: non-shared */
00519 /* terms are traversed once; shared terms are traversed at most twice (this */
00520 /* only occurs if the first occurrence encountered is strict and a later    */
00521 /* occurrence is nonstrict).  The translation table is used to indicate (1) */
00522 /* whether a term has already been traversed, and if so, (2) whether there  */
00523 /* was a nonstrict traversal (in that case, the info field is FALSE). */
00524 void mark_eval(t) /* 24.8 25.8 */
00525 ptr_psi_term t;
00526 {
00527   clear_copy();
00528   mark_nonstrict_flag=FALSE;
00529   mark_eval_new(t);
00530 }
00531 
00532 /* Same as above, except that the status is only changed from 0 to 4 when */
00533 /* needed; it is never changed from 4 to 0. */
00534 void mark_nonstrict(t)
00535 ptr_psi_term t;
00536 {
00537   clear_copy();
00538   mark_nonstrict_flag=TRUE;
00539   mark_eval_new(t);
00540 }
00541 
00542 /* Mark a term as quoted. */
00543 void mark_quote_new2(t)
00544 ptr_psi_term t;
00545 {
00546   clear_copy();
00547   mark_nonstrict_flag=FALSE;
00548   mark_quote_new(t);
00549 }
00550 
00551 void mark_eval_new(t)
00552 ptr_psi_term t;
00553 {
00554   ptr_list l;
00555   long *infoptr,flag;
00556   ptr_psi_term u;
00557   long old_status;
00558 
00559   if (t) {
00560     deref_ptr(t);
00561     flag = t->type->evaluate_args;
00562     u=translate(t,&infoptr);
00563     if (u) {
00564       /* Quote the subgraph if it was already copied as to be evaluated. */
00565       if (!flag && *infoptr) {
00566         mark_quote_new(t);
00567         *infoptr=FALSE;
00568       }
00569       /* If any subterm has zero curr_status (i.e., if t->status==0),
00570          then so does the whole term: PVR 14.2.94 */
00571       old_status=curr_status;
00572       curr_status=t->status;
00573       if (curr_status) curr_status=old_status;
00574     }
00575     else {
00576       insert_translation(t,(ptr_psi_term)TRUE,flag);
00577       old_status=curr_status;
00578       curr_status=4;
00579 
00580       if (flag) /* 16.9 */
00581         mark_eval_tree_new(t->attr_list);
00582       else
00583         mark_quote_tree_new(t->attr_list);
00584 
00585       switch(t->type->type) {
00586       case type:
00587         if (t->type->properties)
00588           curr_status=0;
00589         break;
00590         
00591       case function:
00592         curr_status=0;
00593         break;
00594 
00595       case global: /*  RM: Feb  8 1993  */
00596         curr_status=0;
00597         break;
00598 
00599       default:
00600         break;
00601       }
00602       if (mark_nonstrict_flag) { /* 25.8 */
00603         if (curr_status) {
00604           /* Only increase the status, never decrease it: */
00605           t->status=curr_status;
00606         }
00607       }
00608       else {
00609         t->status=curr_status;
00610         t->flags=curr_status?QUOTED_TRUE:FALSE; /* 14.9 */
00611       }
00612       /* If any subterm has zero curr_status, then so does the whole term: */
00613       if (curr_status) curr_status=old_status;
00614     }
00615   }
00616 }
00617 
00618 void mark_eval_tree_new(n)
00619 ptr_node n;
00620 {
00621   if (n) {
00622     mark_eval_tree_new(n->left);
00623     mark_eval_new((ptr_psi_term) (n->data));
00624     mark_eval_tree_new(n->right);
00625   }
00626 }
00627 
00628 
00629 void mark_quote_new(t)
00630 ptr_psi_term t;
00631 {
00632   ptr_list l;
00633   long *infoptr;
00634   ptr_psi_term u;
00635 
00636   if (t) {
00637     deref_ptr(t);
00638     u=translate(t,&infoptr);
00639 
00640     /* Return if the subgraph is already quoted. */
00641     if (u && !*infoptr) return;
00642 
00643     /* Otherwise quote the subgraph */
00644     if (!u) insert_translation(t,(ptr_psi_term)TRUE,FALSE);
00645     else *infoptr = FALSE;      /* sanjay */
00646     t->status=4;
00647     t->flags=QUOTED_TRUE; /* 14.9 */
00648     mark_quote_tree_new(t->attr_list);
00649   }
00650 }
00651 
00652 
00653 void mark_quote_tree_new(n)
00654 ptr_node n;
00655 {
00656   if (n) {
00657     mark_quote_tree_new(n->left);
00658     mark_quote_new((ptr_psi_term) (n->data));
00659     mark_quote_tree_new(n->right);
00660   }
00661 }
00662 
00663 
00664 /****************************************************************************/
00665 
00666 /* A more efficient version of mark_quote */
00667 /* This version avoids using the translation table by setting a 'visited' */
00668 /* in the status field. */
00669 
00670 extern void mark_quote_tree(); /* A forward declaration */
00671 
00672 /* Mark a psi-term as completely evaluated. */
00673 void mark_quote(t)
00674 ptr_psi_term t;
00675 {
00676   ptr_list l;
00677 
00678   if (t && !(t->status&RMASK)) {
00679     t->status = 4;
00680     t->flags=QUOTED_TRUE; /* 14.9 */
00681     t->status |= RMASK;
00682     mark_quote(t->coref);
00683     mark_quote_tree(t->attr_list);
00684     t->status &= ~RMASK;
00685   }
00686 }
00687 
00688 void mark_quote_tree(t)
00689 ptr_node t;
00690 {
00691   if (t) {
00692     mark_quote_tree(t->left);
00693     mark_quote((ptr_psi_term) (t->data));
00694     mark_quote_tree(t->right);
00695   }
00696 }
00697 
00698 
00699 /* Back-trackably mark a psi-term as completely evaluated. */
00700 
00701 void bk_mark_quote_tree();
00702      
00703 void bk_mark_quote(t)
00704 ptr_psi_term t;
00705 {
00706   ptr_list l;
00707 
00708   if (t && !(t->status&RMASK)) {
00709     if(t->status!=4 && (GENERIC)t<heap_pointer)/*  RM: Jul 16 1993  */
00710       push_ptr_value(int_ptr,&(t->status));
00711     t->status = 4;
00712     t->flags=QUOTED_TRUE; /* 14.9 */
00713     t->status |= RMASK;
00714     bk_mark_quote(t->coref);
00715     bk_mark_quote_tree(t->attr_list);
00716     t->status &= ~RMASK;
00717   }
00718 }
00719 
00720 void bk_mark_quote_tree(t)
00721 ptr_node t;
00722 {
00723   if (t) {
00724     bk_mark_quote_tree(t->left);
00725     bk_mark_quote((ptr_psi_term) (t->data));
00726     bk_mark_quote_tree(t->right);
00727   }
00728 }
00729 
00730 
00731 /****************************************************************************/

Generated on Sat Jan 26 08:48:06 2008 for WildLife by  doxygen 1.5.4