Start development on 386BSD 0.0
[unix-history] / .ref-BSD-4_3_Net_2 / usr / src / contrib / isode / pepsy / fre.c
/* fre.c */
#ifndef lint
static char *rcsid = "$Header: /f/osi/pepsy/RCS/fre.c,v 7.10 91/03/09 11:55:08 mrose Exp $";
#endif
/*
* $Header: /f/osi/pepsy/RCS/fre.c,v 7.10 91/03/09 11:55:08 mrose Exp $
*
*
* $Log: fre.c,v $
* Revision 7.10 91/03/09 11:55:08 mrose
* update
*
* Revision 7.9 91/02/22 09:48:58 mrose
* Interim 6.8
*
* Revision 7.8 91/01/07 12:41:20 mrose
* update
*
* Revision 7.7 90/12/23 17:24:30 mrose
* patches
*
* Revision 7.6 90/11/11 10:53:52 mrose
* update
*
* Revision 7.5 90/11/04 19:17:06 mrose
* update
*
* Revision 7.4 90/10/23 20:43:01 mrose
* update
*
* Revision 7.3 90/08/18 00:44:26 mrose
* touch-up
*
* Revision 7.2 90/07/27 08:48:48 mrose
* update
*
* Revision 7.1 90/07/09 14:52:38 mrose
* sync
*
* Revision 7.0 90/07/01 19:54:20 mrose
* *** empty log message ***
*
*/
/*
* 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 */
/* LINTLIBRARY */
/*
* These routines are the driving routines for freeing of the data
*/
#include <stdio.h>
#include "pepsy-driver.h" /* for PEPSY_VERSION defn */
#include "psap.h"
#include "pepsy.h"
extern tpe *next_tpe();
extern int pepsylose ();
#define NEXT_TPE(p) p = next_tpe(p)
#define CHKTAG(mod, p, pe) ismatch(p, mod, pe->pe_class, pe->pe_id)
/*
* free an objects data. Basic algorithm is to walk through it twice
* first time freeing all the "children" of the data structure - then
* the second time free the structure itself
*/
fre_obj(parm, p, mod, dofree)
modtyp *mod;
tpe *p;
char *parm;
int dofree;
{
char *malptr = NULL; /* Have we seen a malloc */
int ndofree = dofree; /* Does the function below deallocate space */
if (parm == 0)
return (OK);
if (p->pe_type != PE_START) {
(void) pepsylose (mod, p, NULLPE, "fre_obj: missing PE_START\n");
return (NOTOK);
}
for (p++; p->pe_type != PE_END; NEXT_TPE(p)) {
again:
/*
* we have to have all these cases here because it is different to the
* situation when the entry is not the main entry of the typereference.
*/
switch (p->pe_type) {
case MEMALLOC:
if (dofree) {
malptr = parm;
ndofree = 0; /* we are deallocating space on this level */
}
break;
default:
if (fre_type(parm, p, mod, ndofree) != OK)
return (NOTOK);
break;
}
}
if (malptr && dofree) { /* If we saw a malloc free item */
free(malptr);
malptr = NULLCP;
}
return (OK);
}
/*
* Handle freeing of single type field. All the more general routines
* fall back to this so we can put the code to free something just
* here once and it will handle all the cases else where
*/
fre_type(parm, p, mod, dofree)
char *parm;
tpe *p;
modtyp *mod; /* Module it is from */
int dofree;
{
if (parm == 0)
return OK;
again:
switch (p->pe_type) {
case MEMALLOC:
break;
case PE_END:
case PE_START:
case UCODE:
break;
case BOPTIONAL:
case FREE_ONLY: /* this next entry is for us */
case DFLT_F:
p++;
goto again;
case ETAG:
switch (p->pe_ucode) {
default:
p++;
if (fre_type(parm, p, mod, dofree) != OK)
return (NOTOK);
}
break;
case SEQ_START:
case SET_START:
if (fre_seq(*(char **) (parm + p->pe_ucode), p, mod, 1) != OK)
return (NOTOK);
break;
case SEQOF_START:
case SETOF_START:
if (fre_seqof(*(char **) (parm + p->pe_ucode), p, mod, 1) != OK)
return (NOTOK);
break;
case SSEQ_START:
case SSET_START:
if (fre_seq((char *) parm + p->pe_ucode, p, mod, dofree) != OK)
return (NOTOK);
break;
case SSEQOF_START:
case SSETOF_START:
if (fre_seqof((char *) parm + p->pe_ucode, p, mod, dofree) != OK)
return (NOTOK);
break;
case IMP_OBJ:
p++;
if (p->pe_type == EXTOBJ) {
if (fre_obj(*(char **) (parm + p->pe_ucode),
(EXT2MOD(mod, (p + 1)))->md_dtab[p->pe_tag],
EXT2MOD(mod, (p + 1)), 1) != OK)
return (NOTOK);
} else if (p->pe_type == SEXTOBJ) {
if (fre_obj((parm + p->pe_ucode),
(EXT2MOD(mod, (p + 1)))->md_dtab[p->pe_tag],
EXT2MOD(mod, (p + 1)), dofree) != OK)
return (NOTOK);
} else if (p->pe_type == SOBJECT) {
if (fre_obj((char *) parm + p->pe_ucode, mod->md_dtab[p->pe_tag], mod, dofree) != OK)
return (NOTOK);
} else
if (fre_obj(*(char **) (parm + p->pe_ucode),
mod->md_dtab[p->pe_tag], mod, 1) != OK)
return (NOTOK);
break;
case SOBJECT:
if (fre_obj((char *) parm + p->pe_ucode, mod->md_dtab[p->pe_tag], mod, dofree) != OK)
return (NOTOK);
break;
case OBJECT:
if (fre_obj(*(char **) (parm + p->pe_ucode), mod->md_dtab[p->pe_tag],
mod, 1) != OK)
return (NOTOK);
break;
case SCHOICE_START:
if (fre_choice((char *) parm + p->pe_ucode, p, mod, dofree) != OK)
return (NOTOK);
break;
case CHOICE_START:
if (fre_choice(*(char **) (parm + p->pe_ucode), p, mod, 1) != OK)
return (NOTOK);
break;
case SEXTOBJ:
if (p[1].pe_type != EXTMOD) {
(void) pepsylose (mod, p, NULLPE, "fre_type:missing EXTMOD");
return (NOTOK);
}
if (fre_obj(parm + p->pe_ucode, (EXT2MOD(mod, (p + 1)))->md_dtab[p->pe_tag],
EXT2MOD(mod, (p + 1)), dofree) != OK)
return (NOTOK);
break;
case EXTOBJ:
if (p[1].pe_type != EXTMOD) {
(void) pepsylose (mod, p, NULLPE, "fre_type:missing EXTMOD");
return (NOTOK);
}
if (fre_obj(*(char **) (parm + p->pe_ucode),
(EXT2MOD(mod, (p + 1)))->md_dtab[p->pe_tag],
EXT2MOD(mod, (p + 1)), 1) != OK)
return (NOTOK);
break;
case INTEGER:
case BOOLEAN:
case T_NULL:
case REALTYPE:
break;
case SANY:
/*
* These tests of the pointer don't appear necessary from the
* definition of encoding and decoding but ISODE generates
* freeing code that does these checks and ISODE's ps layer
* definitely requires it
*/
if (parm != NULL) {
pe_free((PE) parm);
parm = NULL;
}
break;
case ANY:
if (*(char **) (parm + p->pe_ucode) != NULL) {
pe_free(*(PE *) (parm + p->pe_ucode));
*((PE *) (parm + p->pe_ucode)) = NULLPE;
}
break;
case SOCTETSTRING:
if (parm != NULL) {
qb_free((struct qbuf *) parm);
parm = NULL;
}
break;
case T_STRING:
case OCTET_PTR:
case BITSTR_PTR:
if (*(char **) (parm + p->pe_ucode) != NULL) {
free(*(char **) (parm + p->pe_ucode));
*(char **) (parm + p->pe_ucode) = NULLCP;
}
break;
case OCTETSTRING:
if (*(char **) (parm + p->pe_ucode) != NULL) {
qb_free(*(struct qbuf **) (parm + p->pe_ucode));
*(struct qbuf **) (parm + p->pe_ucode) = (struct qbuf *)0;
}
break;
case SBITSTRING:
if (parm != NULL) {
pe_free((PE) parm);
parm = NULL;
}
break;
case BITSTRING:
if (*(char **) (parm + p->pe_ucode) != NULL) {
pe_free(*(PE *) (parm + p->pe_ucode));
*(PE *) (parm + p->pe_ucode) = NULLPE;
}
break;
case SOBJID:
if (parm != NULL) {
oid_free((OID) parm);
parm = NULL;
}
break;
case OBJID:
if (*(char **) (parm + p->pe_ucode) != NULL) {
oid_free(*(OID *) (parm + p->pe_ucode));
*(OID *) (parm + p->pe_ucode) = NULLOID;
}
break;
case FN_CALL:
break; /* can't do anything with this */
case FFN_CALL:
if ((FN_PTR(mod, p))(parm) == NOTOK)
return pepsylose (mod, p, NULLPE,
"fre_type:FN_CALL:call failed");
break;
default:
(void) pepsylose (mod, p, NULLPE, "fre_type: %d not implemented\n",
p->pe_type);
return (NOTOK);
}
return (OK);
}
/*
* free elements of a sequential type. e.g. sequence or set
*/
static fre_seq(parm, p, mod, dofree)
char *parm;
tpe *p;
modtyp *mod; /* Module it is from */
int dofree;
{
int *popt = NULL; /* Pointer to optional field */
int optcnt = 0; /* Number of optionals bits so far */
char *malptr = NULL; /* Have we seen a malloc */
int ndofree = dofree; /* Does the function below deallocate space */
if (parm == 0)
return OK;
if (p->pe_type != SEQ_START && p->pe_type != SET_START
&& p->pe_type != SSEQ_START && p->pe_type != SSET_START) {
(void) pepsylose (mod, p, NULLPE, "fre_seq: bad starting item %d\n",
p->pe_type);
return (NOTOK);
}
p++;
if (p->pe_type == DFLT_B)
p++;
while (p->pe_type != PE_END) {
switch (p->pe_type) {
case MEMALLOC:
if (dofree) {
malptr = parm;
ndofree = 0; /* we are deallocating space on this level */
}
break;
case OPTL:
popt = (int *) (parm + p->pe_ucode);
break;
case ETAG:
p++;
continue;
case UCODE:
break;
case SET_START:
case SEQ_START:
if (fre_seq(*(char **) (parm + p->pe_ucode), p, mod, 1) != OK)
return (NOTOK);
break;
case SETOF_START:
case SEQOF_START:
if (fre_seqof(*(char **) (parm + p->pe_ucode), p, mod, 1) != OK)
return (NOTOK);
break;
case SSEQ_START:
case SSET_START:
if (fre_seq((char *) parm + p->pe_ucode, p, mod, ndofree) != OK)
return (NOTOK);
break;
case SSEQOF_START:
case SSETOF_START:
if (fre_seqof((char *) parm + p->pe_ucode, p, mod, ndofree) != OK)
return (NOTOK);
break;
case IMP_OBJ:
p++;
continue;
case SOBJECT:
if (fre_obj((char *) parm + p->pe_ucode,
mod->md_dtab[p->pe_tag], mod, ndofree) != OK)
return (NOTOK);
break;
case OBJECT:
if (fre_obj(*(char **) (parm + p->pe_ucode),
mod->md_dtab[p->pe_tag], mod, 1) != OK)
return (NOTOK);
break;
case SCHOICE_START:
if (fre_choice((char *) parm + p->pe_ucode, p, mod, ndofree) != OK)
return (NOTOK);
break;
case CHOICE_START:
if (fre_choice(*(char **) (parm + p->pe_ucode), p, mod, 1) != OK)
return (NOTOK);
break;
case SEXTOBJ:
if (p[1].pe_type != EXTMOD) {
(void) pepsylose (mod, p, NULLPE, "fre_seq:missing EXTMOD");
return (NOTOK);
}
if (fre_obj(parm + p->pe_ucode, (EXT2MOD(mod, (p + 1)))->md_dtab[p->pe_tag],
EXT2MOD(mod, (p + 1)), ndofree) != OK)
return (NOTOK);
break;
case EXTOBJ:
if (p[1].pe_type != EXTMOD) {
(void) pepsylose (mod, p, NULLPE, "fre_seq:missing EXTMOD");
return (NOTOK);
}
if (fre_obj(*(char **) (parm + p->pe_ucode),
(EXT2MOD(mod, (p + 1)))->md_dtab[p->pe_tag],
EXT2MOD(mod, (p + 1)), 1) != OK)
return (NOTOK);
break;
default:
if (fre_type(parm, p, mod, ndofree) != OK)
return (NOTOK);
break;
}
next:
NEXT_TPE(p);
}
if (malptr && dofree) { /* If we saw a malloc free item */
free(malptr);
malptr = NULLCP;
}
return (OK);
}
/*
* free all the fields in a SET OF/SEQUENCE OF type structure. We
* must follow the linked list until the end
*/
static fre_seqof(parm, p, mod, dofree)
char *parm;
tpe *p;
modtyp *mod; /* Module it is from */
int dofree;
{
tpe *start; /* first entry in list */
char *oparm;
if (parm == 0)
return OK;
if (p->pe_type != SEQOF_START && p->pe_type != SETOF_START
&& p->pe_type != SSEQOF_START && p->pe_type != SSETOF_START) {
(void) pepsylose (mod, p, NULLPE, "fre_seqof: illegal field");
return (NOTOK);
}
for (start = p; (char *) parm != NULL; p = start) {
p++;
if (p->pe_type == DFLT_B)
p++;
while (p->pe_type != PE_END) {
switch (p->pe_type) {
case MEMALLOC:
break;
case ETAG:
p++;
continue;
case UCODE:
break;
case SEQ_START:
case SET_START:
if (fre_seq(*(char **) (parm + p->pe_ucode), p, mod, 1) != OK)
return (NOTOK);
break;
case SEQOF_START:
case SETOF_START:
if (fre_seqof(*(char **) (parm + p->pe_ucode), p, mod, 1) != OK)
return (NOTOK);
break;
case SSEQ_START:
case SSET_START:
if (fre_seq((char *) parm + p->pe_ucode, p, mod, dofree) != OK)
return (NOTOK);
break;
case SSEQOF_START:
case SSETOF_START:
if (fre_seqof((char *) parm + p->pe_ucode, p, mod, dofree) != OK)
return (NOTOK);
break;
case IMP_OBJ:
p++;
continue;
case SOBJECT:
if (fre_obj(parm + p->pe_ucode, mod->md_dtab[p->pe_tag], mod, 0) != OK)
return (NOTOK);
break;
case OBJECT:
if (fre_obj(*(char **) (parm + p->pe_ucode),
mod->md_dtab[p->pe_tag], mod, 1) != OK)
return (NOTOK);
break;
case SCHOICE_START:
if (fre_choice((char *) parm + p->pe_ucode, p, mod, 0) != OK)
return (NOTOK);
break;
case CHOICE_START:
if (fre_choice(*(char **)(parm + p->pe_ucode), p, mod, 1) != OK)
return (NOTOK);
break;
case SEXTOBJ:
if (p[1].pe_type != EXTMOD) {
(void) pepsylose (mod, p, NULLPE,
"fre_seqof: missing EXTMOD");
return (NOTOK);
}
if (fre_obj(parm + p->pe_ucode, (EXT2MOD(mod, (p + 1)))->md_dtab[p->pe_tag],
EXT2MOD(mod, (p + 1)), 0) != OK)
return (NOTOK);
break;
case EXTOBJ:
if (p[1].pe_type != EXTMOD) {
(void) pepsylose (mod, p, NULLPE,
"fre_seqof: missing EXTMOD");
return (NOTOK);
}
if (fre_obj(*(char **) (parm + p->pe_ucode),
(EXT2MOD(mod, (p + 1)))->md_dtab[p->pe_tag],
EXT2MOD(mod, (p + 1)), 1) != OK)
return (NOTOK);
break;
default:
if (fre_type(parm, p, mod, 1) != OK)
return (NOTOK);
break;
}
NEXT_TPE(p);
}
oparm = parm;
parm = *(char **) (parm + p->pe_ucode); /* Any more ? */
if (dofree) {
free(oparm);
oparm = NULLCP;
}
}
return (OK);
}
/*
* free the item of the choice. Use the SCTRL field to determine
* which item is present and then call the appropriate routine to
* free it
*/
static fre_choice(parm, p, mod, dofree)
char *parm;
tpe *p;
modtyp *mod; /* Module it is from */
int dofree;
{
int cnt;
char *malptr = NULL; /* Have we seen a malloc */
int ndofree = dofree; /* Does the function below deallocate space */
if (parm == 0)
return OK;
if (p->pe_type != CHOICE_START && p->pe_type != SCHOICE_START) {
(void) pepsylose (mod, p, NULLPE,
"fre_choice:CHOICE_START missing found %d\n", p->pe_type);
}
p++;
if (p->pe_type == DFLT_B)
p++;
if (p->pe_type == MEMALLOC) {
if (dofree) {
malptr = parm;
ndofree = 0; /* we are deallocating space on this level */
}
p++;
}
if (p->pe_type != SCTRL) {
(void) pepsylose (mod, p, NULLPE,
"fre_choice: missing SCTRL information\n");
return (NOTOK);
}
cnt = *(int *) (parm + p->pe_ucode);
if (cnt != 0)
cnt--;
if (cnt < 0) {
(void) pepsylose (mod, p, NULLPE,"fre_choice:offset negative %d", cnt);
return (NOTOK);
}
for (p++; p->pe_type != PE_END; NEXT_TPE(p)) {
if (ISDTYPE(p)) {
if (cnt == 0) {
if (fre_type(parm, p, mod, ndofree) != OK)
return (NOTOK);
if (malptr && dofree) { /* If we saw a malloc free item */
free(malptr);
malptr = NULLCP;
}
return (OK);
}
cnt--;
}
}
(void) pepsylose (mod, p, NULLPE, "fre_choice: no choice taken");
return (NOTOK);
}
/*
* look out for FN_CALL - if this entry is really a FN_CALL return non zero
* else return 0
* Basically we have to stop FN_CALL being tested by hasdata which will call
* the decoding function which is illegal and gives rubbish.
*/
callsfn(p, mod)
tpe *p;
modtyp *mod;
{
while (p->pe_type != PE_END) {
switch (p->pe_type) {
case ETAG:
p++;
continue;
case FN_CALL:
return (1);
default:
case INTEGER:
case REALTYPE:
case BOOLEAN:
case T_NULL:
case IMP_OBJ:
case OBJECT:
return (0);
}
}
(void) pepsylose (mod, p, NULLPE,"callsfn:Corrupted tables:PE_END found\n");
ferr(1, "callsfn:Mangled tables\n");
/*NOTREACHED*/
}