]>
git.saurik.com Git - apple/security.git/blob - SecuritySNACCRuntime/compiler/core/normalize.c 
   2   * compiler/core/normalize.c    4   * 1. swap COMPONENTS OF for actual types    5   *     - do this since save lots of special case handling in    8   * 2. change SEQUENCE OF/SET OF (type def (not ref))    9   *    to     SEQUENCE OF/SEQ OF (type ref)   10   *           and add type def for orig.   11   *     - do this since OF type are AsnList   13   * 3. change CHOICE defs within other constructed types   15   *        - makes code production easier. can be changed   18   * 4. change SEQUENCE/SET defs within other constructed types   19   *      into SEQUENCE/SET refs   20   *        - makes code production easier. can be changed   21   *          with some work (allocation in decode is wrong   22   *                          - isPtr set incorrectly)   24   * 5. change SELECTION types to the actual field from the choice   26   * 6. convert Linked oid's with value refs into a ENC_OID's   27   *    so values can be easily defined in C/C++. MS 92/03/01   29   * 7. if IMPLICIT-TAGS is specified, mark type references   30   *    as implicit, if the ref'd type is not CHOICE or ANY.   31   *    (Extra tags on primitives (ie not references) are already   32   *     removed in the parsing step (asn1.yacc)).   34   * 8.  SET OF/SEQ OF defs nested in other SETs/SEQ/CHOICEs/SET OF/SEQ OF   35   *     types are moved to separate type defs - added 08/92 to support   36   *     C++ lists more easily.   38   * 9.  INTEGERs with named elmts and ENUM defs nested in other   39   * SETs/SEQ/CHOICEs/SET OF/SEQ OF types are moved to separate type   40   * defs - added 08/92 to support C++ class hierarchy better.   42   * ******** 10 is no longer done - in fact it was stupid for ******   43   * ******** ANY DEFINED BY types                MS 09/92     ******   44   * 10.  Move ANY and ANY DEFINED BY type defs nested in SET/SEQ/CHOICE/SET OF   45   * /SEQ OF to a separate definition - this should make fixing the   46   * produced code simpler.   51   * Copyright (C) 1991, 1992 Michael Sample   52   *            and the University of British Columbia   54   * This program is free software; you can redistribute it and/or modify   55   * it under the terms of the GNU General Public License as published by   56   * the Free Software Foundation; either version 2 of the License, or   57   * (at your option) any later version.   59   * $Header: /cvs/Darwin/Security/SecuritySNACCRuntime/compiler/core/normalize.c,v 1.1 2001/06/20 21:27:58 dmitch Exp $   60   * $Log: normalize.c,v $   61   * Revision 1.1  2001/06/20 21:27:58  dmitch   62   * Adding missing snacc compiler files.   64   * Revision 1.1.1.1  1999/03/16 18:06:50  aram   65   * Originals from SMIME Free Library.   67   * Revision 1.3  1995/07/25 19:41:40  rj   68   * changed `_' to `-' in file names.   70   * Revision 1.2  1994/09/01  00:40:56  rj   71   * snacc_config.h removed.   73   * Revision 1.1  1994/08/28  09:49:23  rj   74   * first check-in. for a list of changes to the snacc-1.1 distribution please refer to the ChangeLog.   82  #include  "asn1module.h"   84  #include  "lib-types.h"   85  #include  "snacc-util.h"   86  #include  "normalize.h"   88  #define LIST_ELMT_SUFFIX  "ListElmt"   89  #define CHOICE_SUFFIX  "Choice"   90  #define SET_SUFFIX  "Set"   91  #define SEQ_SUFFIX  "Seq"   92  #define SETOF_SUFFIX  "SetOf"   93  #define SEQOF_SUFFIX  "SeqOf"   94  #define INT_SUFFIX  "Int"   95  #define ENUM_SUFFIX  "Enum"   96  #define BITS_SUFFIX  "Bits"   97  #define ANY_SUFFIX  "Any"   99  long int  oidRecursionCountG 
=  0 ;  101  void  NormalizeTypeDef 
PROTO  (( Module 
* m
,  TypeDef 
* td
));  103  void  NormalizeType 
PROTO  (( Module 
* m
,  TypeDef 
* td
,  Type 
* parent
,  NamedTypeList 
* e
,  Type 
* t
));  105  void  NormalizeElmtTypes 
PROTO  (( Module 
* m
,  TypeDef 
* td
,  Type 
* parent
,  NamedTypeList 
* e
));  107  void  NormalizeBasicType 
PROTO  (( Module  
* m
,  TypeDef 
* td
,  Type 
* parent
,  NamedTypeList 
* e
,  Type 
* type
,  BasicType 
* bt
));  109  TypeDef 
* AddListElmtTypeDef 
PROTO  (( Module 
* m
,  TypeDef 
* td
,  Type 
* t
,  BasicType 
* bt
));  111  TypeDef 
* AddConsTypeDef 
PROTO  (( Module 
* m
,  TypeDef 
* td
,  Type 
* t
,  BasicType 
* bt
,  char  * suffix
));  113  void  NormalizeValueDef 
PROTO  (( Module 
* m
,  ValueDef 
* vd
));  115  int   FlattenLinkedOid 
PROTO  (( OID 
* o
,  char  * asn1FileName
,  AsnInt lineNo
,  int  quiet
));  118   * looks through the given module and performs the operations  122  NormalizeModule 
PARAMS  (( m
),  129       * go through each type in typeList  131      FOR_EACH_LIST_ELMT  ( td
,  m
-> typeDefs
)  133          NormalizeTypeDef  ( m
,  td
);  137       *  go through each value for types?  139      FOR_EACH_LIST_ELMT  ( vd
,  m
-> valueDefs
)  141          NormalizeValueDef  ( m
,  vd
);  144  }    /* NormalizeModule */  148  NormalizeTypeDef 
PARAMS  (( m
,  td
),  155      NormalizeType  ( m
,  td
,  NULL
,  NULL
,  td
-> type
);  157  }  /* NormalizeTypeDef */  161  NormalizeType 
PARAMS  (( m
,  td
,  parent
,  e
,  t
),  165   NamedTypeList 
* e _AND_
 168      enum  BasicTypeChoiceId typeId
;  175      NormalizeBasicType  ( m
,  td
,  parent
,  e
,   t
,  t
-> basicType
);  178       * make type refs implicit if IMPLICIT-TAGS specified and  179       * ref'd type is OK for implicit tagging.  180       * Tag removal work is done in parsing (yacc).  182      if  (( m
-> tagDefault 
==  IMPLICIT_TAGS
))  184          tmpType 
=  ParanoidGetType  ( t
);  185          typeId 
=  tmpType
-> basicType
-> choiceId
;  187          if  (( t
-> tags 
!=  NULL
) && (! LIST_EMPTY  ( t
-> tags
)))  188              lastTag 
= ( Tag
*) LAST_LIST_ELMT  ( t
-> tags
);  193           * only mark as implicit if  194           *  1. This type has a tag in it's taglist  195           *  2. This type is a reference to another type  196           *  3. the referenced type is not an untagged CHOICE, ANY or  197           *     ANY DEFINED BY (just need to check that it has  198           *     tags since all other types have tags)  200          if  ((( lastTag 
!=  NULL
) && !( lastTag
-> explicit )) &&  201              (( t
-> basicType
-> choiceId 
==  BASICTYPE_LOCALTYPEREF
) ||  202               ( t
-> basicType
-> choiceId 
==  BASICTYPE_IMPORTTYPEREF
)) &&  203              ( CountTags  ( t
-> basicType
-> a
. localTypeRef
-> link
-> type
) !=  0 ))  209  }  /* NormalizeType */  214  NormalizeElmtTypes 
PARAMS  (( m
,  td
,  parent
,  e
),  222      FOR_EACH_LIST_ELMT  ( nt
,  e
)  224          NormalizeType  ( m
,  td
,  parent
,  e
,  nt
-> type
);  226  }   /* NormalizeElmtTypes */  230   * this is where most of the action happens  231   * assumes that "e"'s curr ptr is namedtype that holds "type"  234  NormalizeBasicType 
PARAMS  (( m
,  td
,  parent
,  e
,  type
,  bt
),  238      NamedTypeList 
* e _AND_
 242      int  i
,  numElmtsAdded
;  244      NamedType 
** newElmtHndl
;  246      NamedTypeList 
* elmts
;  251      BasicType 
* tmpBasicType
;  259      switch  ( bt
-> choiceId
)  262          case  BASICTYPE_COMPONENTSOF
:  264               * copy elmts of COMPONENTS OF type into this type  268                  PrintErrLoc  ( m
-> asn1SrcFileName
,  type
-> lineNo
);  269                  fprintf  ( stderr
, "ERROR - COMPONENTS OF must be a SET or SEQUENCE element \n " );  270                  m
-> status 
=  MOD_ERROR
;  274          compType 
=  ParanoidGetType  ( bt
-> a
. componentsOf
);  275          parentType 
=  ParanoidGetType  ( parent
);  277          /* COMPONENTS OF must be nested in a SET or SEQUENCE type */  278          if  (( parentType
-> basicType
-> choiceId 
!=  BASICTYPE_SET
) &&  279              ( parentType
-> basicType
-> choiceId 
!=  BASICTYPE_SEQUENCE
))  281              PrintErrLoc  ( m
-> asn1SrcFileName
,  type
-> lineNo
);  282              fprintf  ( stderr
, "ERROR - COMPONENTS OF must be a SET or SEQUENCE element \n " );  283              m
-> status 
=  MOD_ERROR
;  287              /* COMPONENTS OF in a SET must ref a SET and vice versa for SEQ */  288              if  ((( parentType
-> basicType
-> choiceId 
==  BASICTYPE_SET
) &&  289                   ( compType
-> basicType
-> choiceId 
!=  BASICTYPE_SET
)) ||  290                  (( parentType
-> basicType
-> choiceId 
==  BASICTYPE_SEQUENCE
) &&  291                  ( compType
-> basicType
-> choiceId 
!=  BASICTYPE_SEQUENCE
)))  293                  PrintErrLoc  ( m
-> asn1SrcFileName
,  type
-> lineNo
);  294                  fprintf  ( stderr
, "ERROR - COMPONENTS OF in a SET must reference a SET type and  COMPONENTS OF in SEQUENCE must reference a SEQUENCE type \n " );  295                  type
-> basicType 
=  compType
-> basicType
;  296                  m
-> status 
=  MOD_ERROR
;  301               * replace "COMPONENTS OF" with elmts from ref'd set  303              elmts 
=  compType
-> basicType
-> a
. set
;  309               * add new list elmts that  point to elmts  310               * of type ref'd by COMPONENTS OF  312              FOR_EACH_LIST_ELMT  ( nt
,  elmts
)  314                  newElmtHndl 
= ( NamedType
**) AsnListAdd  ( e
);  319               * Set e list's curr  ptr to first of of the  320               * newly added components.  321               * Do this so NormalizeElmtTypes will do the  322               * newly added ones as well  324              numElmtsAdded 
=  AsnListCount  ( elmts
);  325              for  ( i 
=  0 ;  i 
<  numElmtsAdded
;  i
++)  328              /* remove the componets of ref since elmts copied in */  334          case  BASICTYPE_SELECTION
:  336               * first normalize the CHOICE that is selected from  337               * - this will be done twice to the CHOICE but nothing  338               * bad should happen.  The main reason for 'normalizing'  339               * the CHOICE first is to strip tags from the choice elmts  340               * if IMPLICIT-TAGS is set.  341               * NOTE: this call assumes that import/local type refs  342               * both use the 'TypeRef' struct and that a selection references  343               * a CHOICE by name (not definition)  345              NormalizeType  ( m
,  type
-> basicType
-> a
. selection
-> typeRef
-> basicType
-> a
. localTypeRef
-> link
,  NULL
,  NULL
,  type
-> basicType
-> a
. selection
-> typeRef
-> basicType
-> a
. localTypeRef
-> link
-> type
);  348               * use SELECTION field name if this is an elmt type with no  352                  ((( NamedType
*)  e
-> curr
-> data
)-> fieldName 
==  NULL
))  353                  (( NamedType
*)  e
-> curr
-> data
)-> fieldName 
=  354                      type
-> basicType
-> a
. selection
-> link
-> fieldName
;  357               * replace SELECTION type with refd type.  358               * must append the named CHOICE field's tags to  359               * any existing tags on this SELECTION type.  361              tmpBasicType 
=   type
-> basicType
-> a
. selection
-> link
-> type
-> basicType
;  362              tags 
=  type
-> basicType
-> a
. selection
-> link
-> type
-> tags
;  365              FOR_EACH_LIST_ELMT  ( tag
,  tags
)  367                  if  (!((( m
-> tagDefault 
==  IMPLICIT_TAGS
) || ( type
-> implicit
)) &&  368                      ( tag 
== ( Tag
*) FIRST_LIST_ELMT  ( tags
))))  370                      tagHndl 
= ( Tag
**)  AsnListAppend  ( type
-> tags
);  373                  type
-> implicit 
=  FALSE
;  376              if  ( type
-> basicType
-> a
. selection
-> link
-> type
-> implicit
)  377                  type
-> implicit 
=  TRUE
;  379              Free  ( type
-> basicType
-> a
. selection
-> fieldName
);  380              Free  ( type
-> basicType
-> a
. selection
-> typeRef
-> basicType
);  381              Free  ( type
-> basicType
-> a
. selection
-> typeRef
);  382              type
-> basicType 
=  tmpBasicType
;  388          case  BASICTYPE_SEQUENCEOF
:  389          case  BASICTYPE_SETOF
:  390              /* convert def inside other type into a ref */  391              if  ( td
-> type 
!=  type
)  393                  if  ( bt
-> choiceId 
==  BASICTYPE_SETOF
)  394                      newDef 
=  AddConsTypeDef  ( m
,  td
,  type
,  bt
,  SETOF_SUFFIX
);  396                      newDef 
=  AddConsTypeDef  ( m
,  td
,  type
,  bt
,  SEQOF_SUFFIX
);  398                  NormalizeType  ( m
,  newDef
,  NULL
,  NULL
,  newDef
-> type
);  401                  NormalizeType  ( m
,  td
,  type
,  NULL
,  type
-> basicType
-> a
. setOf
);  404              /*  NOT NEEDED ANY MORE  405               * convert typdef after SET OF/SEQ OF to type REFS  406              switch (bt->a.setOf->basicType->choiceId)  408                  case BASICTYPE_SEQUENCE:  410                  case BASICTYPE_CHOICE:  411                  case BASICTYPE_SEQUENCEOF:  412                  case BASICTYPE_SETOF:  413                  case BASICTYPE_COMPONENTSOF:  414                      newDef = AddListElmtTypeDef (m, td, type, bt);  415                      NormalizeType (m, newDef, NULL, NULL, newDef->type);  419                      NormalizeType (m, td, NULL, NULL, bt->a.setOf);  426          case  BASICTYPE_CHOICE
:  428               * change CHOICE defs embedded in other types  431              if  ( td
-> type 
!=  type
)  433                  newDef 
=  AddConsTypeDef  ( m
,  td
,  type
,  bt
,  CHOICE_SUFFIX
);  434                  NormalizeType  ( m
,  newDef
,  NULL
,  NULL
,  newDef
-> type
);  437                  NormalizeElmtTypes  ( m
,  td
,  type
,  bt
-> a
. set
);  442          case  BASICTYPE_SEQUENCE
:  444               * change SEQ defs embedded in other types  447              if  ( td
-> type 
!=  type
)  449                  newDef 
=  AddConsTypeDef  ( m
,  td
,  type
,  bt
,  SEQ_SUFFIX
);  450                  NormalizeType  ( m
,  newDef
,  NULL
,  NULL
,  newDef
-> type
);  453                  NormalizeElmtTypes  ( m
,  td
,  type
,  bt
-> a
. sequence
);  459               * change SET defs embedded in other types  462              if  ( td
-> type 
!=  type
)  464                  newDef 
=  AddConsTypeDef  ( m
,  td
,  type
,  bt
,  SET_SUFFIX
);  465                  NormalizeType  ( m
,  newDef
,  NULL
,  NULL
,  newDef
-> type
);  468                  NormalizeElmtTypes  ( m
,  td
,  type
,  bt
-> a
. set
);  472          case  BASICTYPE_INTEGER
:  473              /* if they have named elements convert this def into a ref */  474              if  (( td
-> type 
!=  type
) && ( bt
-> a
. integer 
!=   NULL
) &&  475                  (! LIST_EMPTY  ( bt
-> a
. integer
)))  477                  newDef 
=  AddConsTypeDef  ( m
,  td
,  type
,  bt
,  INT_SUFFIX
);  481          case  BASICTYPE_ENUMERATED
:  482              /* if they have named elements convert this def into a ref */  483              if  (( td
-> type 
!=  type
) && ( bt
-> a
. enumerated 
!=   NULL
) &&  484                  (! LIST_EMPTY  ( bt
-> a
. enumerated
)))  486                  newDef 
=  AddConsTypeDef  ( m
,  td
,  type
,  bt
,  ENUM_SUFFIX
);  490          case  BASICTYPE_BITSTRING
:  491              /* if they have named elements convert this def into a ref */  492              if  (( td
-> type 
!=  type
) && ( bt
-> a
. bitString 
!=   NULL
) &&  493                  (! LIST_EMPTY  ( bt
-> a
. bitString
)))  495                  newDef 
=  AddConsTypeDef  ( m
,  td
,  type
,  bt
,  BITS_SUFFIX
);  500          case  BASICTYPE_ANYDEFINEDBY
:  503               * change ANY defs embedded in other types  506              if (td->type != type)  507                  newDef = AddConsTypeDef (m, td, type, bt, ANY_SUFFIX);  512            /* the rest are not processed */  515  }   /* NormalizeBasicType */  521   * given a set of/seq of type t within typedef td, change the  522   * set of /seq of elmt type def  into a type ref and  523   * add a type def for the elmt at the top level.  526  AddListElmtTypeDef 
PARAMS  (( m
,  td
,  t
,  bt
),  533      TypeDef 
** typeDefHndl
;  540      newDef 
= ( TypeDef
*) Malloc  ( sizeof  ( TypeDef
));  541      newDef
-> exported 
=  FALSE
;  542      newDef
-> type 
=  bt
-> a
. setOf
;  544       * make name for new type  545       * Foo ::= SET OF SEQUENCE {...}  547       * FooListElmt ::=  SEQUENCE {...}  548       * Foo ::=  SET OF FooListElmt  550      newDef
-> definedName 
=  551          Malloc  ( strlen  ( td
-> definedName
) +  552                 strlen  ( LIST_ELMT_SUFFIX
) +  4 );  554      strcpy  ( newDef
-> definedName
,  td
-> definedName
);  555      strcat  ( newDef
-> definedName
,  LIST_ELMT_SUFFIX
);  556      end 
=  strlen  ( newDef
-> definedName
);  558      while  ( LookupType  ( m
-> typeDefs
,  newDef
-> definedName
) !=  NULL
)  560          newDef
-> definedName
[ end
] =  '\0' ;  561          AppendDigit  ( newDef
-> definedName
,  digit
++);  565       * now put new type at head of list  567      typeDefHndl 
= ( TypeDef
**) AsnListPrepend  ( m
-> typeDefs
);  568      * typeDefHndl 
=  newDef
;  573       * replace SET OF/SEQ OF body with type ref  575      bt
-> a
. setOf 
= ( Type
*) Malloc  ( sizeof  ( Type
));  576      bt
-> a
. setOf
-> optional 
=  FALSE
;  577      bt
-> a
. setOf
-> implicit 
=  FALSE
;  578      bt
-> a
. setOf
-> lineNo 
=  t
-> lineNo
;  579      bt
-> a
. setOf
-> basicType 
= ( BasicType
*) Malloc  ( sizeof  ( BasicType
));  580      bt
-> a
. setOf
-> basicType
-> choiceId 
=  BASICTYPE_LOCALTYPEREF
;  581      bt
-> a
. setOf
-> basicType
-> a
. localTypeRef 
= ( TypeRef
*) Malloc  ( sizeof  ( TypeRef
));  582      bt
-> a
. setOf
-> basicType
-> a
. localTypeRef
-> link 
=  newDef
;  583      bt
-> a
. setOf
-> basicType
-> a
. localTypeRef
-> typeName 
=  585      bt
-> a
. setOf
-> basicType
-> a
. localTypeRef
-> moduleName 
=  NULL
;  590  }  /* AddListElmtTypeDefs */  595   * given a CHOICE/SET/SEQ/etc type t within typedef td, make t into a ref  596   * to a new  top level typdef of the CHOICE/SET/SEQ  599  AddConsTypeDef 
PARAMS  (( m
,  td
,  t
,  bt
,  suffix
),  607      TypeDef 
** typeDefHndl
;  616      newDef 
= ( TypeDef
*) Malloc  ( sizeof  ( TypeDef
));  617      newDef
-> exported 
=  FALSE
;  618      newDef
-> recursive 
=  FALSE
;  619      newDef
-> localRefCount 
=  1 ;  620      newDef
-> type 
= ( Type
*) Malloc  ( sizeof  ( Type
));  621      newDef
-> type
-> optional 
=  FALSE
;  622      newDef
-> type
-> lineNo 
=  t
-> lineNo
;  623      newDef
-> type
-> basicType 
=  bt
;  626       * make name for new choice/SET/SEQ  627       * Foo ::= SEQUENCE { .., bar CHOICE { ...}, ..}  629       * FooChoice ::=  CHOICE { ...}  630       * Foo ::=  SEQUENCE { .., bar FooChoice, .. }  632      newDef
-> definedName 
=  633          Malloc  ( strlen  ( td
-> definedName
) +  634                 strlen  ( suffix
) +  4 );  636      strcpy  ( newDef
-> definedName
,  td
-> definedName
);  637      strcat  ( newDef
-> definedName
,  suffix
);  638      end 
=  strlen  ( newDef
-> definedName
);  641      /* keep name unique */  642      while  ( LookupType  ( m
-> typeDefs
,  newDef
-> definedName
) !=  NULL
)  644          newDef
-> definedName
[ end
] =  '\0' ;  645          AppendDigit  ( newDef
-> definedName
,  digit
++);  649       * now put new type at head of list  651      typeDefHndl 
= ( TypeDef
**) AsnListPrepend  ( m
-> typeDefs
);  652      * typeDefHndl 
=  newDef
;  655       * what to do with tags? Use default universal type on  656       * newly defined type and adjust (new) reference's tags  659       *  NOTE: may be simpler just to move all the tags to the  663      newDef
-> type
-> tags 
= ( TagList
*) AsnListNew  ( sizeof  ( void *));  664      if  ( LIBTYPE_GET_UNIV_TAG_CODE  (( newDef
-> type
-> basicType
-> choiceId
))  667           tmpPtr 
= ( Tag
**) AsnListAppend  ( newDef
-> type
-> tags
);  668           * tmpPtr 
= ( Tag
*) Malloc  ( sizeof  ( Tag
));  669           (* tmpPtr
)-> tclass 
=  UNIV
;  670           (* tmpPtr
)-> code 
=  LIBTYPE_GET_UNIV_TAG_CODE  (( newDef
-> type
-> basicType
-> choiceId
));  673      /* adjust tags of new ref to new def */  674      if  (( t
-> tags 
!=  NULL
) && (! LIST_EMPTY  ( t
-> tags
)))  676          lastTag 
= ( Tag
*) LAST_LIST_ELMT  ( t
-> tags
);  677          if  (( lastTag
-> tclass 
==  UNIV
) &&  679               LIBTYPE_GET_UNIV_TAG_CODE  (( newDef
-> type
-> basicType
-> choiceId
))))  681              /* zap it since same as default universal tag */  682              SET_CURR_LIST_NODE  ( t
-> tags
,  LAST_LIST_NODE  ( t
-> tags
));  683              AsnListRemove  ( t
-> tags
);  688              t
-> implicit 
=  TRUE
;  /* this will probably already be true */  694       * replace embeded CHOICE/SET/SEQ def with ref to newly defined type  696      t
-> basicType 
= ( BasicType
*) Malloc  ( sizeof  ( BasicType
));  697      t
-> basicType
-> choiceId 
=  BASICTYPE_LOCALTYPEREF
;  698      t
-> basicType
-> a
. localTypeRef 
= ( TypeRef
*) Malloc  ( sizeof  ( TypeRef
));  699      t
-> basicType
-> a
. localTypeRef
-> link 
=  newDef
;  700      t
-> basicType
-> a
. localTypeRef
-> typeName 
=  702      t
-> basicType
-> a
. localTypeRef
-> moduleName 
=  NULL
;  707  }  /* AddConsTypeDef */  711  NormalizeValueDef 
PARAMS  (( m
,  vd
),  715      NormalizeValue  ( m
,  vd
,  vd
-> value
,  FALSE
);  719  NormalizeValue 
PARAMS  (( m
,  vd
,  v
,  quiet
),  731       * convert linked oids into ENC_OID's  733      if  ( v
-> basicValue
-> choiceId 
==  BASICVALUE_LINKEDOID
)  735          if  (! FlattenLinkedOid  ( v
-> basicValue
-> a
. linkedOid
,  m
-> asn1SrcFileName
,  v
-> lineNo
,  quiet
))  737          eLen 
=  EncodedOidLen  ( v
-> basicValue
-> a
. linkedOid
);  739          eoid
-> octetLen 
=  eLen
;  740          eoid
-> octs 
= ( char *) Malloc  ( eLen
);  741          BuildEncodedOid  ( v
-> basicValue
-> a
. linkedOid
,  eoid
);  743          /* free linked  oid */  744          for  ( o 
=  v
-> basicValue
-> a
. linkedOid
;  o 
!=  NULL
; )  750          v
-> basicValue
-> choiceId 
=  BASICVALUE_OID
;  751          v
-> basicValue
-> a
. oid 
=  eoid
;  757   * replaces value refs with the value's number if poss  758   * returns TRUE if successfully done.  759   * returns FALSE if a value ref could not be traced  760   *  (false should not happen if the value link succeeded)  761   * "quiet" parameter allows err msg to be turned off  762   *  which prevents cascading errors by other oid's that  763   *  reference a bad oid.  766  FlattenLinkedOid 
PARAMS  (( o
,  asn1FileName
,  lineNo
,  quiet
),  768      char  * asn1FileName _AND_
 779      if  ( oidRecursionCountG 
>  100 )  781          PrintErrLoc  ( asn1FileName
,  lineNo
);  782          fprintf  ( stderr
, "ERROR - recursive OBJECT IDENTIFIER value. \n " );  788      for  (;  o 
!=  NULL
;  o 
=  o
-> next
)  790          valRef 
=  o
-> valueRef
;  791          if  (( valRef 
==  NULL
) || ( o
-> arcNum 
!=  NULL_OID_ARCNUM
))  792              continue ;  /* no linking nec for this one */  794          val 
=  GetValue  ( o
-> valueRef
);  797           * if the very first component is an oid val ref  798           * then insert that value  800          if  (( o 
==  firstElmt
) && ( val
-> basicValue
-> choiceId 
==  BASICVALUE_OID
))  802              UnbuildEncodedOid  ( val
-> basicValue
-> a
. oid
, & refdOid
);  803              for  ( tmpOid 
=  refdOid
;  tmpOid
-> next 
!=  NULL
;  tmpOid 
=  tmpOid
-> next
)  805              tmpOid
-> next 
=  o
-> next
;  806              memcpy  ( firstElmt
,  refdOid
,  sizeof  ( OID
));  807              Free  ( refdOid
);  /* free first component of OID since copied */  810          else if  (( o 
==  firstElmt
) && ( val
-> basicValue
-> choiceId 
==  BASICVALUE_LINKEDOID
))  812              oidRecursionCountG
++;  813              if  (! FlattenLinkedOid  ( val
-> basicValue
-> a
. linkedOid
,  asn1FileName
,  lineNo
,  TRUE
))  815                  oidRecursionCountG
--;  818              oidRecursionCountG
--;  821              for  ( tmpOid 
=  val
-> basicValue
-> a
. linkedOid
;  822                  tmpOid 
!=  NULL
;  tmpOid 
=  tmpOid
-> next
)  824                  * nextOid 
= ( OID
*) Malloc  ( sizeof  ( OID
));  825                  (* nextOid
)-> arcNum 
=  tmpOid
-> arcNum
;  826                  nextOid 
= &(* nextOid
)-> next
;  828              (* nextOid
) =  o
-> next
;  829              memcpy  ( firstElmt
,  refdOid
,  sizeof  ( OID
));  830              Free  ( refdOid
);  /* since copied into firstElmt */  833          else if  (( val
-> basicValue
-> choiceId 
==  BASICVALUE_INTEGER
))  835              o
-> arcNum 
=  val
-> basicValue
-> a
. integer
;  836              if  (( o
-> arcNum 
<  0 ) && ! quiet
)  838                  PrintErrLoc  ( asn1FileName
,  lineNo
);  839                  fprintf  ( stderr
, "ERROR - OBJECT IDENTIFIER arc values cannot be negative. \n " );  842          else  /* bad arc value type */  846                  PrintErrLoc  ( asn1FileName
,  lineNo
);  847                  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 " );  852          /* free mem assoc with value ref */  853          Free  ( valRef
-> basicValue
-> a
. localValueRef
-> valueName
);  854          Free  ( valRef
-> basicValue
-> a
. localValueRef
);  855          Free  ( valRef
-> basicValue
);  860  }  /* FlattenLinkedOid */