/* * 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: xc/lib/dps/dpsclient.c,v 1.3 2000/09/26 15:56:59 tsi Exp $ */ #include #include #include #include #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||nchobjBuf = (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&&nchobjBuf = (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; }