00001
00002
00003
00004
00005
00006 #ifndef lint
00007 static char vcid[] = "$Id: copy.c,v 1.2 1994/12/08 23:21:30 duchier Exp $";
00008 #endif
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
00017
00018 jmp_buf env;
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #define HASHSIZE 2048
00031
00032
00033
00034 #define NUMBUCKETS 1024
00035
00036
00037 #define HASH(A) (((long) A + ((long) A >> 3)) & (HASHSIZE-1))
00038
00039
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;
00056 static long hashtime;
00057 static long hashfree;
00058 static long numbuckets;
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 void init_copy()
00069 {
00070 long i;
00071
00072
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
00083
00084
00085
00086 void clear_copy()
00087 {
00088 hashtime++;
00089 hashfree=0;
00090 }
00091
00092
00093
00094
00095
00096
00097 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
00106 if (hashfree >= numbuckets) {
00107 numbuckets *= 2;
00108 hashbuckets = (struct hashbucket *)
00109 realloc((void *) hashbuckets, numbuckets * sizeof(struct hashbucket));
00110
00111 Traceline("doubled the number of hashbuckets to %d\n", numbuckets);
00112 }
00113
00114
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
00132
00133
00134
00135 ptr_psi_term translate(a,infoptr)
00136 ptr_psi_term a;
00137 long **infoptr;
00138 {
00139 long index;
00140
00141 long bucket;
00142
00143 index = HASH(a);
00144 if (hashtable[index].timestamp != hashtime) return NULL;
00145 bucket = hashtable[index].bucketindex;
00146
00147 while (bucket != HASHEND && hashbuckets[bucket].old_value != a) {
00148
00149 bucket = hashbuckets[bucket].next;
00150 }
00151
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
00165
00166
00167
00168
00169
00170
00171
00172
00173 long to_heap;
00174
00175
00176 #define ONHEAP(R) ((GENERIC)R>=heap_pointer)
00177
00178
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
00191 #define HEAPDONE(R) (to_heap && ONHEAP(R))
00192
00193
00194 ptr_psi_term copy();
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
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
00216
00217 return r;
00218 }
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253 #define EXACT_FLAG 0
00254 #define QUOTE_FLAG 1
00255 #define EVAL_FLAG 2
00256
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
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);
00295
00296 if (HEAPDONE(t)) return t;
00297 u = translate(t,&infoptr);
00298
00299 if (u && *infoptr!=QUOTE_STUB) {
00300
00301 if (*infoptr==EVAL_FLAG && copy_flag==QUOTE_FLAG) {
00302 mark_quote_c(t,heap_flag);
00303 *infoptr=QUOTE_FLAG;
00304 }
00305 if (copy_flag==EVAL_FLAG) {
00306
00307
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);
00318 }
00319 if (copy_flag==EVAL_FLAG && !t->type->evaluate_args)
00320 local_copy_flag=QUOTE_FLAG;
00321 else
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) {
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);
00335 }
00336 *u = *t;
00337 u->resid=NULL;
00338 #ifdef TS
00339 u->time_stamp=global_time_stamp;
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:
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;
00365
00366
00367 if (curr_status) curr_status=old_status;
00368 } else if (copy_flag==QUOTE_FLAG) {
00369 u->status=4;
00370 u->flags=QUOTED_TRUE;
00371 }
00372
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
00394
00395
00396
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
00417
00418
00419
00420
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;
00431 #endif
00432
00433 res->attr_list=distinct_tree(t->attr_list);
00434
00435 return res;
00436 }
00437
00438
00439
00440
00441
00442
00443 extern void mark_quote_tree_c();
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
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
00474 if (u) {
00475 if (*infoptr==EVAL_FLAG) {
00476 *infoptr=QUOTE_FLAG;
00477 u->status=4;
00478 u->flags=QUOTED_TRUE;
00479 mark_quote_tree_c(t->attr_list,heap_flag);
00480 }
00481 }
00482 else {
00483
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
00504
00505
00506
00507
00508
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
00517
00518
00519
00520
00521
00522
00523
00524 void mark_eval(t)
00525 ptr_psi_term t;
00526 {
00527 clear_copy();
00528 mark_nonstrict_flag=FALSE;
00529 mark_eval_new(t);
00530 }
00531
00532
00533
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
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
00565 if (!flag && *infoptr) {
00566 mark_quote_new(t);
00567 *infoptr=FALSE;
00568 }
00569
00570
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)
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:
00596 curr_status=0;
00597 break;
00598
00599 default:
00600 break;
00601 }
00602 if (mark_nonstrict_flag) {
00603 if (curr_status) {
00604
00605 t->status=curr_status;
00606 }
00607 }
00608 else {
00609 t->status=curr_status;
00610 t->flags=curr_status?QUOTED_TRUE:FALSE;
00611 }
00612
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
00641 if (u && !*infoptr) return;
00642
00643
00644 if (!u) insert_translation(t,(ptr_psi_term)TRUE,FALSE);
00645 else *infoptr = FALSE;
00646 t->status=4;
00647 t->flags=QUOTED_TRUE;
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
00667
00668
00669
00670 extern void mark_quote_tree();
00671
00672
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;
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
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)
00710 push_ptr_value(int_ptr,&(t->status));
00711 t->status = 4;
00712 t->flags=QUOTED_TRUE;
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