summaryrefslogtreecommitdiffstats
path: root/src/isode/pepsy/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/isode/pepsy/util.c')
-rw-r--r--src/isode/pepsy/util.c780
1 files changed, 780 insertions, 0 deletions
diff --git a/src/isode/pepsy/util.c b/src/isode/pepsy/util.c
new file mode 100644
index 000000000..5682985af
--- /dev/null
+++ b/src/isode/pepsy/util.c
@@ -0,0 +1,780 @@
+/* util.c */
+
+#ifndef lint
+static char *rcsid = "$Header$";
+#endif
+
+/*
+ * $Header$
+ *
+ *
+ * $Log$
+ * Revision 1.1 1994/06/10 03:31:50 eichin
+ * autoconfed isode for kerberos work
+ *
+ * Revision 1.1 1994/05/31 20:40:44 eichin
+ * reduced-isode release from /mit/isode/isode-subset/src
+ *
+ * Revision 8.0 91/07/17 12:43:19 isode
+ * Release 7.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 "pepsy-driver.h"
+#include "psap.h"
+#include "pepsy.h"
+#include <varargs.h>
+#include "tailor.h"
+
+#ifndef PEPYPARM
+#define PEPYPARM char *
+#endif
+
+static char *pr_petype ();
+
+extern void exit();
+
+#ifdef lint
+/* VARARGS4 */
+
+int pepsylose (module, p, pe, str)
+modtyp *module;
+tpe *p;
+char *str;
+PE pe;
+{
+ return pepsylose (module, p, pe, str);
+}
+
+#else
+int pepsylose (va_alist)
+va_dcl
+{
+ va_list ap;
+ int type;
+ modtyp *module;
+ tpe *p;
+ char *cp;
+ PE pe;
+ char buffer[BUFSIZ];
+
+ va_start (ap);
+
+ module = va_arg (ap, modtyp *);
+ p = va_arg (ap, tpe *);
+ pe = va_arg (ap, PE);
+
+ _asprintf (buffer, NULLCP, ap);
+ (void) sprintf (PY_pepy, "%s: module %s",
+ buffer, module ? module -> md_name : "<none>");
+ if (p) {
+ cp = PY_pepy + strlen (PY_pepy);
+ (void) sprintf (cp, " %s/class=%s/id=%d",
+ pr_petype (p -> pe_type),
+ pe_classlist[p -> pe_flags & FL_CLASS],
+ p -> pe_tag);
+ }
+ if (pe && pe -> pe_class >= 0 && ((int)pe -> pe_class) < pe_maxclass) {
+ cp = PY_pepy + strlen (PY_pepy);
+ (void) sprintf (cp, " got %s/%d", pe_classlist[pe -> pe_class],
+ pe -> pe_id);
+ }
+
+ SLOG (psap_log, LLOG_EXCEPTIONS, NULLCP, ("%s", PY_pepy));
+
+ va_end (ap);
+ return NOTOK;
+}
+#endif
+
+#ifdef lint
+/* VARARGS4 */
+
+int ppepsylose (module, p, pe, str)
+modtyp *module;
+ptpe *p;
+char *str;
+PE pe;
+{
+ return ppepsylose (module, p, pe, str);
+}
+
+#else
+int ppepsylose (va_alist)
+va_dcl
+{
+ va_list ap;
+ int type;
+ modtyp *module;
+ ptpe *p;
+ char *cp;
+ PE pe;
+ char buffer[BUFSIZ];
+
+ va_start (ap);
+
+ module = va_arg (ap, modtyp *);
+ p = va_arg (ap, ptpe *);
+ pe = va_arg (ap, PE);
+
+ _asprintf (buffer, NULLCP, ap);
+ (void) sprintf (PY_pepy, "%s: module %s",
+ buffer, module ? module -> md_name : "<none>");
+ if (p) {
+ cp = PY_pepy + strlen (PY_pepy);
+ (void) sprintf (cp, " %s/class=%s/id=%d",
+ pr_petype (p -> pe_type),
+ pe_classlist[p -> pe_flags & FL_CLASS],
+ p -> pe_tag);
+ if (p->pe_typename)
+ (void) sprintf (cp, "(%s)", *p -> pe_typename);
+ }
+ if (pe && pe -> pe_class >= 0 && ((int)pe -> pe_class) < pe_maxclass) {
+ cp = PY_pepy + strlen (PY_pepy);
+ (void) sprintf (cp, " got %s/%d", pe_classlist[pe -> pe_class],
+ pe -> pe_id);
+ }
+
+ SLOG (psap_log, LLOG_EXCEPTIONS, NULLCP, ("%s", PY_pepy));
+
+ va_end (ap);
+ return NOTOK;
+}
+#endif
+
+/*
+ * Useful little routines
+ */
+/*
+ * print out the message and if the arguement is greater than 0
+ * terminate
+ */
+ferr(n, mesg)
+char *mesg;
+{
+ (void) printf(mesg);
+ if (n > 0)
+ exit(n);
+}
+/*
+ * print out the message and number and if the arguement is greater
+ * than 0 terminate
+ */
+ferrd(n, mesg, d)
+char *mesg;
+int d;
+{
+ (void) printf(mesg, d);
+ if (n > 0)
+ exit(n);
+}
+
+/*
+ * 0 = Encoding table, 1 = Decoding table, 2 = Printing table
+ */
+#define TYP_ENC 0
+#define TYP_DEC 1
+#define TYP_PRINT 2
+#define TYP_LAST 2
+
+dmp_tpe(s, p, mod)
+char *s;
+modtyp *mod; /* Module it is from */
+tpe *p;
+{
+ int typ, i, j;
+ tpe **par, **prev;
+ char *name;
+
+ (void) printf("%s: (%s)", s, mod->md_name);
+ /*
+ * Calculate what table it is in - we assume they are in order of
+ * increasing address
+ */
+
+ par = NULL;
+ for (typ = 0; typ <= TYP_LAST; typ++) {
+ switch (typ) {
+ case TYP_ENC:
+ if (mod->md_etab != NULL && mod->md_etab[0] < p) {
+ par = mod->md_etab;
+ name = "Encoding:";
+ }
+ break;
+
+ case TYP_DEC:
+ if (mod->md_dtab != NULL && mod->md_dtab[0] < p) {
+ par = mod->md_dtab;
+ name = "Decoding:";
+ }
+ break;
+
+ case TYP_PRINT:
+ if (mod->md_ptab != NULL && mod->md_ptab[0] < (ptpe *) p) {
+ par = (tpe **) mod->md_ptab;
+ name = "Printing:";
+ }
+ break;
+
+ default:
+ (void) pepsylose (mod, p, NULLPE, "dmp_tpe:typ = %d internal error\n",
+ typ);
+ return;
+ }
+ }
+ if (par == NULL) {
+ (void) printf("can't find entry 0x%x\n", p);
+ return;
+ }
+ prev = par;
+ for (i = mod->md_nentries; i > 0; i--) {
+ if (*par > p)
+ break;
+ par++;
+ }
+ if (par == prev)
+ (void) pepsylose (mod, p, NULLPE,
+ "dmp_tpe:par == prev == 0x%x internal error\n", (int) par);
+ par--;
+ j = p - *par;
+
+ (void) printf("%s type %d + %d ", name, par - prev, j);
+ pr_entry(p);
+}
+#define NENTRY(x) ((sizeof (x)/sizeof (x[0])))
+/*
+ * Print out a tpe entry
+ */
+static char *ntypes[] = { "PE_START", "PE_END", "illegal 1", "illegal 2",
+ "XOBJECT", "illegal 4", "illegal 5", "UCODE", "MALLOC", "SCTRL", "CH_ACT",
+ "OPTL", "BOPTIONAL", "FFN_CALL",},
+
+ *otypes[] = { "ANY", "INTEGER", "BOOLEAN", "OBJECT",
+ "BITSTRING", "OCTETSTRING", "SET_START", "SEQ_START", "SEQOF_START",
+ "SETOF_START", "CHOICE_START", "UNKNOWN", "T_NULL", "T_OID",
+ "ETAG", "IMP_OBJ", "EXTOBJ", "EXTMOD", "OBJID", "DFLT_F", "DFLT_B",
+ "T_STRING", "OCTET_PTR", "OCTET_LEN", "BITSTR_PTR", "BITSTR_LEN",
+ "FN_CALL" };
+
+static char *
+pr_petype (type)
+int type;
+{
+ static char nbuf[30];
+
+ if (type >= PE_START && type < NENTRY(ntypes) - 1)
+ return ntypes[type + 1];
+ else if (type >= TYPE_DATA && type < NENTRY(otypes) + TYPE_DATA)
+ return otypes[type - TYPE_DATA];
+ (void) sprintf (nbuf, "%d", type);
+ return nbuf;
+}
+
+pr_entry(p)
+tpe *p;
+{
+ (void) printf ("%s, ", pr_petype (p -> pe_type));
+ (void) printf("%d, %d, %d}\n", p->pe_ucode, p->pe_tag, p->pe_flags);
+}
+
+p_pr_entry(p)
+ptpe *p;
+{
+ if (p->pe_type >= PE_START && p->pe_type < NENTRY(ntypes) - 1)
+ (void) printf("{%s, ", ntypes[p->pe_type + 1]);
+ else if (p->pe_type >= TYPE_DATA && p->pe_type < NENTRY(otypes) + TYPE_DATA)
+ (void) printf("{%s, ", otypes[p->pe_type - TYPE_DATA]);
+ else
+ (void) printf("{%d, ", p->pe_type);
+
+ (void) printf("%d, %d, %d}\n", p->pe_ucode, p->pe_tag, p->pe_flags);
+}
+
+
+/*
+ * null function for what evr purposes
+ */
+f_null()
+{
+}
+
+/*
+ * compare a given number of bits pointed to by the two character
+ * pointers return 0 if they are the same non zero otherwise
+ */
+bitscmp(p1, p2, len)
+register char *p1, *p2;
+int len;
+{
+ register int i;
+ register unsigned int mask;
+
+ if (len >= 8 && bcmp(p1, p2, len / 8))
+ return (1);
+
+ if (len % 8 == 0)
+ return (0);
+ /* Check those last few bits */
+ i = len / 8;
+ mask = (0xff00 >> len % 8) & 0xff;
+ if ((p1[i] & mask) != (p2[i] & mask))
+ return (1);
+
+ return (0);
+}
+
+#define MIN(a, b) (a < b ? a : b)
+/*
+ * compare an octet string and a qb and return 0 if they are the same
+ * and non zero otherwise
+ */
+ostrcmp(p, len, qb)
+register char *p;
+register int len;
+register struct qbuf *qb;
+{
+ register struct qbuf *qp;
+
+ if (len < 0 || qb == NULL || p == NULL)
+ return (1);
+ qp = qb;
+ do {
+ if (qp->qb_data != NULL) {
+ if (qp->qb_len < 0)
+ ferrd(1, "ostrcmp:qb_len %d < 0", qp->qb_len);
+ if (qp->qb_len > len)
+ return (1);
+ if (bcmp(qp->qb_data, p, qp->qb_len))
+ return (1);
+ if ((len -= qp->qb_len) == 0)
+ return (0);
+ p += qp->qb_len;
+ }
+ qp = qp->qb_forw;
+ } while (qp != qb);
+
+ return (len);
+}
+
+/*
+ * Is data present for the optional item? 1 for yes 0 for no
+ */
+hasdata(parm, p, mod, popt, optcnt)
+PEPYPARM parm;
+tpe *p;
+modtyp *mod; /* Module it is from */
+int *popt, *optcnt;
+{
+ int val;
+
+ switch (p->pe_type) {
+ case INTEGER:
+ case REALTYPE:
+ case BOOLEAN:
+ case T_NULL:
+ if (DEFAULT(p)) {
+ /* Default's don't have bit map */
+ if (p[1].pe_type == DFLT_B && same(p, p + 1, parm, mod)
+ || p[-1].pe_type == DFLT_F && same(p, p - 1, parm, mod))
+ goto next;
+ break;
+ }
+ if (!TESTBIT(*popt, (*optcnt)++))
+ goto next; /* Missing so skip */
+ break;
+
+ case ETAG:
+ if (!hasdata(parm, p + 1, mod, popt, optcnt))
+ goto next;
+ break;
+
+ case IMP_OBJ:
+ if (p[1].pe_type == SOBJECT && parm == NULL
+ || *((char **) (parm + p[1].pe_ucode)) == NULL)
+ goto next;
+ break;
+
+ case FN_CALL: /* function call */
+ if ((val = (FN_PTR(mod, p))(parm, (PE *)0)) == NOTOK)
+ return pepsylose (mod, p, NULLPE,
+ "hasdata:FN_CALL:call failed");
+ if (val != OK)
+ goto next;
+ break;
+
+ default:
+ if (*((char **) (parm + p->pe_ucode)) == NULL)
+ goto next;
+ break;
+ }
+ return (1);
+
+next:
+ return (0);
+}
+
+/*
+ * determine if the default value is the same as the value in the
+ * structure and if so return greater than zero (meaning don't encode this
+ * item). On error return NOTOK
+ */
+same(typ, dflt, parm, mod)
+tpe *typ, *dflt;
+char *parm;
+modtyp *mod; /* Module it is from */
+{
+ int val;
+ int len;
+ char *p1;
+ PE pe;
+ struct qbuf *qb;
+
+ switch (typ->pe_type) {
+ case INTEGER:
+ val = IVAL(mod, dflt) == *(integer *) (parm + typ->pe_ucode);
+ break;
+
+#ifdef PEPSY_REALS
+ case REALTYPE:
+ val = RVAL(mod, dflt) == *(double *) (parm + typ->pe_ucode);
+ break;
+#endif
+
+ case BOOLEAN:
+ val = IVAL(mod, dflt) == *(char *) (parm + typ->pe_ucode);
+ break;
+
+ case T_NULL:
+ val = 1; /* Only one value */
+ break;
+
+ case SBITSTRING:
+ if ((pe = (PE) parm) == NULL) {
+ val = 1;
+ break;
+ }
+ goto bstring;
+
+ case BITSTRING:
+ if ((pe = *(PE *) (parm + typ->pe_ucode)) == NULL) {
+ val = 1;
+ break;
+ }
+bstring:
+ if ((p1 = bitstr2strb(pe, &val)) == NULL) {
+ (void) pepsylose (mod, typ, pe, "same:bad bitstring\n");
+ return (NOTOK);
+ /* Should really abort encoding here but how can we comunicate this
+ * to the routine that calls us?
+ */
+ }
+bstring2:
+ if (val != IVAL(mod, dflt) || bitscmp(PVAL(mod, dflt), p1, val))
+ val = 0;
+ else
+ val = 1;
+ if (typ->pe_type != BITSTR_PTR)
+ free(p1);
+ break;
+
+ case BITSTR_PTR:
+ if (typ[1].pe_type != BITSTR_LEN)
+ return pepsylose (mod, typ, pe, "same:missing BITSTR_LEN\n");
+ if ((p1 = *(char **) (parm + typ->pe_ucode)) == NULL) {
+ val = 1;
+ break;
+ }
+ val = *(int *) (parm + (typ + 1)->pe_ucode);
+ goto bstring2;
+
+ case SOCTETSTRING:
+ if ((qb = (struct qbuf *) parm) == NULL) {
+ val = 1;
+ break;
+ }
+ goto ostring;
+
+ case OCTETSTRING:
+ if ((qb = *(struct qbuf **) (parm + typ->pe_ucode)) == NULL) {
+ val = 1;
+ break;
+ }
+ostring:
+ if (ostrcmp(PVAL(mod, dflt), (int ) IVAL(mod, dflt), qb))
+ val = 0;
+ else
+ val = 1;
+ break;
+
+ case OCTET_PTR:
+ if (typ[1].pe_type != OCTET_LEN)
+ return pepsylose (mod, typ, pe, "same:missing OCTET_LEN\n");
+ if ((p1 = *(char **) (parm + typ->pe_ucode)) == NULL) {
+ val = 1;
+ break;
+ }
+ len = *(int *) (parm + (typ + 1)->pe_ucode);
+ goto o1string;
+
+ case T_STRING:
+ if ((p1 = *(char **) (parm + typ->pe_ucode)) == NULL) {
+ val = 1;
+ break;
+ }
+ len = strlen(p1);
+o1string:
+ if (len != IVAL(mod, dflt)) {
+ val = 0;
+ break;
+ }
+ if (bcmp(PVAL(mod, dflt), p1, len))
+ val = 0;
+ else
+ val = 1;
+ break;
+
+ case OBJECT:
+ if (*(char **) (parm + typ->pe_ucode) == NULL) {
+ val = 1; /* to conform with pepy's way of
+ * doing default */
+ break;
+ }
+ val = same(mod->md_etab[typ->pe_tag] + 1, dflt,
+ *(char **) (parm + typ->pe_ucode), mod);
+ break;
+
+ case SOBJECT:
+ if ((char *) parm == NULL) {
+ val = 1; /* to conform with pepy's way of
+ * doing default */
+ break;
+ }
+ val = same(mod->md_etab[typ->pe_tag] + 1, dflt, parm, mod);
+ break;
+
+ case IMP_OBJ:
+ typ++; /* fall through */
+
+ case ANY:
+ case SANY:
+ case SEXTOBJ:
+ case EXTOBJ:
+ case OBJID:
+ case SOBJID:
+ case SEQ_START:
+ case SET_START:
+ case -1: /* Just use the pepy method of null
+ * pointers */
+ /*
+ * This is the posy/pepy hack way of doing things at the
+ * moment
+ */
+ val = *(char **) (parm + typ->pe_ucode) == NULL;
+ break;
+
+ case FN_CALL: /* function call */
+ if ((val = (FN_PTR(mod, typ))(parm, (PE *)0)) == NOTOK)
+ return pepsylose (mod, typ, NULLPE,
+ "same:FN_CALL:call failed");
+ if (val != OK)
+ val = 1;
+ else
+ val = 0;
+ break;
+
+
+ default:
+ (void) pepsylose (mod, typ, NULLPE, "same: %d not implemented\n",
+ typ->pe_type);
+ return (NOTOK);
+ }
+
+ return (val);
+}
+
+/*
+ * Calculate the next tpe entry in the sequence. Count a sequence as
+ * one element
+ */
+tpe *
+next_tpe(p)
+tpe *p;
+{
+ int level;
+
+
+
+ level = 0;
+ if (p->pe_type == PE_END) {
+ (void) pepsylose (NULLMODTYP, p, NULLPE,
+ "next_tpe:internal error: unexpected PE_END found");
+ return (p);
+ }
+ do {
+again:
+ switch (p->pe_type) {
+ case SSEQ_START:
+ case SSEQOF_START:
+ case SSET_START:
+ case SSETOF_START:
+ case SCHOICE_START:
+ case SEQ_START:
+ case SEQOF_START:
+ case SET_START:
+ case SETOF_START:
+ case CHOICE_START:
+ level++;
+ break;
+
+ case UCODE:
+ case MEMALLOC:
+ case SCTRL:
+ case CH_ACT:
+ case INTEGER:
+ case REALTYPE:
+ case BOOLEAN:
+ case SANY:
+ case ANY:
+ case T_NULL:
+ case OBJECT:
+ case SOBJECT:
+ case BITSTRING:
+ case BITSTR_LEN:
+ case SBITSTRING:
+ case OCTETSTRING:
+ case T_STRING:
+ case OCTET_LEN:
+ case SOCTETSTRING:
+ case OBJID:
+ case SOBJID:
+ case OPTL:
+ case EXTMOD:
+ case DFLT_B:
+ case FN_CALL:
+ case FFN_CALL:
+ break;
+
+ case IMP_OBJ:
+ case ETAG:
+ case EXTOBJ:
+ case SEXTOBJ:
+ case DFLT_F:
+ case OCTET_PTR:
+ case BITSTR_PTR:
+ case BOPTIONAL:
+ case FREE_ONLY:
+ p++;
+ goto again;
+
+ case PE_END:
+ level--;
+ break;
+
+ default:
+ ferrd(1, "next_tpe: unknown type %d\n", p->pe_type);
+ }
+ p++;
+ } while (level > 0 || p->pe_type == DFLT_B);
+
+ return (p);
+}
+
+/*
+ * Is there a match at for this tag and class pair. Return 1 if yes 0
+ * if no We will search through contained objects and through choices
+ */
+ismatch(p, mod, cl, tag)
+tpe *p;
+modtyp *mod; /* Module it is from */
+unsigned int cl, tag;
+{
+ while (!ISDTYPE(p))
+ p++;
+
+ switch (p->pe_type) {
+ case SOBJECT:
+ case OBJECT:
+ /* Needs to be changed for optional and default */
+ return (ismatch(p = mod->md_dtab[p->pe_tag] + 1, mod, cl, tag));
+
+ case SEXTOBJ:
+ case EXTOBJ:
+ if (p[1].pe_type != EXTMOD) {
+ dmp_tpe("ismatch: missing EXTMOD", p, mod);
+ ferr(1, "ismatch:internal error\n");
+ }
+ return (ismatch(EXT2MOD(mod, (p + 1))->md_dtab[p->pe_tag] + 1,
+ EXT2MOD(mod, (p + 1)), cl, tag));
+
+ case CHOICE_START:
+ case SCHOICE_START:
+ for (p++; p->pe_type != PE_END; p = next_tpe (p)) {
+ if (!ISDTYPE(p))
+ continue;
+ if (ismatch(p, mod, cl, tag))
+ return (1);
+ }
+ return (0);
+
+ case SANY:
+ return (1);
+
+ case FN_CALL:
+ case ANY:
+ if (STAG(p) == -1)
+ return (1);
+ /* else fall through - not sure if this is needed */
+
+ default:
+ return (tag == TAG(p) && cl == CLASS(p));
+ }
+}
+
+/*
+ * find the data entry that goes with this DFLT_F entry
+ * bascially skip over any ETAGS that (an arbitary number but almost always 1)
+ */
+tpe *
+fdflt_f(p)
+register tpe *p;
+{
+ if (p->pe_type != DFLT_F)
+ ferr(1, "fdlt_f:Internal Error missing DFLT_F\n");
+
+ for (p++; p->pe_type != PE_END; p++) {
+ if (p->pe_type != ETAG)
+ return (p);
+ }
+ ferr(1, "fdlt_f:Internal Error PE_END found\n");
+ /*NOTREACHED*/
+}
+
+/*
+ * find the DFLT_B entry
+ */
+tpe *
+fdflt_b(p)
+register tpe *p;
+{
+ for (p++; p->pe_type != PE_END; p++) {
+ if (p->pe_type == DFLT_B)
+ return (p);
+ }
+ ferr(1, "fdflt_b:Internal Error PE_END found\n");
+ /*NOTREACHED*/
+}