Metropoli BBS
VIEWER: getcb.c MODE: TEXT (ASCII)
/* Copyright (C) 1993 by Thomas Glen Smith.  All Rights Reserved. */
/* getcb APL2 V1.0.1 ***************************************************
* Called to obtain an initialized APLCB.                               *
* 971211 Smitty changed to handle bus errors on HPUX.                  *
***********************************************************************/
#define INCLUDES APLMEM+APLCB
#include "includes.h"
#include <limits.h>
Aplcb getcb(dataptr,datacnt,datatyp,rank,dimptr)
void *dataptr; /* data address */
int  datacnt, datatyp, rank, *dimptr /* dimensions */;
{
	Chrcopy; Intcopy;
	extern int aplerr;
	Aplcb out;
	long int ilong,jlong;
	int bump=0,datasize,i,*ip,protocnt=0,typ,unitsize;
	char *cp;
	void **vp;

	if (datacnt < 0) { aplerr = 92; return(NULL); } /* too big */
	switch (typ = datatyp & (APLMASK + APLAPL)) {
		case APLCPLX:
			unitsize=sizeof(double);
			datasize=unitsize*2;
			break;
		case APLNUMB:
			unitsize=datasize=sizeof(double);
			break;
		case APLINT:
			unitsize=datasize=sizeof(int);
			break;
		case APLCHAR:
			unitsize=datasize=sizeof(char);
			bump=1; /* Allow room for \0 at end. */
			break;
		case APLAPL:
			unitsize=datasize=sizeof(Aplcb);
			if (datacnt == 0) protocnt = 1;
			break;
		default: aplerr=999; return(NULL);
	} /* end switch */
	jlong = sizeof(struct aplcb) + rank*sizeof(int);
	if (jlong % (long int) unitsize)
		jlong = ((jlong / (long int) datasize)+1)*(long int) datasize;
	/* jlong is size before data starts. */

	ilong = (long int) datasize * ((long int) datacnt
		+ (long int) protocnt) + jlong + (long int) bump;
	/* ilong is size to allocate. */

	if (ilong > INT_MAX) { aplerr = 92; return(NULL); } /* too big */
	if (NULL == (out=malloc((int) ilong))) return(NULL);
	cp = jlong + (char *)out; /* Point where data starts. */
	out->aplsize = datasize;
	out->aplcount = datacnt;
	out->aplflags = datatyp;
	out->aplrank = rank;
	out->aplptr.aplchar = (datacnt + protocnt) ? cp : NULL;
	out->apldim = (rank) ? ((int *)(out+1)) : NULL;
	if (bump) *(cp + datacnt) = '\0'; /* Delimit string. */
	if (dataptr != NULL && (datacnt + protocnt) != 0) {
		cp = chrcopy(out->aplptr.aplchar,dataptr,datasize*datacnt,1);
		free(dataptr); /* copy, then free data */
	}
	else if (protocnt) *((void **)out->aplptr.aplchar) = NULL;
	else if (typ == APLAPL && datacnt)
		for (i=datacnt, vp = (void **)cp; i; i--) *vp++ = NULL;
	if (rank != 0) {
		if (dimptr != NULL) {
			ip = intcopy(out->apldim,dimptr,rank,1);
			free(dimptr); /* copy, then free input dimensions */
		}
		else if (rank==1) *(out->apldim)=datacnt; /* vector */
	}
	if (aplerr) { endoper(out); out = NULL; }
	return(out);
}
[ RETURN TO DIRECTORY ]