/* qbuf2pe.c - build PE(s) from an SSDU assumed to be in qbuf(s) */ #ifndef lint static char *rcsid = "$Header: /f/osi/psap/RCS/qbuf2pe_f.c,v 7.2 91/03/09 11:55:34 mrose Exp $"; #endif /* * $Header: /f/osi/psap/RCS/qbuf2pe_f.c,v 7.2 91/03/09 11:55:34 mrose Exp $ * * * $Log: qbuf2pe_f.c,v $ * Revision 7.2 91/03/09 11:55:34 mrose * update * * Revision 7.1 91/02/22 09:36:48 mrose * Interim 6.8 * * Revision 7.0 91/01/19 13:46:20 mrose * *** empty log message *** * * Revision 6.0 89/03/18 23:39:13 mrose * Release 5.0 * */ /* * NOTICE * * Acquisition, use, and distribution of this module and related * materials are subject to the restrictions of a license agreement. * Consult the Preface in the User's Manual for the full terms of * this agreement. * */ /* LINTLIBRARY */ #include "stdio.h" #include "psap.h" #include "tailor.h" /* */ /* * The following macro takes one byte from a qbuf, stuffs it in c, * and adjusts the qbuf. */ #define qbuf2char(c) { \ qp = Qb; \ if (qp->qb_len > 0 && qp != Hqb) { \ (c) = *qp->qb_data++; \ Byteno++; \ if(--qp->qb_len == 0) { \ if(!(Qb = qp->qb_forw)) \ abort(); \ } \ } \ else { \ SLOG (psap_log, LLOG_EXCEPTIONS, \ NULLCP, \ ("bad qbuf length=%d", \ ((qp == Hqb) ? 0: qp->qb_len))); \ *result = PS_ERR_EOF; \ if (pe) pe_free(pe); \ return(NULLPE); \ } \ } int Byteno; int Qbrefs; struct qbuf *Hqb; struct qbuf *Fqb; struct qbuf *Qb; static int pe_id_overshift = PE_ID_MASK << (PE_ID_BITS - PE_ID_SHIFT); /* */ PE qbuf2pe_f (result) int *result; { register PE pe; register struct qbuf *qp; byte c, d; register PElementClass class; register PElementForm form; register PElementID id; register PElementLen len; register int i; register PElementLen j; pe = NULLPE; /* * Just take the qbuf directly and build PEs. * First, decode the id. */ qbuf2char(c); class = (c & PE_CLASS_MASK) >> PE_CLASS_SHIFT; form = (c & PE_FORM_MASK) >> PE_FORM_SHIFT; j = (c & PE_CODE_MASK); if (j == PE_ID_XTND) for (j = 0;; j <<= PE_ID_SHIFT) { qbuf2char(d); j |= d & PE_ID_MASK; if (!(d & PE_ID_MORE)) break; if (j & pe_id_overshift) { #ifdef DEBUG DLOG (psap_log, LLOG_DEBUG, ("j is %x d is %x %x %x %x\n", j, d, *(Qb->qb_data-1), *(Qb->qb_data-2), *(Qb->qb_data-3))); #endif *result = PS_ERR_OVERID; return (NULLPE); } } id = j; DLOG (psap_log, LLOG_DEBUG, ("class=%d form=%d id=%d", class, form, id)); if ((pe = pe_alloc (class, form, id)) == NULLPE) { *result = PS_ERR_NMEM; return (NULLPE); } qbuf2char(c); if ((i = c) & PE_LEN_XTND) { if ((i &= PE_LEN_MASK) > sizeof (PElementLen)) { #ifdef DEBUG DLOG (psap_log, LLOG_DEBUG, ("c (%x) i (%x) %d is %x %x %x %x\n", c, i, sizeof(PElementLen), *(Qb->qb_data-1), *(Qb->qb_data-2), *(Qb->qb_data-3), *(Qb->qb_data-4))); qbprintf(); #endif *result = PS_ERR_OVERLEN; return (NULLPE); } if (i) { for (j = 0; i-- > 0;) { qbuf2char(c); j = (j << 8) | (c & 0xff); } len = j; } else len = PE_LEN_INDF; } else len = i; SLOG (psap_log, LLOG_DEBUG, NULLCP, ("len=%d", len)); pe -> pe_len = len; /* Now get the value. */ switch (pe -> pe_form) { case PE_FORM_PRIM: if (len == PE_LEN_INDF) { *result = PS_ERR_INDF; goto you_lose; } if (len > 0) { qp = Qb; if (qp->qb_len >= len) { pe->pe_prim = (PElementData) qp->qb_data; pe->pe_inline = 1; Qbrefs++; Byteno += len; if (qp->qb_len == len) { if(!(Qb = qp->qb_forw)) abort(); } else { qp->qb_len -= len; qp->qb_data += len; } } else { if ((pe->pe_prim = PEDalloc (len)) == NULLPED) { *result = PS_ERR_NMEM; goto you_lose; } if (qbuf2data(pe->pe_prim, len) != len) { SLOG (psap_log, LLOG_EXCEPTIONS, NULLCP, ("bad qbuf lenght=%d",len)); *result = PS_ERR_EOF; goto you_lose; } } } break; case PE_FORM_CONS: if ((len == PE_LEN_INDF || len > 0) && qb_read_cons (&pe -> pe_cons, len, result) == NOTOK) goto you_lose; break; } return pe; you_lose: ; if (psap_log -> ll_events & LLOG_PDUS) { LLOG (psap_log, LLOG_PDUS, ("PE read thus far")); pe2text (psap_log, pe, 1, *result); } pe_free (pe); return NULLPE; } /* */ static int qb_read_cons (pe, len, cresult) register PE *pe; register PElementLen len; register int *cresult; { register int cc; register PE p, q; int result; *pe = NULLPE; cc = Byteno + len; if ((p = qbuf2pe_f (&result)) == NULLPE) { no_cons: ; #ifdef DEBUG if (len == PE_LEN_INDF) LLOG (psap_log, LLOG_DEBUG, ("error building indefinite cons, %s", ps_error (result))); else LLOG (psap_log, LLOG_DEBUG, ("error building cons, stream at %d, wanted %d: %s", Byteno, cc, ps_error (result))); #endif *cresult = result; return NOTOK; } *pe = p; if (len == PE_LEN_INDF) { if (p->pe_class == PE_CLASS_UNIV && p->pe_id == PE_UNIV_EOC) { pe_free (p); *pe = NULLPE; return OK; } for(q = p; p = qbuf2pe_f(&result); q = q->pe_next = p) { if (p->pe_class == PE_CLASS_UNIV && p->pe_id == PE_UNIV_EOC) { pe_free (p); return OK; } } goto no_cons; } for (q = p;; q = q -> pe_next = p) { if (cc < Byteno) { #ifdef DEBUG DLOG (psap_log, LLOG_DEBUG, ("cc %d Byteno %d last length was %d\n", cc, Byteno)); qbprintf(); #endif *cresult = PS_ERR_LEN; return (NOTOK); } if (cc == Byteno) { return OK; } if ((p = qbuf2pe_f (&result)) == NULLPE) goto no_cons; } } /* */ static qbuf2data(data, len) PElementData data; PElementLen len; { register struct qbuf *qp; register int i, cc; for (qp = Qb, cc = 0; len > 0; data += i, cc += i, len -= i) { if (qp == Hqb) goto leave; i = min (qp -> qb_len, len); bcopy (qp -> qb_data, (char *) data, i); qp -> qb_len -= i; if (qp -> qb_len <= 0) { if(!(Qb = (qp = qp->qb_forw))) abort(); } else qp->qb_data += i; } leave: Byteno += cc; return cc; } /* */ #ifdef DEBUG qbprintf() { int len; struct qbuf *qb; char *cp; for(qb = Fqb, cp = qb->qb_data;qb != Hqb;qb = qb->qb_forw) { for(len = 0;len < qb->qb_len;cp++, len++) { ll_printf (psap_log, "%x ", *cp); if((len % 15) == 0) ll_printf(psap_log, "\n"); } } ll_sync (psap_log); } #endif