diff options
Diffstat (limited to 'nx-X11/lib/dps/dpsclient.c')
-rw-r--r-- | nx-X11/lib/dps/dpsclient.c | 2969 |
1 files changed, 2969 insertions, 0 deletions
diff --git a/nx-X11/lib/dps/dpsclient.c b/nx-X11/lib/dps/dpsclient.c new file mode 100644 index 000000000..c75d76ce8 --- /dev/null +++ b/nx-X11/lib/dps/dpsclient.c @@ -0,0 +1,2969 @@ +/* + * dpsclient.c -- Implementation of the Display PostScript Client Library. + * + * (c) Copyright 1988-1994 Adobe Systems Incorporated. + * All rights reserved. + * + * Permission to use, copy, modify, distribute, and sublicense this software + * and its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notices appear in all copies and that + * both those copyright notices and this permission notice appear in + * supporting documentation and that the name of Adobe Systems Incorporated + * not be used in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. No trademark license + * to use the Adobe trademarks is hereby granted. If the Adobe trademark + * "Display PostScript"(tm) is used to describe this software, its + * functionality or for any other purpose, such use shall be limited to a + * statement that this software works in conjunction with the Display + * PostScript system. Proper trademark attribution to reflect Adobe's + * ownership of the trademark shall be given whenever any such reference to + * the Display PostScript system is made. + * + * ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR + * ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. + * ADOBE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON- INFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL ADOBE BE LIABLE + * TO YOU OR ANY OTHER PARTY FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE, STRICT LIABILITY OR ANY OTHER ACTION ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ADOBE WILL NOT + * PROVIDE ANY TRAINING OR OTHER SUPPORT FOR THE SOFTWARE. + * + * Adobe, PostScript, and Display PostScript are trademarks of Adobe Systems + * Incorporated which may be registered in certain jurisdictions + * + * Author: Adobe Systems Incorporated + */ +/* $XFree86$ */ + +#include <stdlib.h> +#include <stdio.h> +#include <ctype.h> +#include <string.h> + +#include "dpsXpriv.h" +#include "DPS/dpsclient.h" +#include "dpsprivate.h" +#include "dpsdict.h" +#include "DPS/dpsexcept.h" +#include "dpsassert.h" + +#ifdef XDPS +#include "dpsXint.h" +#endif /* XDPS */ + +#if defined(SVR4) || defined(SYSV) || defined(SystemV) +#define os_bcopy(f,t,c) memcpy(t,f,c) +#else +#define os_bcopy(f,t,c) bcopy(f,t,c) +#endif + +#if !IEEEFLOAT +extern void IEEEHighToNative(/* FloatRep *from, real *to */); +/* Converts from IEEE high-byte-first real to native real. */ + +extern void NativeToIEEEHigh(/* real *from, FloatRep *to */); +/* Converts from native real to IEEE high-byte-first real. */ + +extern void IEEELowToNative(/* FloatRep *from, real *to */); +/* Converts from IEEE low-byte-first real to native real. */ + +extern void NativeToIEEELow(/* real *from, FloatRep *to */); +/* Converts from native real to IEEE low-byte-first real. */ +#endif /* !IEEEFLOAT */ + +typedef union { /* 32 bit number representations */ + unsigned int u; + int i; + float f; + unsigned char bytes[4]; + /* raw bytes, in whatever order they appear in memory */ + } Swap32Rec; + +typedef union { /* 16 bit number representations */ + unsigned short u; + short i; + unsigned char bytes[2]; + } Swap16Rec; + +#if SWAPBITS +#define Copy4SrcLo(src, dst)\ + (((Swap32Rec *) dst)->bytes[0] = ((Swap32Rec *) src)->bytes[0], \ + ((Swap32Rec *) dst)->bytes[1] = ((Swap32Rec *) src)->bytes[1], \ + ((Swap32Rec *) dst)->bytes[2] = ((Swap32Rec *) src)->bytes[2], \ + ((Swap32Rec *) dst)->bytes[3] = ((Swap32Rec *) src)->bytes[3] ) +#define Copy4SrcHi(src, dst)\ + (((Swap32Rec *) dst)->bytes[0] = ((Swap32Rec *) src)->bytes[3], \ + ((Swap32Rec *) dst)->bytes[1] = ((Swap32Rec *) src)->bytes[2], \ + ((Swap32Rec *) dst)->bytes[2] = ((Swap32Rec *) src)->bytes[1], \ + ((Swap32Rec *) dst)->bytes[3] = ((Swap32Rec *) src)->bytes[0] ) +#define Copy2SrcLo(src, dst)\ + (((Swap16Rec *) dst)->bytes[0] = ((Swap16Rec *) src)->bytes[0], \ + ((Swap16Rec *) dst)->bytes[1] = ((Swap16Rec *) src)->bytes[1] ) +#define Copy2SrcHi(src, dst)\ + (((Swap16Rec *) dst)->bytes[0] = ((Swap16Rec *) src)->bytes[1], \ + ((Swap16Rec *) dst)->bytes[1] = ((Swap16Rec *) src)->bytes[0] ) +#else /* SWAPBITS */ +#define Copy4SrcHi(src, dst)\ + (((Swap32Rec *) dst)->bytes[0] = ((Swap32Rec *) src)->bytes[0], \ + ((Swap32Rec *) dst)->bytes[1] = ((Swap32Rec *) src)->bytes[1], \ + ((Swap32Rec *) dst)->bytes[2] = ((Swap32Rec *) src)->bytes[2], \ + ((Swap32Rec *) dst)->bytes[3] = ((Swap32Rec *) src)->bytes[3] ) +#define Copy4SrcLo(src, dst)\ + (((Swap32Rec *) dst)->bytes[0] = ((Swap32Rec *) src)->bytes[3], \ + ((Swap32Rec *) dst)->bytes[1] = ((Swap32Rec *) src)->bytes[2], \ + ((Swap32Rec *) dst)->bytes[2] = ((Swap32Rec *) src)->bytes[1], \ + ((Swap32Rec *) dst)->bytes[3] = ((Swap32Rec *) src)->bytes[0] ) +#define Copy2SrcHi(src, dst)\ + (((Swap16Rec *) dst)->bytes[0] = ((Swap16Rec *) src)->bytes[0], \ + ((Swap16Rec *) dst)->bytes[1] = ((Swap16Rec *) src)->bytes[1] ) +#define Copy2SrcLo(src, dst)\ + (((Swap16Rec *) dst)->bytes[0] = ((Swap16Rec *) src)->bytes[1], \ + ((Swap16Rec *) dst)->bytes[1] = ((Swap16Rec *) src)->bytes[0] ) +#endif /* SWAPBITS */ + + +#define DPS_ERR_TAG 250 + +#define CONTEXTBUFFERSIZE 256 +#define MAXQUEUEDBUFFERS 5 + +DPSContext DPSGlobalContext; + +Globals DPSglobals = NULL; + +char *DPScalloc(integer e, integer n) +{ + char *p; + while (!(p = (char *)calloc(e, n))) { + DPSOutOfMemory(); + } + return p; +} + + + +void DPSSafeSetLastNameIndex(DPSContext ctxt) +{ + /* we're about to call the error handler, so roll back the + lastNameIndex to the last known valid index */ + DPSCheckInitClientGlobals(); + if (ctxt != dummyCtx && ctxt->space != NIL) + ((DPSPrivContext)ctxt)->lastNameIndex = ((DPSPrivSpace)(ctxt->space))->lastNameIndex; +} + +void DPSCheckInitClientGlobals(void) +{ + if (!DPSglobals) { + DPSglobals = (Globals)DPScalloc(sizeof(GlobalsRec), 1); + globLastNameIndex = -1; + } +} + +/**************************************************************/ +/* Procedures that support the DPSCreateContext context procs */ +/**************************************************************/ + +/* ARGSUSED */ +static void ReleaseInput( + char *unused, char *buffer) +{ + ContextBuffer cb = (ContextBuffer)buffer; + if (cb == NIL) return; + cb->next = contextBuffers; + contextBuffers = cb; + queuedBuffers--; +} + +/* ARGSUSED */ +static void StuffResultVal( + DPSContext ctxt, + DPSResults result, + integer tag, + DPSBinObj obj) +{ + + integer type = obj->attributedType & ~DPS_EXEC; + integer nObjs = 1; + + /* check if array */ + if (type == DPS_ARRAY) { + nObjs = obj->length; + if (nObjs < 1) return; + if (result->count == -1 && nObjs != 1) { + DPSSafeSetLastNameIndex(ctxt); + if (ctxt->errorProc != NIL) + (*ctxt->errorProc)(ctxt, dps_err_resultTypeCheck, (long unsigned)obj, 0); + return; + } + obj = (DPSBinObj) ((char *)obj + obj->val.arrayVal); + type = obj->attributedType & ~DPS_EXEC; + } + + do { + integer bump = 0; + if (result->count == 0) return; + switch (result->type) { + case dps_tBoolean: + if (type == DPS_BOOL) { + int *b = (int *) result->value; + *b = (int) obj->val.booleanVal; + bump = sizeof(int); + } + break; + case dps_tFloat: { + float *f = (float *) result->value; + if (type == DPS_REAL) { + *f = obj->val.realVal; + bump = sizeof(float); + } + else if (type == DPS_INT) { + *f = (float) obj->val.integerVal; + bump = sizeof(float); + } + break; + } + case dps_tDouble: { + double *d = (double *) result->value; + if (type == DPS_REAL) { + *d = (double) obj->val.realVal; + bump = sizeof(double); + } + else if (type == DPS_INT) { + *d = (double) obj->val.integerVal; + bump = sizeof(double); + } + break; + } + case dps_tShort: + if (type == DPS_INT) { + short *s = (short *) result->value; + *s = (short) obj->val.integerVal; + bump = sizeof(short); + } + break; + case dps_tUShort: + if (type == DPS_INT) { + unsigned short *us = (unsigned short *) result->value; + *us = (unsigned short) obj->val.integerVal; + bump = sizeof(unsigned short); + } + break; + case dps_tInt: + if (type == DPS_INT) { + int *i = (int *) result->value; + *i = (int) obj->val.integerVal; + bump = sizeof(int); + } + break; + case dps_tUInt: + if (type == DPS_INT) { + unsigned int *ui = (unsigned int *) result->value; + *ui = (unsigned int) obj->val.integerVal; + bump = sizeof(unsigned int); + } + break; + case dps_tLong: + if (type == DPS_INT) { + long int *li = (long int *) result->value; + *li = obj->val.integerVal; + bump = sizeof(long int); + } + break; + case dps_tULong: + if (type == DPS_INT) { + unsigned long *u = (unsigned long *) result->value; + *u = (unsigned long) obj->val.integerVal; + bump = sizeof(unsigned long); + } + break; + case dps_tChar: + case dps_tUChar: + if (nObjs != 1) { + DPSSafeSetLastNameIndex(ctxt); + if (ctxt->errorProc != NIL) + (*ctxt->errorProc)(ctxt, dps_err_resultTypeCheck, (long unsigned)obj, 0); + } + else if (type == DPS_STRING) { + if (result->count == -1) { + /* char * result, copy first, ignore subsequent, null terminate */ + os_bcopy(((integer)(obj->val.stringVal)) + (char *)obj, + result->value, obj->length); + (result->value)[obj->length] = '\0'; + result->count = 0; + } + else { + unsigned slen; + if (result->count >= (int) obj->length) { + /* copy entire string into char array */ + slen = obj->length; + } + else if (result->count > 0) { + /* copy partial string into char array */ + slen = result->count; + } + else return; /* ignore string result, no room left */ + os_bcopy(((integer)(obj->val.stringVal)) + (char *)obj, + result->value, slen); + result->value += slen; + result->count -= slen; + } + return; + } + break; + + default: + DPSSafeSetLastNameIndex(ctxt); + if (ctxt->errorProc != NIL) + (*ctxt->errorProc)(ctxt, dps_err_resultTypeCheck, (long unsigned)obj, 0); + } /* switch (result->type) */ + + if (bump == 0) { + DPSSafeSetLastNameIndex(ctxt); + if (ctxt->errorProc != NIL) + (*ctxt->errorProc)(ctxt, dps_err_resultTypeCheck, (long unsigned)obj, 0); + return; + } + if (result->count != -1) { + result->count--; + result->value += bump; + } + obj += 1; + nObjs--; + } while (nObjs > 0); /* do */ + +} /* StuffResultVal */ + + +static void NumFormatFromTokenType( + unsigned char t, + DPSNumFormat *numFormat) +{ + switch (t) { + case DPS_HI_IEEE: + *numFormat = dps_ieee; + break; + case DPS_LO_IEEE: + *numFormat = dps_ieee; + break; + case DPS_HI_NATIVE: + *numFormat = dps_native; + break; + case DPS_LO_NATIVE: + *numFormat = dps_native; + break; + default: DPSCantHappen(); + } +} + + +#if !IEEEFLOAT +/* called to deal with results from the server */ +static void ConvSeqInPlace(nObjs, currObj, base, tokenType) + integer nObjs; + DPSBinObj currObj; + char *base; + unsigned char tokenType; +{ + DPSNumFormat numFormat; + + NumFormatFromTokenType(tokenType, &numFormat); + + while (nObjs--) { + unsigned char t = currObj->attributedType & 0x07f; + integer i; + switch (t) { + case DPS_REAL: { + float f; + if (numFormat == dps_ieee) { + if (DPSDefaultByteOrder == dps_hiFirst) + IEEEHighToNative(&currObj->val.realVal, &f); + else + IEEELowToNative(&currObj->val.realVal, &f); + } + else break; /* switch */ + currObj->val.realVal = f; + break; + } + case DPS_ARRAY: + if (currObj->length > 0) + ConvSeqInPlace(currObj->length, (DPSBinObj)(base + currObj->val.arrayVal), base, tokenType); + break; + case DPS_NAME: + case DPS_STRING: + break; + default:; + } /* end switch */ + ++currObj; + } /* end while */ +} +#endif /* !IEEEFLOAT */ + +boolean DPSKnownContext(DPSContext ctxt) +{ + DPSPrivContext cc, c = (DPSPrivContext) ctxt; + DPSPrivSpace ss; + for (ss = spaces; ss != NIL; ss = ss->next) + for (cc = ss->firstContext; cc != NIL; cc = cc->next) + if (cc == c) return true; + return false; +} + +boolean DPSKnownSpace(DPSSpace space) +{ + DPSPrivSpace ss, s = (DPSPrivSpace) space; + for (ss = spaces; ss != NIL; ss = ss->next) + if (ss == s) return true; + return false; +} + +void DPSclientPrintProc ( + DPSContext ctxt, + char *buf, + unsigned nch) +{ + DPSPrivContext cc = (DPSPrivContext) ctxt; + +#define DPS_SEQ_MIN 2 + + DPSCheckInitClientGlobals(); + if (cc == NIL) cc = (DPSPrivContext)dummyCtx; + if (cc == NIL) return; + + if (nch == 0) { /* this is an EOF */ + DPSAssertWarn(buf == NIL, cc, "non-nil output buffer with 0 length"); + cc->eofReceived = true; + if (cc->objBuf) { + /* we were buffering; drop buffered chars on the floor */ + free(cc->objBuf); + cc->objBuf = NIL; + cc->nObjBufChars = 0; + } + } + while (nch > 0) { + char *oldBuf = NIL; + unsigned oldNch = 0; + unsigned n; + if (cc->objBuf) { /* we're buffering */ + unsigned long int m; + char *b = cc->objBuf + cc->nObjBufChars; + integer minSize; + while (cc->nObjBufChars < DPS_SEQ_MIN) { + if (nch == 0) return; + *b++ = *buf++; + ++cc->nObjBufChars; + --nch; + } + b = cc->objBuf; + minSize = (*(b+1) == 0) ? DPS_EXT_HEADER_SIZE : DPS_HEADER_SIZE; + if (cc->nObjBufChars < minSize) { + if (nch + cc->nObjBufChars < (unsigned) minSize) { + os_bcopy(buf, b + cc->nObjBufChars, nch); + cc->nObjBufChars += nch; + return; + } + else { + os_bcopy(buf, b + cc->nObjBufChars, minSize - cc->nObjBufChars); + buf += minSize - cc->nObjBufChars; + nch -= minSize - cc->nObjBufChars; + cc->nObjBufChars = minSize; + } + } + + if (minSize == DPS_HEADER_SIZE) { + unsigned short *sizeP = (unsigned short *)(cc->objBuf+2); + m = *sizeP; + } + else { + unsigned long *extSizeP = (unsigned long *)(cc->objBuf+4); + m = *extSizeP; + } + + /* here with m = BOS total length in bytes, b = cc->objBuf */ + cc->objBuf = (char *)realloc(b, m); + + if (nch + cc->nObjBufChars < m) { + os_bcopy(buf, cc->objBuf + cc->nObjBufChars, nch); + cc->nObjBufChars += nch; + return; + } + else { + os_bcopy(buf, cc->objBuf + cc->nObjBufChars, m - cc->nObjBufChars); + buf += m - cc->nObjBufChars; + nch -= m - cc->nObjBufChars; + cc->nObjBufChars = m; + } + /* we're here only if cc->objBuf contains a complete BOS */ + oldBuf = buf; + oldNch = nch; + buf = cc->objBuf; + nch = cc->nObjBufChars; + cc->objBuf = NIL; + cc->nObjBufChars = 0; + } /* if we're buffering */ + + /* dispose of any plain text. If no binary conversion, all output + is plain text */ + if (cc->contextFlags & DPS_FLAG_NO_BINARY_CONVERSION) n = nch; + else { + for (n = 0; n < nch && + ((unsigned char) buf[n] < 128 || (unsigned char) buf[n] > 159); n++); + } + if ((n > 0) && (cc->textProc != NIL)) { + (*cc->textProc)((DPSContext)cc, buf, n); + } + buf += n; + nch -= n; + + if (nch != 0) { + /* here with the next binary object sequence from a server */ + DPSExtendedBinObjSeq bos; + DPSExtendedBinObjSeqRec bosRec; + DPSBinObj firstObj; + unsigned t; + unsigned long int m; + unsigned minSize; + + if (nch < DPS_SEQ_MIN) { + /* gotta buffer it */ + DPSAssertWarn(nch == 1 && !oldBuf, cc, "illegal binary output from context (oldBuf)"); + cc->objBuf = (char *)DPScalloc(DPS_EXT_HEADER_SIZE, 1); + cc->nObjBufChars = nch; + *cc->objBuf = *buf; + return; + } + /* check for quadbyte alignment */ + if ((long int)buf & (MIN_POINTER_ALIGN - 1)) { + /* not aligned, we gotta copy the buffer */ + /* we assert that we can't have an oldBuf if we're not aligned, + since we only get an oldBuf if we copied to a new buffer, + and we have already tested nch to be at least DPS_SEQ_MIN */ + DPSAssertWarn(!oldBuf && nch > 1, cc, "return values garbled (oldBuf||nch<DPS_SEQ_MIN"); + /* copy DPS_SEQ_MIN bytes, so we can use existing buffering code */ + cc->objBuf = (char *)DPScalloc(DPS_EXT_HEADER_SIZE, 1); + cc->nObjBufChars = DPS_SEQ_MIN; + os_bcopy(buf, cc->objBuf, cc->nObjBufChars); + buf += DPS_SEQ_MIN; + nch -= DPS_SEQ_MIN; + /* now go to top of loop and go through the buffer update code */ + continue; + } + bos = (DPSExtendedBinObjSeq) buf; + t = bos->tokenType; + minSize = (bos->escape == 0) ? DPS_EXT_HEADER_SIZE : DPS_HEADER_SIZE; + if (nch < minSize) { + /* gotta buffer it */ + char *tb; + DPSAssertWarn(!oldBuf, cc, "return values garbled (oldBuf)"); + tb = cc->objBuf = (char *)DPScalloc(minSize, 1); + cc->nObjBufChars = nch; + while (nch--) *tb++ = *buf++; + return; + } + else if (minSize == DPS_HEADER_SIZE) { + /* this is not an extended BOS */ + DPSBinObjSeq seqHead = (DPSBinObjSeq) buf; + bos = &bosRec; + bos->tokenType = t; + bos->nTopElements = seqHead->nTopElements; + bos->length = seqHead->length; + firstObj = &(seqHead->objects[0]); + } + else firstObj = &(bos->objects[0]); + m = bos->length; + if (nch < m) { + /* gotta buffer it */ + DPSAssertWarn(!oldBuf, cc, "return values garbled (oldBuf&&nch<m"); + cc->objBuf = (char *)DPScalloc(bos->length, 1); + cc->nObjBufChars = nch; + os_bcopy(buf, cc->objBuf, nch); + return; + } + DPSAssertWarn(bos->nTopElements == 1, cc, "illegal binary output detected (bos->nTopElements!=1)"); +#if !IEEEFLOAT + if (t != DPS_DEF_TOKENTYPE) + ConvSeqInPlace(1, firstObj, firstObj, bos->tokenType); +#endif /* !IEEEFLOAT */ + t = firstObj->tag; + if (t == DPS_ERR_TAG) { + cc->resultTable = NIL; + DPSSafeSetLastNameIndex((DPSContext)cc); + DURING + if (cc->errorProc != NIL) + (*cc->errorProc)((DPSContext)cc, dps_err_ps, (unsigned long)buf, m); + HANDLER + if (oldBuf) free(buf); + RERAISE; + END_HANDLER + } + else { /* dispatch this result */ + if (!cc->resultTable || t > cc->resultTableLength) { + if (cc->chainParent == NIL && cc->errorProc != NIL) { + DPSSafeSetLastNameIndex((DPSContext)cc); + (*cc->errorProc)((DPSContext)cc, dps_err_resultTagCheck, (unsigned long)buf, m); + } + } + else if (t == cc->resultTableLength) { + cc->resultTable = NIL; + } + else { + StuffResultVal((DPSContext)cc, &cc->resultTable[t], t, firstObj); + } + } + if (!oldBuf) + buf += m; + nch -= m; + } /* if (nch != 0) ... the next binary object sequence from a server */ + if (oldBuf) { + DPSAssertWarn(nch == 0, cc, "some return values/data lost (nch)"); + free(buf); + buf = oldBuf; + nch = oldNch; + } + } /* while (nch > 0) */ + +} /* DPSclientPrintProc */ + +/**************************************/ +/* Context procs for DPSCreateContext */ +/**************************************/ + + +static void procWaitContext(DPSContext ctxt) +{ + typedef struct { + unsigned char tokenType; + unsigned char topLevelCount; + unsigned short int nBytes; + + DPSBinObjGeneric obj0; + DPSBinObjGeneric obj1; + DPSBinObjGeneric obj2; + DPSBinObjGeneric obj3; + } DPSQ; + static DPSQ dpsF = { + DPS_DEF_TOKENTYPE, 4, sizeof(DPSQ), + {DPS_LITERAL|DPS_INT, 0, 0, -23}, /* arbitrary int */ + {DPS_LITERAL|DPS_INT, 0, 0, 0}, /* termination tag = 0 */ + {DPS_EXEC|DPS_NAME, 0, DPSSYSNAME, 119}, /* printobject */ + {DPS_EXEC|DPS_NAME, 0, DPSSYSNAME, 70}, /* flush */ + }; /* DPSQ */ + DPSResultsRec DPSR; + + if (DPSPrivateCheckWait(ctxt)) return; + + ctxt->resultTable = &DPSR; /* must be non-null for handler to work */ + ctxt->resultTableLength = 0; /* same value as termination tag */ + DPSBinObjSeqWrite(ctxt, (char *) &dpsF,sizeof(DPSQ)); + DPSAwaitReturnValues(ctxt); +} + +static void procUpdateNameMap(DPSContext ctxt) +{ + integer i; + DPSPrivContext c = (DPSPrivContext) ctxt; + DPSPrivSpace s = (DPSPrivSpace) ctxt->space; + DPSContext children = ctxt->chainChild; + + /* unlink context from chain temporarily, so DPSPrintf can be called */ + if (children != NIL) ctxt->chainChild = NIL; + DURING + for (i = s->lastNameIndex+1; i <= globLastNameIndex; i++) + DPSPrintf(ctxt, "%d /%s defineusername\n", i, userNames[i]); + HANDLER + if (children != NIL) ctxt->chainChild = children; + RERAISE; + END_HANDLER + c->lastNameIndex = globLastNameIndex; + if (children != NIL) { + /* update any children */ + ctxt->chainChild = children; + DPSUpdateNameMap(ctxt->chainChild); + } +} + +static void procWriteData( + DPSContext ctxt, + char *buf, + unsigned int count) +{ + /* safe to call with chain */ + DPSinnerProcWriteData(ctxt, buf, count); + if (ctxt->chainChild != NIL) DPSWriteData(ctxt->chainChild, buf, count); +} + +static void procBinObjSeqWrite( + DPSContext ctxt, + char *buf, + unsigned int count) +{ + if (((DPSPrivContext)ctxt)->lastNameIndex < globLastNameIndex) DPSUpdateNameMap(ctxt); + DPSinnerProcWriteData(ctxt, buf, count); + if (ctxt->chainChild != NIL) DPSBinObjSeqWrite(ctxt->chainChild, buf, count); +} + +static void procWriteStringChars( + DPSContext ctxt, + char *buf, + unsigned int count) +{ + DPSinnerProcWriteData(ctxt, buf, count); + if (ctxt->chainChild != NIL) DPSWriteStringChars(ctxt->chainChild, buf, count); +} + +static void procWritePostScript( + DPSContext ctxt, + char *buf, + unsigned int count) +{ + DPSinnerProcWriteData(ctxt, buf, count); + if (ctxt->chainChild != NIL) DPSWritePostScript(ctxt->chainChild, buf, count); +} + +static void innerProcWriteNumstring( + DPSContext ctxt, + DPSDefinedType type, + char *data, + unsigned int size, + int scale, + void (*writeProc)(DPSContext, char *, unsigned)) +{ + unsigned char HNumHeader[4]; + register int i; +#define NBUFSIZE 10 + int ibuf[NBUFSIZE]; /* This needs to be a 32 bit datatype */ + + HNumHeader[0] = 149; + switch (type) { + case dps_tLong: + HNumHeader[1] = (DPS_DEF_TOKENTYPE % 2) * 128 + scale; + break; + + case dps_tInt: + HNumHeader[1] = ((sizeof(int) >= 4) ? 0 : 32) + + ((DPS_DEF_TOKENTYPE % 2) * 128) + scale; + break; + + case dps_tShort: + HNumHeader[1] = 32 + ((DPS_DEF_TOKENTYPE % 2) * 128) + scale; + break; + + case dps_tFloat: + HNumHeader[1] = 48 + ((DPS_DEF_TOKENTYPE % 2) * 128) + + ((DPS_DEF_TOKENTYPE >= 130) ? 1 : 0); + break; + + default: + break; + } + + HNumHeader[(DPS_DEF_TOKENTYPE % 2) ? 2 : 3] = (unsigned char) size; + HNumHeader[(DPS_DEF_TOKENTYPE % 2) ? 3 : 2] = (unsigned char) (size >> 8); + + (*writeProc)(ctxt, (char *)HNumHeader, 4); + + switch (type) { + case dps_tLong: + if (sizeof(long) == 4) { + (*writeProc)(ctxt, (char *) data, size * 4); + } else { + while (size > 0) { + for (i = 0; i < NBUFSIZE && (unsigned) i < size; i++) { + ibuf[i] = ((long *) data)[i]; + } + (*writeProc)(ctxt, (char *) ibuf, + 4 * (size < NBUFSIZE ? size : NBUFSIZE)); + size -= NBUFSIZE; + } + } + break; + + case dps_tInt: + (*writeProc)(ctxt, (char *) data, size * sizeof(int)); + break; + + case dps_tShort: + (*writeProc)(ctxt, (char *) data, size * sizeof(short)); + break; + + case dps_tFloat: + (*writeProc)(ctxt, (char *) data, size * sizeof(float)); + + default: + break; + } +} /* innerProcWriteNumstring */ + +static void procWriteNumstring( + DPSContext ctxt, + DPSDefinedType type, + char *data, + unsigned int size, + int scale) +{ + innerProcWriteNumstring(ctxt, type, data, size, scale, DPSinnerProcWriteData); + if (ctxt->chainChild != NIL) DPSWriteNumString(ctxt->chainChild, type, data, size, scale); +} + +static void writeTypedObjectArray( + DPSContext ctxt, + DPSDefinedType type, + char *array, + unsigned int length) +{ + +#define DPSMAX_SEQ 10 + unsigned int i; + DPSPrivContext c = (DPSPrivContext)(ctxt); + static DPSBinObjGeneric bboolObj[DPSMAX_SEQ] = { + {DPS_LITERAL | DPS_BOOL, 0,0,0}, + {DPS_LITERAL | DPS_BOOL, 0,0,0}, + {DPS_LITERAL | DPS_BOOL, 0,0,0}, + {DPS_LITERAL | DPS_BOOL, 0,0,0}, + {DPS_LITERAL | DPS_BOOL, 0,0,0}, + {DPS_LITERAL | DPS_BOOL, 0,0,0}, + {DPS_LITERAL | DPS_BOOL, 0,0,0}, + {DPS_LITERAL | DPS_BOOL, 0,0,0}, + {DPS_LITERAL | DPS_BOOL, 0,0,0}, + {DPS_LITERAL | DPS_BOOL, 0,0,0}, + }; + static DPSBinObjReal rrealObj[DPSMAX_SEQ] = { + {DPS_LITERAL | DPS_REAL, 0,0,0}, + {DPS_LITERAL | DPS_REAL, 0,0,0}, + {DPS_LITERAL | DPS_REAL, 0,0,0}, + {DPS_LITERAL | DPS_REAL, 0,0,0}, + {DPS_LITERAL | DPS_REAL, 0,0,0}, + {DPS_LITERAL | DPS_REAL, 0,0,0}, + {DPS_LITERAL | DPS_REAL, 0,0,0}, + {DPS_LITERAL | DPS_REAL, 0,0,0}, + {DPS_LITERAL | DPS_REAL, 0,0,0}, + {DPS_LITERAL | DPS_REAL, 0,0,0}, + }; + static DPSBinObjGeneric iintObj[DPSMAX_SEQ] = { + {DPS_LITERAL | DPS_INT, 0,0,0}, + {DPS_LITERAL | DPS_INT, 0,0,0}, + {DPS_LITERAL | DPS_INT, 0,0,0}, + {DPS_LITERAL | DPS_INT, 0,0,0}, + {DPS_LITERAL | DPS_INT, 0,0,0}, + {DPS_LITERAL | DPS_INT, 0,0,0}, + {DPS_LITERAL | DPS_INT, 0,0,0}, + {DPS_LITERAL | DPS_INT, 0,0,0}, + {DPS_LITERAL | DPS_INT, 0,0,0}, + {DPS_LITERAL | DPS_INT, 0,0,0}, + }; + + if (DPSCheckShared(c)) return; + + switch (type) { + case dps_tChar: + case dps_tUChar: + DPSCantHappen(); + break; + + case dps_tBoolean: { + while (length > 0) { + for (i = 0; i < MIN(DPSMAX_SEQ, length); i++) { + bboolObj[i].val = *((int *)array); + array += sizeof(int); + } + DPSWritePostScript(ctxt, (char *) bboolObj, sizeof(DPSBinObjGeneric) * i); + length -= i; + } + break; + } + + case dps_tFloat: { + while (length > 0) { + for (i = 0; i < MIN(DPSMAX_SEQ, length); i++) { + rrealObj[i].realVal = *((float *)array); + array += sizeof(float); + } + DPSWritePostScript(ctxt, (char *) rrealObj, sizeof(DPSBinObjReal) * i); + length -= i; + } + break; + } + + case dps_tDouble: { + while (length > 0) { + for (i = 0; i < MIN(DPSMAX_SEQ, length); i++) { + rrealObj[i].realVal = *((double *)array); + array += sizeof(double); + } + DPSWritePostScript(ctxt, (char *) rrealObj, sizeof(DPSBinObjReal) * i); + length -= i; + } + break; + } + + case dps_tShort: { + while (length > 0) { + for (i = 0; i < MIN(DPSMAX_SEQ, length); i++) { + iintObj[i].val = *((short *)array); + array += sizeof(short); + } + DPSWritePostScript(ctxt, (char *) iintObj, sizeof(DPSBinObjGeneric) * i); + length -= i; + } + break; + } + + case dps_tUShort: { + while (length > 0) { + for (i = 0; i < MIN(DPSMAX_SEQ, length); i++) { + iintObj[i].val = *((unsigned short *)array); + array += sizeof(unsigned short); + } + DPSWritePostScript(ctxt, (char *) iintObj, sizeof(DPSBinObjGeneric) * i); + length -= i; + } + break; + } + + case dps_tInt: { + while (length > 0) { + for (i = 0; i < MIN(DPSMAX_SEQ, length); i++) { + iintObj[i].val = *((int *)array); + array += sizeof(int); + } + DPSWritePostScript(ctxt, (char *) iintObj, sizeof(DPSBinObjGeneric) * i); + length -= i; + } + break; + } + + case dps_tUInt: { + while (length > 0) { + for (i = 0; i < MIN(DPSMAX_SEQ, length); i++) { + iintObj[i].val = *((unsigned int *)array); + array += sizeof(unsigned int); + } + DPSWritePostScript(ctxt, (char *) iintObj, sizeof(DPSBinObjGeneric) * i); + length -= i; + } + break; + } + + case dps_tLong: { + while (length > 0) { + for (i = 0; i < MIN(DPSMAX_SEQ, length); i++) { + iintObj[i].val = *((long *)array); + array += sizeof(long); + } + DPSWritePostScript(ctxt, (char *) iintObj, sizeof(DPSBinObjGeneric) * i); + length -= i; + } + break; + } + + case dps_tULong: { + while (length > 0) { + for (i = 0; i < MIN(DPSMAX_SEQ, length); i++) { + iintObj[i].val = *((unsigned long *)array); + array += sizeof(unsigned long); + } + DPSWritePostScript(ctxt, (char *) iintObj, sizeof(DPSBinObjGeneric) * i); + length -= i; + } + break; + + + } + + default:; + } +} /* writeTypedObjectArray */ + +static void procDestroyContext(DPSContext ctxt) +{ + DPSPrivContext c = (DPSPrivContext)ctxt, cc, prev; + DPSPrivSpace ss = (DPSPrivSpace)(c->space); + + if (c->buf != NIL) { + ContextBuffer b = (ContextBuffer)(c->buf); + b->next = contextBuffers; + contextBuffers = b; + c->buf = NIL; + } + if (c->objBuf != NIL) { + free(c->objBuf); + c->objBuf = NIL; + } + + DPSUnchainContext(ctxt); + + prev = NIL; + DPSAssert(ss != NIL); + for (cc = ss->firstContext; (cc != NIL) && (cc != c); cc = cc->next) + prev = cc; + DPSAssert(cc != NIL); + DPSAssert(cc != prev); + if (prev == NIL) ss->firstContext = cc->next; + else { + prev->next = cc->next; + DPSAssert(prev->next != prev); + } + + DPSPrivateDestroyContext(ctxt); + free(c); +} + +static void procDestroySpace(DPSSpace space) +{ + DPSPrivSpace ns, prevS, ss = (DPSPrivSpace)space; + integer sid = ss->sid; + + while (ss->firstContext != NIL) + DPSDestroyContext((DPSContext)(ss->firstContext)); + + prevS = NIL; + for (ns = spaces; (ns != NIL) && (ns->sid != sid); ns = ns->next) + prevS = ns; + DPSAssert(ns != NIL); + DPSAssert(ns == ss); + if (prevS == NIL) spaces = ns->next; + else { + prevS->next = ns->next; + DPSAssert(prevS->next != prevS); + } + + DPSPrivateDestroySpace(space); + free(ss); +} + +static void procInterrupt(DPSContext ctxt) +{ + DPSPrivContext c = (DPSPrivContext)ctxt; + DPSSendInterrupt((XDPSPrivContext)c->wh, c->cid, DPSclientPrintProc); + if (ctxt->chainChild != NIL) DPSInterruptContext(ctxt->chainChild); +} + + +/****************************************************************/ +/* Procedures that support the DPSCreateTextContext context procs */ +/****************************************************************/ + +/* precondition: (c >= 129 && c <= 159), which means that c is the + first byte of either a binary token or a binary object sequence */ + +static boolean IsBinaryToken(unsigned char c) +{ + return (c != DPS_HI_IEEE && c != DPS_LO_IEEE + && c != DPS_HI_NATIVE && c != DPS_LO_NATIVE); +} + +/* returns the number of initial bytes of a given goody that are + required to figure out how many bytes are needed for the entire goody */ + +static unsigned GetHdrNBytes(unsigned char *t) +{ + if (!IsBinaryToken(*t)) { + if (*(++t) == 0) return DPS_EXT_HEADER_SIZE; + else return DPS_HEADER_SIZE; + } + switch (*t) { + case 137: + case 142: + return(2); + case 143: + case 144: + return(3); + case 149: + return(4); + default: + if (*t > 149 && *t < 160) return(1); /* unassigned */ + else return(1); + } +} + + +static void WriteHomogeneousArrayAsASCII( + DPSContext ctxt, + register unsigned char *buf) +{ + Swap32Rec n32; + Swap16Rec n16; + register unsigned char *b; + + unsigned char r = *buf++; + float f; + boolean hi = (r < 128); + + if (!hi) r -= 128; + DPSPrintf(ctxt, "[ "); + b = n16.bytes; + if (hi) {Copy2SrcHi(buf, b);} else {Copy2SrcLo(buf, b);} + buf += 2; + if (r < 32) /* 32-bit fixed */ + while (n16.u--) { + b = n32.bytes; + if (hi) {Copy4SrcHi(buf, b);} else {Copy4SrcLo(buf, b);} + if (r == 0) + DPSPrintf(ctxt, "%d ", n32.i); + else { + f = n32.i; /* convert to float */ + n32.f = f / (1 << r); /* scale */ + DPSPrintf(ctxt, "%g ", n32.f); + } + buf += 4; + } + else if (r < 48) { /* 16-bit fixed */ + unsigned l = n16.u; + r -= 32; + while (l--) { + b = n16.bytes; + if (hi) {Copy2SrcHi(buf, b);} else {Copy2SrcLo(buf, b);} + if (r == 0) + DPSPrintf(ctxt, "%d ", n16.i); + else { + f = n16.i; /* convert to float */ + n32.f = f / (1 << r); /* scale */ + DPSPrintf(ctxt, "%g ", n32.f); + } + buf += 2; + } + } + else if (r == 48) /* 32-bit IEEE */ + while (n16.u--) { +#if IEEEFLOAT + b = n32.bytes; + if (hi) {Copy4SrcHi(buf, b);} else {Copy4SrcLo(buf, b);} +#else /* IEEEFLOAT */ + if (hi) IEEEHighToNative(buf, &n32.f); + else IEEELowToNative(buf, &n32.f); +#endif /* IEEEFLOAT */ + DPSPrintf(ctxt, "%g ", n32.f); + buf += 4; + } + else if (r == 49) /* 32-bit native */ + while (n16.u--) { + b = n32.bytes; + *b++ = *buf++,*b++ = *buf++,*b++ = *buf++,*b = *buf++; + DPSPrintf(ctxt, "%g ", n32.f); + } + else DPSCantHappen(); + DPSPrintf(ctxt, "\n] "); +} /* WriteHomogeneousArrayAsASCII */ + +/* returns the number of bytes needed for the entire goody. buf points + to enough initial bytes of the goody to figure this out (see above). */ + +static integer GetNBytes(register unsigned char *buf) +{ + unsigned short int nBytes; + register unsigned char *r = (unsigned char *)&nBytes; + + switch (*buf) { + case DPS_HI_IEEE: + case DPS_HI_NATIVE: + if (*(buf+1) == 0) { + unsigned int nb; + r = (unsigned char *)&nb; + buf += 4; + Copy4SrcHi(buf, r); + return(nb); + } + else { + buf += 2; + Copy2SrcHi(buf, r); + } + break; + case DPS_LO_IEEE: + case DPS_LO_NATIVE: + if (*(buf+1) == 0) { + unsigned int nb; + r = (unsigned char *)&nb; + buf += 4; + Copy4SrcLo(buf, r); + return(nb); + } + else { + buf += 2; + Copy2SrcLo(buf, r); + } + break; + case 132: + case 133: + case 138: + case 139: + case 140: + nBytes = 5; break; + case 134: + case 135: + nBytes = 3; break; + case 136: + case 141: + case 145: + case 146: + case 147: + case 148: + nBytes = 2; break; + case 137: { + unsigned int l = *(buf+1); + if (l < 32) {nBytes = 6; break;} + if (l < 48) {nBytes = 4; break;} + if (l-128 < 32) {nBytes = 6; break;} + if (l-128 < 48) {nBytes = 4; break;} + DPSCantHappen(); + } + case 142: + nBytes = *(buf+1); + nBytes += 2; + break; + case 143: + buf++; + Copy2SrcHi(buf, r); + nBytes += 3; + break; + case 144: + buf++; + Copy2SrcLo(buf, r); + nBytes += 3; + break; + case 149: { + unsigned char scale = *(buf+1); + buf += 2; + if (scale < 128) + Copy2SrcHi(buf, r); + else { + scale -= 128; + Copy2SrcLo(buf, r); + } + if (scale < 32) + nBytes *= 4; + else if (scale < 48) + nBytes *= 2; + else + nBytes *= 4; + nBytes += 4; + break; + } + default: nBytes = 1; /* unassigned */ + } + return(nBytes); +} + +static void WriteSeqAsAscii( + DPSContext ctxt, + char *base, + DPSBinObj currObj, + unsigned int nObjs, + unsigned char tokenType, + int *numstringOffsets) +{ + integer nLineObjs = 0; + DPSNumFormat numFormat; + float f; + long int i; + unsigned short int length; + + /* NOTE: It's ok to call DPSPrintf (which calls DPSWritePostScript) + from here since we are only sending text, so there's no problem + with re-entering DPSWritePostScript. Caller guarantees + that this context has no children. */ + + NumFormatFromTokenType(tokenType, &numFormat); + + while (nObjs--) { + unsigned char type = currObj->attributedType & ~DPS_EXEC; + boolean lit = ((currObj->attributedType & DPS_EXEC) == 0); + + switch (type) { + case DPS_NULL: + break; + case DPS_BOOL: + i = currObj->val.booleanVal; + if (i) + DPSPrintf(ctxt, "true "); + else + DPSPrintf(ctxt, "false "); + break; + case DPS_INT: + i = currObj->val.integerVal; + DPSPrintf(ctxt, "%d ", i); + break; + case DPS_REAL: +#if IEEEFLOAT + f = currObj->val.realVal; +#else /* IEEEFLOAT */ + if (numFormat != DPSDefaultNumFormat) +#if SWAPBITS + IEEELowToNative(&currObj->val.realVal, &f); +#else /* SWAPBITS */ + IEEEHighToNative(&currObj->val.realVal, &f); +#endif /* SWAPBITS */ + else + f = currObj->val.realVal; +#endif /* IEEEFLOAT */ + + DPSPrintf(ctxt, "%g ", f); + break; + case DPS_NAME: { + char *p = 0; + integer index; + + index = currObj->val.nameVal; + length = currObj->length; + + if (lit) DPSPrintf(ctxt, "/"); + + if (length == DPSSYSNAME) { /* system name index */ + if (index <= DPS_LAST_COMMON_SYSNAME) { + if (!lit && (ctxt->contextFlags & DPS_FLAG_USE_ABBREVS)) { + p = DPSGetSysnameAbbrev(index); + if (p == NULL) p = DPSSysNames[index]; + } else p = DPSSysNames[index]; + } else if (DPS_FIRST_AUX_SYSNAME <= index + && index <= DPS_LAST_AUX_SYSNAME) + p = DPSSysNamesAux[index - DPS_FIRST_AUX_SYSNAME]; + else DPSCantHappen(); + length = strlen(p); + } + else if (length == 0) { /* user name index */ + p = DPSNameFromIndex(index); + length = strlen(p); + } + else + p = base + index; + + DPSWriteData(ctxt, p, length); + DPSPrintf(ctxt, " "); + break; + } + case DPS_ARRAY: + DPSPrintf(ctxt, (lit ? "[ " : "{ ")); + WriteSeqAsAscii( + ctxt, + base, + (DPSBinObj)(base+currObj->val.arrayVal), + currObj->length, + tokenType, numstringOffsets); + DPSPrintf(ctxt, (lit ? " ] " : " } ")); + break; + case DPS_MARK: + if (lit) + DPSPrintf(ctxt, "/mark "); + else + DPSPrintf(ctxt, "mark "); + break; + case DPS_STRING: { + char *p; + int j; + i = currObj->val.stringVal; + length = currObj->length; + p = base + i; + if (numstringOffsets != NULL) { + for (j = 2; j < numstringOffsets[1] && + numstringOffsets[j] != i; j++) ; + if (numstringOffsets[j] == i) { + DPSAssert(*(unsigned char *) p++ == 149); + WriteHomogeneousArrayAsASCII(ctxt, (unsigned char *) p); + break; + } + } + DPSPrintf(ctxt, "("); +#ifdef VMS + WriteVMSStringBody(ctxt, p, length); /* write this */ +#else /* VMS */ + /* render string bytes correctly */ + while (length--) { + char c = *p++; + if (c == '(' || c == ')' || c == '\\') + DPSPrintf(ctxt, "\\%c", c); + else if (c == '\n') + DPSPrintf(ctxt, "\\n"); + else if (!(isascii(c) && isprint(c))) + DPSPrintf(ctxt, "\\%03.3o", (unsigned char) c); + else DPSWriteData(ctxt, &c, 1); + } +#endif /* VMS */ + DPSPrintf(ctxt, ") "); + break; + } + default: DPSCantHappen(); + } + + currObj++; + if (++nLineObjs == 15) { + nLineObjs = 0; + DPSPrintf(ctxt, "\n "); + } + } /* end while */ + + DPSPrintf(ctxt, "\n"); + +} /* WriteSeqAsAscii */ + +static void ConvertAndWriteSeqAsData( + DPSContext ctxt, + char *bosBuf, + int pass) +{ + DPSPrivContext cc = (DPSPrivContext) ctxt; + DPSExtendedBinObjSeq bos; + DPSExtendedBinObjSeqRec bosRec; + DPSNumFormat numFormat; + unsigned int offset, firstCharOffset; + unsigned int nameOffset; + unsigned int len = 0; + DPSBinObj currObj; + integer headSize; + char *seqBase; + + if (*(bosBuf+1) != 0) { + /* not an extended BOS */ + DPSBinObjSeq seqHead = (DPSBinObjSeq) bosBuf; + bos = &bosRec; + bos->tokenType = seqHead->tokenType; + bos->escape = seqHead->nTopElements; + bos->nTopElements = seqHead->nTopElements; + bos->length = seqHead->length; + currObj = &(seqHead->objects[0]); + seqBase = (char *) &(seqHead->objects[0]); + headSize = DPS_HEADER_SIZE; + } + else { + bos = (DPSExtendedBinObjSeq) bosBuf; + currObj = &(bos->objects[0]); + seqBase = (char *) &(bos->objects[0]); + headSize = DPS_EXT_HEADER_SIZE; + } + firstCharOffset = bos->length - headSize; + nameOffset = firstCharOffset; + + /* Caller guarantees that this context has no children, + so it is okay to call DPSWriteData */ + + NumFormatFromTokenType(bos->tokenType, &numFormat); + + /* Pass 0: If we're expanding name indices, find all name objects, + lookup their strings, sum the lengths. + Write the modified sequence header regardless. + Pass 1: we're converting indices to strings and/or + converting numbers. Write each modified object, and + subsidiary strings. + Pass 2: Find all name objects, lookup and write the strings. */ + + if (pass == 0 && ctxt->nameEncoding != dps_strings) + /* we're just converting numbers, so skip while loop */ + offset = firstCharOffset; + else + offset = 0; + + while (offset < firstCharOffset) { + DPSBinObjRec newObj; + unsigned char type = (currObj->attributedType & ~DPS_EXEC); + + newObj = *currObj; + +#if !IEEEFLOAT + if (type == DPS_REAL) { + if (numFormat != cc->numFormat) { + if (numFormat == dps_ieee) { + if (DPSDefaultByteOrder == dps_loFirst) + IEEELowToNative(&currObj->val.realVal, &newObj.val.realVal); + else + IEEEHighToNative(&currObj->val.realVal, &newObj.val.realVal); + } + else { /* numFormat is native */ + if (DPSDefaultByteOrder == dps_loFirst) + NativeToIEEELow(&currObj->val.realVal, &newObj.val.realVal); + else + NativeToIEEEHigh(&currObj->val.realVal, &newObj.val.realVal); + } + } + } +#endif /* !IEEEFLOAT */ + + if (type == DPS_STRING && newObj.length > 0) { + /* keep track of where strings start */ + firstCharOffset = ((unsigned) newObj.val.stringVal < firstCharOffset) + ? newObj.val.stringVal : firstCharOffset; + } + if (type == DPS_NAME) { + if (newObj.length == DPSSYSNAME) { /* system name index, never expand to string body */ + if (pass != 1) goto next_obj; + } + else if (newObj.length == 0) { /* user name index */ + register char *p = DPSNameFromIndex(newObj.val.nameVal); + switch (pass) { + case 0: len += strlen(p); goto next_obj; + case 1: + if (ctxt->nameEncoding == dps_strings) { + newObj.length = strlen(p); + newObj.val.nameVal = nameOffset; + nameOffset += newObj.length; + } + break; + case 2: DPSWriteData(ctxt, p, strlen(p)); goto next_obj; + default:; + } + } + else { /* name is already a string */ + /* keep track of where strings start */ + firstCharOffset = ((unsigned) newObj.val.nameVal < firstCharOffset) + ? newObj.val.nameVal : firstCharOffset; + } + } /* end if type == DPS_NAME */ + if (pass == 1) { + DPSWriteData(ctxt, (char *) &newObj, sizeof(newObj)); + } + +next_obj: + offset += sizeof(newObj); + ++currObj; + } /* end while */ + + /* finish pass */ + switch (pass) { + case 0: { + unsigned char t; + /* write modified seqHead */ + if (DPSDefaultByteOrder == dps_hiFirst && cc->numFormat == dps_ieee) + t = DPS_HI_IEEE; + else if (DPSDefaultByteOrder == dps_loFirst && cc->numFormat == dps_ieee) + t = DPS_LO_IEEE; + else if (DPSDefaultByteOrder == dps_hiFirst && cc->numFormat == dps_native) + t = DPS_HI_NATIVE; + else + t = DPS_LO_NATIVE; + DPSWriteData(ctxt, (char *) &t, 1); + if (headSize == DPS_HEADER_SIZE) { + unsigned short int nBytes; + unsigned char c = bos->nTopElements; + /* write top level count */ + DPSWriteData(ctxt, (char *) &c, 1); + /* write nBytes */ + nBytes = (ctxt->nameEncoding == dps_strings) ? bos->length + len : + bos->length; + DPSWriteData(ctxt, (char *)&nBytes, 2); + } + else { + unsigned int nBytes; + /* write escape code & top level count */ + DPSWriteData(ctxt, (char *)&bos->escape, 3); + /* write nBytes */ + nBytes = (ctxt->nameEncoding == dps_strings) ? bos->length + len : + bos->length; + DPSWriteData(ctxt, (char *)&nBytes, 4); + } + break; + } + case 1: { + char *stringStart = seqBase + firstCharOffset; + DPSWriteData(ctxt, stringStart, (bos->length - headSize - firstCharOffset)); + break; + } + default:; + } + +} /* ConvertAndWriteSeqAsData */ + +#define MIN16 -32768 +#define MAX16 32767 + +/* TestHomogeneous will return a non-negative representation code 'r' + if all of the array elements are "integers", or all are "reals". + Will return -1 for any other case. */ + +static integer TestHomogeneous( + DPSBinObj aryObj, + unsigned short length, + DPSNumFormat numFormat) +{ + integer tmp, r = -1; + + while (length--) { + switch (aryObj->attributedType & ~DPS_EXEC) { + case DPS_INT: +#if SWAPBITS + tmp = (aryObj->val.integerVal < MIN16 + || aryObj->val.integerVal > MAX16) ? 128 : 128+32; +#else /* SWAPBITS */ + tmp = (aryObj->val.integerVal < MIN16 + || aryObj->val.integerVal > MAX16) ? 0 : 32; +#endif /* SWAPBITS */ + if ((r == -1) || ((r & 0x07F) == 32 && (tmp & 0x07F) == 0)) + r = tmp; /* first element, or was 16-bit => bump to 32-bit */ + else if ((r & 0x07F) == 0 && (tmp & 0x07F) == 32) + goto bump_obj; /* is 32-bit => stay 32-bit */ + else if (r != tmp) + return(-1); + /* else fall thru, r == tmp */ + break; + case DPS_REAL: +#if SWAPBITS + tmp = (numFormat == dps_ieee) ? 128+48 : 128+49; +#else /* SWAPBITS */ + tmp = (numFormat == dps_ieee) ? 48 : 49; +#endif /* SWAPBITS */ + if (r == -1) + r = tmp; + else if (r != tmp) return(-1); + break; + default: return(-1); + } +bump_obj: + ++aryObj; + } + return(r); +} /* TestHomogeneous */ + +static void WriteSeqAsTokens( + DPSContext ctxt, + char *base, + DPSBinObj currObj, + unsigned int nObjs, + unsigned char tokenType, + int *numstringOffsets) +{ + int nLineObjs = 0; + DPSNumFormat numFormat; + unsigned short length; + Swap32Rec n32; + Swap16Rec n16; + unsigned char c; + +#define PB(byte) c = (byte),DPSWriteData(ctxt, (char *) &c, 1) +#if SWAPBITS +#define WTT(byte) PB((byte)+1) +#else /* SWAPBITS */ +#define WTT(byte) PB(byte) +#endif /* SWAPBITS */ + + NumFormatFromTokenType(tokenType, &numFormat); + + while (nObjs--) { + unsigned char type = currObj->attributedType & ~DPS_EXEC; + boolean lit = ((currObj->attributedType & DPS_EXEC) == 0); + + switch (type) { + case DPS_NULL: + break; + case DPS_BOOL: + PB(141); /* boolean */ + if (currObj->val.booleanVal) + PB(true); + else + PB(false); + break; + case DPS_INT: + n32.i = currObj->val.integerVal; + if (n32.i < MIN16 || n32.i > MAX16) { + WTT(132); /* 32-bit int */ + DPSWriteData(ctxt, (char *) n32.bytes, 4); + } + else if (n32.i < -128 || n32.i > 127) { + WTT(134); /* 16-bit int */ + n16.i = n32.i; + DPSWriteData(ctxt, (char *) n16.bytes, 2); + } + else { + WTT(136); /* 8-bit int */ + PB(n32.i); + } + break; + case DPS_REAL: +#if IEEEFLOAT + WTT(138); /* 32-bit IEEE float */ +#else /* IEEEFLOAT */ + if (numFormat != DPSDefaultNumFormat) + /* then it must be IEEE */ + WTT(138); /* 32-bit IEEE float */ + else + PB(140); /* 32-bit native float */ +#endif /* IEEEFLOAT */ + + DPSWriteData(ctxt, (char *) &currObj->val.realVal, 4); + break; + case DPS_NAME: { + char *p = 0; + integer index = currObj->val.nameVal; + + length = currObj->length; + if (length == DPSSYSNAME) {/* system name index */ + if (index >= 0 && index < 256) { + if (lit) + PB(145); /* literal system name */ + else + PB(146); /* exec. system name */ + PB(index); + goto next_obj; + } + else if (DPS_FIRST_AUX_SYSNAME <= index + && index <= DPS_LAST_AUX_SYSNAME) + p = DPSSysNamesAux[index - DPS_FIRST_AUX_SYSNAME]; + else DPSCantHappen(); + length = strlen(p); + } + else if (length == 0) { /* user name index */ + if (ctxt->nameEncoding == dps_indexed && index < 256) { + if (lit) + PB(147); /* literal user name index */ + else + PB(148); /* executable user name index */ + PB(index); + goto next_obj; + } + else { + p = DPSNameFromIndex(index); + length = strlen(p); + } + } + else + p = base + index; + if (lit) DPSPrintf(ctxt, "/"); + DPSWriteData(ctxt, p, length); + DPSPrintf(ctxt, " "); + break; + } + case DPS_ARRAY: { + DPSBinObj aryObj = (DPSBinObj)(base+currObj->val.arrayVal); + integer r; + length = currObj->length; + if (lit && (r = TestHomogeneous(aryObj, length, numFormat)) != -1) { + PB(149); /* homogeneous number array */ + PB(r); + DPSWriteData(ctxt, (char *) &length, 2); + if (r > 127) r -= 128; + while (length--) { + switch (r) { + case 0: + DPSWriteData(ctxt, (char *) &aryObj->val.integerVal, 4); + break; + case 32: + n16.i = aryObj->val.integerVal; + DPSWriteData(ctxt, (char *) n16.bytes, 2); + break; + case 48: + case 49: + DPSWriteData(ctxt, (char *) &aryObj->val.realVal, 4); + break; + default: DPSCantHappen(); + } + ++aryObj; + } + } + else { + DPSPrintf(ctxt, (lit ? "[ " : "{ ")); + WriteSeqAsTokens(ctxt, base, aryObj, length, tokenType, + numstringOffsets); + DPSPrintf(ctxt, (lit ? " ] " : " } ")); + } + break; } + case DPS_MARK: + if (lit) + DPSPrintf(ctxt, "/mark "); + else + DPSPrintf(ctxt, "mark "); + break; + case DPS_STRING: { + char *p = base + currObj->val.stringVal; + int i; + if (numstringOffsets != NULL) { + for (i = 2; i < numstringOffsets[1] && + numstringOffsets[i] != currObj->val.stringVal; i++) ; + if (numstringOffsets[i] == currObj->val.stringVal) { + DPSAssert(*(unsigned char *) p == 149); + DPSWriteData(ctxt, p, length); + break; + } + } + length = currObj->length; + if (length < 256) { + PB(142); /* short string */ + PB(length); + } + else { + WTT(143); /* long string */ + DPSWriteData(ctxt, (char *) &length, 2); + } + DPSWriteData(ctxt, p, length); + break; + } + default: DPSCantHappen(); + } +next_obj: + ++currObj; + if (++nLineObjs == 15) { + nLineObjs = 0; + DPSPrintf(ctxt, "\n "); + } + } /* end while */ + + DPSPrintf(ctxt, "\n"); +} /* WriteSeqAsTokens */ + +static void WriteTokenAsAscii( + DPSContext ctxt, + register unsigned char *buf) +{ + Swap32Rec n32; + Swap16Rec n16; + register unsigned char *b; + + switch (*buf++) { + case 132: /* 32-bit int, hi */ + b = n32.bytes; + Copy4SrcHi(buf, b); + DPSPrintf(ctxt, "%d ", n32.i); + break; + case 133: /* 32-bit int, lo */ + b = n32.bytes; + Copy4SrcLo(buf, b); + DPSPrintf(ctxt, "%d ", n32.i); + break; + case 134: /* 16-bit int, hi */ + b = n16.bytes; + Copy2SrcHi(buf, b); + DPSPrintf(ctxt, "%d ", n16.i); + break; + case 135: /* 16-bit int, lo */ + b = n16.bytes; + Copy2SrcLo(buf, b); + DPSPrintf(ctxt, "%d ", n16.i); + break; + case 136: /* 8-bit int, signed */ + n32.i = (char) *buf; + DPSPrintf(ctxt, "%d ", n32.i); + break; + case 137: { /* 16 or 32-bit fixed */ + unsigned char r = *buf++; + float f = 0.0; + boolean hi = (r < 128); + + if (!hi) r -= 128; + if (r < 32) { /* 32-bit */ + b = n32.bytes; + if (hi) {Copy4SrcHi(buf, b);} else {Copy4SrcLo(buf, b);} + if (r == 0) { + DPSPrintf(ctxt, "%d ", n32.i); + break; + } + else { + f = n32.i; /* convert to float */ + goto do_scale; + } + } + else if (r < 48) { /* 16-bit */ + b = n16.bytes; + if (hi) {Copy2SrcHi(buf, b);} else {Copy2SrcLo(buf, b);}; + if (r == 0) { + DPSPrintf(ctxt, "%d ", n16.i); + break; + } + else { + r -= 32; + f = n16.i; /* convert to float */ + goto do_scale; + } + } + else DPSCantHappen(); +do_scale: + n32.f = f / (1 << r); /* scale */ + DPSPrintf(ctxt, "%g ", n32.f); + break; + } + case 138: /* 32-bit IEEE float, hi */ +#if IEEEFLOAT + b = n32.bytes; + Copy4SrcHi(buf, b); +#else /* IEEEFLOAT */ + IEEEHighToNative(buf, &n32.f); +#endif /* IEEEFLOAT */ + DPSPrintf(ctxt, "%g ", n32.f); + break; + case 139: /* 32-bit IEEE float, lo */ +#if IEEEFLOAT + b = n32.bytes; + Copy4SrcLo(buf, b); +#else /* IEEEFLOAT */ + IEEELowToNative(buf, &n32.f); +#endif /* IEEEFLOAT */ + DPSPrintf(ctxt, "%g ", n32.f); + break; + case 140: /* 32-bit native float */ + b = n32.bytes; + *b++ = *buf++,*b++ = *buf++,*b++ = *buf++,*b = *buf; + DPSPrintf(ctxt, "%g ", n32.f); + break; + case 141: /* boolean */ + if (*buf) + DPSPrintf(ctxt, "true "); + else + DPSPrintf(ctxt, "false "); + break; + case 142: /* short string */ + DPSPrintf(ctxt, "("); + n16.u = *buf++; + goto share_str_code; + case 143: /* long string, hi */ + b = n16.bytes; + Copy2SrcHi(buf, b); + DPSPrintf(ctxt, "("); + buf += 2; + goto share_str_code; + case 144: /* long string, lo */ + b = n16.bytes; + Copy2SrcLo(buf, b); + DPSPrintf(ctxt, "("); + buf += 2; +share_str_code: +#ifdef VMS + WriteVMSStringBody(ctxt, buf, n16.u); /* write this */ +#else /* VMS */ + /* render string bytes correctly */ + while (n16.u--) { + unsigned char c = *buf++; + if (c == '(' || c == ')' || c == '\\') + DPSPrintf(ctxt, "\\%c", c); + else if (c == '\n') + DPSPrintf(ctxt, "\\n"); + else if (!(isascii(c) && isprint(c))) + DPSPrintf(ctxt, "\\%03.3o", c); + else DPSWriteData(ctxt, (char *) &c, 1); + } +#endif /* VMS */ + DPSPrintf(ctxt, ") "); + break; + case 145: /* literal system name index */ + DPSPrintf(ctxt, "/%s ", DPSSysNames[*buf]); + break; + case 146: /* executable system name index */ + DPSPrintf(ctxt, "%s ", DPSSysNames[*buf]); + break; + case 147: /* literal user name index */ + DPSPrintf(ctxt, "/%s ", DPSNameFromIndex(*buf)); + break; + case 148: /* executable user name index */ + DPSPrintf(ctxt, "%s ", DPSNameFromIndex(*buf)); + break; + case 149: { /* homogeneous number array */ + WriteHomogeneousArrayAsASCII(ctxt, buf); + break; + } + default:; /* unassigned */ + } +} /* WriteTokenAsAscii */ + + +/* WriteEntireGoody converts an entire binary token or binary object + sequence as specified by ctxt's encoding parameters. Write the + converted bytes via DPSWriteData. buf points to the complete goody. */ + +static void WriteEntireGoody( + DPSContext ctxt, + unsigned char *buf, + int *numstringOffsets) +{ + + DPSExtendedBinObjSeq bos = (DPSExtendedBinObjSeq) buf; + DPSExtendedBinObjSeqRec bosRec; + DPSBinObj currObj; + DPSPrivContext cc = (DPSPrivContext) ctxt; + + if (IsBinaryToken(*buf)) { + /* only supported conversion is binary token to ASCII */ + WriteTokenAsAscii(ctxt, buf); + if (numstringOffsets) numstringOffsets[1] = 2; + return; + } + + if (bos->escape != 0) { + /* not extended BOS */ + DPSBinObjSeq seqHead = (DPSBinObjSeq) buf; + bos = &bosRec; + bos->tokenType = seqHead->tokenType; + bos->escape = seqHead->nTopElements; + bos->nTopElements = seqHead->nTopElements; + bos->length = seqHead->length; + currObj = &(seqHead->objects[0]); + } + else currObj = &(bos->objects[0]); + + switch (ctxt->programEncoding) { + case dps_binObjSeq: + if (ctxt->nameEncoding == dps_strings) { + /* takes three passes to do conversions */ + ConvertAndWriteSeqAsData(ctxt, (char *) buf, 0); + ConvertAndWriteSeqAsData(ctxt, (char *) buf, 1); + ConvertAndWriteSeqAsData(ctxt, (char *) buf, 2); + } + else if (bos->tokenType != DPS_DEF_TOKENTYPE + || cc->numFormat != DPSDefaultNumFormat) { + /* first pass just writes modified seqHead */ + ConvertAndWriteSeqAsData(ctxt, (char *) buf, 0); + /* second pass converts numbers and writes the sequence */ + ConvertAndWriteSeqAsData(ctxt, (char *) buf, 1); + } + else DPSWriteData(ctxt, (char *) buf, bos->length); + break; + case dps_ascii: + case dps_encodedTokens: { + + if (ctxt->programEncoding == dps_ascii) + { + WriteSeqAsAscii( + ctxt, (char *)currObj, currObj, bos->nTopElements, + bos->tokenType, numstringOffsets); + } + else + WriteSeqAsTokens( + ctxt, (char *)currObj, currObj, bos->nTopElements, + bos->tokenType, numstringOffsets); + DPSWriteData(ctxt, "\n", 1); + break; + } + default:; + } + if (numstringOffsets) numstringOffsets[1] = 2; +} /* WriteEntireGoody */ + + +/**************************************/ +/* Context procs for DPSCreateTextContext */ +/**************************************/ + +static void textWriteData(DPSContext ctxt, char *buf, unsigned int nch) +{ + (*ctxt->textProc)(ctxt, buf, nch); + if (ctxt->chainChild != NIL) DPSWriteData(ctxt->chainChild, buf, nch); +} + +static void textFlushContext(DPSContext ctxt) +{ + if (ctxt->chainChild != NIL) DPSFlushContext(ctxt->chainChild); +} + +static void textInterruptContext(DPSContext ctxt) +{ + if (ctxt->chainChild != NIL) DPSInterruptContext(ctxt->chainChild); +} + +static void textDestroyContext(DPSContext ctxt) +{ + DPSPrivContext c = (DPSPrivContext)ctxt; + + DPSUnchainContext(ctxt); + + free(c); +} + +static void textInnerWritePostScript( + DPSContext ctxt, char *buf, unsigned int nch) +{ + DPSPrivContext cc = (DPSPrivContext)ctxt; + while (nch > 0) { + char *oldBuf = NIL; + integer oldNch = 0; + unsigned n; + if (cc->outBuf) { /* we're buffering */ + unsigned m; + integer bst; + if (!IsBinaryToken(cc->outBuf[0]) && cc->nOutBufChars < DPS_SEQ_MIN) { + char *tb = cc->outBuf + cc->nOutBufChars; + integer nn = DPS_SEQ_MIN - cc->nOutBufChars; + DPSAssert(nn == 1); + cc->nOutBufChars += nn; + nch -= nn; + *tb++ = *buf++; + } + bst = GetHdrNBytes((unsigned char *) cc->outBuf); + /* # bytes needed to determine size */ + if (cc->nOutBufChars < bst) { + char *b = cc->outBuf; + if (nch + cc->nOutBufChars < (unsigned) bst) { + os_bcopy(buf, cc->outBuf + cc->nOutBufChars, nch); + cc->nOutBufChars += nch; + return; + } + os_bcopy(buf, b + cc->nOutBufChars, bst - cc->nOutBufChars); + buf += bst - cc->nOutBufChars; + nch -= bst - cc->nOutBufChars; + cc->nOutBufChars = bst; + m = GetNBytes((unsigned char *) cc->outBuf); + cc->outBuf = (char *)DPScalloc(m, 1); + os_bcopy(b, cc->outBuf, bst); + free(b); + } + else m = GetNBytes((unsigned char *) cc->outBuf); + + /* here with size of entire goody in m and outBuf set up */ + if (nch + cc->nOutBufChars < m) { + os_bcopy(buf, cc->outBuf + cc->nOutBufChars, nch); + cc->nOutBufChars += nch; + return; + } + os_bcopy(buf, cc->outBuf + cc->nOutBufChars, m - cc->nOutBufChars); + buf += m - cc->nOutBufChars; + nch -= m - cc->nOutBufChars; + cc->nOutBufChars = m; + oldBuf = buf; + oldNch = nch; + buf = cc->outBuf; + nch = cc->nOutBufChars; + cc->outBuf = NIL; + cc->nOutBufChars = 0; + } /* if (cc->outBuf) */ + + /* dispose of any plain text. If no binary conversion, all output + is plain text */ + if (cc->contextFlags & DPS_FLAG_NO_BINARY_CONVERSION) n = nch; + else { + for (n = 0; n < nch && + ((unsigned char) buf[n] < 128 || (unsigned char) buf[n] > 159); n++); + } + if (n > 0) { + /* Assumes below that any error proc called uses dpsexcept.h + if it rips control away */ + DURING + DPSWriteData((DPSContext)cc, buf, n); + HANDLER + if (oldBuf) free(buf); + RERAISE; + END_HANDLER + } + buf += n; + nch -= n; + + if (nch != 0) { + /* here with the next binary object sequence or encoded token */ + unsigned m = 0; + integer bst; + if (!IsBinaryToken(buf[0]) && nch < DPS_SEQ_MIN) { + /* gotta buffer it */ + DPSAssertWarn(nch == 1 && !oldBuf, cc, "problem converting binary token/sequence (nch!=1||oldBuf)"); + cc->outBuf = (char *)DPScalloc(DPS_EXT_HEADER_SIZE, 1); + cc->nOutBufChars = nch; + cc->outBuf[0] = *buf; + return; + } + bst = GetHdrNBytes((unsigned char *) buf); + if (nch < (unsigned)bst || nch < (m = GetNBytes((unsigned char *) buf))) { + /* gotta buffer it */ + DPSAssertWarn(!oldBuf, cc, "problem converting binary token/sequence (oldBuf)"); + if (nch < (unsigned) bst) { + cc->outBuf = (char *)DPScalloc(bst, 1); + } + else { + cc->outBuf = (char *)DPScalloc(m, 1); + } + cc->nOutBufChars = nch; + os_bcopy(buf, cc->outBuf, nch); + return; + } + + /* Assumes below that any error proc called uses dpsexcept.h + if it rips control away */ + DURING + WriteEntireGoody(ctxt, (unsigned char *) buf, cc->numstringOffsets); + HANDLER + if (oldBuf) { + DPSAssertWarn(nch == m, cc, "some converted PostScript language may be lost during error recovery (nch!=m)"); + free(buf); + } + RERAISE; + END_HANDLER + + if (oldBuf) { + DPSAssertWarn(nch == m, cc, "some converted PostScript language may be lost (nch!=m)"); + free(buf); + buf = oldBuf; + nch = oldNch; + oldBuf = NIL; + } + else { + buf += m; + nch -= m; + } + } /* if (nch != 0) */ + } /* while (nch > 0) */ +} /* textInnerWritePostScript */ + +static void textWritePostScript( + DPSContext ctxt, char *buf, unsigned int nch) +{ + DPSContext children = ctxt->chainChild; + /* disconnect temporarily so that high level procs can + be called safely */ + if (children != NIL) ctxt->chainChild = NIL; + DURING + textInnerWritePostScript(ctxt, buf, nch); + HANDLER + if (children != NIL) ctxt->chainChild = children; + RERAISE; + END_HANDLER + if (children != NIL) { + ctxt->chainChild = children; + DPSWritePostScript(ctxt->chainChild, buf, nch); + } +} + +static void textWriteStringChars( + DPSContext ctxt, char *buf, unsigned int nch) +{ + DPSContext children = ctxt->chainChild; + + if (DPSCheckShared((DPSPrivContext)ctxt)) return; + /* disconnect temporarily so that high level procs can + be called safely */ + if (children != NIL) ctxt->chainChild = NIL; + DURING + textInnerWritePostScript(ctxt, buf, nch); + HANDLER + if (children != NIL) ctxt->chainChild = children; + RERAISE; + END_HANDLER + if (children != NIL) { + ctxt->chainChild = children; + DPSWriteStringChars(ctxt->chainChild, buf, nch); + } +} + +static void textBinObjSeqWrite( + DPSContext ctxt, char *buf, unsigned int nch) +{ + DPSContext children = ctxt->chainChild; + DPSPrivContext c = (DPSPrivContext) ctxt; + + if (DPSCheckShared(c)) return; + if (c->lastNameIndex < globLastNameIndex) + DPSUpdateNameMap(ctxt); + /* disconnect temporarily so that high level procs can + be called safely */ + if (children != NIL) ctxt->chainChild = NIL; + DURING + textInnerWritePostScript(ctxt, buf, nch); + HANDLER + if (children != NIL) ctxt->chainChild = children; + RERAISE; + END_HANDLER + if (children != NIL) { + ctxt->chainChild = children; + DPSBinObjSeqWrite(ctxt->chainChild, buf, nch); + } +} + +static void textWriteNumstring( + DPSContext ctxt, + DPSDefinedType type, + char *data, + unsigned int size, + int scale) +{ + DPSPrivContext cc = (DPSPrivContext) ctxt; +#define BUFFER_GROW 10 + + if (cc->contextFlags & DPS_FLAG_CONVERT_NUMSTRINGS) { + if (cc->numstringOffsets == NULL) { + cc->numstringOffsets = (int *) DPScalloc(sizeof(int), + BUFFER_GROW + 2); + cc->numstringOffsets[0] = BUFFER_GROW + 2; /* Current size */ + cc->numstringOffsets[1] = 2; /* Next slot */ + } else if (cc->numstringOffsets[1] >= cc->numstringOffsets[0]) { + cc->numstringOffsets[0] += BUFFER_GROW; + cc->numstringOffsets = + (int *) realloc(cc->numstringOffsets, + sizeof(int)* cc->numstringOffsets[0]); + } + + /* Subtract 4 because of binary object sequence header */ + cc->numstringOffsets[cc->numstringOffsets[1]] = cc->nOutBufChars - 4; + cc->numstringOffsets[1] += 1; + } + + innerProcWriteNumstring(ctxt, type, data, size, scale, textInnerWritePostScript); +#undef BUFFER_GROW +} /* textWriteNumstring */ + +/*********************/ +/* Public procedures */ +/*********************/ + +/********************************************/ +/* Public procs for dealing with user names */ + +char *DPSNameFromIndex(long int index) +{ + if (DPSglobals == NIL || index < 0 || index > globLastNameIndex + || userNameDict == NIL) + return NIL; + return (char *) userNames[index]; +} + +void DPSMapNames( + DPSContext ctxt, + unsigned int nNames, + char **names, + int **indices) +{ + unsigned i; + char *last = names[0]; + + DPSCheckInitClientGlobals(); + +#define USERNAMEDICTLENGTH 100 + + if (userNameDict == NIL) { + userNameDict = DPSCreatePSWDict(USERNAMEDICTLENGTH); + userNames = (char **)DPScalloc(sizeof(char *), USERNAMEDICTLENGTH); + userNamesLength = USERNAMEDICTLENGTH; + } + + for (i = 0; i < nNames; i++) { + integer j; + char *n = names[i]; + DPSContext c; + + if (n == NIL) + n = last; + else + last = n; + DPSAssert(n != NIL); + if (strlen(n) > 128) { + DPSSafeSetLastNameIndex(ctxt); + (*ctxt->errorProc)(ctxt, dps_err_nameTooLong, (unsigned long) n, strlen(n)); + return; + } + j = DPSWDictLookup(userNameDict, n); + if (j >= 0) { + *(indices[i]) = j; + /* handle the case where another context in another space has + defined this name */ + if (((DPSPrivContext)ctxt)->lastNameIndex < j) + DPSUpdateNameMap(ctxt); + } + else { + /* handle other cases where another context in another + space has defined names */ + if (((DPSPrivContext)ctxt)->lastNameIndex < globLastNameIndex) + DPSUpdateNameMap(ctxt); + globLastNameIndex++; + if (((globLastNameIndex + 1) > userNamesLength)) { + char **t = (char **)DPScalloc(sizeof(char *), + userNamesLength + USERNAMEDICTLENGTH); + for (j = 0; j < userNamesLength; j++) { + t[j] = userNames[j]; + } + free(userNames); + userNames = t; + userNamesLength += USERNAMEDICTLENGTH; + } + userNames[globLastNameIndex] = n; + DPSWDictEnter(userNameDict, n, globLastNameIndex); + *(indices[i]) = globLastNameIndex; + DPSPrintf(ctxt, "%d /%s defineusername\n", globLastNameIndex, n); + for (c = ctxt; c != NIL; c = c->chainChild) + ((DPSPrivContext)c)->lastNameIndex = globLastNameIndex; + } + } /* for */ +} + +/**********************/ +/* Other public procs */ + +void DPSDefaultErrorProc( + DPSContext ctxt, + DPSErrorCode errorCode, + long unsigned int arg1, long unsigned int arg2) +{ + + DPSTextProc textProc = DPSGetCurrentTextBackstop(); + + char *prefix = "%%[ Error: "; + char *suffix = " ]%%\n"; + + char *infix = "; OffendingCommand: "; + char *nameinfix = "User name too long; Name: "; + char *contextinfix = "Invalid context: "; + char *taginfix = "Unexpected wrap result tag: "; + char *typeinfix = "Unexpected wrap result type; tag: "; + + switch (errorCode) { + case dps_err_ps: { + char *buf = (char *)arg1; + DPSBinObj ary = (DPSBinObj) (buf+DPS_HEADER_SIZE); + DPSBinObj elements; + char *error, *errorName; + integer errorCount, errorNameCount; + boolean resyncFlg; + + if ((ary->attributedType & 0x7f) != DPS_ARRAY + || ary->length != 4) { + DPSHandleBogusError(ctxt, prefix, suffix); + } + + elements = (DPSBinObj)(((char *) ary) + ary->val.arrayVal); + + errorName = (char *)(((char *) ary) + elements[1].val.nameVal); + errorNameCount = elements[1].length; + + error = (char *)(((char *) ary) + elements[2].val.nameVal); + errorCount = elements[2].length; + + resyncFlg = elements[3].val.booleanVal; + + if (textProc != NIL) { + (*textProc)(ctxt, prefix, strlen(prefix)); + (*textProc)(ctxt, errorName, errorNameCount); + (*textProc)(ctxt, infix, strlen(infix)); + (*textProc)(ctxt, error, errorCount); + (*textProc)(ctxt, suffix, strlen(suffix)); + } + if (resyncFlg && (ctxt != dummyCtx) && (ctxt != NULL)) { +#if 0 /* Postpone the raise 'til later to avoid RAISEing through Xlib */ + RAISE(dps_err_ps, (char *) ctxt); + DPSCantHappen(); +#else + DPSPrivContext cc = (DPSPrivContext) ctxt; + cc->resyncing = true; +#endif + } + break; + } + case dps_err_nameTooLong: + if (textProc != NIL) { + char *buf = (char *)arg1; + (*textProc)(ctxt, prefix, strlen(prefix)); + (*textProc)(ctxt, nameinfix, strlen(nameinfix)); + (*textProc)(ctxt, buf, arg2); + (*textProc)(ctxt, suffix, strlen(suffix)); + } + break; + case dps_err_invalidContext: + if (textProc != NIL) { + char m[100]; + (void) sprintf(m, "%s%s%ld%s", prefix, contextinfix, arg1, suffix); + (*textProc)(ctxt, m, strlen(m)); + } + break; + case dps_err_resultTagCheck: + if (textProc != NIL) { + char m[100]; + unsigned char tag = *((unsigned char *) arg1+1); + (void) sprintf(m, "%s%s%d%s", prefix, taginfix, tag, suffix); + (*textProc)(ctxt, m, strlen(m)); + } + break; + case dps_err_resultTypeCheck: + if (textProc != NIL) { + char m[100]; + unsigned char tag = *((unsigned char *) arg1+1); + (void) sprintf(m, "%s%s%d%s", prefix, typeinfix, tag, suffix); + (*textProc)(ctxt, m, strlen(m)); + } + break; + default: + DPSDefaultPrivateHandler(ctxt, errorCode, arg1, arg2, prefix, suffix); + break; + } +} /* DPSDefaultErrorProc */ + +void DPSCheckRaiseError(DPSContext c) +{ + DPSPrivContext cc = (DPSPrivContext) c; + if (cc != NULL && cc->resyncing) { + cc->resyncing = false; + RAISE(dps_err_ps, (char *) c); + DPSCantHappen(); + } +} + +/**************************************/ +/* Public procs for creating contexts */ + +/* dps_err_invalidAccess is now defined for all clients. */ + +static void textAwaitReturnValues(DPSContext ctxt) +{ + (*ctxt->errorProc)(ctxt, dps_err_invalidAccess, 0, 0); +} + +static void Noop(void) +{ +} + +DPSContext DPSCreateTextContext( + DPSTextProc textProc, DPSErrorProc errorProc) +{ + DPSPrivContext c; + + if (DPSInitialize () != 0) return((DPSContext) NIL); + if (!textCtxProcs) { + textCtxProcs = (DPSProcs)DPScalloc(sizeof(DPSProcsRec), 1); + DPSInitCommonTextContextProcs(textCtxProcs); + DPSInitSysNames(); + } + + c = (DPSPrivContext)DPScalloc(sizeof(DPSPrivContextRec), 1); + c->textProc = textProc; + c->procs = textCtxProcs; + c->textProc = textProc; + c->errorProc = errorProc; + c->programEncoding = dps_ascii; + c->nameEncoding = dps_strings; /* don't write user name indices on a file */ + c->contextFlags = DPS_FLAG_CONVERT_NUMSTRINGS; /* Convert by default */ + c->numFormat = DPSDefaultNumFormat; + c->numstringOffsets = NULL; + c->lastNameIndex = -1; + + /* Setup a dummy space */ + if (textSpace == NIL) + { + textSpace = (DPSPrivSpace) DPScalloc(sizeof (DPSPrivSpaceRec), 1); + textSpace->procs = (DPSSpaceProcs) DPScalloc(sizeof (DPSSpaceProcsRec), 1); + textSpace->procs->DestroySpace = (DPSSpaceProc) Noop; + textSpace->lastNameIndex = -1; + DPSInitPrivateSpaceFields(textSpace); + } + c->space = (DPSSpace) textSpace; + + DPSInitPrivateTextContextFields(c, textSpace); + return (DPSContext)c; +} /* DPSCreateTextContext */ + + +static DPSContext CreateDummyContext(void) +{ + DPSPrivContext c; + + DPSCheckInitClientGlobals(); + if (!dummyCtxProcs) { + dummyCtxProcs = (DPSProcs)DPScalloc(sizeof(DPSProcsRec), 1); + dummyCtxProcs->BinObjSeqWrite = (DPSContextBufProc) Noop; + dummyCtxProcs->WriteTypedObjectArray = (DPSContextTypedArrayProc) Noop; + dummyCtxProcs->WriteStringChars = (DPSContextBufProc) Noop; + dummyCtxProcs->WritePostScript = (DPSContextBufProc) Noop; + dummyCtxProcs->WriteData = (DPSContextBufProc) Noop; + dummyCtxProcs->FlushContext = (DPSContextProc) Noop; + dummyCtxProcs->ResetContext = (DPSContextProc) Noop; + dummyCtxProcs->WaitContext = (DPSContextProc) Noop; + dummyCtxProcs->UpdateNameMap = (DPSContextProc) Noop; + dummyCtxProcs->AwaitReturnValues = (DPSContextProc) Noop; + dummyCtxProcs->Interrupt = (DPSContextProc) Noop; + dummyCtxProcs->DestroyContext = (DPSContextProc) Noop; + dummyCtxProcs->WriteNumString = (DPSWriteNumStringProc) Noop; + } + + c = (DPSPrivContext)DPScalloc(sizeof(DPSPrivContextRec), 1); + c->procs = dummyCtxProcs; + c->programEncoding = DPSDefaultProgramEncoding; + c->nameEncoding = DPSDefaultNameEncoding; /* don't care */ + c->numFormat = DPSDefaultNumFormat; + c->lastNameIndex = -1; + c->numstringOffsets = NULL; + + return (DPSContext)c; +} /* CreateDummyContext */ + +void DPSSetTextBackstop(DPSTextProc textProc) +{ + DPSCheckInitClientGlobals(); + if (!dummyCtx) dummyCtx = CreateDummyContext(); + dummyCtx->textProc = textProc; +} + +DPSTextProc DPSGetCurrentTextBackstop(void) +{ + DPSCheckInitClientGlobals(); + if (dummyCtx == NIL) return NIL; + else return dummyCtx->textProc; +} + +void DPSSetErrorBackstop(DPSErrorProc errorProc) +{ + DPSCheckInitClientGlobals(); + if (!dummyCtx) dummyCtx = CreateDummyContext(); + dummyCtx->errorProc = errorProc; +} + +DPSErrorProc DPSGetCurrentErrorBackstop(void) +{ + DPSCheckInitClientGlobals(); + if (dummyCtx == NIL) return NIL; + else return dummyCtx->errorProc; +} + +static void NoteInitFailure(DPSContext ctxt, char *buf, long unsigned length) +{ + initFailed = -1; +} + +int DPSInitialize(void) +{ + DPSCheckInitClientGlobals(); + if (!clientStarted) { + clientStarted = true; + initFailed = 0; + DPSInitClient(NoteInitFailure, ReleaseInput); /* may call DPSCreateContext */ + /* textProc will not be used unless DPS initialization fails */ + } + return initFailed; +} + +DPSContext DPSCreateContext( + char *wh, + DPSTextProc textProc, + DPSErrorProc errorProc, + DPSSpace space) +{ + + DPSPrivSpace ss; + DPSPrivContext c; + + if (DPSInitialize() != 0) return NIL; + + if (!ctxProcs) { + ctxProcs = (DPSProcs)DPScalloc(sizeof(DPSProcsRec), 1); + ctxProcs->BinObjSeqWrite = procBinObjSeqWrite; + ctxProcs->WriteTypedObjectArray = writeTypedObjectArray; + ctxProcs->WriteStringChars = procWriteStringChars; + ctxProcs->WritePostScript = procWritePostScript; + ctxProcs->WriteData = procWriteData; + ctxProcs->UpdateNameMap = procUpdateNameMap; + ctxProcs->Interrupt = procInterrupt; + ctxProcs->WriteNumString = (DPSWriteNumStringProc) procWriteNumstring; + } + if (!spaceProcs) { + spaceProcs = (DPSSpaceProcs)DPScalloc(sizeof(DPSSpaceProcsRec), 1); + DPSInitCommonSpaceProcs(spaceProcs); + } + + ss = (DPSPrivSpace)space; + + if (ss == NIL) { + ss = (DPSPrivSpace)DPScalloc(sizeof(DPSPrivSpaceRec), 1); + ss->procs = spaceProcs; + ss->lastNameIndex = -1; + ss->next = spaces; + DPSAssert(ss->next != ss); + spaces = ss; + DPSInitPrivateSpaceFields(ss); + } + + if (ss->wh == NIL) ss->wh = wh; /* KLUDGE to support DPSSendDestroySpace */ + + c = (DPSPrivContext)DPScalloc(sizeof(DPSPrivContextRec), 1); + c->procs = ctxProcs; + c->wh = wh; + c->textProc = textProc; + c->errorProc = errorProc; + c->programEncoding = DPSDefaultProgramEncoding; + c->nameEncoding = DPSDefaultNameEncoding; + c->lastNameIndex = -1; + c->space = (DPSSpace)ss; + c->numstringOffsets = NULL; + + c->next = ss->firstContext; + DPSAssert(c->next != c); + ss->firstContext = c; + + DPSInitPrivateContextFields(c, ss); + + c->numFormat = DPSCreatePrivContext( + (XDPSPrivContext)wh, + (DPSContext)c, + (ContextPSID *)&c->cid, + (SpaceXID *)&ss->sid, + (space == NIL), DPSclientPrintProc); + if (c->numFormat == (DPSNumFormat) -1) + { /* can't create the context */ + if (space == NIL) { + spaces = ss->next; + free(ss); + } + else ss->firstContext = c->next; + free(c); + return NIL; + } + else return (DPSContext)c; +} /* DPSCreateContext */ + +char *DPSSetWh( + DPSContext ctxt, + char *newWh) +{ + DPSPrivContext cc = (DPSPrivContext) ctxt; + char *tmp = cc->wh; + cc->wh = newWh; + return(tmp); +} + +/* + The chainParent field is non-NIL if this context automatically receives + a copy of the PostScript code sent to the referenced (parent) context. + + The chainChild field is non-NIL if this context automatically sends along + to the referenced (child) context a copy of any PostScript code received. +*/ +int DPSChainContext(DPSContext parent, DPSContext child) +{ + DPSContext cc = child->chainChild; + + if (child->chainParent != NIL) + return -1; /* report an error */ + + /* insert new child between parent and existing children */ + child->chainChild = parent->chainChild; + if (parent->chainChild != NIL) { + DPSAssertWarn(parent->chainChild->chainParent == parent, (DPSPrivContext)parent, "attempting to chain context on invalid chain"); + child->chainChild->chainParent = child; + } + child->chainParent = parent; + parent->chainChild = child; + /* if child has children, recursively chain them */ + if (cc != NIL) { + cc->chainParent = NIL; + (void) DPSChainContext(child, cc); + } + return 0; +} + +void DPSUnchainContext(DPSContext ctxt) +{ + DPSContext p = ctxt->chainParent; + DPSContext c = ctxt->chainChild; + + if (p != NIL) { /* remove ctxt from parent's chain */ + DPSAssertWarn(p->chainChild == ctxt, (DPSPrivContext)p, "attempting to unchain context from wrong chain (parent)"); + p->chainChild = c; + ctxt->chainParent = NIL; + } + if (c != NIL) { /* remove ctxt's child (if any) from ctxt's chain */ + DPSAssertWarn(c->chainParent == ctxt, (DPSPrivContext)c, "attempting to unchain context from wrong chain (child)"); + c->chainParent = p; + ctxt->chainChild = NIL; + } +} + +/****************/ +/* Veneer procs */ + +void DPSAwaitReturnValues(DPSContext ctxt) +{ + (*(ctxt)->procs->AwaitReturnValues)((ctxt)); +} + +void DPSDestroyContext(DPSContext ctxt) +{ + (*(ctxt)->procs->DestroyContext)((ctxt)); +} + +void DPSDestroySpace(DPSSpace spc) +{ + (*(spc)->procs->DestroySpace)((spc)); +} + +void DPSFlushContext(DPSContext ctxt) +{ + (*(ctxt)->procs->FlushContext)((ctxt)); +} + +DPSContext DPSGetCurrentContext(void) { return DPSGlobalContext; } + +void DPSInterruptContext(DPSContext ctxt) +{ + (*(ctxt)->procs->Interrupt)((ctxt)); +} + +DPSContext DPSPrivCurrentContext(void) { return DPSGlobalContext; } + +void DPSResetContext(DPSContext ctxt) +{ + (*(ctxt)->procs->ResetContext)((ctxt)); +} + +void DPSSetResultTable( + register DPSContext ctxt, + DPSResults tbl, + unsigned int len) +{ + (ctxt)->resultTable = (tbl); + (ctxt)->resultTableLength = (len); +} + +void DPSSetContext( + DPSContext ctxt) +{ + DPSGlobalContext = ctxt; +} + +void DPSUpdateNameMap( + DPSContext ctxt) +{ + (*(ctxt)->procs->UpdateNameMap)((ctxt)); +} + +void DPSWaitContext( + DPSContext ctxt) +{ + (*(ctxt)->procs->WaitContext)(ctxt); +} + +void DPSBinObjSeqWrite( + DPSContext ctxt, + char *buf, + unsigned int count) +{ + (*(ctxt)->procs->BinObjSeqWrite)((ctxt), (buf), (count)); +} + +void DPSWriteData( + DPSContext ctxt, + char *buf, + unsigned int count) +{ + (*(ctxt)->procs->WriteData)((ctxt), (buf), (count)); +} + +void DPSWritePostScript( + DPSContext ctxt, + char *buf, + unsigned int count) +{ + (*(ctxt)->procs->WritePostScript)((ctxt), (buf), (count)); +} + +void DPSWriteStringChars( + DPSContext ctxt, + char *buf, + unsigned int count) +{ + (*(ctxt)->procs->WriteStringChars)((ctxt), (buf), (count)); +} + +void DPSWriteNumString(ctxt, type, data, size, scale) + DPSContext ctxt; + DPSDefinedType type; + char *data; + unsigned int size; + int scale; +{ + (*(ctxt)->procs->WriteNumString)((ctxt), (type), (data), (size), (scale)); +} + +void DPSWriteTypedObjectArray(ctxt, type, array, length) + DPSContext ctxt; + DPSDefinedType type; + char *array; + unsigned int length; { + (*(ctxt)->procs->WriteTypedObjectArray)((ctxt), (type), (array), (length)); + } + +void DPSInitCommonTextContextProcs(DPSProcs p) +{ + p->BinObjSeqWrite = textBinObjSeqWrite; + p->WriteTypedObjectArray = writeTypedObjectArray; + p->WriteStringChars = textWriteStringChars; + p->WritePostScript = textWritePostScript; + p->WriteData = textWriteData; + p->FlushContext = textFlushContext; + p->ResetContext = (DPSContextProc) Noop; + p->WaitContext = (DPSContextProc) Noop; + p->UpdateNameMap = procUpdateNameMap; + p->AwaitReturnValues = textAwaitReturnValues; + p->Interrupt = textInterruptContext; + p->DestroyContext = textDestroyContext; + p->WriteNumString = (DPSWriteNumStringProc) textWriteNumstring; +} + +void DPSInitCommonContextProcs(DPSProcs p) +{ + p->BinObjSeqWrite = procBinObjSeqWrite; + p->WriteTypedObjectArray = writeTypedObjectArray; + p->WriteStringChars = procWriteStringChars; + p->WritePostScript = procWritePostScript; + p->WaitContext = procWaitContext; + p->DestroyContext = procDestroyContext; + p->WriteData = procWriteData; + p->UpdateNameMap = procUpdateNameMap; + p->Interrupt = procInterrupt; + p->WriteNumString = (DPSWriteNumStringProc) procWriteNumstring; +} + +void DPSInitCommonSpaceProcs(DPSSpaceProcs p) +{ + p->DestroySpace = procDestroySpace; +} + +void DPSSetNumStringConversion(ctxt, flag) + DPSContext ctxt; + int flag; +{ + if (flag) ctxt->contextFlags |= DPS_FLAG_CONVERT_NUMSTRINGS; + else ctxt->contextFlags &= ~DPS_FLAG_CONVERT_NUMSTRINGS; +} + +void DPSSetWrapSynchronization(ctxt, flag) + DPSContext ctxt; + int flag; +{ + if (flag) ctxt->contextFlags |= DPS_FLAG_SYNC; + else ctxt->contextFlags &= ~DPS_FLAG_SYNC; +} + +void DPSSuppressBinaryConversion(ctxt, flag) + DPSContext ctxt; + int flag; +{ + if (flag) ctxt->contextFlags |= DPS_FLAG_NO_BINARY_CONVERSION; + else ctxt->contextFlags &= ~DPS_FLAG_NO_BINARY_CONVERSION; +} + +void DPSSetAbbrevMode(ctxt, flag) + DPSContext ctxt; + int flag; +{ + if (flag) ctxt->contextFlags |= DPS_FLAG_USE_ABBREVS; + else ctxt->contextFlags &= ~DPS_FLAG_USE_ABBREVS; +} + +DPSContextExtensionRec *DPSGetContextExtensionRec(ctxt, extensionId) + DPSContext ctxt; + int extensionId; +{ + DPSContextExtensionRec *r = ctxt->extension; + + while (r != NULL && r->extensionId != extensionId) r = r->next; + return r; +} + +void DPSAddContextExtensionRec(ctxt, rec) + DPSContext ctxt; + DPSContextExtensionRec *rec; +{ + rec->next = ctxt->extension; + ctxt->extension = rec; +} + +DPSContextExtensionRec *DPSRemoveContextExtensionRec(ctxt, extensionId) + DPSContext ctxt; + int extensionId; +{ + DPSContextExtensionRec *rret, **r = &ctxt->extension; + + + while (*r != NULL && (*r)->extensionId != extensionId) { + r = &(*r)->next; + } + rret = *r; + if (*r != NULL) *r = (*r)->next; + return rret; +} + +int DPSGenerateExtensionRecID(void) +{ + static int id = 1; + + return id++; +} + +DPSContextType DPSGetContextType(ctxt) + DPSContext ctxt; +{ + DPSPrivContext c = (DPSPrivContext) ctxt; + + if (c->procs == textCtxProcs) return dps_context_text; + else return dps_context_execution; +} |