4.3BSD/usr/contrib/icon/functions/copy.c

Compare this file to the similar file:
Show the results in this format:

#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)