#include <stdio.h>
#include "asn-incl.h"
#include "asn1module.h"
#include "tbl.h"
#include "gen-tbls.h"
extern Module *usefulTypeModG;
void GenTypeDefIds PROTO ((TBL *tbl, Module *m));
int GenTblModule PROTO ((TBL *tbl, Module *m, TBLModule **newTbl));
int GenTblTypeDefs PROTO ((TBL *tbl, Module *m, TBLModule *tblMod));
int GenTblTypes PROTO ((TBL *tbl, Module *m, TBLModule *tblMod, TypeDef *td, TBLTypeDef *tblTd));
TBLType *GenTblTypesRec PROTO ((TBL *tbl,Module *m, TBLModule *tblMod, TypeDef *td, TBLTypeDef *tblTd, Type *t));
static int abortTblTypeDefG;
static int tblTypesTotalG;
static int tblTagsTotalG;
static int tblStringsTotalG;
static int tblStringLenTotalG;
static int tableFileVersionG;
void
GenTypeTbls PARAMS ((mods, fileName, tableFileVersion),
ModuleList *mods _AND_
char *fileName _AND_
int tableFileVersion)
{
TBL tbl;
TBLModule *newTblMod;
FILE *tblFile;
ExpBuf *buf;
ExpBuf *tmpBuf;
Module *m;
tableFileVersionG = tableFileVersion;
tbl.modules = AsnListNew (sizeof (void*));
tbl.totalNumModules = 0;
tbl.totalNumTypeDefs = 0;
tbl.totalNumTypes = 0;
tbl.totalNumTags = 0;
tbl.totalNumStrings = 0;
tbl.totalLenStrings = 0;
FOR_EACH_LIST_ELMT (m, mods)
{
GenTypeDefIds (&tbl, m);
}
if (usefulTypeModG != NULL)
GenTypeDefIds (&tbl, usefulTypeModG);
FOR_EACH_LIST_ELMT (m, mods)
{
if (!GenTblModule (&tbl, m, &newTblMod))
{
fprintf (stderr,"ERROR: type table generator failed for module \"%s\", so file \"%s\" will not be written.\n", m->modId->name, fileName);
return;
}
}
if (usefulTypeModG != NULL)
{
if (!GenTblModule (&tbl, usefulTypeModG, &newTblMod))
{
fprintf (stderr,"ERROR: type table generator failed for useful types module, file \"%s\" will not be written.\n",fileName);
return;
}
newTblMod->isUseful = TRUE;
}
ExpBufInit (1024);
buf = ExpBufAllocBufAndData();
BEncTBL (&buf, &tbl);
if (ExpBufWriteError (&buf))
{
fprintf (stderr,"ERROR: buffer write error during encoding of type table.\n", fileName);
return;
}
tblFile = fopen (fileName,"w");
if (tblFile == NULL)
{
fprintf (stderr,"ERROR: Could not open file \"%s\" for the type table.\n", fileName);
return;
}
buf->curr = buf->dataStart;
for (tmpBuf = buf; tmpBuf != NULL; tmpBuf = tmpBuf->next)
{
fwrite (tmpBuf->dataStart, tmpBuf->dataEnd - tmpBuf->dataStart, 1, tblFile);
}
fclose (tblFile);
}
void
GenTypeDefIds PARAMS ((tbl,m),
TBL *tbl _AND_
Module *m)
{
TypeDef *td;
tbl->totalNumModules++;
FOR_EACH_LIST_ELMT (td, m->typeDefs)
{
td->tmpRefCount = tbl->totalNumTypeDefs;
tbl->totalNumTypeDefs++;
}
}
int
GenTblModule PARAMS ((tbl, m, newTblMod),
TBL *tbl _AND_
Module *m _AND_
TBLModule **newTblMod)
{
TBLModule **mHndl;
TBLModule *tblMod;
int eLen;
AsnOid *result;
mHndl = AsnListAppend (tbl->modules);
tblMod = MT (TBLModule);
*newTblMod = *mHndl = tblMod;
tblMod->name.octetLen = strlen (m->modId->name);
tblMod->name.octs = Malloc (tblMod->name.octetLen + 1);
strcpy (tblMod->name.octs, m->modId->name);
tbl->totalNumStrings++;
tbl->totalLenStrings += tblMod->name.octetLen;
if (m->modId->oid != NULL)
{
if (FlattenLinkedOid (m->modId->oid))
{
eLen = EncodedOidLen (m->modId->oid);
tblMod->id.octetLen = eLen;
tblMod->id.octs = (char*)Malloc (eLen);
BuildEncodedOid (m->modId->oid, &tblMod->id);
tbl->totalNumStrings++;
tbl->totalLenStrings += eLen;
}
}
tblMod->isUseful = FALSE;
return GenTblTypeDefs (tbl, m, tblMod);
}
int
GenTblTypeDefs PARAMS ((tbl, m, tblMod),
TBL *tbl _AND_
Module *m _AND_
TBLModule *tblMod)
{
TypeDef *td;
TBLTypeDef **tblTdHndl;
TBLTypeDef *tblTd;
int isOk = TRUE;
tblMod->typeDefs = AsnListNew (sizeof (void*));
FOR_EACH_LIST_ELMT (td, m->typeDefs)
{
tblTd = MT (TBLTypeDef);
tblTd->typeDefId = td->tmpRefCount;
tblTd->typeName.octetLen = strlen (td->definedName);
tblTd->typeName.octs = Malloc (tblTd->typeName.octetLen + 1);
strcpy (tblTd->typeName.octs, td->definedName);
tbl->totalNumStrings++;
tbl->totalLenStrings += tblTd->typeName.octetLen;
if (m!=usefulTypeModG)
{
MyString attr;
char* attrName;
char* attrValue;
int result = FALSE;
FOR_EACH_LIST_ELMT(attr,td->attrList)
{
int loc = 0;
while (TRUE)
{
ParseAttr(attr,&loc,&attrName,&attrValue);
if (!attrName)
break;
if (!strcmp(attrName,"isPdu"))
if (ParseBool(attrValue,&result)<0)
fprintf(stderr,"Warning: ignoring attribute with improper value (%s/%s)\n",attrName,attrValue);
Free(attrValue);
}
}
if (result)
tblTd->isPdu = MT (AsnNull);
}
if (!GenTblTypes (tbl, m, tblMod, td, tblTd) && !abortTblTypeDefG)
isOk = FALSE;
if (!abortTblTypeDefG)
{
tblTdHndl = AsnListAppend (tblMod->typeDefs);
*tblTdHndl = tblTd;
tbl->totalNumTypes += tblTypesTotalG;
tbl->totalNumTags += tblTagsTotalG;
tbl->totalNumStrings += tblStringsTotalG;
tbl->totalLenStrings += tblStringLenTotalG;
}
}
return isOk;
}
int
GenTblTypes PARAMS ((tbl, m, tblMod, td, tblTd),
TBL *tbl _AND_
Module *m _AND_
TBLModule *tblMod _AND_
TypeDef *td _AND_
TBLTypeDef *tblTd)
{
abortTblTypeDefG = FALSE;
tblTypesTotalG = 0;
tblTagsTotalG = 0;
tblStringsTotalG = 0;
tblStringLenTotalG = 0;
tblTd->type = GenTblTypesRec (tbl, m, tblMod, td, tblTd, td->type);
if (tblTd->type == NULL)
return FALSE;
else
return TRUE;
}
BasicValue*
GetTblValue PARAMS ((v),
Value* v)
{
switch (v->basicValue->choiceId)
{
case BASICVALUE_INTEGER:
return v->basicValue;
default:
return NULL;
}
}
enum BasicTypeChoiceId
GetTblBasicType PARAMS ((bt),
BasicType* bt)
{
switch (bt->choiceId)
{
case BASICTYPE_LOCALTYPEREF:
case BASICTYPE_IMPORTTYPEREF:
return GetTblBasicType (bt->a.localTypeRef->link->type->basicType);
default:
return bt->choiceId;
}
}
TBLRange*
GenTblValueRange PARAMS ((tbl, m, tblMod, s, doSize),
TBL *tbl _AND_
Module *m _AND_
TBLModule *tblMod _AND_
Subtype *s _AND_
int doSize)
{
TBLRange* range;
BasicValue* from;
BasicValue* to;
if (tableFileVersionG<=1)
return NULL;
switch (s->choiceId)
{
case SUBTYPE_SINGLE:
switch (s->a.single->choiceId)
{
case SUBTYPEVALUE_SINGLEVALUE:
if (doSize)
return NULL;
from = to = GetTblValue (s->a.single->a.singleValue);
break;
case SUBTYPEVALUE_VALUERANGE:
if (doSize)
return NULL;
from =GetTblValue(s->a.single->a.valueRange->lowerEndValue);
to = GetTblValue (s->a.single->a.valueRange->upperEndValue);
break;
case SUBTYPEVALUE_SIZECONSTRAINT:
if (!doSize)
return NULL;
return GenTblValueRange (tbl, m, tblMod,
s->a.single->a.sizeConstraint, 0);
break;
default:
return NULL;
}
break;
case SUBTYPE_AND:
if (s->a.and && LIST_COUNT(s->a.and)==1)
return GenTblValueRange (tbl, m, tblMod,
FIRST_LIST_ELMT(s->a.and), doSize);
return NULL;
case SUBTYPE_OR:
if (s->a.and && LIST_COUNT(s->a.or)==1)
return GenTblValueRange (tbl, m, tblMod,
FIRST_LIST_ELMT(s->a.or), doSize);
return NULL;
case SUBTYPE_NOT:
return NULL;
}
if (!from || !to)
return NULL;
range = MT (TBLRange);
range->from = from->a.integer;
range->to = to->a.integer;
return range;
}
TBLNamedNumberList*
GenTblValues PARAMS ((tbl, m, tblMod, list),
TBL *tbl _AND_
Module *m _AND_
TBLModule *tblMod _AND_
NamedNumberList* list)
{
TBLNamedNumberList* tnnl = NULL;
if (tableFileVersionG<=1)
return NULL;
if (list && !LIST_EMPTY(list))
{
ValueDef* vd;
tnnl = (TBLNamedNumberList*) AsnListNew(sizeof(void*));
FOR_EACH_LIST_ELMT(vd,list)
{
BasicValue* bv = GetTblValue(vd->value);
if (bv)
{
TBLNamedNumber* tnn = MT(TBLNamedNumber);
*(TBLNamedNumber**)AsnListAppend(tnnl) = tnn;
tnn->value = bv->a.integer;
if (vd->definedName)
{
tnn->name.octetLen = strlen(vd->definedName);
tnn->name.octs = Malloc(tnn->name.octetLen+1);
strcpy(tnn->name.octs,vd->definedName);
tblStringsTotalG++;
tblStringLenTotalG += tnn->name.octetLen;
}
}
}
}
return tnnl;
}
TBLType*
GenTblTypesRec PARAMS ((tbl, m, tblMod, td, tblTd, t),
TBL *tbl _AND_
Module *m _AND_
TBLModule *tblMod _AND_
TypeDef *td _AND_
TBLTypeDef *tblTd _AND_
Type *t)
{
TBLType *tblT;
NamedType *e;
TBLType **tblTHndl;
Tag *tag;
TBLTag **tblTagHndl;
tblTypesTotalG++;
tblT = MT (TBLType);
tblT->content = MT (TBLTypeContent);
switch (t->basicType->choiceId)
{
case BASICTYPE_BOOLEAN:
tblT->typeId = TBL_BOOLEAN;
tblT->content->choiceId = TBLTYPECONTENT_PRIMTYPE;
break;
case BASICTYPE_INTEGER:
tblT->typeId = TBL_INTEGER;
tblT->content->choiceId = TBLTYPECONTENT_PRIMTYPE;
break;
case BASICTYPE_BITSTRING:
tblT->typeId = TBL_BITSTRING;
tblT->content->choiceId = TBLTYPECONTENT_PRIMTYPE;
tblT->values = GenTblValues(tbl,m,tblMod,t->basicType->a.bitString);
break;
case BASICTYPE_OCTETSTRING:
tblT->typeId = TBL_OCTETSTRING;
tblT->content->choiceId = TBLTYPECONTENT_PRIMTYPE;
if (t->subtypes)
tblT->constraint = GenTblValueRange(tbl, m, tblMod,t->subtypes,1);
break;
case BASICTYPE_NULL:
tblT->typeId = TBL_NULL;
tblT->content->choiceId = TBLTYPECONTENT_PRIMTYPE;
break;
case BASICTYPE_OID:
tblT->typeId = TBL_OID;
tblT->content->choiceId = TBLTYPECONTENT_PRIMTYPE;
break;
case BASICTYPE_REAL:
tblT->typeId = TBL_REAL;
tblT->content->choiceId = TBLTYPECONTENT_PRIMTYPE;
break;
case BASICTYPE_ENUMERATED:
tblT->typeId = TBL_ENUMERATED;
tblT->content->choiceId = TBLTYPECONTENT_PRIMTYPE;
tblT->values = GenTblValues(tbl,m,tblMod,t->basicType->a.enumerated);
break;
case BASICTYPE_SEQUENCE:
tblT->typeId = TBL_SEQUENCE;
tblT->content->choiceId = TBLTYPECONTENT_ELMTS;
tblT->content->a.elmts = AsnListNew (sizeof (void*));
FOR_EACH_LIST_ELMT (e, t->basicType->a.sequence)
{
tblTHndl = AsnListAppend (tblT->content->a.elmts);
*tblTHndl = GenTblTypesRec (tbl, m, tblMod, td, tblTd, e->type);
if (*tblTHndl == NULL)
break;
if (e->fieldName != NULL)
{
(**tblTHndl).fieldName.octetLen = strlen (e->fieldName);
(**tblTHndl).fieldName.octs =
Malloc ((**tblTHndl).fieldName.octetLen + 1);
strcpy ((**tblTHndl).fieldName.octs, e->fieldName);
tblStringsTotalG++;
tblStringLenTotalG += (**tblTHndl).fieldName.octetLen;
}
(**tblTHndl).optional =
((e->type->optional) || (e->type->defaultVal != NULL));
}
break;
case BASICTYPE_SET:
tblT->typeId = TBL_SET;
tblT->content->choiceId = TBLTYPECONTENT_ELMTS;
tblT->content->a.elmts = AsnListNew (sizeof (void*));
FOR_EACH_LIST_ELMT (e, t->basicType->a.set)
{
tblTHndl = AsnListAppend (tblT->content->a.elmts);
*tblTHndl = GenTblTypesRec (tbl, m, tblMod, td, tblTd, e->type);
if (*tblTHndl == NULL)
break;
if (e->fieldName != NULL)
{
(**tblTHndl).fieldName.octetLen = strlen (e->fieldName);
(**tblTHndl).fieldName.octs =
Malloc ((**tblTHndl).fieldName.octetLen + 1);
strcpy ((**tblTHndl).fieldName.octs, e->fieldName);
tblStringsTotalG++;
tblStringLenTotalG += (**tblTHndl).fieldName.octetLen;
}
(**tblTHndl).optional =
((e->type->optional) || (e->type->defaultVal != NULL));
}
break;
case BASICTYPE_SEQUENCEOF:
tblT->typeId = TBL_SEQUENCEOF;
tblT->content->choiceId = TBLTYPECONTENT_ELMTS;
tblT->content->a.elmts = AsnListNew (sizeof (void*));
tblTHndl = AsnListAppend (tblT->content->a.elmts);
*tblTHndl = GenTblTypesRec (tbl, m, tblMod, td, tblTd, t->basicType->a.sequenceOf);
if (t->subtypes)
tblT->constraint = GenTblValueRange(tbl, m, tblMod,t->subtypes,1);
break;
case BASICTYPE_SETOF:
tblT->typeId = TBL_SETOF;
tblT->content->choiceId = TBLTYPECONTENT_ELMTS;
tblT->content->a.elmts = AsnListNew (sizeof (void*));
tblTHndl = AsnListAppend (tblT->content->a.elmts);
*tblTHndl = GenTblTypesRec (tbl, m, tblMod, td, tblTd, t->basicType->a.setOf);
if (t->subtypes)
tblT->constraint = GenTblValueRange(tbl, m, tblMod,t->subtypes,1);
break;
case BASICTYPE_CHOICE:
tblT->typeId = TBL_CHOICE;
tblT->content->choiceId = TBLTYPECONTENT_ELMTS;
tblT->content->a.elmts = AsnListNew (sizeof (void*));
FOR_EACH_LIST_ELMT (e, t->basicType->a.set)
{
tblTHndl = AsnListAppend (tblT->content->a.elmts);
*tblTHndl = GenTblTypesRec (tbl, m, tblMod, td, tblTd, e->type);
if (*tblTHndl == NULL)
break;
if (e->fieldName != NULL)
{
(**tblTHndl).fieldName.octetLen = strlen (e->fieldName);
(**tblTHndl).fieldName.octs =
Malloc ((**tblTHndl).fieldName.octetLen + 1);
strcpy ((**tblTHndl).fieldName.octs, e->fieldName);
tblStringsTotalG++;
tblStringLenTotalG += (**tblTHndl).fieldName.octetLen;
}
(**tblTHndl).optional =
((e->type->optional) || (e->type->defaultVal != NULL));
}
break;
case BASICTYPE_LOCALTYPEREF:
case BASICTYPE_IMPORTTYPEREF:
tblT->typeId = TBL_TYPEREF;
tblT->content->choiceId = TBLTYPECONTENT_TYPEREF;
tblT->content->a.typeRef = MT (TBLTypeRef);
tblT->content->a.typeRef->implicit = t->implicit;
tblT->content->a.typeRef->typeDef =
t->basicType->a.localTypeRef->link->tmpRefCount;
break;
default:
if (!abortTblTypeDefG)
fprintf (stderr,"WARNING: Type definition \"%s\" will not be included in the type table because it contains a weird type.\n",td->definedName);
abortTblTypeDefG = TRUE;
Free (tblT->content);
Free (tblT);
tblT = NULL;
break;
}
if (t->subtypes)
{
switch (GetTblBasicType(t->basicType))
{
case BASICTYPE_INTEGER:
tblT->constraint = GenTblValueRange(tbl,m,tblMod,t->subtypes,0);
break;
case BASICTYPE_OCTETSTRING:
case BASICTYPE_SEQUENCEOF:
tblT->constraint = GenTblValueRange(tbl,m,tblMod,t->subtypes,1);
break;
default:
break;
}
}
if ((tblT != NULL) &&
((t->tags != NULL) && (!LIST_EMPTY (t->tags))))
{
tblT->tagList = AsnListNew (sizeof (void*));
FOR_EACH_LIST_ELMT (tag, t->tags)
{
tblTagsTotalG++;
tblTagHndl = AsnListAppend (tblT->tagList);
*tblTagHndl = MT (TBLTag);
switch (tag->tclass)
{
case UNIV:
(**tblTagHndl).tclass = UNIVERSAL;
break;
case APPL:
(**tblTagHndl).tclass = APPLICATION;
break;
case CNTX:
(**tblTagHndl).tclass = CONTEXT;
break;
case PRIV:
(**tblTagHndl).tclass = PRIVATE;
break;
}
(**tblTagHndl).code = tag->code;
}
}
return tblT;
}