/* stack.c * * Copyright (c) 1984, 1985 Xerox Corp. * * This module manipulates the RES stack. * */ #include "stack.h" extern long filepos; extern unsigned char **malloc(); /* Private procedures defined in this module. */ extern unsigned char *makeitem(); extern double readdouble(); struct item { int length; /* total byte length of this stack item. */ struct item *next; /* next element on the stack. */ int type; /* stack element type. */ int subtype; /* subtype within this type. */ }; struct number { int length; struct item *next; int type; int subtype; unsigned char nbytes; unsigned char num[1]; }; struct string { int length; struct item *next; int type; int subtype; char s[1]; /* the string follows here, above char gives room for terminating null */ }; struct vector { int length; struct item *next; int type; int subtype; int depth; }; struct integers { int length; struct item *next; int type; int subtype; int bytesPerInteger; long bytepos; long bytelength; }; struct transformation { int length; struct item *next; int type; int subtype; double a; double b; double c; double d; double e; double f; }; static struct item *stack = (struct item *) 0; #define err0 "(%d) stack: pop called on an empty stack!\n" #define err1 "(%d) stack: expecting type (%s, %s), got (%d, %d)!\n" #define err2 "(%d) stack: should be 8 elements in pixelarray, got %d!\n" /* * Items on the stack. * */ stackempty() { return(stack == (struct item *) 0); } unsigned char *pop(type, subtype) int type, subtype; { unsigned char *ptr; struct item *pitem; pitem = stack; if (pitem == (struct item *) 0) error(err0, filepos); stack = pitem->next; ptr = (unsigned char *) pitem; checktype(ptr, type, subtype); return (ptr); } push(pitem) struct item *pitem; { pitem->next = stack; stack = pitem; } unsigned char *duplicate(from) unsigned char *from; { int n; unsigned char *to; to = makeitem(getlength(from), gettype(from), getsubtype(from)); for (n=0; n < getlength(from); n++) to[n] = from[n]; return (to); } gettype(pitem) struct item *pitem; { return(pitem->type); } getsubtype(pitem) struct item *pitem; { return(pitem->subtype); } getlength(pitem) struct item *pitem; { return(pitem->length); } checktype(ptr, type, subtype) unsigned char *ptr; int type, subtype; { int intype, insubtype, problem; char *typename, *subtypename; intype = gettype(ptr); insubtype = getsubtype(ptr); problem = 0; if (type) { if ((type & intype) == 0) problem = 1; if ((subtype != 0) && ((subtype & insubtype) == 0)) problem = 1; } if (problem) { typename = gettypename(type); subtypename = getsubtypename(subtype); error(err1, filepos, typename, subtypename, intype, insubtype); } } char *gettypename(type) int type; { switch (type) { case 0: return("undefined"); case 1: return("number"); case 2: return("string"); case 4: return("vector"); case 8: return("operator"); case 16: return("color"); case 32: return("pixelarray"); case 64: return("transformation"); case 128: return("integers"); default: return("unknown"); }; } char *getsubtypename(subtype) int subtype; { switch (subtype) { case 0: return("undefined"); case 1: return("integer"); case 2: return("rational"); case 4: return("identifier"); case 8: return("string"); case 16: return("general"); case 32: return("integers"); case 64: return("samples"); case 128: return("decompressop"); case 256: return("colorop"); case 512: return("colormodelop"); case 1024: return("value"); case 2048: return("name"); case 4096: return("operator"); default: return("unknown"); }; } /* * Numbers * */ unsigned char *makenumber(nbytes, array, subtype) int nbytes; unsigned char *array; { int n; unsigned char *ptr; struct number *pnumber; ptr = makeitem(sizeof(struct number)+nbytes, type_number, subtype); pnumber = (struct number *) ptr; pnumber->nbytes = nbytes; for (n=0; n < nbytes; n++) pnumber->num[n] = array[n]; return(ptr); } getnumlen(pnumber) struct number *pnumber; { checktype(pnumber, type_number, 0); return(pnumber->nbytes); } unsigned char *getnumber(pnumber) struct number *pnumber; { checktype(pnumber, type_number, 0); return(pnumber->num); } getint(ptr) unsigned char *ptr; { int result; result = getdouble(ptr); return (result); } double getdouble(pnumber) struct number *pnumber; { int nbytes; double result, numerator, denominator; checktype(pnumber, type_number, subtype_integer | subtype_rational); switch (getsubtype(pnumber)) { case subtype_integer: result = readdouble(pnumber->nbytes, pnumber->num); break; case subtype_rational: nbytes = pnumber->nbytes/2; numerator = readdouble(nbytes, pnumber->num); denominator = readdouble(nbytes, pnumber->num+nbytes); result = numerator/denominator; break; } return (result); } double getnumerator(pnumber) unsigned char *pnumber; { int nbytes; double numerator; checktype(pnumber, type_number, subtype_rational); nbytes = getnumlen(pnumber)/2; numerator = readdouble(nbytes, getnumber(pnumber)); return (numerator); } double getdenominator(pnumber) unsigned char *pnumber; { int nbytes; double denominator; checktype(pnumber, type_number, subtype_rational); nbytes = getnumlen(pnumber)/2; denominator = readdouble(nbytes, getnumber(pnumber)+nbytes); return (denominator); } /* * Strings * */ unsigned char *makestring(string, subtype) char *string; int subtype; { unsigned char *ptr; struct string *pstring; ptr = makeitem(sizeof(struct string)+strlen(string), type_string, subtype); pstring = (struct string *) ptr; strcpy(pstring->s, string); return(ptr); } unsigned char *makeidentifier(ptr, prefix) unsigned char *ptr; char *prefix; { char *string; int n, len, depth; unsigned char *composite, **array; depth = getdepth(ptr); array = getvector(ptr); len = strlen(prefix); for (n=0; n < depth; n++) { string = getstring(array[n], subtype_identifier); len += strlen(string)+1; /* add one for '/' character */ } /* added one too many, gives extra space */ string = (char *) malloc(len+1); /* add one for null character */ strcpy(string, prefix); for (n=0; n < depth; n++) { if (n) strcat(string, "/"); strcat(string, getstring(array[n], subtype_identifier)); } free(array); composite = makestring(string, subtype_identifier); free(string); return(composite); } char *getstring(pstring, subtype) struct string *pstring; { checktype(pstring, type_string, subtype); return(pstring->s); } /* * Vectors * */ unsigned char *makevector(array, type, subtype) unsigned char **array; int type, subtype; { int n, m, len, depth; unsigned char *ptr, *to, *from; struct vector *pvector; len = sizeof(struct vector); for (depth=0; array[depth] != (unsigned char *) 0; depth++) len += getlength(array[depth]); ptr = makeitem(len, type, subtype); pvector = (struct vector *) ptr; pvector->depth = depth; to = ptr; to += sizeof(struct vector); for (n=0; n < depth; n++) { from = array[n]; len = getlength(from); for (m=0; m < len; m++) to[m] = from[m]; to += len; } return(ptr); } unsigned char **getvector(from) unsigned char *from; { int n, m, depth, len; unsigned char *to, **array; depth = getdepth(from); array = malloc((depth+1)*sizeof(unsigned char *)); from += sizeof(struct vector); for (n=0; n < depth; n++) { array[n] = from; len = getlength(from); from += len; } array[depth] = (unsigned char *) 0; /* null terminated list */ return(array); } getdepth(pvector) struct vector *pvector; { return(pvector->depth); } /* * Operators * */ unsigned char *makeoperator(array, subtype) unsigned char **array; int subtype; { unsigned char *ptr; ptr = makevector(array, type_operator, subtype); return(ptr); } unsigned char **getoperator(ptr) unsigned char *ptr; { unsigned char **array; array = getvector(ptr); return(array); } /* * Colors * */ unsigned char *makecolor(array, subtype) unsigned char **array; int subtype; { unsigned char *ptr; ptr = makevector(array, type_color, subtype); return(ptr); } unsigned char **getcolor(ptr) unsigned char *ptr; { unsigned char **array; array = getvector(ptr); return(array); } /* * Pixel array * */ unsigned char *makepixelarray(array) unsigned char **array; { int depth; unsigned char *ptr; for (depth=0; array[depth] != (unsigned char *) 0; depth++) ; if (depth != 8) error(err2, filepos, depth); ptr = makevector(array, type_pixelarray, 0); return(ptr); } unsigned char *makeselect(max, samples) int max, samples; { int n, mask, depth; unsigned char *ptr, **array, value; array = malloc((max+1)*sizeof(unsigned char *)); depth = 0; for (n=0; n < max; n++) { value = n; mask = 1 << n; if (samples & mask) { array[depth] = makenumber(1, &value, subtype_integer); depth++; } } array[depth] = (unsigned char *) 0; /* null terminated list */ ptr = makevector(array, type_vector, subtype_general); for (n=0; n < depth; n++) free(array[n]); free(array); return(ptr); } unsigned char **getpixelarray(from) unsigned char *from; { if (getdepth(from) != 8) error(err2, filepos, getdepth(from)); return(getvector(from)); } /* * Transformations * */ unsigned char *maketransformation(a, b, c, d, e, f) double a, b, c, d, e, f; { unsigned char *ptr; struct transformation *ptransformation; ptr = makeitem(sizeof(struct transformation), type_transformation, 0); ptransformation = (struct transformation *) ptr; ptransformation->a = a; ptransformation->b = b; ptransformation->c = c; ptransformation->d = d; ptransformation->e = e; ptransformation->f = f; return(ptr); } double *gettransformation(ptransformation) struct transformation *ptransformation; { double *array; checktype(ptransformation, type_transformation, 0); array = (double *) malloc(6*sizeof(double)); array[0] = ptransformation->a; array[1] = ptransformation->b; array[2] = ptransformation->c; array[3] = ptransformation->d; array[4] = ptransformation->e; array[5] = ptransformation->f; return(array); } /* * Integers * */ unsigned char *makeintegers(bytesPerInteger, bytepos, bytelength) int bytesPerInteger; long bytepos, bytelength; { unsigned char *ptr; struct integers *pintegers; ptr = makeitem(sizeof(struct integers), type_integers, 0); pintegers = (struct integers *) ptr; pintegers->bytesPerInteger = bytesPerInteger; pintegers->bytepos = bytepos; pintegers->bytelength = bytelength; return(ptr); } getbytesPerInteger(pintegers) struct integers *pintegers; { checktype(pintegers, type_integers, 0); return(pintegers->bytesPerInteger); } long getbytepos(pintegers) struct integers *pintegers; { checktype(pintegers, type_integers, 0); return(pintegers->bytepos); } long getbytelength(pintegers) struct integers *pintegers; { checktype(pintegers, type_integers, 0); return(pintegers->bytelength); } /* * Private procedures to this module. * */ static unsigned char *makeitem(length, type, subtype) int length, type, subtype; { unsigned char *ptr; struct item *pitem; length = (length+sizeof(int)-1)/sizeof(int); length *= sizeof(int); ptr = (unsigned char *) malloc(length); pitem = (struct item *) ptr; pitem->length = length; pitem->type = type; pitem->subtype = subtype; return(ptr); } static double readdouble(nbytes, array) int nbytes; unsigned char *array; { int n, negative, temp; double result; negative = 0; if (array[0] > 127) { negative = 1; for (n=0; n < nbytes; n++) array[n] = ~array[n]; } result = 0; for (n=0; n < nbytes; n++) { temp = array[n]; result = 256.*result+(double)temp; } if (negative) result = -result-1; return(result); } /* Change Log * * K. Knox, 29-Mar-85 18:20:18, Created first version. * K. Knox, 13-May-85 9:50:52, Fixed negative number bug in readdouble(). * * * */