Start development on 386BSD 0.0
[unix-history] / .ref-BSD-4_3_Net_2 / usr / src / contrib / isode / pepsy / util.c
CommitLineData
459ebbd7
C
1/* util.c */
2
3#ifndef lint
4static char *rcsid = "$Header: /f/osi/pepsy/RCS/util.c,v 7.7 91/02/22 09:50:13 mrose Interim $";
5#endif
6
7/*
8 * $Header: /f/osi/pepsy/RCS/util.c,v 7.7 91/02/22 09:50:13 mrose Interim $
9 *
10 *
11 * $Log: util.c,v $
12 * Revision 7.7 91/02/22 09:50:13 mrose
13 * Interim 6.8
14 *
15 * Revision 7.6 90/12/11 10:41:13 mrose
16 * sync
17 *
18 * Revision 7.5 90/11/04 19:21:19 mrose
19 * update
20 *
21 * Revision 7.4 90/10/23 20:43:20 mrose
22 * update
23 *
24 * Revision 7.3 90/08/18 00:44:30 mrose
25 * touch-up
26 *
27 * Revision 7.2 90/08/08 14:14:45 mrose
28 * update
29 *
30 * Revision 7.1 90/07/09 14:53:23 mrose
31 * sync
32 *
33 * Revision 7.0 90/07/01 19:54:33 mrose
34 * *** empty log message ***
35 *
36 */
37
38/*
39 * NOTICE
40 *
41 * Acquisition, use, and distribution of this module and related
42 * materials are subject to the restrictions of a license agreement.
43 * Consult the Preface in the User's Manual for the full terms of
44 * this agreement.
45 *
46 */
47
48
49/* LINTLIBRARY */
50
51#include <stdio.h>
52#include "pepsy-driver.h"
53#include "psap.h"
54#include "pepsy.h"
55#include <varargs.h>
56#include "tailor.h"
57
58#ifndef PEPYPARM
59#define PEPYPARM char *
60#endif
61
62static char *pr_petype ();
63
64extern void exit();
65
66#ifdef lint
67/* VARARGS4 */
68
69int pepsylose (module, p, pe, str)
70modtyp *module;
71tpe *p;
72char *str;
73PE pe;
74{
75 return pepsylose (module, p, pe, str);
76}
77
78#else
79int pepsylose (va_alist)
80va_dcl
81{
82 va_list ap;
83 int type;
84 modtyp *module;
85 tpe *p;
86 char *cp;
87 PE pe;
88 char buffer[BUFSIZ];
89
90 va_start (ap);
91
92 module = va_arg (ap, modtyp *);
93 p = va_arg (ap, tpe *);
94 pe = va_arg (ap, PE);
95
96 _asprintf (buffer, NULLCP, ap);
97 (void) sprintf (PY_pepy, "%s: module %s",
98 buffer, module ? module -> md_name : "<none>");
99 if (p) {
100 cp = PY_pepy + strlen (PY_pepy);
101 (void) sprintf (cp, " %s/class=%s/id=%d",
102 pr_petype (p -> pe_type),
103 pe_classlist[p -> pe_flags & FL_CLASS],
104 p -> pe_tag);
105 }
106 if (pe && pe -> pe_class >= 0 && pe -> pe_class < pe_maxclass) {
107 cp = PY_pepy + strlen (PY_pepy);
108 (void) sprintf (cp, " got %s/%d", pe_classlist[pe -> pe_class],
109 pe -> pe_id);
110 }
111
112 SLOG (psap_log, LLOG_EXCEPTIONS, NULLCP, ("%s", PY_pepy));
113
114 va_end (ap);
115 return NOTOK;
116}
117#endif
118
119#ifdef lint
120/* VARARGS4 */
121
122int ppepsylose (module, p, pe, str)
123modtyp *module;
124ptpe *p;
125char *str;
126PE pe;
127{
128 return ppepsylose (module, p, pe, str);
129}
130
131#else
132int ppepsylose (va_alist)
133va_dcl
134{
135 va_list ap;
136 int type;
137 modtyp *module;
138 ptpe *p;
139 char *cp;
140 PE pe;
141 char buffer[BUFSIZ];
142
143 va_start (ap);
144
145 module = va_arg (ap, modtyp *);
146 p = va_arg (ap, ptpe *);
147 pe = va_arg (ap, PE);
148
149 _asprintf (buffer, NULLCP, ap);
150 (void) sprintf (PY_pepy, "%s: module %s",
151 buffer, module ? module -> md_name : "<none>");
152 if (p) {
153 cp = PY_pepy + strlen (PY_pepy);
154 (void) sprintf (cp, " %s/class=%s/id=%d",
155 pr_petype (p -> pe_type),
156 pe_classlist[p -> pe_flags & FL_CLASS],
157 p -> pe_tag);
158 if (p->pe_typename)
159 (void) sprintf (cp, "(%s)", p -> pe_typename);
160 }
161 if (pe && pe -> pe_class >= 0 && pe -> pe_class < pe_maxclass) {
162 cp = PY_pepy + strlen (PY_pepy);
163 (void) sprintf (cp, " got %s/%d", pe_classlist[pe -> pe_class],
164 pe -> pe_id);
165 }
166
167 SLOG (psap_log, LLOG_EXCEPTIONS, NULLCP, ("%s", PY_pepy));
168
169 va_end (ap);
170 return NOTOK;
171}
172#endif
173
174/*
175 * Useful little routines
176 */
177/*
178 * print out the message and if the arguement is greater than 0
179 * terminate
180 */
181ferr(n, mesg)
182char *mesg;
183{
184 (void) printf(mesg);
185 if (n > 0)
186 exit(n);
187}
188/*
189 * print out the message and number and if the arguement is greater
190 * than 0 terminate
191 */
192ferrd(n, mesg, d)
193char *mesg;
194int d;
195{
196 (void) printf(mesg, d);
197 if (n > 0)
198 exit(n);
199}
200
201/*
202 * 0 = Encoding table, 1 = Decoding table, 2 = Printing table
203 */
204#define TYP_ENC 0
205#define TYP_DEC 1
206#define TYP_PRINT 2
207#define TYP_LAST 2
208
209dmp_tpe(s, p, mod)
210char *s;
211modtyp *mod; /* Module it is from */
212tpe *p;
213{
214 int typ, i, j;
215 tpe **par, **prev;
216 char *name;
217
218 (void) printf("%s: (%s)", s, mod->md_name);
219 /*
220 * Calculate what table it is in - we assume they are in order of
221 * increasing address
222 */
223
224 par = NULL;
225 for (typ = 0; typ <= TYP_LAST; typ++) {
226 switch (typ) {
227 case TYP_ENC:
228 if (mod->md_etab != NULL && mod->md_etab[0] < p) {
229 par = mod->md_etab;
230 name = "Encoding:";
231 }
232 break;
233
234 case TYP_DEC:
235 if (mod->md_dtab != NULL && mod->md_dtab[0] < p) {
236 par = mod->md_dtab;
237 name = "Decoding:";
238 }
239 break;
240
241 case TYP_PRINT:
242 if (mod->md_ptab != NULL && mod->md_ptab[0] < (ptpe *) p) {
243 (ptpe **) par = mod->md_ptab;
244 name = "Printing:";
245 }
246 break;
247
248 default:
249 (void) pepsylose (mod, p, NULLPE, "dmp_tpe:typ = %d internal error\n",
250 typ);
251 return;
252 }
253 }
254 if (par == NULL) {
255 (void) printf("can't find entry 0x%x\n", p);
256 return;
257 }
258 prev = par;
259 for (i = mod->md_nentries; i > 0; i--) {
260 if (*par > p)
261 break;
262 par++;
263 }
264 if (par == prev)
265 (void) pepsylose (mod, p, NULLPE,
266 "dmp_tpe:par == prev == 0x%x internal error\n", (int) par);
267 par--;
268 j = p - *par;
269
270 (void) printf("%s type %d + %d ", name, par - prev, j);
271 pr_entry(p);
272}
273#define NENTRY(x) ((sizeof (x)/sizeof (x[0])))
274/*
275 * Print out a tpe entry
276 */
277static char *ntypes[] = { "PE_START", "PE_END", "illegal 1", "illegal 2",
278 "XOBJECT", "illegal 4", "illegal 5", "UCODE", "MALLOC", "SCTRL", "CH_ACT",
279 "OPTL", "BOPTIONAL", "FFN_CALL",},
280
281 *otypes[] = { "ANY", "INTEGER", "BOOLEAN", "OBJECT",
282 "BITSTRING", "OCTETSTRING", "SET_START", "SEQ_START", "SEQOF_START",
283 "SETOF_START", "CHOICE_START", "UNKNOWN", "T_NULL", "T_OID",
284 "ETAG", "IMP_OBJ", "EXTOBJ", "EXTMOD", "OBJID", "DFLT_F", "DFLT_B",
285 "T_STRING", "OCTET_PTR", "OCTET_LEN", "BITSTR_PTR", "BITSTR_LEN",
286 "FN_CALL" };
287
288static char *
289pr_petype (type)
290int type;
291{
292 static char nbuf[30];
293
294 if (type >= PE_START && type < NENTRY(ntypes) - 1)
295 return ntypes[type + 1];
296 else if (type >= TYPE_DATA && type < NENTRY(otypes) + TYPE_DATA)
297 return otypes[type - TYPE_DATA];
298 (void) sprintf (nbuf, "%d", type);
299 return nbuf;
300}
301
302pr_entry(p)
303tpe *p;
304{
305 (void) printf ("%s, ", pr_petype (p -> pe_type));
306 (void) printf("%d, %d, %d}\n", p->pe_ucode, p->pe_tag, p->pe_flags);
307}
308
309p_pr_entry(p)
310ptpe *p;
311{
312 if (p->pe_type >= PE_START && p->pe_type < NENTRY(ntypes) - 1)
313 (void) printf("{%s, ", ntypes[p->pe_type + 1]);
314 else if (p->pe_type >= TYPE_DATA && p->pe_type < NENTRY(otypes) + TYPE_DATA)
315 (void) printf("{%s, ", otypes[p->pe_type - TYPE_DATA]);
316 else
317 (void) printf("{%d, ", p->pe_type);
318
319 (void) printf("%d, %d, %d}\n", p->pe_ucode, p->pe_tag, p->pe_flags);
320}
321
322
323/*
324 * null function for what evr purposes
325 */
326f_null()
327{
328}
329
330/*
331 * compare a given number of bits pointed to by the two character
332 * pointers return 0 if they are the same non zero otherwise
333 */
334bitscmp(p1, p2, len)
335register char *p1, *p2;
336int len;
337{
338 register int i;
339 register unsigned int mask;
340
341 if (len >= 8 && bcmp(p1, p2, len / 8))
342 return (1);
343
344 if (len % 8 == 0)
345 return (0);
346 /* Check those last few bits */
347 i = len / 8;
348 mask = (0xff00 >> len % 8) & 0xff;
349 if ((p1[i] & mask) != (p2[i] & mask))
350 return (1);
351
352 return (0);
353}
354
355#define MIN(a, b) (a < b ? a : b)
356/*
357 * compare an octet string and a qb and return 0 if they are the same
358 * and non zero otherwise
359 */
360ostrcmp(p, len, qb)
361register char *p;
362register int len;
363register struct qbuf *qb;
364{
365 register struct qbuf *qp;
366
367 if (len < 0 || qb == NULL || p == NULL)
368 return (1);
369 qp = qb;
370 do {
371 if (qp->qb_data != NULL) {
372 if (qp->qb_len < 0)
373 ferrd(1, "ostrcmp:qb_len %d < 0", qp->qb_len);
374 if (qp->qb_len > len)
375 return (1);
376 if (bcmp(qp->qb_data, p, qp->qb_len))
377 return (1);
378 if ((len -= qp->qb_len) == 0)
379 return (0);
380 p += qp->qb_len;
381 }
382 qp = qp->qb_forw;
383 } while (qp != qb);
384
385 return (len);
386}
387
388/*
389 * Is data present for the optional item? 1 for yes 0 for no
390 */
391hasdata(parm, p, mod, popt, optcnt)
392PEPYPARM parm;
393tpe *p;
394modtyp *mod; /* Module it is from */
395int *popt, optcnt;
396{
397 int val;
398
399 switch (p->pe_type) {
400 case INTEGER:
401 case REALTYPE:
402 case BOOLEAN:
403 case T_NULL:
404 if (DEFAULT(p)) {
405 /* Default's don't have bit map */
406 if (p[1].pe_type == DFLT_B && same(p, p + 1, parm, mod)
407 || p[-1].pe_type == DFLT_F && same(p, p - 1, parm, mod))
408 goto next;
409 break;
410 }
411 if (!TESTBIT(*popt, optcnt++))
412 goto next; /* Missing so skip */
413 break;
414
415 case ETAG:
416 if (!hasdata(parm, p + 1, mod, popt, optcnt))
417 goto next;
418 break;
419
420 case IMP_OBJ:
421 if (p[1].pe_type == SOBJECT && parm == NULL
422 || *((char **) (parm + p[1].pe_ucode)) == NULL)
423 goto next;
424 break;
425
426 case FN_CALL: /* function call */
427 if ((val = (FN_PTR(mod, p))(parm, (PE *)0)) == NOTOK)
428 return pepsylose (mod, p, NULLPE,
429 "hasdata:FN_CALL:call failed");
430 if (val != OK)
431 goto next;
432 break;
433
434 default:
435 if (*((char **) (parm + p->pe_ucode)) == NULL)
436 goto next;
437 break;
438 }
439 return (1);
440
441next:
442 return (0);
443}
444
445/*
446 * determine if the default value is the same as the value in the
447 * structure and if so return greater than zero (meaning don't encode this
448 * item). On error return NOTOK
449 */
450same(typ, dflt, parm, mod)
451tpe *typ, *dflt;
452char *parm;
453modtyp *mod; /* Module it is from */
454{
455 int val;
456 int len;
457 char *p1;
458 PE pe;
459 struct qbuf *qb;
460
461 switch (typ->pe_type) {
462 case INTEGER:
463 val = IVAL(mod, dflt) == *(integer *) (parm + typ->pe_ucode);
464 break;
465
466#ifdef PEPSY_REALS
467 case REALTYPE:
468 val = RVAL(mod, dflt) == *(double *) (parm + typ->pe_ucode);
469 break;
470#endif
471
472 case BOOLEAN:
473 val = IVAL(mod, dflt) == *(char *) (parm + typ->pe_ucode);
474 break;
475
476 case T_NULL:
477 val = 1; /* Only one value */
478 break;
479
480 case SBITSTRING:
481 if ((pe = (PE) parm) == NULL) {
482 val = 1;
483 break;
484 }
485 goto bstring;
486
487 case BITSTRING:
488 if ((pe = *(PE *) (parm + typ->pe_ucode)) == NULL) {
489 val = 1;
490 break;
491 }
492bstring:
493 if ((p1 = bitstr2strb(pe, &val)) == NULL) {
494 (void) pepsylose (mod, typ, pe, "same:bad bitstring\n");
495 return (NOTOK);
496 /* Should really abort encoding here but how can we comunicate this
497 * to the routine that calls us?
498 */
499 }
500bstring2:
501 if (val != IVAL(mod, dflt) || bitscmp(PVAL(mod, dflt), p1, val))
502 val = 0;
503 else
504 val = 1;
505 if (typ->pe_type != BITSTR_PTR)
506 free(p1);
507 break;
508
509 case BITSTR_PTR:
510 if (typ[1].pe_type != BITSTR_LEN)
511 return pepsylose (mod, typ, pe, "same:missing BITSTR_LEN\n");
512 if ((p1 = *(char **) (parm + typ->pe_ucode)) == NULL) {
513 val = 1;
514 break;
515 }
516 val = *(int *) (parm + (typ + 1)->pe_ucode);
517 goto bstring2;
518
519 case SOCTETSTRING:
520 if ((qb = (struct qbuf *) parm) == NULL) {
521 val = 1;
522 break;
523 }
524 goto ostring;
525
526 case OCTETSTRING:
527 if ((qb = *(struct qbuf **) (parm + typ->pe_ucode)) == NULL) {
528 val = 1;
529 break;
530 }
531ostring:
532 if (ostrcmp(PVAL(mod, dflt), (int ) IVAL(mod, dflt), qb))
533 val = 0;
534 else
535 val = 1;
536 break;
537
538 case OCTET_PTR:
539 if (typ[1].pe_type != OCTET_LEN)
540 return pepsylose (mod, typ, pe, "same:missing OCTET_LEN\n");
541 if ((p1 = *(char **) (parm + typ->pe_ucode)) == NULL) {
542 val = 1;
543 break;
544 }
545 len = *(int *) (parm + (typ + 1)->pe_ucode);
546 goto o1string;
547
548 case T_STRING:
549 if ((p1 = *(char **) (parm + typ->pe_ucode)) == NULL) {
550 val = 1;
551 break;
552 }
553 len = strlen(p1);
554o1string:
555 if (len != IVAL(mod, dflt)) {
556 val = 0;
557 break;
558 }
559 if (bcmp(PVAL(mod, dflt), p1, len))
560 val = 0;
561 else
562 val = 1;
563 break;
564
565 case OBJECT:
566 if (*(char **) (parm + typ->pe_ucode) == NULL) {
567 val = 1; /* to conform with pepy's way of
568 * doing default */
569 break;
570 }
571 val = same(mod->md_etab[typ->pe_tag] + 1, dflt,
572 *(char **) (parm + typ->pe_ucode), mod);
573 break;
574
575 case SOBJECT:
576 if ((char *) parm == NULL) {
577 val = 1; /* to conform with pepy's way of
578 * doing default */
579 break;
580 }
581 val = same(mod->md_etab[typ->pe_tag] + 1, dflt, parm, mod);
582 break;
583
584 case IMP_OBJ:
585 typ++; /* fall through */
586
587 case ANY:
588 case SANY:
589 case SEXTOBJ:
590 case EXTOBJ:
591 case OBJID:
592 case SOBJID:
593 case SEQ_START:
594 case SET_START:
595 case -1: /* Just use the pepy method of null
596 * pointers */
597 /*
598 * This is the posy/pepy hack way of doing things at the
599 * moment
600 */
601 val = *(char **) (parm + typ->pe_ucode) == NULL;
602 break;
603
604 case FN_CALL: /* function call */
605 if ((val = (FN_PTR(mod, typ))(parm, (PE *)0)) == NOTOK)
606 return pepsylose (mod, typ, NULLPE,
607 "same:FN_CALL:call failed");
608 if (val != OK)
609 val = 1;
610 else
611 val = 0;
612 break;
613
614
615 default:
616 (void) pepsylose (mod, typ, NULLPE, "same: %d not implemented\n",
617 typ->pe_type);
618 return (NOTOK);
619 }
620
621 return (val);
622}
623
624/*
625 * Calculate the next tpe entry in the sequence. Count a sequence as
626 * one element
627 */
628tpe *
629next_tpe(p)
630tpe *p;
631{
632 int level;
633
634
635
636 level = 0;
637 if (p->pe_type == PE_END) {
638 (void) pepsylose (NULLMODTYP, p, NULLPE,
639 "next_tpe:internal error: unexpected PE_END found");
640 return (p);
641 }
642 do {
643again:
644 switch (p->pe_type) {
645 case SSEQ_START:
646 case SSEQOF_START:
647 case SSET_START:
648 case SSETOF_START:
649 case SCHOICE_START:
650 case SEQ_START:
651 case SEQOF_START:
652 case SET_START:
653 case SETOF_START:
654 case CHOICE_START:
655 level++;
656 break;
657
658 case UCODE:
659 case MEMALLOC:
660 case SCTRL:
661 case CH_ACT:
662 case INTEGER:
663 case REALTYPE:
664 case BOOLEAN:
665 case SANY:
666 case ANY:
667 case T_NULL:
668 case OBJECT:
669 case SOBJECT:
670 case BITSTRING:
671 case BITSTR_LEN:
672 case SBITSTRING:
673 case OCTETSTRING:
674 case T_STRING:
675 case OCTET_LEN:
676 case SOCTETSTRING:
677 case OBJID:
678 case SOBJID:
679 case OPTL:
680 case EXTMOD:
681 case DFLT_B:
682 case FN_CALL:
683 case FFN_CALL:
684 break;
685
686 case IMP_OBJ:
687 case ETAG:
688 case EXTOBJ:
689 case SEXTOBJ:
690 case DFLT_F:
691 case OCTET_PTR:
692 case BITSTR_PTR:
693 case BOPTIONAL:
694 case FREE_ONLY:
695 p++;
696 goto again;
697
698 case PE_END:
699 level--;
700 break;
701
702 default:
703 ferrd(1, "next_tpe: unknown type %d\n", p->pe_type);
704 }
705 p++;
706 } while (level > 0 || p->pe_type == DFLT_B);
707
708 return (p);
709}
710
711/*
712 * Is there a match at for this tag and class pair. Return 1 if yes 0
713 * if no We will search through contained objects and through choices
714 */
715ismatch(p, mod, cl, tag)
716tpe *p;
717modtyp *mod; /* Module it is from */
718unsigned int cl, tag;
719{
720 while (!ISDTYPE(p))
721 p++;
722
723 switch (p->pe_type) {
724 case SOBJECT:
725 case OBJECT:
726 /* Needs to be changed for optional and default */
727 return (ismatch(p = mod->md_dtab[p->pe_tag] + 1, mod, cl, tag));
728
729 case SEXTOBJ:
730 case EXTOBJ:
731 if (p[1].pe_type != EXTMOD) {
732 dmp_tpe("ismatch: missing EXTMOD", p, mod);
733 ferr(1, "ismatch:internal error\n");
734 }
735 return (ismatch(EXT2MOD(mod, (p + 1))->md_dtab[p->pe_tag] + 1,
736 EXT2MOD(mod, (p + 1)), cl, tag));
737
738 case CHOICE_START:
739 case SCHOICE_START:
740 for (p++; p->pe_type != PE_END; p = next_tpe (p)) {
741 if (!ISDTYPE(p))
742 continue;
743 if (ismatch(p, mod, cl, tag))
744 return (1);
745 }
746 return (0);
747
748 case SANY:
749 return (1);
750
751 case FN_CALL:
752 case ANY:
753 if (STAG(p) == -1)
754 return (1);
755 /* else fall through - not sure if this is needed */
756
757 default:
758 return (tag == TAG(p) && cl == CLASS(p));
759 }
760}
761
762/*
763 * find the data entry that goes with this DFLT_F entry
764 * bascially skip over any ETAGS that (an arbitary number but almost always 1)
765 */
766tpe *
767fdflt_f(p)
768register tpe *p;
769{
770 if (p->pe_type != DFLT_F)
771 ferr(1, "fdlt_f:Internal Error missing DFLT_F\n");
772
773 for (p++; p->pe_type != PE_END; p++) {
774 if (p->pe_type != ETAG)
775 return (p);
776 }
777 ferr(1, "fdlt_f:Internal Error PE_END found\n");
778 /*NOTREACHED*/
779}
780
781/*
782 * find the DFLT_B entry
783 */
784tpe *
785fdflt_b(p)
786register tpe *p;
787{
788 for (p++; p->pe_type != PE_END; p++) {
789 if (p->pe_type == DFLT_B)
790 return (p);
791 }
792 ferr(1, "fdflt_b:Internal Error PE_END found\n");
793 /*NOTREACHED*/
794}