#include <stdio.h>
#include "asn-incl.h"
#include "mem.h"
#include "asn1module.h"
#include "oid.h"
#include "lib-types.h"
#include "snacc-util.h"
#include "normalize.h"
#define LIST_ELMT_SUFFIX "ListElmt"
#define CHOICE_SUFFIX "Choice"
#define SET_SUFFIX "Set"
#define SEQ_SUFFIX "Seq"
#define SETOF_SUFFIX "SetOf"
#define SEQOF_SUFFIX "SeqOf"
#define INT_SUFFIX "Int"
#define ENUM_SUFFIX "Enum"
#define BITS_SUFFIX "Bits"
#define ANY_SUFFIX "Any"
long int oidRecursionCountG = 0;
void NormalizeTypeDef PROTO ((Module *m, TypeDef *td));
void NormalizeType PROTO ((Module *m, TypeDef *td, Type *parent, NamedTypeList *e, Type *t));
void NormalizeElmtTypes PROTO ((Module *m, TypeDef *td, Type *parent, NamedTypeList *e));
void NormalizeBasicType PROTO ((Module *m, TypeDef *td, Type *parent, NamedTypeList *e, Type *type, BasicType *bt));
TypeDef *AddListElmtTypeDef PROTO ((Module *m, TypeDef *td, Type *t, BasicType *bt));
TypeDef *AddConsTypeDef PROTO ((Module *m, TypeDef *td, Type *t, BasicType *bt, char *suffix));
void NormalizeValueDef PROTO ((Module *m, ValueDef *vd));
int FlattenLinkedOid PROTO ((OID *o, char *asn1FileName, AsnInt lineNo, int quiet));
void
NormalizeModule PARAMS ((m),
Module *m)
{
TypeDef *td;
ValueDef *vd;
FOR_EACH_LIST_ELMT (td, m->typeDefs)
{
NormalizeTypeDef (m, td);
}
FOR_EACH_LIST_ELMT (vd, m->valueDefs)
{
NormalizeValueDef (m, vd);
}
}
void
NormalizeTypeDef PARAMS ((m, td),
Module *m _AND_
TypeDef *td)
{
if (td == NULL)
return;
NormalizeType (m, td, NULL, NULL, td->type);
}
void
NormalizeType PARAMS ((m, td, parent, e, t),
Module *m _AND_
TypeDef *td _AND_
Type *parent _AND_
NamedTypeList *e _AND_
Type *t)
{
enum BasicTypeChoiceId typeId;
Type *tmpType;
Tag *lastTag;
if (t == NULL)
return;
NormalizeBasicType (m, td, parent, e, t, t->basicType);
if ((m->tagDefault == IMPLICIT_TAGS))
{
tmpType = ParanoidGetType (t);
typeId = tmpType->basicType->choiceId;
if ((t->tags != NULL) && (!LIST_EMPTY (t->tags)))
lastTag = (Tag*)LAST_LIST_ELMT (t->tags);
else
lastTag = NULL;
if (((lastTag != NULL) && !(lastTag->explicit)) &&
((t->basicType->choiceId == BASICTYPE_LOCALTYPEREF) ||
(t->basicType->choiceId == BASICTYPE_IMPORTTYPEREF)) &&
(CountTags (t->basicType->a.localTypeRef->link->type) != 0))
{
t->implicit = TRUE;
}
}
}
void
NormalizeElmtTypes PARAMS ((m, td, parent, e),
Module *m _AND_
TypeDef *td _AND_
Type *parent _AND_
NamedTypeList *e)
{
NamedType *nt;
FOR_EACH_LIST_ELMT (nt, e)
{
NormalizeType (m, td, parent, e, nt->type);
}
}
void
NormalizeBasicType PARAMS ((m, td, parent, e, type, bt),
Module *m _AND_
TypeDef *td _AND_
Type *parent _AND_
NamedTypeList *e _AND_
Type *type _AND_
BasicType *bt)
{
int i, numElmtsAdded;
NamedType *newElmt;
NamedType **newElmtHndl;
NamedType *nt;
NamedTypeList *elmts;
NamedType *origNext;
Type *compType;
Type *parentType;
TypeDef *newDef;
BasicType *tmpBasicType;
TagList *tags;
Tag *tag;
Tag **tagHndl;
if (bt == NULL)
return;
switch (bt->choiceId)
{
case BASICTYPE_COMPONENTSOF:
if (parent == NULL)
{
PrintErrLoc (m->asn1SrcFileName, type->lineNo);
fprintf (stderr,"ERROR - COMPONENTS OF must be a SET or SEQUENCE element\n");
m->status = MOD_ERROR;
return;
}
compType = ParanoidGetType (bt->a.componentsOf);
parentType = ParanoidGetType (parent);
if ((parentType->basicType->choiceId != BASICTYPE_SET) &&
(parentType->basicType->choiceId != BASICTYPE_SEQUENCE))
{
PrintErrLoc (m->asn1SrcFileName, type->lineNo);
fprintf (stderr,"ERROR - COMPONENTS OF must be a SET or SEQUENCE element\n");
m->status = MOD_ERROR;
return;
}
if (((parentType->basicType->choiceId == BASICTYPE_SET) &&
(compType->basicType->choiceId != BASICTYPE_SET)) ||
((parentType->basicType->choiceId == BASICTYPE_SEQUENCE) &&
(compType->basicType->choiceId != BASICTYPE_SEQUENCE)))
{
PrintErrLoc (m->asn1SrcFileName, type->lineNo);
fprintf (stderr,"ERROR - COMPONENTS OF in a SET must reference a SET type and COMPONENTS OF in SEQUENCE must reference a SEQUENCE type\n");
type->basicType = compType->basicType;
m->status = MOD_ERROR;
return;
}
elmts = compType->basicType->a.set;
if (elmts == NULL)
break;
FOR_EACH_LIST_ELMT (nt, elmts)
{
newElmtHndl = (NamedType**)AsnListAdd (e);
*newElmtHndl = nt;
}
numElmtsAdded = AsnListCount (elmts);
for (i = 0; i < numElmtsAdded; i++)
AsnListPrev (e);
AsnListRemove (e);
break;
case BASICTYPE_SELECTION:
NormalizeType (m, type->basicType->a.selection->typeRef->basicType->a.localTypeRef->link, NULL, NULL, type->basicType->a.selection->typeRef->basicType->a.localTypeRef->link->type);
if ((e != NULL) &&
(((NamedType*) e->curr->data)->fieldName == NULL))
((NamedType*) e->curr->data)->fieldName =
type->basicType->a.selection->link->fieldName;
tmpBasicType = type->basicType->a.selection->link->type->basicType;
tags = type->basicType->a.selection->link->type->tags;
FOR_EACH_LIST_ELMT (tag, tags)
{
if (!(((m->tagDefault == IMPLICIT_TAGS) || (type->implicit)) &&
(tag == (Tag*)FIRST_LIST_ELMT (tags))))
{
tagHndl = (Tag**) AsnListAppend (type->tags);
*tagHndl = tag;
}
type->implicit = FALSE;
}
if (type->basicType->a.selection->link->type->implicit)
type->implicit = TRUE;
Free (type->basicType->a.selection->fieldName);
Free (type->basicType->a.selection->typeRef->basicType);
Free (type->basicType->a.selection->typeRef);
type->basicType = tmpBasicType;
break;
case BASICTYPE_SEQUENCEOF:
case BASICTYPE_SETOF:
if (td->type != type)
{
if (bt->choiceId == BASICTYPE_SETOF)
newDef = AddConsTypeDef (m, td, type, bt, SETOF_SUFFIX);
else
newDef = AddConsTypeDef (m, td, type, bt, SEQOF_SUFFIX);
NormalizeType (m, newDef, NULL, NULL, newDef->type);
}
else
NormalizeType (m, td, type, NULL, type->basicType->a.setOf);
break;
break;
case BASICTYPE_CHOICE:
if (td->type != type)
{
newDef = AddConsTypeDef (m, td, type, bt, CHOICE_SUFFIX);
NormalizeType (m, newDef, NULL, NULL, newDef->type);
}
else
NormalizeElmtTypes (m, td, type, bt->a.set);
break;
case BASICTYPE_SEQUENCE:
if (td->type != type)
{
newDef = AddConsTypeDef (m, td, type, bt, SEQ_SUFFIX);
NormalizeType (m, newDef, NULL, NULL, newDef->type);
}
else
NormalizeElmtTypes (m, td, type, bt->a.sequence);
break;
case BASICTYPE_SET:
if (td->type != type)
{
newDef = AddConsTypeDef (m, td, type, bt, SET_SUFFIX);
NormalizeType (m, newDef, NULL, NULL, newDef->type);
}
else
NormalizeElmtTypes (m, td, type, bt->a.set);
break;
case BASICTYPE_INTEGER:
if ((td->type != type) && (bt->a.integer != NULL) &&
(!LIST_EMPTY (bt->a.integer)))
{
newDef = AddConsTypeDef (m, td, type, bt, INT_SUFFIX);
}
break;
case BASICTYPE_ENUMERATED:
if ((td->type != type) && (bt->a.enumerated != NULL) &&
(!LIST_EMPTY (bt->a.enumerated)))
{
newDef = AddConsTypeDef (m, td, type, bt, ENUM_SUFFIX);
}
break;
case BASICTYPE_BITSTRING:
if ((td->type != type) && (bt->a.bitString != NULL) &&
(!LIST_EMPTY (bt->a.bitString)))
{
newDef = AddConsTypeDef (m, td, type, bt, BITS_SUFFIX);
}
break;
case BASICTYPE_ANY:
case BASICTYPE_ANYDEFINEDBY:
m->hasAnys = TRUE;
break;
default:
break;
}
}
TypeDef*
AddListElmtTypeDef PARAMS ((m, td, t, bt),
Module *m _AND_
TypeDef *td _AND_
Type *t _AND_
BasicType *bt)
{
TypeDef *newDef;
TypeDef **typeDefHndl;
int end;
int digit;
newDef = (TypeDef*)Malloc (sizeof (TypeDef));
newDef->exported = FALSE;
newDef->type = bt->a.setOf;
newDef->definedName =
Malloc (strlen (td->definedName) +
strlen (LIST_ELMT_SUFFIX) + 4);
strcpy (newDef->definedName, td->definedName);
strcat (newDef->definedName, LIST_ELMT_SUFFIX);
end = strlen (newDef->definedName);
digit = 1;
while (LookupType (m->typeDefs, newDef->definedName) != NULL)
{
newDef->definedName[end] = '\0';
AppendDigit (newDef->definedName, digit++);
}
typeDefHndl = (TypeDef**)AsnListPrepend (m->typeDefs);
*typeDefHndl = newDef;
bt->a.setOf = (Type*)Malloc (sizeof (Type));
bt->a.setOf->optional = FALSE;
bt->a.setOf->implicit = FALSE;
bt->a.setOf->lineNo = t->lineNo;
bt->a.setOf->basicType = (BasicType*)Malloc (sizeof (BasicType));
bt->a.setOf->basicType->choiceId = BASICTYPE_LOCALTYPEREF;
bt->a.setOf->basicType->a.localTypeRef = (TypeRef*)Malloc (sizeof (TypeRef));
bt->a.setOf->basicType->a.localTypeRef->link = newDef;
bt->a.setOf->basicType->a.localTypeRef->typeName =
newDef->definedName;
bt->a.setOf->basicType->a.localTypeRef->moduleName = NULL;
return newDef;
}
TypeDef*
AddConsTypeDef PARAMS ((m, td, t, bt, suffix),
Module *m _AND_
TypeDef *td _AND_
Type *t _AND_
BasicType *bt _AND_
char *suffix)
{
TypeDef *newDef;
TypeDef **typeDefHndl;
Tag **tmpPtr;
Tag *lastTag;
int end;
int digit;
newDef = (TypeDef*)Malloc (sizeof (TypeDef));
newDef->exported = FALSE;
newDef->recursive = FALSE;
newDef->localRefCount = 1;
newDef->type = (Type*)Malloc (sizeof (Type));
newDef->type->optional = FALSE;
newDef->type->lineNo = t->lineNo;
newDef->type->basicType = bt;
newDef->definedName =
Malloc (strlen (td->definedName) +
strlen (suffix) + 4);
strcpy (newDef->definedName, td->definedName);
strcat (newDef->definedName, suffix);
end = strlen (newDef->definedName);
digit = 1;
while (LookupType (m->typeDefs, newDef->definedName) != NULL)
{
newDef->definedName[end] = '\0';
AppendDigit (newDef->definedName, digit++);
}
typeDefHndl = (TypeDef**)AsnListPrepend (m->typeDefs);
*typeDefHndl = newDef;
newDef->type->tags = (TagList*)AsnListNew (sizeof (void*));
if (LIBTYPE_GET_UNIV_TAG_CODE ((newDef->type->basicType->choiceId))
!= NO_TAG_CODE)
{
tmpPtr = (Tag**)AsnListAppend (newDef->type->tags);
*tmpPtr = (Tag*)Malloc (sizeof (Tag));
(*tmpPtr)->tclass = UNIV;
(*tmpPtr)->code = LIBTYPE_GET_UNIV_TAG_CODE ((newDef->type->basicType->choiceId));
if ((t->tags != NULL) && (!LIST_EMPTY (t->tags)))
{
lastTag = (Tag*)LAST_LIST_ELMT (t->tags);
if ((lastTag->tclass == UNIV) &&
(lastTag->code ==
LIBTYPE_GET_UNIV_TAG_CODE ((newDef->type->basicType->choiceId))))
{
SET_CURR_LIST_NODE (t->tags, LAST_LIST_NODE (t->tags));
AsnListRemove (t->tags);
t->implicit = FALSE;
}
else
{
t->implicit = TRUE;
}
}
}
t->basicType = (BasicType*)Malloc (sizeof (BasicType));
t->basicType->choiceId = BASICTYPE_LOCALTYPEREF;
t->basicType->a.localTypeRef = (TypeRef*)Malloc (sizeof (TypeRef));
t->basicType->a.localTypeRef->link = newDef;
t->basicType->a.localTypeRef->typeName =
newDef->definedName;
t->basicType->a.localTypeRef->moduleName = NULL;
return newDef;
}
void
NormalizeValueDef PARAMS ((m, vd),
Module *m _AND_
ValueDef *vd)
{
NormalizeValue (m, vd, vd->value, FALSE);
}
void
NormalizeValue PARAMS ((m, vd, v, quiet),
Module *m _AND_
ValueDef *vd _AND_
Value *v _AND_
int quiet)
{
AsnOid *eoid;
OID *o;
OID *tmp;
int eLen;
if (v->basicValue->choiceId == BASICVALUE_LINKEDOID)
{
if (!FlattenLinkedOid (v->basicValue->a.linkedOid, m->asn1SrcFileName, v->lineNo, quiet))
return;
eLen = EncodedOidLen (v->basicValue->a.linkedOid);
eoid = MT (AsnOid);
eoid->octetLen = eLen;
eoid->octs = (char*)Malloc (eLen);
BuildEncodedOid (v->basicValue->a.linkedOid, eoid);
for (o = v->basicValue->a.linkedOid; o != NULL; )
{
tmp = o->next;
Free (o);
o = tmp;
}
v->basicValue->choiceId = BASICVALUE_OID;
v->basicValue->a.oid = eoid;
}
}
int
FlattenLinkedOid PARAMS ((o, asn1FileName, lineNo, quiet),
OID *o _AND_
char *asn1FileName _AND_
AsnInt lineNo _AND_
int quiet)
{
OID *firstElmt;
OID *refdOid;
OID *tmpOid;
OID **nextOid;
Value *val;
Value *valRef;
if (oidRecursionCountG > 100)
{
PrintErrLoc (asn1FileName, lineNo);
fprintf (stderr,"ERROR - recursive OBJECT IDENTIFIER value.\n");
return FALSE;
}
firstElmt = o;
for (; o != NULL; o = o->next)
{
valRef = o->valueRef;
if ((valRef == NULL) || (o->arcNum != NULL_OID_ARCNUM))
continue;
val = GetValue (o->valueRef);
if ((o == firstElmt) && (val->basicValue->choiceId == BASICVALUE_OID))
{
UnbuildEncodedOid (val->basicValue->a.oid, &refdOid);
for (tmpOid = refdOid; tmpOid->next != NULL; tmpOid = tmpOid->next)
;
tmpOid->next = o->next;
memcpy (firstElmt, refdOid, sizeof (OID));
Free (refdOid);
}
else if ((o == firstElmt) && (val->basicValue->choiceId == BASICVALUE_LINKEDOID))
{
oidRecursionCountG++;
if (!FlattenLinkedOid (val->basicValue->a.linkedOid, asn1FileName, lineNo, TRUE))
{
oidRecursionCountG--;
return FALSE;
}
oidRecursionCountG--;
nextOid = &refdOid;
for (tmpOid = val->basicValue->a.linkedOid;
tmpOid != NULL; tmpOid = tmpOid->next)
{
*nextOid = (OID*)Malloc (sizeof (OID));
(*nextOid)->arcNum = tmpOid->arcNum;
nextOid = &(*nextOid)->next;
}
(*nextOid) = o->next;
memcpy (firstElmt, refdOid, sizeof (OID));
Free (refdOid);
}
else if ((val->basicValue->choiceId == BASICVALUE_INTEGER))
{
o->arcNum = val->basicValue->a.integer;
if ((o->arcNum < 0) && !quiet)
{
PrintErrLoc (asn1FileName, lineNo);
fprintf (stderr,"ERROR - OBJECT IDENTIFIER arc values cannot be negative.\n");
}
}
else
{
if (!quiet)
{
PrintErrLoc (asn1FileName, lineNo);
fprintf (stderr,"ERROR - type mismatch for an arc value. Values ref'd from an OBJECT IDENTIFIER value must be either an OBJECT IDENTIFIER (first oid elmt only) or INTEGER value (this may be reported twice!)\n");
}
return FALSE;
}
Free (valRef->basicValue->a.localValueRef->valueName);
Free (valRef->basicValue->a.localValueRef);
Free (valRef->basicValue);
Free (valRef);
o->valueRef = NULL;
}
return TRUE;
}