/* (C) Copyright International Business Machines Corporation 23 January */
/* 1990.  All Rights Reserved. */
/*  */
/* See the file USERAGREEMENT distributed with this software for full */
/* terms and conditions of use. */
#ifndef lint
static char sccsinfo[] = "@(#)o_record.c	1.9 3/13/90";
#endif

#include "ops.h"
#include "ops_parm.h"
#include "recursiv.h"
#include "storage.h"

extern datarep dr_record;

NILOP(o_new_record)
{
    void re_finalize();
    dfd_record *new_record();
    dfd_record *newrec;
    extern flag cherm_flag;

    if ((newrec = new_record((counter) args->qualifiers.integer)) is nil)
      raise(Depletion);
    else {
        if (not cherm_flag)
	  re_finalize(DstObj, F_DISCARD, args->sched);
				/* finalize the value of the destination; */
	Dst.record = newrec;
	set_init(DstObj, dr_record);
    }
}


dfd_record *
new_record(size)
counter size;
{
    dfd_record *rp;


    if ((rp = getdotmain(size)) isnt nil) /* allocate the record */
      rp->info.record_size = size; /* and record its size */

    return(rp);
}


/*ARGSUSED*/
void
fin_record(record, f_op, sched)
valcell record;
finalize_op f_op;
schedblock *sched;
{
    void re_finalize();

    counter size, i;

    size = record.record->info.record_size;
				/* get the number of fields in the */
				/*  record. */

    for (i = 0; i < size; i++)	/* free all of the components */
      re_finalize(& record.record->data[i], f_op, sched);

    { freedotmain(record.record, size); } /* free up the storage used */
}


status
eq_record(r1, r2)
valcell r1, r2;
{
    status re_equal();

    counter i, size;


    size = r1.record->info.record_size;

    for (i = 0; i < size; i++) 
      if (!re_equal(&r1.record->data[i], &r2.record->data[i]))
	return(FAILURE);

    return(SUCCESS);
}


predef_exception
cp_record(dst, src)
valcell *dst, src;
{
    predef_exception re_copy();
    void re_finalize();

    counter size, i;
    dfd_record *rp;


    size = src.record->info.record_size;
				/* get size of record. */

    if ((rp = (dfd_record *) getdotmain(size)) is nil)
      return(Depletion);
    rp->info.record_size = size;

    for (i = 0; i < size; i++) 
      if (re_copy(& src.record->data[i], & rp->data[i]) isnt Normal) {
	  while (i-- > 0)
	    /* notice that finalizing new copies should never cause */
	    /* any suspended processes to be revived... if it does, */
	    /* the nil arg below will cause the interpreter to abort */
	    re_finalize(& rp->data[i], F_DISCARD, (schedblock *) nil);
	  { freedotmain(rp, size); }
	  return(Depletion);
      }
    dst->record = rp;		/* set the new value. */

    return(Normal);
}
