+/* 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);
+ }
+
+
+
+
+/*
+ * 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().
+ *
+ *
+ *
+ */
+
+
+
+