4.3BSD/usr/contrib/icon/functions/copy.c
#include "../h/rt.h"
#include "../h/record.h"
/*
* copy(x) - make a copy of object x.
*/
Xcopy(nargs, arg1, arg0)
int nargs;
struct descrip arg1, arg0;
{
register int i;
struct descrip *d1, *d2;
union block *bp, *ep, **tp;
extern struct b_table *alctable();
extern struct b_telem *alctelem();
extern struct b_set *alcset();
extern struct b_selem *alcselem();
extern union block *allocate();
DeRef(arg1)
if (NULLDESC(arg1) || QUAL(arg1))
/*
* x is a string or &null, just copy its descriptor
* into arg0.
*/
arg0 = arg1;
else {
switch (TYPE(arg1)) {
case T_INTEGER:
#ifdef LONGS
case T_LONGINT:
#endif LONGS
case T_REAL:
case T_FILE:
case T_CSET:
case T_PROC:
case T_ESTACK:
/*
* Copy integers, long integers, reals, files, csets, procedures,
* and co-expressions by copying the descriptor. Note that for
* integers, this results in the assignment of a value, for the
* other types, a pointer is directed to a data block.
*/
arg0 = arg1;
break;
case T_LIST:
/*
* Pass the buck to cplist to copy a list.
*/
cplist(&arg1, &arg0, 1, BLKLOC(arg1)->list.cursize + 1);
break;
case T_TABLE:
/*
* Allocate space for table and elements and copy old table
* block into new.
*/
hneed((sizeof(struct b_table)) +
(sizeof(struct b_telem)) * BLKLOC(arg1)->table.cursize);
bp = (union block *) alctable(&nulldesc);
bp->table = BLKLOC(arg1)->table;
/*
* Work down the chain of table element blocks in each bucket
* and create identical chains in new table.
*/
for (i = 0; i < NBUCKETS; i++) {
tp = &(BLKLOC(bp->table.buckets[i]));
for (ep = *tp; ep != NULL; ep = *tp) {
*tp = (union block *) alctelem();
(*tp)->telem = ep->telem;
tp = &(BLKLOC((*tp)->telem.blink));
}
}
/*
* Return the copied table.
*/
arg0.type = D_TABLE;
BLKLOC(arg0) = bp;
break;
#ifdef SETS
case T_SET:
/*
* Allocate space for set and elements and copy old set
* block into new.
*/
hneed((sizeof(struct b_set)) +
(sizeof(struct b_selem)) * BLKLOC(arg1)->set.setsize);
bp = (union block *) alcset(&nulldesc);
bp->set = BLKLOC(arg1)->set;
/*
* Work down the chain of set elements in each bucket
* and create identical chains in new set.
*/
for (i = 0; i < NBUCKETS; i++) {
tp = &(BLKLOC(bp->set.sbucks[i]));
for (ep = *tp; ep != NULL; ep = *tp) {
*tp = (union block *) alcselem(&nulldesc,0);
(*tp)->selem = ep->selem;
tp = &(BLKLOC((*tp)->selem.sblink));
}
}
/*
* Return the copied set.
*/
arg0.type = D_SET;
BLKLOC(arg0) = bp;
break;
#endif SETS
case T_RECORD:
/*
* Allocate space for the new record and copy the old
* one into it.
*/
i = BLKLOC(arg1)->record.size;
hneed(i);
bp = allocate(i);
bp->record = BLKLOC(arg1)->record;
/*
* The above assignment doesn't copy the fields, they are
* copied individually via a loop.
*/
i = bp->record.recptr->nfields;
d1 = bp->record.fields;
d2 = BLKLOC(arg1)->record.fields;
while (i--)
*d1++ = *d2++;
/*
* Return the copied record
*/
arg0.type = D_RECORD;
BLKLOC(arg0) = bp;
break;
default:
syserr("copy: illegal datatype.");
}
}
}
Procblock(copy,1)