[esnacc-dev] [RFC 2/2] ENOTREADY: Python backend

Aaron Conole aconole at bytheb.org
Tue Jan 10 22:15:29 UTC 2017


Here be dragons...

Signed-off-by: Aaron Conole <aconole at bytheb.org>

---
 compiler/automake.mk                 |    5 +
 compiler/back-ends/py-gen/gen-any.c  |  300 ++++
 compiler/back-ends/py-gen/gen-code.c | 2722 ++++++++++++++++++++++++++++++++++
 compiler/back-ends/py-gen/rules.c    |  569 +++++++
 compiler/back-ends/py-gen/rules.h    |   36 +
 compiler/back-ends/py-gen/types.c    |  529 +++++++
 compiler/back-ends/str-util.c        |   48 +-
 compiler/back-ends/str-util.h        |    1 +
 compiler/core/define.c               |    3 +-
 compiler/core/snacc.c                |  171 ++-
 10 files changed, 4341 insertions(+), 43 deletions(-)
 create mode 100644 compiler/back-ends/py-gen/gen-any.c
 create mode 100644 compiler/back-ends/py-gen/gen-code.c
 create mode 100644 compiler/back-ends/py-gen/rules.c
 create mode 100644 compiler/back-ends/py-gen/rules.h
 create mode 100644 compiler/back-ends/py-gen/types.c

diff --git a/compiler/automake.mk b/compiler/automake.mk
index 7a1f910..b46372f 100644
--- a/compiler/automake.mk
+++ b/compiler/automake.mk
@@ -70,6 +70,11 @@ compiler_esnacc_SOURCES = \
 	compiler/back-ends/idl-gen/gen-code.c \
 	compiler/back-ends/idl-gen/types.c \
 	compiler/back-ends/idl-gen/gen-vals.c \
+	compiler/back-ends/py-gen/gen-any.c \
+	compiler/back-ends/py-gen/gen-code.c \
+	compiler/back-ends/py-gen/rules.c \
+	compiler/back-ends/py-gen/rules.h \
+	compiler/back-ends/py-gen/types.c \
 	policy.h \
 	version.h
 
diff --git a/compiler/back-ends/py-gen/gen-any.c b/compiler/back-ends/py-gen/gen-any.c
new file mode 100644
index 0000000..5d1ce8e
--- /dev/null
+++ b/compiler/back-ends/py-gen/gen-any.c
@@ -0,0 +1,300 @@
+/*
+ * compiler/back-ends/py-gen/gen-any.c - routines for printing python
+ *                                       anytype code
+ *
+ * assumes that the type tree has already been run through the
+ * python type generator (py-gen/types.c).
+ *
+ * Copyright (C) 2016 Aaron Conole
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <string.h>
+#include "asn-incl.h"
+#include "asn1module.h"
+#include "str-util.h"
+#include "rules.h"
+#include "snacc-util.h"
+
+#ifdef WIN32
+#pragma  warning( disable : 4100 )  /* IGNORE unreferenced formal parameter */
+#endif
+
+
+void PrintPyAnyEnum PROTO ((FILE *hdr, Module *m));
+void PrintPyAnyHashInitRoutine PROTO ((FILE *src, FILE *hdr,
+									   Module *m, PyRules *r));
+void PrintPyOidValue PROTO ((FILE *f, PyRules *r, AsnOid *oid, int parenOrQuote));
+
+static TypeDef* GetTypeDef PROTO ((Type *t));
+
+
+extern int anyEnumValG;
+
+
+void
+PrintPyAnyCode PARAMS ((src, hdr, r, mods, m),
+    FILE *src _AND_
+    FILE *hdr _AND_
+    PyRules *r _AND_
+    ModuleList *mods _AND_
+    Module *m)
+{
+
+    if (!m->hasAnys)
+        return;
+
+    PrintPyAnyEnum(hdr, m);
+    PrintPyAnyHashInitRoutine(src, hdr, m, r);
+
+}  /* PrintAnyCode */
+
+
+
+void
+PrintPyAnyEnum PARAMS ((hdr, m),
+                       FILE *hdr _AND_
+                       Module *m)
+{
+    int firstPrinted = TRUE;
+    char *modName;
+	ValueDef *vd;
+	Type *t;
+    char anyId[512];
+
+    modName = Asn1TypeName2CTypeName (m->modId->name);
+
+    fprintf (hdr,"typedef enum %sAnyId\n", modName);
+    fprintf (hdr,"{\n");
+
+    FOR_EACH_LIST_ELMT (vd, m->valueDefs) {
+        if (vd->value != NULL) {
+            t = vd->value->type;
+            if ((GetBuiltinType(t) == BASICTYPE_MACROTYPE) &&
+                (t->basicType->a.macroType->choiceId == 
+                 MACROTYPE_SNMPOBJECTTYPE)) {
+                strcpy(anyId, vd->definedName);
+                Dash2Underscore(anyId, strlen (anyId));
+                strcat(anyId, "_ANY_ID");
+
+                if (!firstPrinted)
+                    fprintf (hdr,",\n");
+                fprintf (hdr,"    %s = %d", anyId, anyEnumValG);
+                anyEnumValG++;
+                firstPrinted = FALSE;
+            }
+        }
+    }
+
+    if (firstPrinted)
+        fprintf (hdr,"/* NO INTEGER or OBJECT IDENTIFIER to ANY type relationships were defined (via MACROs or other mechanism) */\n ??? \n");
+
+    fprintf (hdr,"\n} %sAnyId;\n\n\n", modName);
+    Free (modName);
+
+}  /* PrintAnyEnum */
+
+
+void
+PrintPyAnyHashInitRoutine PARAMS ((src, hdr, m, r),
+    FILE *src _AND_
+    FILE *hdr _AND_
+    Module *m _AND_
+    PyRules *r)
+{
+
+    TypeDef *td;
+    int i;
+    int installedSomeHashes=0;
+    struct CxxTDI *cxxtdi;
+    char *modName;
+/* REN -- 5/11/2001 */
+/*  AnyRef *ar;
+    AnyRefList *arl;
+    int j; */
+    enum BasicTypeChoiceId typeId;
+	ValueDef *vd;
+	Type *t;
+	BasicValue *bv;
+    char anyId[512];
+	char *typeName = NULL;
+/* REN -- end */
+
+    modName = Asn1TypeName2CTypeName (m->modId->name);
+
+    /* print Any class src file */
+    fprintf (src,"// this class will automatically intialize the any hash tbl\n");
+    fprintf (src,"class InitAny%s\n", modName);
+    fprintf (src,"{\n");
+    fprintf (src,"  public:\n");
+    fprintf (src,"    InitAny%s();\n", modName);
+    fprintf (src,"    /* Do not add a destructor to this class!  It could\n");
+    fprintf (src,"     * cause pre-mature destruction of the ANY tables.\n");
+    fprintf (src,"     * The ANY tables will be destroyed by the runtime library.\n");
+    fprintf (src,"     */\n");
+#if 0
+    fprintf (src,"    ~InitAny%s() { AsnAny::AsnAnyDestroyHashTbls(); }\n",modName);
+#endif
+    fprintf (src,"};\n\n");
+
+    fprintf (src,"static InitAny%s anyInitalizer;\n", modName);
+
+    /* print constructor method that build hash tbl to src file*/
+    fprintf (src,"InitAny%s::InitAny%s()\n", modName, modName);
+    fprintf (src,"{\n");
+
+	/* first print value for OID's */
+    i = 0;
+
+    FOR_EACH_LIST_ELMT (vd, m->valueDefs)
+    {
+        if (vd->value != NULL)
+		{
+			t = vd->value->type;
+			if ((GetBuiltinType(t) == BASICTYPE_MACROTYPE) &&
+				(t->basicType->a.macroType->choiceId == 
+				MACROTYPE_SNMPOBJECTTYPE))
+			{
+				bv = vd->value->basicValue;
+				if (bv != NULL)
+				{
+					installedSomeHashes = TRUE;
+					if (bv->choiceId == BASICVALUE_OID)
+					{
+	                    fprintf (src,"    %s oid%d", 
+							r->typeConvTbl[BASICTYPE_OID].className, i++);
+#if 0
+		                PrintPyOidValue(src, r, bv->a.oid, 1);
+#endif
+			            fprintf (src,";\n");
+					}
+				}
+            }
+        }
+    }
+    fprintf (src,"\n\n");
+
+    /* now print hash init calls */
+    i = 0;
+
+    FOR_EACH_LIST_ELMT (vd, m->valueDefs)
+    {
+        if (vd->value != NULL)
+		{
+			t = vd->value->type;
+			if ((GetBuiltinType(t) == BASICTYPE_MACROTYPE) &&
+				(t->basicType->a.macroType->choiceId ==
+				MACROTYPE_SNMPOBJECTTYPE))
+			{
+				bv = vd->value->basicValue;
+				if (bv != NULL)
+				{
+					strcpy (anyId, vd->definedName);
+				    Dash2Underscore (anyId, strlen (anyId));
+					strcat (anyId, "_ANY_ID");
+
+					installedSomeHashes = TRUE;
+					t = t->basicType->a.macroType->a.snmpObjectType->syntax;
+
+					/* If the syntax of this any is a basic type, get the
+					class name from the rules table. */
+					typeId = t->basicType->choiceId;
+					if (((typeId >= BASICTYPE_BOOLEAN) &&
+						(typeId <= BASICTYPE_SETOF)) ||
+						((typeId >= BASICTYPE_NUMERIC_STR) &&
+						(typeId <= BASICTYPE_T61_STR)))
+					{
+						typeName = r->typeConvTbl[typeId].className;
+					}
+					/* Else if the syntax of this any is either a locally
+					defined type or an imported type, get the class name from
+					the this type's ref info. */
+					else
+					{
+						td = GetTypeDef(t);
+						if (td != NULL)
+						{
+							cxxtdi = td->cxxTypeDefInfo;
+							typeName = cxxtdi->className;
+						}
+						else
+					        typeName = NULL;
+					}
+
+					if (typeName == NULL)
+						fprintf(src, "*** ERROR *** Unknown ANY\n\n");
+					else
+					{
+						if (bv->choiceId == BASICVALUE_OID)
+						{
+							fprintf (src,
+								"    AsnAny::InstallAnyByOid (oid%d, %s, new %s);\n",
+								i++, anyId, typeName);
+						}
+						else if (bv->choiceId == BASICVALUE_INTEGER)
+						{
+							fprintf (src,
+								"    AsnAny::InstallAnyByInt (%d, %s, new %s);\n",
+								bv->a.integer, anyId, typeName);
+						}
+					}
+				}
+            }
+        }
+    }
+/* REN -- end */
+
+    if (!installedSomeHashes)
+    {
+        fprintf (src,"    /* Since no INTEGER/OID to ANY type relations were defined\n");
+        fprintf (src,"     * (usually done via MACROs) you must manually do the code\n");
+        fprintf (src,"     * to fill the hash tbl.\n");
+        fprintf (src,"     * if the ids are INTEGER use the following:\n");
+        fprintf (src,"     * AsnAny::InstallAnyByInt (3, ??_ANY_ID, new <className>);\n");
+        fprintf (src,"     * if the ids are OBJECT IDENTIFIERs use the following:\n");
+        fprintf (src,"     * AsnAny::InstallAnyByOid (OidValue, ??_ANY_ID, new <className>);\n");
+        fprintf (src,"     * put the ??_ANY_IDs in the AnyId enum.\n\n");
+        fprintf (src,"     * For example if you have some thing like\n");
+        fprintf (src,"     * T1 ::= SEQUENCE { id INTEGER, ANY DEFINED BY id }\n");
+        fprintf (src,"     * and the id 1 maps to the type BOOLEAN use the following:\n");
+        fprintf (src,"     * AsnAny::InstallAnyByInt (1, SOMEBOOL_ANY_ID, new AsnBool);\n");
+        fprintf (src,"     */\n ???????\n");  /* generate compile error */
+    }
+
+
+    fprintf (src,"}  /* InitAny::InitAny */\n\n\n");
+/* RWC;4/23/01;#endif */
+
+/* RWC;4/23/01;    r;m;mods;hdr;src;  */ /*AVOIDS warning.*/
+}  /* PrintAnyHashInitRoutine */
+
+
+/* REN -- 5/11/2001 -- GetTypeDef() function added to return the type def info
+for the given type. */
+static TypeDef*
+GetTypeDef PARAMS ((t),
+    Type *t)
+{
+    if (t == NULL)
+		return NULL;
+
+	switch (t->basicType->choiceId)
+    {
+        case BASICTYPE_LOCALTYPEREF:
+        case BASICTYPE_IMPORTTYPEREF:
+			return t->basicType->a.localTypeRef->link;
+            break;
+
+        default:
+            return NULL;
+    }
+    /*fprintf (errFileG, "GetTypeDef: ERROR - cannot get type def for unlinked local/import type refs\n");
+    return NULL;*/
+
+}  /* GetTypeDef */
+/* REN -- end */
diff --git a/compiler/back-ends/py-gen/gen-code.c b/compiler/back-ends/py-gen/gen-code.c
new file mode 100644
index 0000000..d793f74
--- /dev/null
+++ b/compiler/back-ends/py-gen/gen-code.c
@@ -0,0 +1,2722 @@
+/*
+ * compiler/back-ends/py-gen/gen-code.c - routines for printing python
+ *                                        code from type trees
+ *
+ * assumes that the type tree has already been run through the
+ * python type generator (py-gen/types.c).
+ *
+ * Copyright (C) 2016 Aaron Conole
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include "snacc.h"
+
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+#  include <sys/time.h>
+# else
+#  include <time.h>
+# endif
+#endif
+
+#include <string.h>
+
+#include "asn-incl.h"
+#include "asn1module.h"
+#include "rules.h"
+#include "snacc-util.h"
+#include "print.h"
+#include "tag-util.h"  /* get GetTags/FreeTags/CountTags/TagByteLen */
+
+#if META
+#include "meta.h"
+#endif
+
+
+enum BasicTypeChoiceId ParanoidGetBuiltinType PARAMS ((t),Type *t);
+void PrintPyAnyCode PROTO ((FILE *src, FILE *hdr, PyRules *r,
+							ModuleList *mods, Module *m));
+void PrintPyValueDef PROTO ((FILE *src, PyRules *r, ValueDef *v));
+void PrintPyValueExtern PROTO ((FILE *hdr, PyRules *r, ValueDef *v));
+void PrintPySetTypeByCode(NamedType *defByNamedType, CxxTRI *cxxtri, FILE *src);
+void PrintPyEncodeContaining(Type *t, PyRules *r, FILE *src);
+void PrintPyPEREncodeContaining(Type *t, PyRules *r, FILE *src);
+void PrintPyPERDecodeContaining(Type *t, PyRules *r, FILE *src);
+void PrintPyDecodeContaining(Type *t, PyRules *r, FILE *src);
+static char *
+LookupNamespace PROTO ((Type *t, ModuleList *mods));
+static void PrintPySeqSetPrintFunction(FILE* src, FILE* hdr,
+                                       MyString className,
+                                       BasicType *pBasicType);
+static void PrintPyDefCode_PERSort(NamedType ***pppElementNamedType,
+                                   int **ppElementTag,
+                                   AsnList *pElementList);
+static void PrintPyDefCode_SetSeqPEREncode(FILE *src, FILE *hdr, PyRules *r,
+                                           TypeDef *td,
+                                           NamedType **pSetElementNamedType,
+                                           int iElementCount);
+static void PrintPyDefCode_SetSeqPERDecode(FILE *src, FILE *hdr,
+                                           PyRules *r, TypeDef *td,
+                                           NamedType **pSetElementNamedType,
+                                           int iElementCount);
+
+
+/* flag to see if constraints were present */
+static int constraints_flag;
+static long lconstraintvar=0;
+
+extern char *bVDAGlobalDLLExport;
+extern int gNO_NAMESPACE;
+extern const char *gAlternateNamespaceString;
+extern int genPERCode;
+//extern short ImportedFilesG;
+
+static const char bufTypeNameG[] = "asn_buffer.AsnBuf";
+static const char lenTypeNameG[] = "AsnLen";
+static const char tagTypeNameG[] = "AsnTag";
+static const char baseClassesG[] = "(asn_base.AsnBase)";
+
+static int printTypesG;
+static int printEncodersG;
+static int printDecodersG;
+static int printPrintersG;
+static int printFreeG;
+
+// normalizeValue
+// 
+// strip whitespace and { } from valueNation values.
+//
+static void
+normalizeValue(char **normalized, char *input)
+{
+   int i;
+   while(*input == ' ' || *input == '{' )
+      input++;
+
+   *normalized = strdup(input);
+   
+   i = strlen(*normalized) - 1;
+   while ( (*normalized)[i] == ' ' || (*normalized)[i] == '}' )
+   {
+      (*normalized)[i] = 0;
+      i--;
+   }
+}
+
+static char *GetImportFileName (char *Impname, ModuleList *mods)
+{
+    Module *currMod;
+    char *fileName = NULL;
+    FOR_EACH_LIST_ELMT (currMod, mods) {
+        /* Find the import Module in the Modules and
+         * return the header file name
+         */
+        if ((strcmp(Impname, currMod->modId->name) == 0)) {
+            /* Set the file name and break */
+            fileName = currMod->cxxHdrFileName;
+            break;
+        }
+    }
+    return fileName;
+}
+
+static Module *GetImportModuleRef (char *Impname, ModuleList *mods)
+{
+    Module *currMod=NULL;
+    FOR_EACH_LIST_ELMT (currMod, mods) {
+        /* Find the import Module in the Modules and
+         * return the header file name
+         */
+        if ((strcmp(Impname, currMod->modId->name) == 0)) {
+            break;
+        }
+    }
+    return currMod;
+}
+
+static void
+PrintSimpleMeta(FILE *hdr, char *className,int exportMember)
+{
+
+}
+
+static void
+PrintSimpleCheck(FILE *hdr, FILE* src, char *className, int exportMember)
+{
+	fprintf(src, "int %s::checkConstraints(ConstraintFailList* pConstraintFails) const\n{\n",
+		className);
+	fprintf(src, "\treturn checkListConstraints(pConstraintFails);\n");
+	fprintf(src, "}\n");
+}
+
+static void
+PrintSrcComment PARAMS ((src, m),
+    FILE *src _AND_
+    Module *m)
+{
+    time_t now = time (NULL);
+
+    fprintf (src, "# %s - class definitions for ASN.1 module %s\n",
+             m->cxxSrcFileName, m->modId->name);
+    fprintf (src, "#\n");
+    fprintf (src, "#   This file was generated by esnacc on %s\n",
+             ctime(&now));
+    fprintf (src, "#   NOTE: this is a machine generated file-"
+             "-editing not recommended\n");
+    fprintf (src, "\n");
+
+} /* PrintSrcComment */
+
+
+static void
+PrintSrcIncludes PARAMS ((src), FILE *src)
+{
+    fprintf(src, "from esnacc import asn_base\n");
+    fprintf(src, "from esnacc import asn_bool\n");
+    fprintf(src, "from esnacc import asn_buffer\n");
+    fprintf(src, "from esnacc import asn_ints\n");
+    fprintf(src, "from esnacc import asn_list\n");
+    fprintf(src, "from esnacc import asn_octs\n");
+    fprintf(src, "from esnacc import asn_useful\n");
+    fprintf(src, "\n");
+} /* PrintSrcIncludes */
+
+
+static void
+PrintTypeDecl PARAMS ((f, td),
+    FILE *f _AND_
+    TypeDef *td)
+{
+    switch (td->type->basicType->choiceId)
+    {   
+        case BASICTYPE_COMPONENTSOF:
+        case BASICTYPE_SELECTION:
+        case BASICTYPE_UNKNOWN:
+        case BASICTYPE_MACRODEF:
+        case BASICTYPE_MACROTYPE:
+            return; /* do nothing */
+
+        default:
+            if (IsNewType (td->type))
+                fprintf(f, "class %s;\n", td->cxxTypeDefInfo->className);
+    }
+	
+} /* PrintTypeDecl */
+
+
+static void
+PrintPyType PARAMS ((hdr, mods, m, r, td, parent, t),
+    FILE *hdr _AND_
+    ModuleList *mods _AND_
+    Module *m _AND_
+    PyRules *r _AND_
+    TypeDef *td _AND_
+    Type *parent _AND_
+    Type *t)
+{
+    char *pszNamespace=NULL;
+    pszNamespace = LookupNamespace(t, mods);
+
+    if (pszNamespace) {
+        fprintf(hdr, "%s::%s       ",
+                pszNamespace, t->cxxTypeRefInfo->className);
+    } else {
+        fprintf(hdr, "%s       ", t->cxxTypeRefInfo->className);
+    }
+
+    if (t->cxxTypeRefInfo->isPtr)
+        fprintf (hdr, "*");
+
+} /* PrintPyType */
+
+
+
+/*
+ *  Uses the Constructor that takes no args.
+ *  Assumes file f is positioned inside a class definition.
+ *  All Classes get this to support the ANY type.
+ */
+static void
+PrintCloneMethod PARAMS ((hdr, src, td),
+    FILE *hdr _AND_
+    FILE *src _AND_
+    TypeDef *td)
+{
+//    fprintf (hdr, "  AsnType		*Clone() const;\n\n", td->cxxTypeDefInfo->className);
+//    fprintf (hdr, "  AsnType		*Clone() const;\n\n");
+    fprintf (src, "AsnType *%s::Clone() const\n", td->cxxTypeDefInfo->className);
+    fprintf (src, "{\n");
+    fprintf (src, "  return new %s(*this);\n", td->cxxTypeDefInfo->className);
+    fprintf (src, "}\n\n");
+
+} /* PrintCloneMethod */
+
+
+/*
+ * prints inline definition of constructors if this class is
+ * derived from a library class.
+ * assumes FILE *f is positioned in the derived class definition (.h)
+ *
+ * 12/92 MS - added overloaded "=" ops for string types.
+ */
+static void
+PrintDerivedConstructors PARAMS ((f, td),
+    FILE *f _AND_
+    TypeDef *td)
+{
+    char *baseClassName = td->type->cxxTypeRefInfo->className;
+    fprintf(f,
+            "    def __init__(self, value=None):\n"
+            "        %s.__init__(self,value)\n\n", baseClassName);
+} /* PrintDerivedConstructors */
+
+#if DEPRECATED
+static void
+PrintPyEocEncoders PARAMS ((src, td, t, bufVarName),
+    FILE *src _AND_
+    TypeDef *td _AND_
+    Type *t _AND_
+    char *bufVarName)
+{
+    TagList *tl;
+    Tag *tag;
+    int stoleChoiceTags;
+    
+    /* get all the tags on this type*/
+    tl = (TagList*) GetTags (t, &stoleChoiceTags);
+    FreeTags (tl);
+    bufVarName=bufVarName;td=td;  /*AVOIDS warning.*/
+
+} /* PrintPyEocEncoders */
+#endif
+
+static int
+HasShortLen PARAMS ((t),
+    Type *t)
+{
+    enum BasicTypeChoiceId typesType;
+    /*
+     * efficiency hack - use simple length (1 byte)
+     * encoded for type (almost) guaranteed to have
+     * encoded lengths of 0 <= len <= 127
+     */
+    typesType = GetBuiltinType (t);
+    /*RWC;8/9/01;REMOVED when INTEGER made AsnOcts;return typesType == BASICTYPE_BOOLEAN || typesType == BASICTYPE_INTEGER || typesType == BASICTYPE_NULL || typesType == BASICTYPE_REAL || typesType == BASICTYPE_ENUMERATED; */
+    return typesType == BASICTYPE_BOOLEAN || typesType == BASICTYPE_NULL || typesType == BASICTYPE_REAL || typesType == BASICTYPE_ENUMERATED;
+} /* HasShortLen */
+
+
+/*
+ * prints length encoding code.  Primitives always use
+ * definite length and constructors get "ConsLen"
+ * which can be configured at compile to to be indefinite
+ * or definite.  Primitives can also be "short" (isShort is true)
+ * in which case a fast macro is used to write the length.
+ * Types for which isShort apply are: boolean, null and
+ * (almost always) integer and reals
+ */
+static void
+PrintPyLenEncodingCode PARAMS ((f, lenVarName, bufVarName, classStr,
+                                formStr),
+                               FILE *f _AND_
+                               char *lenVarName _AND_
+                               char *bufVarName _AND_
+                               char *classStr _AND_
+                               char *formStr)
+{
+    fprintf(f, "        %s += asn_buffer.BEncDefLen(%s, %s)\n",
+            lenVarName, bufVarName, lenVarName);
+    fprintf(f, "        TAG_CODE = asn_base.BERConsts.MakeTag(asn_base.BERConsts.%s,\n"
+             "                                              self.%s,\n"
+             "                                              self.BER_CODE)\n",
+             classStr, formStr);
+}
+
+/* prints last tag's encoding code first */
+static void
+PrintPyTagAndLenList PARAMS ((src, tagList, lenVarName, bufVarName),
+    FILE *src _AND_
+    TagList *tagList _AND_
+    char *lenVarName _AND_
+    char *bufVarName)
+{
+    char *classStr;
+    char *formStr;
+    Tag *tg;
+    int tagLen;
+
+    if ((tagList == NULL) || LIST_EMPTY (tagList))
+        return;
+
+    /*
+     * since encoding backward encode tags backwards
+     */
+    FOR_EACH_LIST_ELMT_RVS (tg, tagList) {
+        classStr = Class2ClassStr (tg->tclass);
+
+        if (tg->form == CONS) {
+            formStr = Form2FormStr (CONS);
+        } else {
+            formStr = Form2FormStr (PRIM);
+        }
+        PrintPyLenEncodingCode (src, lenVarName, bufVarName,
+                                classStr, formStr);
+        fprintf (src, "\n");
+
+        if (tg->tclass == UNIV) {
+            const char* ptr = DetermineCode(tg, &tagLen, 0);
+            fprintf (src, "    %s += BEncTag%d (%s, %s, %s, %s);\n", lenVarName, tagLen, bufVarName, classStr, formStr, ptr);
+        } else {
+            const char* ptr = DetermineCode(tg, &tagLen, 1);
+            fprintf(src, "    %s += BEncTag%d(%s, %s, %s, %s);\n", lenVarName, tagLen, bufVarName, classStr, formStr, ptr);
+        }                                                       //RWC;tg->code);
+    }
+} /* PrintPyTagAndLenList */
+
+/*
+ *  Recursively walks through tags, printing lower lvl tags
+ *  first (since encoding is done backwards).
+ *
+ */
+static void
+PrintPyTagAndLenEncodingCode PARAMS ((src, t, lenVarName, bufVarName),
+    FILE *src _AND_
+    Type *t _AND_
+    char *lenVarName _AND_
+    char *bufVarName)
+{
+    TagList *tl;
+    int stoleChoiceTags;
+
+    /*
+     * get all the tags on this type
+     */
+    tl = (TagList*) GetTags(t, &stoleChoiceTags);
+
+    /*
+     * leave choice elmt tag enc to encoding routine
+     */
+    if (!stoleChoiceTags)
+        PrintPyTagAndLenList(src, tl, lenVarName, bufVarName);
+
+    FreeTags(tl);
+} /* PrintPyTagAndLenEncodingCode */
+
+
+/*
+ * used to figure out local variables to declare
+ * for decoding tags/len pairs on type t
+ */
+static int
+CxxCountVariableLevels PARAMS ((t),
+    Type *t)
+{
+    if (GetBuiltinType (t) == BASICTYPE_CHOICE)
+        return CountTags (t) +1; /* since must decode 1 internal tag type */
+    else
+        return CountTags (t);
+} /* CxxCountVariableLevels */
+
+
+/*
+ * returns true if elmts curr following
+ *  onward are all optional ow. false
+ */
+static int
+RestAreTailOptional PARAMS ((e),
+    NamedTypeList *e)
+{
+    NamedType *elmt;
+    void *tmp;
+    int retVal;
+
+    if (e == NULL)
+        return TRUE;
+
+    tmp = (void*)CURR_LIST_NODE (e);
+    retVal = TRUE;
+    AsnListNext (e);
+    FOR_REST_LIST_ELMT (elmt, e)
+    {
+        if ((!elmt->type->optional) && (elmt->type->defaultVal == NULL)&&(!elmt->type->extensionAddition))
+        {
+            retVal = FALSE;
+            break;
+        }
+    }
+    SET_CURR_LIST_NODE (e, tmp); /* reset list to orig loc */
+    return retVal;
+}
+
+
+/*
+ * prints typedef or new class given an ASN.1  type def of a primitive type
+ * or typeref.  Uses inheritance to cover re-tagging and named elmts.
+ */
+static void
+PrintPySimpleDef PARAMS ((hdr, src, r, td),
+                         FILE *hdr _AND_
+                         FILE *src _AND_
+                         PyRules *r _AND_
+                         TypeDef *td)
+{
+    Tag *tag;
+    TagList *tags;
+    char *formStr;
+    char *classStr;
+    int i;
+    CNamedElmt *n;
+    int stoleChoiceTags;
+    int elmtLevel;
+    enum BasicTypeChoiceId typeId;
+
+    if (IsNewType (td->type)) {
+        int	hasNamedElmts;
+
+        fprintf(src, "class %s(%s):\n",
+                td->cxxTypeDefInfo->className,
+                td->type->cxxTypeRefInfo->className);
+
+        /*
+         * must explicitly call constructors for base class
+         */
+        PrintDerivedConstructors (src, td);
+        if ((hasNamedElmts = HasNamedElmts (td->type)) != 0) {   
+            int count = 0;
+            fprintf(src, "    ENUMERATIONS = Enum(");
+            FOR_EACH_LIST_ELMT (n, td->type->cxxTypeRefInfo->namedElmts) {
+                fprintf(src, "%s = %d", n->name, n->value);
+                if (n != (CNamedElmt *)LAST_LIST_ELMT(
+                        td->type->cxxTypeRefInfo->namedElmts))
+                    fprintf (src, ",");
+                else
+                    fprintf (src, ")\n");
+                count++;
+            }
+        }
+
+        fprintf(src, "    def typename(self):\n");
+        fprintf(src, "        return \"%s\"\n\n",
+                td->cxxTypeDefInfo->className);
+        /*
+         * Re-do BerEncode, BerDeocode, BerDecodePdu and BerDecodePdu
+         * if this type has been re-tagged
+         */
+        if ((IsDefinedByLibraryType(td->type) && !HasDefaultTag(td->type))
+            || (IsTypeRef (td->type) && ((td->type->tags != NULL) 
+                                         && !LIST_EMPTY(td->type->tags)))) {
+
+            int tagLen = 0;
+            tags = GetTags (td->type, &stoleChoiceTags);
+            if (tags->count > 1) {
+                fprintf(src, "    # WARNING: only one tag added...\n");
+            }
+            tag = tags->first->data;
+            typeId = GetBuiltinType (td->type);
+            classStr = Class2ClassStr (tag->tclass);
+            formStr = Form2FormStr((tag->form == ANY_FORM) ? PRIM : tag->form);
+            fprintf(src, "    BER_FORM = asn_base.BERConsts.%s\n", formStr);
+            fprintf(src, "    BER_CLASS = asn_base.BERConsts.%s\n", classStr);
+            fflush(src);
+            if (!stoleChoiceTags) {
+                const char *ptr = DetermineCode(tag, &tagLen, (tag->tclass == UNIV) ? 0 : 1);
+                fprintf(src, "    BER_CODE = %s\n", ptr);
+            }
+            FreeTags (tags);
+            fprintf(src, "\n\n");
+        }
+    } else {
+
+
+		/* JKG 7/31/03 */
+		/* The following code enclosed in this if/else statement */
+		/* is constructed for constraint handling capability     */
+		/* for primitives found outside of                       */
+		/* sequences or sets                                     */
+
+        if (td->type->subtypes != NULL) {
+            switch (td->type->subtypes->choiceId) {
+            case SUBTYPE_AND:
+            case SUBTYPE_OR:
+            case SUBTYPE_SINGLE:
+                {   
+                    struct NamedType temp;
+                    NamedType* tmp = &temp;
+                    tmp->type=td->type;
+                    tmp->type->cxxTypeRefInfo->fieldName=td->definedName;
+                    tmp->fieldName=td->definedName;
+#if 0
+                    if (!PrintPyMultiConstraintOrHandler(hdr, src, NULL, tmp, 0))
+                        PrintTypeDefDefault(hdr, src, td);
+#endif
+                }
+                break;
+            default:
+#if 0
+                PrintTypeDefDefault(hdr, src, td);
+#endif
+                break;
+			}
+		} else {
+#if 0
+            PrintTypeDefDefault(hdr, src, td);
+#endif
+        }
+    }
+
+} /* PrintPySimpleDef */
+
+static void
+PrintPyChoiceDefCode (FILE *src, FILE *hdr, ModuleList *mods, Module *m, PyRules *r ,
+    TypeDef *td,Type *parent, Type *choice, int novolatilefuncs)
+{
+    NamedType *e;
+    char *classStr;
+    char *formStr;
+    char *codeStr;
+    int tagLen=0, i;
+    Tag *tag;
+    TagList *tags;
+    char *varName;
+    CxxTRI *cxxtri;
+    int elmtLevel=0;
+    int varCount, tmpVarCount;
+    int stoleChoiceTags;
+    enum BasicTypeChoiceId tmpTypeId;
+    NamedType *defByNamedType;
+    NamedType **ppElementNamedType;
+    int *pElementTag;
+    int ii;
+    char *ptr="";   /* NOT DLL Exported, or ignored on Unix. */
+    int extensionsExist = FALSE;
+
+    /* put class spec in hdr file */
+    
+    if (bVDAGlobalDLLExport != NULL) 
+       ptr = bVDAGlobalDLLExport;
+
+    fprintf(src, "class %s %s%s:\n", ptr, td->cxxTypeDefInfo->className, baseClassesG);
+    /* write out choiceId enum type */
+
+    FOR_EACH_LIST_ELMT (e, choice->basicType->a.choice) {
+        if(e->type->subtypes != NULL) {
+            switch(e->type->subtypes->choiceId) {   
+            case SUBTYPE_AND:
+            case SUBTYPE_OR:
+            case SUBTYPE_SINGLE:
+#if 0
+                PrintPyMultiConstraintOrHandler(hdr, src,
+                                                td->cxxTypeDefInfo->className,
+                                                e, 3);
+#endif
+            default:
+                break;
+            }
+        }
+    }
+
+    fprintf(src, "    CHOICES_%s = \\\n", r->choiceIdEnumName);
+    fprintf(src, "    {\\\n");
+    FOR_EACH_LIST_ELMT (e, choice->basicType->a.choice) {
+        fprintf(src, "    %s = %d",
+                e->type->cxxTypeRefInfo->choiceIdSymbol,
+                e->type->cxxTypeRefInfo->choiceIdValue);
+        if (e != (NamedType*)LAST_LIST_ELMT (choice->basicType->a.choice))
+            fprintf(src, ",\\\n");
+        else
+            fprintf(src, "\\\n");
+    }
+    fprintf (src, "    }\n");
+
+    /* write out the choice element anonymous union */
+    fprintf (src, "  union\n");
+    fprintf (src, "  {\n");
+    FOR_EACH_LIST_ELMT (e, choice->basicType->a.choice) {
+        fprintf (src, "  ");
+        PrintPyType(hdr, mods, m, r, td, choice, e->type);
+	    fprintf (src, "%s;\n\n", e->type->cxxTypeRefInfo->fieldName);
+    }
+    fprintf (src, "  };\n\n");
+
+
+    fprintf (src, "\n");
+
+    /* constructors and destructor */
+    fprintf (src, "   %s() {Init();}\n", td->cxxTypeDefInfo->className);
+
+    /* PIERCE 8-22-2001 */
+	PrintSimpleMeta(src,td->cxxTypeDefInfo->className,0);
+
+	/* Init() member function*/
+    fprintf (src, "void %s::Init(void)\n", td->cxxTypeDefInfo->className);
+    fprintf (src, "{\n");
+    fprintf (src, "   // initialize choice to no choiceId to first choice and set pointer to NULL\n");
+    e = FIRST_LIST_ELMT (choice->basicType->a.choice);
+    fprintf (src, "  choiceId = %sCid;\n", e->type->cxxTypeRefInfo->fieldName);
+    fprintf (src, "  %s = NULL;\n", e->type->cxxTypeRefInfo->fieldName);
+    fprintf (src, "}\n\n");
+	fprintf(src, "\nint %s::checkConstraints(ConstraintFailList* pConstraintFails) const\n{\n",
+		td->cxxTypeDefInfo->className);
+
+	FOR_EACH_LIST_ELMT (e, choice->basicType->a.choice)
+	{
+		if (e->type->cxxTypeRefInfo->isPtr)
+		{
+			fprintf(src, "\tif (%s != NULL)\n",
+				e->type->cxxTypeRefInfo->fieldName);
+			fprintf(src, "\t\t%s->checkConstraints(pConstraintFails);\n\n",
+				e->type->cxxTypeRefInfo->fieldName);
+		}
+		else
+		{
+			fprintf(src, "\t%s.checkConstraints(pConstraintFails);\n\n",
+				e->type->cxxTypeRefInfo->fieldName);
+		}
+	}
+	fprintf(src, "\treturn 0;\n");
+	fprintf(src, "}\n\n\n");
+
+    /* virtual destructor*/
+    fprintf (src, "void %s::Clear()\n", td->cxxTypeDefInfo->className);
+    fprintf (src, "{\n");
+    fprintf (src, "  switch (choiceId)\n");
+    fprintf (src, "  {\n");
+
+    FOR_EACH_LIST_ELMT (e, choice->basicType->a.choice)
+    {
+        tmpTypeId = GetBuiltinType (e->type);
+
+	    fprintf (src, "    case %s:\n", e->type->cxxTypeRefInfo->choiceIdSymbol);
+	    if (e->type->cxxTypeRefInfo->isPtr)
+       {
+	      fprintf (src, "      delete %s;\n", e->type->cxxTypeRefInfo->fieldName);
+          fprintf (src, "      %s = NULL;\n", e->type->cxxTypeRefInfo->fieldName);
+       }
+        else if(!e->type->cxxTypeRefInfo->isPtr && 
+            ((tmpTypeId == BASICTYPE_CHOICE) ||
+                (tmpTypeId == BASICTYPE_SET) ||
+                (tmpTypeId == BASICTYPE_SEQUENCE)) )
+        {
+            fprintf (src, "  %s.Clear();\n", e->type->cxxTypeRefInfo->fieldName);
+        }
+	    fprintf (src, "      break;\n");
+    }
+
+    fprintf (src, "  } // end of switch\n");
+    fprintf (src, "} // end of Clear()\n");
+    fprintf (src, "\n");
+
+    /* print clone routine for ANY mgmt */
+    PrintCloneMethod (hdr, src, td);
+
+    fprintf (src, "%s &%s::operator = (const %s &that)\n",
+             td->cxxTypeDefInfo->className,
+             td->cxxTypeDefInfo->className,
+             td->cxxTypeDefInfo->className);
+    fprintf (src, "{\n");
+    fprintf (src, "    if (this != &that) {\n");
+    fprintf (src, "        Clear();\n");
+   
+    e = FIRST_LIST_ELMT (choice->basicType->a.choice);
+    fprintf (src, "        if (that.%s != NULL) {\n",
+             e->type->cxxTypeRefInfo->fieldName);
+        fprintf (src, "            switch (choiceId = that.choiceId) {\n");
+
+    FOR_EACH_LIST_ELMT (e, choice->basicType->a.choice) {
+        fprintf (src, "                case %s:\n",
+                 e->type->cxxTypeRefInfo->choiceIdSymbol);
+        if (e->type->cxxTypeRefInfo->isPtr) {
+            fprintf (src, "                    %s = new %s(*that.%s);\n",
+                     e->type->cxxTypeRefInfo->fieldName,
+                     e->type->cxxTypeRefInfo->className,
+                     e->type->cxxTypeRefInfo->fieldName);
+        } else {
+            fprintf (src, "                    %s = that.%s;\n",
+                     e->type->cxxTypeRefInfo->fieldName,
+                     e->type->cxxTypeRefInfo->fieldName);
+        }
+        fprintf (src, "                break;\n");
+    }
+
+    fprintf (src, "            }\n");
+    fprintf (src, "        }\n");
+    fprintf (src, "    }\n");
+    fprintf (src, "\n");
+    fprintf (src, "    return *this;\n");
+    fprintf (src, "}\n\n");
+
+    /* BerEncodeContent */
+    if (printEncodersG)
+    {
+        //fprintf (hdr, "  %s		B%s (%s &_b) const;\n", lenTypeNameG, r->encodeContentBaseName, bufTypeNameG);
+
+        fprintf (src, "%s\n", lenTypeNameG);
+        fprintf (src, "%s::B%s (%s &_b) const\n", td->cxxTypeDefInfo->className, r->encodeContentBaseName, bufTypeNameG);
+        fprintf (src, "{\n");
+        fprintf (src, "    FUNC(\"%s::B%s (%s &_b)\");\n", td->cxxTypeDefInfo->className, r->encodeContentBaseName, bufTypeNameG);
+
+        /* print local vars */
+        fprintf (src, "  %s l=0;\n", lenTypeNameG);
+
+        fprintf (src, "  switch (%s)\n", r->choiceIdFieldName);
+        fprintf (src, "  {\n");
+        FOR_EACH_LIST_ELMT (e, choice->basicType->a.choice)
+        {
+            cxxtri =  e->type->cxxTypeRefInfo;
+            fprintf (src, "    case %s:\n", cxxtri->choiceIdSymbol);
+
+            varName = cxxtri->fieldName;
+
+            /* eSNACC 1.5 does not encode indefinite length
+             *
+             * PrintPyEocEncoders (src, td, e->type, "_b");
+             */
+
+            /* encode content */
+            tmpTypeId = GetBuiltinType (e->type);
+            if (tmpTypeId == BASICTYPE_ANYDEFINEDBY)
+            {
+               defByNamedType = e->type->basicType->a.anyDefinedBy->link;
+               PrintPySetTypeByCode(defByNamedType, cxxtri, src);
+            }
+            else if (tmpTypeId == BASICTYPE_ANY)
+            {
+                fprintf (src, "    l = %s", varName);
+                if (cxxtri->isPtr)
+                    fprintf (src, "->");
+                else
+                    fprintf (src, ".");
+
+                fprintf (src, "B%s (_b);\n", r->encodeBaseName);
+            }
+            else if ( (tmpTypeId == BASICTYPE_OCTETCONTAINING) ||
+                      (tmpTypeId == BASICTYPE_BITCONTAINING))
+            {
+               PrintPyEncodeContaining(e->type, r, src);
+            }
+            else if ( tmpTypeId == BASICTYPE_EXTENSION )
+            {
+                fprintf (src, "      l = %s", varName);
+                if (cxxtri->isPtr)
+                    fprintf (src, "->");
+                else
+                    fprintf (src, ".");
+
+                fprintf (src, "B%s (_b);\n", r->encodeBaseName);
+            }
+            else
+            {
+                fprintf (src, "      l = %s", varName);
+                if (cxxtri->isPtr)
+                    fprintf (src, "->");
+                else
+                    fprintf (src, ".");
+
+                fprintf (src, "B%s (_b);\n", r->encodeContentBaseName);
+            }
+
+            /* encode tag (s) & len (s) */
+            PrintPyTagAndLenEncodingCode(src, e->type, "l", "_b");
+
+            fprintf (src, "      break;\n\n");
+        }
+        fprintf (src, "      default:\n");
+		fprintf (src, "         throw EXCEPT(\"Choice is empty\", ENCODE_ERROR);\n");
+        fprintf (src, "  } // end switch\n");
+
+        fprintf (src, "  return l;\n");
+        fprintf (src, "} // %s::B%s\n\n\n", td->cxxTypeDefInfo->className, r->encodeContentBaseName);
+    }
+    /* end of BerEncodeContent method */
+
+    /* BerDecodeContent */
+    if (printDecodersG)
+    {
+        //fprintf (hdr, "  void			B%s (const %s &_b, %s tag, %s elmtLen, %s &bytesDecoded /*, s env*/);\n", r->decodeContentBaseName, bufTypeNameG, tagTypeNameG, lenTypeNameG, lenTypeNameG);//, envTypeNameG);
+        fprintf (src, "void %s::B%s (const %s &_b, %s tag, %s elmtLen0, %s &bytesDecoded /*, s env*/)\n", td->cxxTypeDefInfo->className, r->decodeContentBaseName, bufTypeNameG, tagTypeNameG, lenTypeNameG, lenTypeNameG);//, envTypeNameG);
+        fprintf (src, "{\n");
+        fprintf (src, "   FUNC(\"%s::B%s()\");\n",td->cxxTypeDefInfo->className, r->decodeContentBaseName); 
+        fprintf (src, "   Clear();\n");
+        //fprintf (src, "   Init();\n");
+        /* print local vars */
+        /* count max number of extra length var nec
+         * by counting tag/len pairs on components of the CHOICE
+         */
+
+        varCount = 0;
+        FOR_EACH_LIST_ELMT (e, choice->basicType->a.choice)
+        {
+            tmpVarCount = CxxCountVariableLevels (e->type);
+            if (tmpVarCount > varCount)
+                varCount = tmpVarCount;
+        }
+        /* write extra length vars - remember choice content
+         * decoders are passed the 'key' tag so need one less
+         * than max var count.
+         */
+        for (i = 1; i < varCount; i++)
+            fprintf (src, "  %s elmtLen%d = 0;\n", lenTypeNameG, i);
+
+        /* switch on given tag - choices always have the key tag decoded */
+        fprintf (src, "  switch (tag)\n");
+        fprintf (src, "  {\n");
+        FOR_EACH_LIST_ELMT (e, choice->basicType->a.choice)
+        {
+            if( e->type->basicType->choiceId == BASICTYPE_EXTENSION )
+            {
+                extensionsExist = TRUE;
+            }
+            else
+            {
+            
+                cxxtri =  e->type->cxxTypeRefInfo;
+                tags = GetTags (e->type, &stoleChoiceTags);
+
+                if (LIST_EMPTY (tags))
+                {
+                    fprintf (src, "    // ANY Type?\n");
+                    fprintf (src, "    case MAKE_TAG_ID (?, ?, ?):\n");
+                }
+                else
+                {
+                    tag = (Tag*)FIRST_LIST_ELMT (tags);
+                    classStr = Class2ClassStr (tag->tclass);
+                    formStr = Form2FormStr (tag->form);
+
+                    if (tag->tclass == UNIV)
+                    {
+                        codeStr = DetermineCode(tag, NULL, 0);//RWC;Code2UnivCodeStr (tag->code);
+                    }
+                    else
+                    {
+                        codeStr = DetermineCode(tag, NULL, 1);
+                    }
+
+                    if (tag->form == ANY_FORM)
+                    {
+                        fprintf (src, "    case MAKE_TAG_ID (%s, %s, %s):\n", classStr, Form2FormStr (PRIM), codeStr);
+                        fprintf (src, "    case MAKE_TAG_ID (%s, %s, %s):\n", classStr, Form2FormStr (CONS), codeStr);
+                    }
+                    else
+                    {
+                        fprintf (src, "    case MAKE_TAG_ID (%s, %s, %s):\n", classStr, formStr, codeStr);
+                    }
+
+                    /* now decode extra tags/length pairs */
+                    AsnListFirst (tags);
+                    AsnListNext (tags);
+                    elmtLevel = 0;
+                    if (stoleChoiceTags)
+                    {
+                        FOR_REST_LIST_ELMT (tag, tags)
+                        {
+                            classStr = Class2ClassStr (tag->tclass);
+
+                            formStr = Form2FormStr (tag->form);
+
+                            if (tag->tclass == UNIV)
+                                codeStr = DetermineCode(tag, NULL, 0);//RWC;Code2UnivCodeStr (tag->code);
+                            else
+                                codeStr = DetermineCode(tag, NULL, 1);
+
+                            if (tag->form == ANY_FORM)
+                            {
+                                fprintf (src, "    case MAKE_TAG_ID (%s, %s, %s):\n", classStr, Form2FormStr (PRIM), codeStr);
+                                fprintf (src, "    case MAKE_TAG_ID (%s, %s, %s):\n", classStr, Form2FormStr (CONS), codeStr);
+                            }
+                            else
+                            {
+                                fprintf (src, "    case MAKE_TAG_ID (%s, %s, %s):\n", classStr, formStr, codeStr);
+                            }
+                        }
+                    }
+                    else /* didn't steal nested choice's tags */
+                    {
+                        FOR_REST_LIST_ELMT (tag, tags)
+                        {
+                            classStr = Class2ClassStr (tag->tclass);
+                            codeStr = DetermineCode(tag, NULL, 0);//RWC;Code2UnivCodeStr (tag->code);
+                            formStr = Form2FormStr (tag->form);
+
+                            fprintf (src, "      tag = BDecTag (_b, bytesDecoded);\n");
+                            if (tag->form == ANY_FORM)
+                            {
+                                if (tag->tclass == UNIV)
+                                {
+                                    fprintf (src, "      if ((tag != MAKE_TAG_ID (%s, %s, %s))\n",  classStr, Form2FormStr (PRIM), codeStr);
+                                    fprintf (src, "          && (tag != MAKE_TAG_ID (%s, %s, %s)))\n", classStr, Form2FormStr (CONS), codeStr);
+                                }
+                                else
+                                {
+                                    fprintf (src, "      if ((tag != MAKE_TAG_ID (%s, %s, %s))\n", classStr, Form2FormStr (PRIM), DetermineCode(tag, NULL, 1));//RWC;tag->code);
+                                    fprintf (src, "          && (tag != MAKE_TAG_ID (%s, %s, %s)))\n", classStr, Form2FormStr (CONS), DetermineCode(tag, NULL, 1));//RWC;tag->code);
+                                }
+                            }
+                            else
+                            {
+                                if (tag->tclass == UNIV)
+                                    fprintf (src, "      if (tag != MAKE_TAG_ID (%s, %s, %s))\n", classStr, formStr, codeStr);
+                                else
+                                    fprintf (src, "      if (tag != MAKE_TAG_ID (%s, %s, %s))\n", classStr, formStr, DetermineCode(tag, NULL, 1));//RWC;tag->code);
+                            }
+
+                            fprintf (src, "      {\n");
+                        
+                            fprintf (src, "        throw InvalidTagException(typeName(), tag, STACK_ENTRY);\n");
+                            fprintf (src, "      }\n\n");
+
+                            fprintf (src, "      elmtLen%d = BDecLen (_b, bytesDecoded);\n", ++elmtLevel);
+                        }
+                    }
+                }
+                /*
+                 * if the choices element is another choice &&
+                 * we didn't steal its tags then we must grab
+                 * the key tag out of the contained CHOICE
+                 */
+                if (!stoleChoiceTags && (GetBuiltinType (e->type) == BASICTYPE_CHOICE))
+                {
+                    fprintf (src, "      tag = BDecTag (_b, bytesDecoded);\n");
+                    fprintf (src, "      elmtLen%d = BDecLen (_b, bytesDecoded);\n", ++elmtLevel);
+                }
+
+                varName = cxxtri->fieldName;
+                /* set choice id for to this elment */
+                fprintf (src, "      %s = %s;\n", r->choiceIdFieldName, cxxtri->choiceIdSymbol);
+
+                /* alloc elmt if nec */
+                if (cxxtri->isPtr)
+                {
+                    fprintf (src, "        %s = new %s;\n", varName, cxxtri->className);
+                }
+                /* decode content */
+                tmpTypeId = GetBuiltinType (e->type);
+                if (tmpTypeId == BASICTYPE_ANYDEFINEDBY)
+                {
+                    /*
+                     * must check for another EOC for ANYs
+                     * since the any decode routines decode
+                     * their own first tag/len pair
+                     */
+                    elmtLevel++;
+                    defByNamedType = e->type->basicType->a.anyDefinedBy->link;
+                    PrintPySetTypeByCode(defByNamedType, cxxtri, src);
+
+                    fprintf (src, "      %s", varName);
+                    if (cxxtri->isPtr)
+                        fprintf (src, "->");
+                    else
+                        fprintf (src, ".");
+                    fprintf (src, "B%s (_b, bytesDecoded);\n",  r->decodeBaseName);
+                }
+                else if (tmpTypeId == BASICTYPE_ANY)
+                {
+                    elmtLevel++;
+                    fprintf (src, "        %s", varName);
+                    if (cxxtri->isPtr)
+                       fprintf (src, "->");
+                    else
+                       fprintf (src, ".");
+                    fprintf (src, "B%s (_b, bytesDecoded);\n",  r->decodeBaseName);
+                }
+                else if ( (tmpTypeId == BASICTYPE_OCTETCONTAINING) ||
+							     (tmpTypeId == BASICTYPE_BITCONTAINING) )
+                {
+                   PrintPyDecodeContaining(e->type, r, src);
+                }
+                else
+                {
+                    fprintf (src, "        %s", varName);
+                    if (cxxtri->isPtr)
+                        fprintf (src, "->");
+                    else
+                        fprintf (src, ".");
+
+                    fprintf (src, "B%s (_b, tag, elmtLen%d, bytesDecoded);\n",  r->decodeContentBaseName, elmtLevel);
+                }
+
+                /* decode Eoc (s) */
+                for (i = elmtLevel-1; i >= 0; i--)
+                {
+                    fprintf (src, "      if (elmtLen%d == INDEFINITE_LEN)\n", i);
+                    fprintf (src, "        BDecEoc (_b, bytesDecoded);\n");
+                }
+
+                fprintf (src, "      break;\n\n");
+                FreeTags (tags);
+            }
+        }
+
+        fprintf (src, "    default:\n");
+        fprintf (src, "    {");
+
+        if(extensionsExist)
+        {
+            fprintf (src, "     AsnAny extAny;\n");
+            fprintf (src, "     extension = new AsnExtension;\n");
+            fprintf (src, "     choiceId = extensionCid;\n");
+            fprintf (src, "     extAny.BDecContent(_b, tag, elmtLen0, bytesDecoded);\n");
+            fprintf (src, "     extension->extList.insert( extension->extList.end(), extAny );\n");
+        }
+        else
+        {
+            fprintf (src, "        throw InvalidTagException(typeName(), tag, STACK_ENTRY);\n");
+        }
+
+        fprintf (src, "      break;\n");
+        fprintf (src, "    }\n");
+        fprintf (src, "  } // end switch\n");
+        fprintf (src, "} // %s::B%s\n\n\n", td->cxxTypeDefInfo->className, r->decodeContentBaseName);
+    }
+    /* end of code for printing BDecodeContent method */
+
+    /* do BEnc function */
+    if (printEncodersG)
+    {
+        //fprintf (hdr, "  %s		B%s (%s &_b) const;\n", lenTypeNameG, r->encodeBaseName, bufTypeNameG);
+        fprintf (src, "%s %s::B%s (%s &_b) const\n", lenTypeNameG, td->cxxTypeDefInfo->className, r->encodeBaseName, bufTypeNameG);
+        fprintf (src, "{\n");
+        fprintf (src, "    %s l=0;\n", lenTypeNameG);
+        fprintf (src, "    l = B%s (_b);\n", r->encodeContentBaseName);
+
+        /* encode each tag/len pair if any */
+        FOR_EACH_LIST_ELMT_RVS (tag, choice->tags)
+        {
+            classStr = Class2ClassStr (tag->tclass);
+            formStr = Form2FormStr (CONS);  /* choices are constructed */
+            //RWC;tagLen = TagByteLen (tag->code);
+            fprintf (src, "    l += BEncConsLen (_b, l);\n");
+
+            if (tag->tclass == UNIV)
+            {
+                const char* ptr = DetermineCode(tag, &tagLen, 1);
+                fprintf (src, "    l += BEncTag%d (_b, %s, %s, %s);\n", tagLen, classStr, formStr, ptr);//RWC;Code2UnivCodeStr (tag->code));
+            }
+            else
+            {
+                const char* ptr = DetermineCode(tag, &tagLen, 1);
+                fprintf (src, "    l += BEncTag%d (_b, %s, %s, %s);\n", tagLen, classStr, formStr, ptr);//RWC;tag->code);
+            }
+        }
+        fprintf (src, "    return l;\n");
+        fprintf (src, "}\n\n");
+    }
+    /* end of BEnc function */
+
+    /* Do BDec function */
+    if (printDecodersG)
+    {
+        //fprintf (hdr, "  void			B%s (const %s &_b, %s &bytesDecoded);\n", r->decodeBaseName, bufTypeNameG, lenTypeNameG);
+        fprintf (src, "void %s::B%s (const %s &_b, %s &bytesDecoded)\n", td->cxxTypeDefInfo->className, r->decodeBaseName, bufTypeNameG, lenTypeNameG);//, envTypeNameG);
+        fprintf (src, "{\n");
+
+        if (choice->tags->count > 0)
+           fprintf (src, "    FUNC(\"%s::B%s\")\n", td->cxxTypeDefInfo->className, r->decodeBaseName);
+
+        fprintf (src, "    %s elmtLen = 0;\n", lenTypeNameG);
+        fprintf (src, "    %s tag;\n", tagTypeNameG);
+
+        /* print extra locals for redundant lengths */
+        for (i = 1; (choice->tags != NULL) && (i <= LIST_COUNT (choice->tags)); i++)
+        {
+            fprintf (src, "    %s extraLen%d = 0;\n", lenTypeNameG, i);
+        }
+        fprintf (src, "\n");
+
+        /*  decode tag/length pair (s) */
+        elmtLevel = 0;
+        FOR_EACH_LIST_ELMT (tag, choice->tags)
+        {
+            classStr = Class2ClassStr (tag->tclass);
+            formStr = Form2FormStr (CONS);  /* choices are constructed */
+            fprintf (src, "    AsnTag tagId = BDecTag (_b, bytesDecoded);\n");
+            fprintf (src, "    if (tagId != ");
+            if (tag->tclass == UNIV)
+            {
+                fprintf (src, "MAKE_TAG_ID (%s, %s, %s))", classStr, formStr, DetermineCode(tag, NULL, 0));//RWC;Code2UnivCodeStr (tag->code));
+            }
+            else
+            {
+                fprintf (src, "MAKE_TAG_ID (%s, %s, %s))", classStr, formStr, DetermineCode(tag, NULL, 1));//RWC;tag->code);
+            }
+            fprintf (src, "    {\n");
+            fprintf (src, "          throw InvalidTagException(typeName(), tagId, STACK_ENTRY);\n");
+            fprintf (src, "    }\n");
+            fprintf (src, "    extraLen%d = BDecLen (_b, bytesDecoded);\n", ++elmtLevel);
+        }
+
+        /* decode identifying tag from choice body */
+        fprintf (src, "    /*  CHOICEs are a special case - grab identifying tag */\n");
+        fprintf (src, "    /*  this allows easier handling of nested CHOICEs */\n");
+        fprintf (src, "    tag = BDecTag (_b, bytesDecoded);\n");
+        fprintf (src, "    elmtLen = BDecLen (_b, bytesDecoded);\n");
+        fprintf (src, "    B%s (_b, tag, elmtLen, bytesDecoded);\n", r->decodeContentBaseName);
+
+        /* grab any EOCs that match redundant, indef lengths */
+        for (i = elmtLevel; i > 0; i--)
+        {
+            fprintf (src, "    if (extraLen%d == INDEFINITE_LEN)\n", i);
+            fprintf (src, "        BDecEoc (_b, bytesDecoded);\n");
+        }
+
+        fprintf (src, "}\n\n");
+    }
+    /* end of BDec function */
+
+
+   if(genPERCode)
+   {
+    /* do PER Encode, PEnc function */
+    if (printEncodersG)
+    {
+        /****************************/
+        /*** FIRST, handle index encoding for PER Choice.  Taking advantage of 
+           * the AsnInt class with constraints for the detailed encoding 
+           * details.  Declare outside scope of source method for PEnc/PDec. */
+        fprintf (src, "class AsnIntChoice_%s: public AsnInt  {\n", td->cxxTypeDefInfo->className);
+        fprintf (src, "  public:\n");
+        fprintf (src, "  AsnIntChoice_%s(AsnIntType val=0):AsnInt(val){ }\n", 
+                         td->cxxTypeDefInfo->className);
+        fprintf (src, "  ValueRange* ValueRanges(int &sizeVRList)\n");
+        fprintf (src, "  {\n");
+        fprintf (src, "  	static ValueRange INT1_ValueRangeList[] = \n");
+        fprintf (src, "  		{{ 0, %d, 1 }};\n",
+                 choice->basicType->a.choice->count);  /* CONSTANT value for this CHOICE. */
+        fprintf (src, "  	sizeVRList = 1;\n");
+        fprintf (src, "  	return INT1_ValueRangeList;\n");
+        fprintf (src, "  }\n");
+        fprintf (src, "};\n\n");
+
+		//RWC;fprintf (hdr, "  AsnLen		PEnc(AsnBufBits &_b, bool bAlign = false) const {AsnLen len; len = 1;return len;};\n");
+        //fprintf (hdr, "  %s		P%s (AsnBufBits &_b) const;\n", lenTypeNameG, r->encodeBaseName);
+        fprintf (src, "%s %s::P%s (AsnBufBits &_b) const\n", lenTypeNameG, td->cxxTypeDefInfo->className, r->encodeBaseName);
+        fprintf (src, "{\n");
+        fprintf (src, "    %s l=0;\n", lenTypeNameG);
+        fprintf (src, "    FUNC(\"%s::P%s (AsnBufBits &_b)\");\n", td->cxxTypeDefInfo->className, r->encodeBaseName);
+
+        /****************************/
+        /*** PERFORM sorting of Choice elements for proper index setting. */
+        PrintPyDefCode_PERSort(&ppElementNamedType, &pElementTag, choice->basicType->a.choice);
+        fprintf (src, "  AsnIntChoice_%s TmpAsnIntChoice(%d);\n", 
+                 td->cxxTypeDefInfo->className, 
+                 choice->basicType->a.choice->count);  /* CONSTANT value for this CHOICE. */
+        for (ii=0; ii < choice->basicType->a.choice->count; ii++)
+        {
+            fprintf (src, "   if (%s == %s::%s)\n", r->choiceIdFieldName, 
+                  td->cxxTypeDefInfo->className, 
+                  ppElementNamedType[ii]->type->cxxTypeRefInfo->choiceIdSymbol);
+            fprintf (src, "      TmpAsnIntChoice.Set(%d); // SORTED index value.\n", ii);
+        }       // END FOR ii
+        free(ppElementNamedType);
+        free(pElementTag);
+
+        /*** SETUP specific sorted index value. */
+        fprintf (src, "  l = TmpAsnIntChoice.PEnc(_b); // LOAD PER encoded, constrained Choice index value.\n");
+
+        fprintf (src, "  switch (%s)\n", r->choiceIdFieldName);
+        fprintf (src, "  {\n");
+        FOR_EACH_LIST_ELMT (e, choice->basicType->a.choice)
+        {
+            cxxtri =  e->type->cxxTypeRefInfo;
+            fprintf (src, "    case %s:\n", cxxtri->choiceIdSymbol);
+      
+            varName = cxxtri->fieldName;
+
+            /* encode content */
+            tmpTypeId = GetBuiltinType (e->type);
+            if (tmpTypeId == BASICTYPE_ANYDEFINEDBY)
+            {
+               defByNamedType = e->type->basicType->a.anyDefinedBy->link;
+               PrintPySetTypeByCode(defByNamedType, cxxtri, src);
+            }
+            else if (tmpTypeId == BASICTYPE_ANY)
+            {
+                fprintf (src, "    l += %s", varName);
+                if (cxxtri->isPtr)
+                    fprintf (src, "->");
+                else
+                    fprintf (src, ".");
+
+                fprintf (src, "P%s (_b);\n", r->encodeBaseName);
+            }
+            else if ( (tmpTypeId == BASICTYPE_OCTETCONTAINING) ||
+                      (tmpTypeId == BASICTYPE_BITCONTAINING))
+            {
+               PrintPyPEREncodeContaining(e->type, r, src);
+            }
+            else
+            {
+                fprintf (src, "      l += %s", varName);
+                if (cxxtri->isPtr)
+                    fprintf (src, "->");
+                else
+                    fprintf (src, ".");
+
+                fprintf (src, "P%s (_b);\n", r->encodeBaseName);
+            }
+            fprintf (src, "      break;\n\n");
+        }
+        fprintf (src, "      default:\n");
+		  fprintf (src, "         throw EXCEPT(\"Choice is empty\", ENCODE_ERROR);\n");
+        fprintf (src, "  } // end switch\n");
+        /****************************/
+
+        fprintf (src, "    return l;\n");
+        fprintf (src, "}    //%s::P%s(...)\n\n", td->cxxTypeDefInfo->className, r->encodeBaseName);
+    }       /* END IF printEncodersG */
+    /* end of PEnc function */
+
+    /* Do PDec function */
+    if (printDecodersG)
+    {
+        //fprintf (hdr, "  void			P%s (AsnBufBits &_b, %s &bitsDecoded);\n", r->decodeBaseName, lenTypeNameG);
+        fprintf (src, "void %s::P%s (AsnBufBits &_b, %s &bitsDecoded)\n", td->cxxTypeDefInfo->className, r->decodeBaseName, lenTypeNameG);//, envTypeNameG);
+        fprintf (src, "{\n");
+        fprintf (src, "\tClear();\n");
+
+        /* print extra locals for redundant lengths */
+        for (i = 1; (choice->tags != NULL) && (i <= LIST_COUNT (choice->tags)); i++)
+        {
+            //fprintf (src, "    %s extraLen%d = 0; \n", lenTypeNameG, i);
+        }
+        fprintf (src, "\n");
+
+        /*  decode tag/length pair (s) */
+        elmtLevel = 0;
+
+        /****************************/
+        fprintf (src, "  AsnIntChoice_%s TmpAsnIntChoice;\n", td->cxxTypeDefInfo->className);
+
+        /*** SETUP specific sorted index value. */
+        fprintf (src, "  TmpAsnIntChoice.PDec(_b, bitsDecoded); // LOAD PER decoded, constrained Choice index value.\n");
+
+        /* decode identifying tag from choice body */
+        fprintf (src, "    /*  CHOICEs are a special case - grab identifying tag */\n");
+        fprintf (src, "    /*  this allows easier handling of nested CHOICEs */\n");
+
+        /* print local vars */
+        /* count max number of extra length var nec
+         * by counting tag/len pairs on components of the CHOICE
+         */
+        varCount = 0;
+        FOR_EACH_LIST_ELMT (e, choice->basicType->a.choice)
+        {
+            tmpVarCount = CxxCountVariableLevels (e->type);
+            if (tmpVarCount > varCount)
+                varCount = tmpVarCount;
+        }
+ 
+        /*** PERFORM sorting of Choice elements for proper index setting, then 
+             determine actual Choice chosen by the user. */
+        PrintPyDefCode_PERSort(&ppElementNamedType, &pElementTag, choice->basicType->a.choice);
+        for (ii=0; ii < choice->basicType->a.choice->count; ii++)
+        {
+            fprintf (src, "   if (TmpAsnIntChoice == %d)\n", ii);
+            fprintf (src, "   {\n"); 
+            fprintf (src, "      %s = %s::%s;\n", r->choiceIdFieldName, 
+                  td->cxxTypeDefInfo->className, 
+                  ppElementNamedType[ii]->type->cxxTypeRefInfo->choiceIdSymbol);
+
+            /* Process specific tag - choices always have the key tag decoded */
+                e = ppElementNamedType[ii];
+                cxxtri =  e->type->cxxTypeRefInfo;
+
+                varName = cxxtri->fieldName;
+
+                /* alloc elmt if nec */
+                if (cxxtri->isPtr)
+                {
+                   fprintf (src, "      %s = new %s;\n", varName, cxxtri->className);
+                }
+                /* decode content */
+                tmpTypeId = GetBuiltinType (e->type);
+                if (tmpTypeId == BASICTYPE_ANYDEFINEDBY)
+                {
+                    /*
+                     * must check for another EOC for ANYs
+                     * since the any decode routines decode
+                     * their own first tag/len pair
+                     */
+                    elmtLevel++;
+
+                    defByNamedType = e->type->basicType->a.anyDefinedBy->link;
+                    PrintPySetTypeByCode(defByNamedType, cxxtri, src);
+
+                    fprintf (src, "      %s", varName);
+                    if (cxxtri->isPtr)
+                        fprintf (src, "->");
+                    else
+                        fprintf (src, ".");
+                    fprintf (src, "P%s (_b, bitsDecoded);\n",  r->decodeBaseName);
+                }
+                else if (tmpTypeId == BASICTYPE_ANY)
+                {
+                    elmtLevel++;
+                    fprintf (src, "        %s", varName);
+                    if (cxxtri->isPtr)
+                       fprintf (src, "->");
+                    else
+                       fprintf (src, ".");
+                    fprintf (src, "P%s (_b, bitsDecoded);\n",  r->decodeBaseName);
+                }
+                else if ( (tmpTypeId == BASICTYPE_OCTETCONTAINING) ||
+							     (tmpTypeId == BASICTYPE_BITCONTAINING) )
+                {
+                   PrintPyPERDecodeContaining(e->type, r, src);
+                }
+                else
+                {
+                    fprintf (src, "      %s", varName);
+                    if (cxxtri->isPtr)
+                        fprintf (src, "->");
+                    else
+                        fprintf (src, ".");
+
+                    fprintf (src, "P%s (_b, bitsDecoded);\n",  r->decodeBaseName);
+                }
+
+
+            fprintf (src, "   }  // END if this Choice ID chosen\n"); 
+        }       // END FOR ii
+
+        free(ppElementNamedType);
+        free(pElementTag);
+
+        fprintf (src, "}   // END %s::P%s(...)\n\n", td->cxxTypeDefInfo->className, r->decodeBaseName);
+    }
+    /* end of PDec function */
+   } /* if genPERCode */
+
+
+    /* ostream printing routine */
+    if (printPrintersG)
+    {
+        fprintf(src, "void %s::Print(std::ostream& os, unsigned short indent) const\n",
+			td->cxxTypeDefInfo->className);
+        fprintf(src, "{\n");
+        fprintf(src, "\tswitch (choiceId)\n");
+        fprintf(src, "\t{\n");
+
+        FOR_EACH_LIST_ELMT (e, choice->basicType->a.choice)
+        {
+            fprintf (src, "\tcase %s:\n", e->type->cxxTypeRefInfo->choiceIdSymbol);
+
+            /* value notation so print the choice elmts field name */
+            if (e->fieldName != NULL)
+                fprintf(src, "\t\tos << \"%s \";\n", e->fieldName);
+
+            if (e->type->cxxTypeRefInfo->isPtr)
+			{
+                fprintf(src, "\t\tif (%s)\n", e->type->cxxTypeRefInfo->fieldName);
+                fprintf(src, "\t\t\t%s->Print(os, indent);\n",
+					e->type->cxxTypeRefInfo->fieldName);
+                fprintf(src, "\t\telse\n");
+                fprintf(src, "\t\t\tos << \"<CHOICE value is missing>\\n\";\n");
+			}
+			else
+			{
+                fprintf(src, "\t\t%s.Print(os, indent);\n",
+					e->type->cxxTypeRefInfo->fieldName);
+			}
+
+            fprintf (src, "\t\tbreak;\n\n");
+        }
+        fprintf (src, "\t} // end of switch\n");
+
+        fprintf (src, "} // end of %s::Print()\n\n", td->cxxTypeDefInfo->className);
+
+        //fprintf(hdr, "  void			PrintXML (std::ostream &os, const char *lpszTitle=NULL) const;\n");
+
+        fprintf(src, "void %s::PrintXML (std::ostream &os, const char *lpszTitle) const\n", td->cxxTypeDefInfo->className);
+        fprintf(src, "{\n");
+        fprintf(src, "    const char *tagName = typeName();\n");
+        fprintf(src, "    if (lpszTitle)\n");
+        fprintf(src, "        tagName = lpszTitle;");
+        fprintf(src, "    os << \"<\" << tagName << \">\";\n");
+        fprintf(src, "    switch (choiceId) {\n");
+
+        FOR_EACH_LIST_ELMT (e, choice->basicType->a.choice)
+        {
+            fprintf(src, "    case %s:\n",
+                     e->type->cxxTypeRefInfo->choiceIdSymbol);
+
+            /* value notation so print the choice elmts field name */
+            if (e->type->cxxTypeRefInfo->isPtr)
+            {
+                fprintf(src, "       if (%s) {\n",
+                        e->type->cxxTypeRefInfo->fieldName);
+                fprintf(src, "           %s->PrintXML(os", e->type->cxxTypeRefInfo->fieldName);
+                if (e->fieldName != NULL)
+                   fprintf(src, ",\"%s\");\n", e->fieldName);
+                else
+                   fprintf(src, ");\n");
+                fprintf(src, "      }\n");
+            } else
+                fprintf(src, "      %s.PrintXML(os, \"%s\");\n",
+                        e->type->cxxTypeRefInfo->fieldName, e->fieldName);
+
+            fprintf(src, "      break;\n\n");
+        }
+        fprintf (src, "    } // end of switch\n");
+        fprintf (src, "    os << \"</\" << tagName << \">\";\n");
+        fprintf (src, "} // %s::PrintXML\n\n", td->cxxTypeDefInfo->className);
+    }
+    /* end of Print Method code */
+} /* PrintPyChoiceDefCode */
+
+static char *
+PyDetermineCode(Tag *tag, int *ptagLen, int bJustIntegerFlag)
+{
+    static char retstring[256];
+    char *codeStr=NULL;
+    int iValue=500;     // WILL indicate a problem on source creation...
+    memset(retstring, 0, sizeof(retstring));
+    if (tag->valueRef == NULL) {
+        if (!bJustIntegerFlag) {
+            char *univstr = Code2UnivCodeStr (tag->code);
+            sprintf(retstring, "asn_base.BERConsts.%s", univstr);
+        } else {
+            sprintf(retstring, "%d", tag->code); 
+        }
+        codeStr = retstring;
+        if (ptagLen) {
+            *ptagLen = TagByteLen(tag->code);
+        }
+    } else {
+        if (tag->valueRef && tag->valueRef->basicValue &&
+            tag->valueRef->basicValue->choiceId == BASICVALUE_LOCALVALUEREF &&
+            tag->valueRef->basicValue->a.localValueRef &&
+            tag->valueRef->basicValue->a.localValueRef->link &&
+            tag->valueRef->basicValue->a.localValueRef->link->value &&
+            tag->valueRef->basicValue->a.localValueRef->link->value->basicValue)
+        {
+            if (tag->valueRef->basicValue->a.localValueRef->link->value->basicValue->choiceId == 
+                        BASICVALUE_INTEGER)
+            {
+                iValue = tag->valueRef->basicValue->a.localValueRef->link->
+                                                value->basicValue->a.integer;
+            }       // IF Integer
+            else if (tag->valueRef->basicValue->a.localValueRef->link->value->basicValue->choiceId == 
+                        BASICVALUE_LOCALVALUEREF)
+            {
+                ValueRef *pvalueRef=NULL;
+                if (tag->valueRef->basicValue->a.localValueRef->link->value->basicValue->choiceId == BASICVALUE_LOCALVALUEREF)
+                {
+                    pvalueRef = tag->valueRef->basicValue->a.localValueRef->link->value->basicValue->a.localValueRef;
+                    if (pvalueRef->link->value && pvalueRef->link->value->basicValue &&
+                        pvalueRef->link->value->basicValue->choiceId == BASICVALUE_INTEGER)
+                        iValue = pvalueRef->link->value->basicValue->a.integer;
+                }
+            }       // END IF Integer/Import
+            else
+            {
+                printf("Tag value type NOT RECOGNIZED; COULD NOT RESOLVE tag integer!\n");
+            }
+        } else if (tag->valueRef->basicValue->choiceId ==
+                   BASICVALUE_IMPORTVALUEREF &&
+                   tag->valueRef->basicValue->a.importValueRef &&
+                   tag->valueRef->basicValue->a.importValueRef->link &&
+                   tag->valueRef->basicValue->a.importValueRef->link->value &&
+                   tag->valueRef->basicValue->a.importValueRef->link->value->
+                   basicValue && 
+                   tag->valueRef->basicValue->a.importValueRef->link->value->
+                   basicValue->choiceId == BASICVALUE_INTEGER) {
+            iValue = tag->valueRef->basicValue->a.importValueRef->link->
+                value->basicValue->a.integer;
+        }
+        sprintf(retstring, "%d", iValue); 
+        codeStr = retstring;
+        if (ptagLen) {
+            *ptagLen = TagByteLen(iValue);
+        }
+    }
+    return(codeStr);
+}
+
+static void
+PrintPySeqOrSetDefCode (FILE *src, FILE *hdr, ModuleList *mods, Module *m,
+                        PyRules *r ,TypeDef *td, Type *parent ESNACC_UNUSED,
+                        Type *seq, int novolatilefuncs ESNACC_UNUSED,
+                        int isSequence)
+{
+    NamedType *e;
+    char *classStr;
+    char *formStr;
+    char *codeStr;
+    int tagLen, i=0;
+    Tag *tag;
+    TagList *tags;
+    char *varName;
+    CxxTRI *cxxtri=NULL;
+    int elmtLevel=0;
+    int varCount, tmpVarCount;
+    int stoleChoiceTags;
+    int inTailOptElmts;
+    enum BasicTypeChoiceId tmpTypeId;
+    NamedType *defByNamedType;
+    NamedType *tmpElmt;
+
+    // DEFINE PER encode/decode tmp vars.
+    NamedType **pSeqElementNamedType=NULL;
+    int ii;
+    int extensionAdditionFound = FALSE;
+
+    fprintf(src, "class %s%s:\n\n", td->cxxTypeDefInfo->className,
+            baseClassesG);
+
+    tag = seq->tags->first->data;
+    classStr = Class2ClassStr (tag->tclass);
+    //formStr = Form2FormStr(CONS);
+    codeStr = PyDetermineCode(tag, NULL, (tag->tclass == UNIV) ? 0 : 1);
+    fprintf(src, "    BER_CLASS=asn_base.BERConsts.%s\n", classStr);
+    fprintf(src, "    BER_FORM=asn_base.BERConsts.BER_CONSTRUCTED_FORM\n\n");
+    fprintf(src, "    BER_TAG=%s\n", codeStr);
+    /* write out the sequence elmts */
+
+    if (!seq->basicType->a.sequence || !seq->basicType->a.sequence->count) {
+        fprintf(stderr, "WARNING: Sequence unknown?\n");
+    }
+
+    /* constructor */
+    fprintf(src, "    def __init__(self");
+    FOR_EACH_LIST_ELMT(e, seq->basicType->a.sequence) {
+        fprintf(src, ", %s", e->type->cxxTypeRefInfo->fieldName);
+
+        if (e->type->defaultVal) {
+            Value *defVal = GetValue(e->type->defaultVal->value);
+            switch (ParanoidGetBuiltinType(e->type)) {
+            case BASICTYPE_INTEGER:
+            case BASICTYPE_ENUMERATED:
+                fprintf(src, " = %s(%s)",
+                        e->type->cxxTypeRefInfo->className,
+                        defVal->basicValue->a.integer);
+                break;
+            case BASICTYPE_BOOLEAN:
+                fprintf(src, " = asn_bool.AsnBool(%s)", 
+                        defVal->basicValue->a.boolean == 0 ?
+                        "\"False\"" : "\"True\"");
+                break;
+            case BASICTYPE_BITSTRING:
+                fprintf(stderr,
+                        "WARNING: unsupported default BIT STRING\n");
+                break;
+            default:
+                fprintf(src, " = %s()\n",
+                        e->type->cxxTypeRefInfo->className);
+                break;
+            } /* end switch */
+        } else {
+            fprintf(src, " = None");
+        }
+    }
+    fprintf(src, "):\n");
+
+    FOR_EACH_LIST_ELMT(e, seq->basicType->a.sequence) {
+        fprintf(src, "        if ");
+        fprintf(src, "%s is not None and ",
+                    e->type->cxxTypeRefInfo->fieldName);
+        fprintf(src, "not isinstance(%s, %s):\n",
+                e->type->cxxTypeRefInfo->fieldName,
+                e->type->cxxTypeRefInfo->className);
+        fprintf(src, "            raise TypeError(\"Expected %s for %s\")\n",
+                e->type->cxxTypeRefInfo->className,
+                e->type->cxxTypeRefInfo->fieldName);
+        fprintf(src, "        else:\n");
+        fprintf(src, "            self.%s = %s\n",
+                e->type->cxxTypeRefInfo->fieldName,
+                e->type->cxxTypeRefInfo->fieldName);
+    }
+
+    fprintf(src, "\n\n");
+
+    /* benccontent */
+    fprintf(src, "    def BEncContent(self, asnbuf):\n");
+    fprintf(src, "        asnlen = 0\n");
+    FOR_EACH_LIST_ELMT(e, seq->basicType->a.sequence) {
+        fprintf(src, "        ");
+        if (e->type->cxxTypeRefInfo->isPtr)
+            fprintf(src, "if self.%s is not None:\n            ",
+                    e->type->cxxTypeRefInfo->fieldName);
+        else
+            fprintf(src, "if self.%s is None:\n            "
+                    "raise UnboundLocalError('Populate %s before encoding')\n"
+                    "        ",
+                    e->type->cxxTypeRefInfo->fieldName,
+                    e->type->cxxTypeRefInfo->fieldName);
+        fprintf(src, "asnlen += self.%s.BEnc(asnbuf)\n",
+                e->type->cxxTypeRefInfo->fieldName);
+    }
+    fprintf(src, "        return asnlen\n\n");
+
+    /* bdeccontent */
+    fprintf(src, "    def BDecContent(self, asnbuf, length):\n");
+    fprintf(src, "        asnlen = 0\n");
+    FOR_EACH_LIST_ELMT(e, seq->basicType->a.sequence) {
+        int i = 0;
+        fprintf(src, "        # Total num tags: %d\n", e->type->tags->count);
+        FOR_EACH_LIST_ELMT(tag, e->type->tags) {
+            if (i) {
+                fprintf(src, "        bufTag = ord(asnbuf.Buffer()[0])\n");
+                fprintf(src, "        if bufTag != TAG_CODE_EXPECTED:\n");
+                fprintf(src, "            raise Exception('AHH!')\n");
+                fprintf(src, "        asnlen += 1\n"
+                             "        asnbuf.swallow(1)\n");
+                fprintf(src, "        tagTotalLen, totalBytesLen = asn_buffer.BDecDefLen(asnbuf)\n");
+                fprintf(src, "        asnlen += tagTotalLen\n");
+            } else {
+                i = 1;
+            }
+            fprintf(src,
+                    "        TAG_CODE_EXPECTED = asn_base.BERConsts.MakeTag(asn_base.BERConsts.%s, asn_base.BERConsts.%s, %d)\n",
+                    Class2ClassStr(tag->tclass), Form2FormStr(tag->form), tag->code);
+        }
+        if (!e->type->tags->count) {
+            fprintf(src,
+                    "        TAG_CODE_EXPECTED = asn_base.BERConsts.MakeTag(%s.BER_CLASS,\n"
+                    "                                              %s.BER_FORM,\n"
+                    "                                              %s.BER_TAG)\n",
+                    e->type->cxxTypeRefInfo->className,
+                    e->type->cxxTypeRefInfo->className,
+                    e->type->cxxTypeRefInfo->className);
+        }
+        fprintf(src, "        bufTag = ord(asnbuf.Buffer()[0])\n");
+        fprintf(src, "        if bufTag != TAG_CODE_EXPECTED:\n");
+        if (!e->type->cxxTypeRefInfo->isPtr)
+            fprintf(src, "            raise Exception('Unexpected: %%x; expected: %%x' % (bufTag, TAG_CODE_EXPECTED))\n");
+        else
+            fprintf(src, "            pass\n");
+        fprintf(src, "        else:\n");
+        fprintf(src, "            self.%s = %s()\n",
+                e->type->cxxTypeRefInfo->fieldName,
+                e->type->cxxTypeRefInfo->className);
+        fprintf(src, "            asnlen += self.%s.BDec(asnbuf, length)\n",
+                e->type->cxxTypeRefInfo->fieldName);
+    }
+    fprintf(src, "        return asnlen\n\n");
+}
+
+
+static void
+PrintPySeqDefCode (FILE *src, FILE *hdr, ModuleList *mods, Module *m,
+                    PyRules *r ,TypeDef *td, Type *parent ESNACC_UNUSED,
+                    Type *seq, int novolatilefuncs ESNACC_UNUSED)
+{
+
+    PrintPySeqOrSetDefCode (src, hdr, mods, m, r, td, parent, seq,
+                            novolatilefuncs, 1);
+
+} /* PrintPySeqDefCode */
+
+
+static void
+PrintPySetDefCode (FILE *src, FILE *hdr, ModuleList *mods, Module *m,
+                    PyRules *r, TypeDef *td, Type *parent ESNACC_UNUSED,
+                    Type *set, int novolatilefuncs ESNACC_UNUSED)
+{
+    PrintPySeqOrSetDefCode (src, hdr, mods, m, r, td, parent, set,
+                            novolatilefuncs, 0);
+
+} /* PrintPySetDefCode */
+
+
+/*
+ * PIERCE added 8-21-2001 template code to handle SET/SEQ OF
+ *    
+ */
+static void
+PrintPyListClass(FILE *src, TypeDef *td, Type *lst, Module* m,
+                 ModuleList *mods)
+{  
+   struct NamedType p_etemp;
+   NamedType* p_e;
+   char typeNameStr[256];
+   char *lcn; /* list class name */
+   char *ecn; /* (list) elmt class name */
+   char pcvarname[100];
+
+   p_e=&p_etemp;
+   p_e->type=lst->basicType->a.setOf;
+
+   ecn = lst->basicType->a.setOf->cxxTypeRefInfo->className;
+   lcn = td->cxxTypeDefInfo->className;
+
+   fprintf(src, "class %s(asn_list.", lcn);
+   switch (lst->basicType->choiceId) {
+   case BASICTYPE_SEQUENCEOF:
+       fprintf(src, "AsnSequenceOf");
+	    break;
+   case BASICTYPE_SETOF:
+       fprintf(src, "AsnSetOf");
+       break;
+
+   default:
+       break;
+   }
+   fprintf(src, "):\n");
+   fprintf(src, "    def __init__(self, elemts=None, expected=None):\n");
+   fprintf(src, "        if expected is None:\n");
+   fprintf(src, "            expected = %s\n", ecn);
+   fprintf(src, "        asn_list.%s.__init__(self, elemts, expected)\n\n",
+           (lst->basicType->choiceId == BASICTYPE_SEQUENCEOF) ?
+           "AsnSequenceOf" : "AsnSetOf");
+
+   fprintf(src, "    def typename(self):\n");
+   fprintf(src, "        return \"%s\"\n\n", lcn);
+	// JKG--added functionality for sequence of and set of constraints
+	if (td->type->subtypes != NULL)
+	{
+        /*Subtype* s_type;*/
+        /*s_type = (Subtype*)td->type->subtypes->a.single->a.sizeConstraint->a.or->last->data;*/
+		/* Only single size constraints that are themselves single are supported */
+		if ((td->type->subtypes->choiceId == SUBTYPE_SINGLE) &&
+			(td->type->subtypes->a.single->choiceId == SUBTYPEVALUE_SIZECONSTRAINT) &&
+			(td->type->subtypes->a.single->a.sizeConstraint->choiceId == SUBTYPE_SINGLE))
+		{
+#if 0
+			PrintPySetOfSizeConstraint(src, 
+				td->type->subtypes->a.single->a.sizeConstraint->a.single,
+				m, td->type);
+#endif
+		}
+		else
+		{
+			PrintErrLoc(m->asn1SrcFileName, (long)td->type->lineNo);
+			fprintf(errFileG, "ERROR - unsupported constraint\n");
+		}
+	}
+
+}
+
+static void
+PrintPySetOfDefCode PARAMS ((src, mods, m, r, td, parent, setOf, novolatilefuncs),
+    FILE *src _AND_
+    ModuleList *mods _AND_
+    Module *m _AND_
+    PyRules *r _AND_
+    TypeDef *td _AND_
+    Type *parent _AND_
+    Type *setOf _AND_
+    int novolatilefuncs)
+{
+	// Get rid of warnings
+	novolatilefuncs = novolatilefuncs;
+	parent = parent;
+	m = m;
+	r = r;
+	mods = mods;
+	src = src;
+
+    /* do class */
+	PrintPyListClass(src, td, setOf, m, mods);
+
+} /* PrintPySetOfDefCode */
+
+
+static void
+PrintPyTypeDefCode PARAMS ((src, hdr, mods, m, r, td, novolatilefuncs),
+                           FILE *src _AND_
+                           FILE *hdr _AND_
+                           ModuleList *mods _AND_
+                           Module *m _AND_
+                           PyRules *r _AND_
+                           TypeDef *td _AND_
+                           int novolatilefuncs)
+{
+    switch (td->type->basicType->choiceId) {
+        case BASICTYPE_BOOLEAN:  /* library type */
+        case BASICTYPE_REAL:  /* library type */
+        case BASICTYPE_OCTETSTRING:  /* library type */
+        case BASICTYPE_NULL:  /* library type */
+        case BASICTYPE_EXTERNAL:		/* library type */
+        case BASICTYPE_OID:  /* library type */
+        case BASICTYPE_RELATIVE_OID:
+        case BASICTYPE_INTEGER:  /* library type */
+        case BASICTYPE_BITSTRING:  /* library type */
+        case BASICTYPE_ENUMERATED:  /* library type */
+        case BASICTYPE_NUMERIC_STR:  /* 22 */
+        case BASICTYPE_PRINTABLE_STR: /* 23 */
+        case BASICTYPE_UNIVERSAL_STR: /* 24 */
+        case BASICTYPE_IA5_STR:      /* 25 */
+        case BASICTYPE_BMP_STR:      /* 26 */
+        case BASICTYPE_UTF8_STR:     /* 27 */
+        case BASICTYPE_UTCTIME:      /* 28 tag 23 */
+        case BASICTYPE_GENERALIZEDTIME: /* 29 tag 24 */
+        case BASICTYPE_GRAPHIC_STR:     /* 30 tag 25 */
+        case BASICTYPE_VISIBLE_STR:     /* 31 tag 26  aka ISO646String */
+        case BASICTYPE_GENERAL_STR:     /* 32 tag 27 */
+        case BASICTYPE_OBJECTDESCRIPTOR:	/* 33 tag 7 */
+        case BASICTYPE_VIDEOTEX_STR:	/* 34 tag 21 */
+        case BASICTYPE_T61_STR:			/* 35 tag 20 */
+            PrintPySimpleDef(hdr, src, r, td);
+            break;
+        case BASICTYPE_SEQUENCEOF:  /* list types */
+        case BASICTYPE_SETOF:
+            PrintPySetOfDefCode(src, mods, m, r, td, NULL, td->type,
+                                novolatilefuncs);
+            break;
+        case BASICTYPE_IMPORTTYPEREF:  /* type references */
+        case BASICTYPE_LOCALTYPEREF:
+            /*
+             * if this type has been re-tagged then
+             * must create new class instead of using a typedef
+             */
+            PrintPySimpleDef(hdr, src, r, td);
+            break;
+        case BASICTYPE_CHOICE:
+            PrintPyChoiceDefCode (src, hdr, mods, m, r, td, NULL, td->type, novolatilefuncs);
+            break;
+        case BASICTYPE_SET:
+            PrintPySetDefCode (src, hdr, mods, m, r, td, NULL, td->type, novolatilefuncs);
+            break;
+        case BASICTYPE_SEQUENCE:
+            PrintPySeqDefCode (src, hdr, mods, m, r, td, NULL, td->type, novolatilefuncs);
+            break;
+        case BASICTYPE_COMPONENTSOF:
+        case BASICTYPE_SELECTION:
+        case BASICTYPE_UNKNOWN:
+        case BASICTYPE_MACRODEF:
+        case BASICTYPE_MACROTYPE:
+        case BASICTYPE_ANYDEFINEDBY:  /* ANY types */
+        case BASICTYPE_ANY:
+            /* do nothing */
+            break;
+        default:
+				/* TBD: print error? */
+				break;
+    }
+} /* PrintPyTypeDefCode */
+
+void
+PrintPyCode PARAMS ((src, hdr, if_META (printMeta COMMA meta COMMA meta_pdus COMMA)
+					 mods, m, r, longJmpVal, printTypes, printValues,
+					 printEncoders, printDecoders, printPrinters, printFree
+					 if_TCL (COMMA printTcl), novolatilefuncs),
+    FILE *src _AND_
+    FILE *hdr _AND_
+    if_META (MetaNameStyle printMeta _AND_)
+    if_META (const Meta *meta _AND_)
+    if_META (MetaPDU *meta_pdus _AND_)
+    ModuleList *mods _AND_
+    Module *m _AND_
+    PyRules *r _AND_
+    long longJmpVal _AND_
+    int printTypes _AND_
+    int printValues _AND_
+    int printEncoders _AND_
+    int printDecoders _AND_
+    int printPrinters _AND_
+    int printFree
+    if_TCL (_AND_ int printTcl) _AND_
+    int novolatilefuncs)
+{
+	Module *currMod;
+    AsnListNode *currModTmp;
+    TypeDef *td;
+    ValueDef *vd;
+
+
+    printTypesG = printTypes;
+    printEncodersG = printEncoders;
+    printDecodersG = printDecoders;
+    printPrintersG = printPrinters;
+    printFreeG = printFree;
+
+#if META
+    printMetaG = printMeta;
+    meta_pdus_G = meta_pdus;
+#if TCL
+    printTclG = printTcl;
+#endif /* TCL */
+#endif /* META */
+
+    PrintSrcComment(src, m);
+    PrintSrcIncludes(src);
+
+    FOR_EACH_LIST_ELMT (currMod, mods) {
+		if (!strcmp(m->cxxHdrFileName, currMod->cxxHdrFileName)) {
+            ImportModuleList *ModLists;
+            ImportModule *impMod;
+            char *ImpFile = NULL;
+            ModLists = currMod->imports;
+            currModTmp = mods->curr;
+            FOR_EACH_LIST_ELMT(impMod, ModLists) {
+                ImpFile = GetImportFileName(impMod->modId->name, mods);
+                if (ImpFile != NULL)
+                    fprintf(src, "import %s\n", ImpFile);
+                if (impMod->moduleRef == NULL)
+                    impMod->moduleRef = GetImportModuleRef(impMod->modId->name, mods);
+            }
+            mods->curr = currModTmp;
+        }
+    }
+    fprintf(src, "\n");
+
+    if (printValues) {
+        fprintf(src, "# value defs\n\n");
+        FOR_EACH_LIST_ELMT (vd, m->valueDefs) {
+#if 0
+            PrintPyValueDef(src, r, vd);
+#endif
+        }
+        fprintf(src, "\n");
+    }
+
+    fprintf(src, "# class member definitions:\n\n");
+    PrintPyAnyCode (src, hdr, r, mods, m);
+
+    FOR_EACH_LIST_ELMT (td, m->typeDefs) {
+        PrintPyTypeDefCode(src, hdr, mods, m, r, td, novolatilefuncs);
+    }
+
+} /* PrintPyCode */
+
+
+void PrintPyEncodeContaining(Type *t, PyRules *r, FILE *src)
+{
+   fprintf(src, "    l += %s", t->cxxTypeRefInfo->fieldName);
+   if (t->cxxTypeRefInfo->isPtr)
+      fprintf(src, "->");
+   else
+      fprintf(src, ".");
+
+   fprintf(src, "B%s(_b);\n", r->encodeBaseName);
+
+   /* If this is a BITSTRING CONTAINING encode a NULL octet for the unused 
+    * bits
+    */
+   if (t->basicType->choiceId == BASICTYPE_BITCONTAINING)
+   {
+      fprintf(src,"    _b.PutByteRvs((char) 0 ); //encode 0 for unused bits\n");
+      fprintf(src,"    l++;\n");
+   }
+}
+
+void PrintPyDecodeContaining(Type *t, PyRules *r, FILE *src)
+{
+   NamedType *defByNamedType;
+
+   /* Encode Content of contained type */
+   if (t->basicType->a.stringContaining->basicType->choiceId == 
+			 BASICTYPE_ANYDEFINEDBY)
+   {
+      defByNamedType = 
+			  t->basicType->a.stringContaining->basicType->a.anyDefinedBy->link;
+      PrintPySetTypeByCode(defByNamedType, t->cxxTypeRefInfo, src);
+   }
+
+   if (t->basicType->choiceId == BASICTYPE_BITCONTAINING)
+   {
+      fprintf(src,"\n");
+      fprintf(src,"    // Decode unused bits and make sure it's 0\n");
+      fprintf(src,"    char unusedBits;\n");
+      fprintf(src,"    unusedBits = _b.GetByte();\n");
+      fprintf(src,"    seqBytesDecoded++;\n");
+      fprintf(src,"    if (unusedBits != '0x0')\n");
+      fprintf(src,"      throw DecodeException(STACK_ENTRY);\n");
+      fprintf(src,"\n");
+   }
+
+   fprintf (src, "    %s", t->cxxTypeRefInfo->fieldName);
+   if (t->cxxTypeRefInfo->isPtr)
+      fprintf (src, "->");
+   else
+      fprintf (src, ".");
+
+   fprintf (src, "B%s (_b, seqBytesDecoded);\n",  r->decodeBaseName);
+}
+
+
+void PrintPyPEREncodeContaining(Type *t, PyRules *r, FILE *src)
+{
+   fprintf(src, "    l += %s", t->cxxTypeRefInfo->fieldName);
+   if (t->cxxTypeRefInfo->isPtr)
+      fprintf(src, "->");
+   else
+      fprintf(src, ".");
+
+   fprintf(src, "P%s(_b);\n", r->encodeBaseName);
+
+   /* If this is a BITSTRING CONTAINING encode a NULL octet for the unused 
+    * bits
+    */
+   if (t->basicType->choiceId == BASICTYPE_BITCONTAINING)
+   {
+      fprintf(src,"    unsigned char _tmp[] = {0x00};\n");
+      fprintf(src,"    _b.PutBits(tmp , 8); //encode 0 for unused bits\n");
+      fprintf(src,"    l++;\n");
+   }
+}
+
+void PrintPyPERDecodeContaining(Type *t, PyRules *r, FILE *src)
+{
+   NamedType *defByNamedType;
+
+   /* Encode Content of contained type */
+   if (t->basicType->a.stringContaining->basicType->choiceId == 
+			 BASICTYPE_ANYDEFINEDBY)
+   {
+      defByNamedType = 
+			  t->basicType->a.stringContaining->basicType->a.anyDefinedBy->link;
+      PrintPySetTypeByCode(defByNamedType, t->cxxTypeRefInfo, src);
+   }
+
+   if (t->basicType->choiceId == BASICTYPE_BITCONTAINING)
+   {
+      fprintf(src,"\n");
+      fprintf(src,"    // Decode unused bits and make sure it's 0\n");
+      fprintf(src,"    unsigned char* unusedBits;\n");
+      fprintf(src,"    unusedBits = _b.GetBits(8);\n");
+      fprintf(src,"    bitsDecoded++;\n");
+      fprintf(src,"    if (unusedBits[0] != '0x0')\n");
+      fprintf(src,"      throw DecodeException(STACK_ENTRY);\n");
+      fprintf(src,"\n");
+   }
+
+   fprintf (src, "    %s", t->cxxTypeRefInfo->fieldName);
+   if (t->cxxTypeRefInfo->isPtr)
+      fprintf (src, "->");
+   else
+      fprintf (src, ".");
+
+   fprintf (src, "P%s (_b, bitsDecoded);\n",  r->decodeBaseName);
+}
+
+
+void PrintPySetTypeByCode(NamedType *defByNamedType, CxxTRI *cxxtri, FILE *src)
+{
+     char *varName = cxxtri->fieldName;
+
+     if (GetBuiltinType (defByNamedType->type) == BASICTYPE_OID)
+     {
+         fprintf (src, "    %s", varName);
+         if (cxxtri->isPtr)
+            fprintf (src, "->");
+         else
+            fprintf (src, ".");
+
+         fprintf (src, "SetTypeByOid (");
+         if (defByNamedType->type->cxxTypeRefInfo->isPtr)
+             fprintf (src, " *");
+         fprintf (src, "%s);\n", defByNamedType->type->cxxTypeRefInfo->fieldName);
+     }
+     else if (GetBuiltinType (defByNamedType->type) == BASICTYPE_INTEGER)
+     {
+         fprintf (src, "    %s", varName);
+         if (cxxtri->isPtr)
+            fprintf (src, "->");
+         else
+            fprintf (src, ".");
+
+         fprintf (src, "SetTypeByInt (");
+         if (defByNamedType->type->cxxTypeRefInfo->isPtr)
+             fprintf (src, " *");
+         fprintf (src, "%s);\n", defByNamedType->type->cxxTypeRefInfo->fieldName);
+     }
+     else if (GetBuiltinType (defByNamedType->type) == BASICTYPE_CHOICE)
+     {
+        NamedType *nt;
+        Type      *t = GetType(defByNamedType->type);
+
+        if (defByNamedType->type->cxxTypeRefInfo->isPtr)
+            fprintf(src, "  switch (%s->choiceId)\n", defByNamedType->type->cxxTypeRefInfo->fieldName);
+        else
+            fprintf(src, "  switch (%s.choiceId)\n", defByNamedType->type->cxxTypeRefInfo->fieldName);
+        fprintf(src, "  {\n");
+
+        FOR_EACH_LIST_ELMT(nt, t->basicType->a.choice)
+        {
+           fprintf(src, "   case %s::%sCid:\n", defByNamedType->type->cxxTypeRefInfo->className, nt->fieldName);
+           if (nt->type->basicType->choiceId == BASICTYPE_INTEGER ||
+               nt->type->basicType->choiceId == BASICTYPE_ENUMERATED)
+           {
+              fprintf (src, "      %s", varName);
+              if (cxxtri->isPtr)
+                 fprintf (src, "->");
+              else
+                 fprintf (src, ".");
+
+              if (defByNamedType->type->cxxTypeRefInfo->isPtr)
+                  fprintf(src, "SetTypeByInt(*%s->%s);\n", defByNamedType->type->cxxTypeRefInfo->fieldName, nt->fieldName);
+              else
+                  fprintf(src, "SetTypeByInt(*%s.%s);\n", defByNamedType->type->cxxTypeRefInfo->fieldName, nt->fieldName);
+           }
+           else
+           {
+              fprintf (src, "      %s", varName);
+              if (cxxtri->isPtr)
+                 fprintf (src, "->");
+              else
+                 fprintf (src, ".");
+
+              if (defByNamedType->type->cxxTypeRefInfo->isPtr)
+                  fprintf(src, "SetTypeByOid(*%s->%s);\n", defByNamedType->type->cxxTypeRefInfo->fieldName, nt->fieldName);
+              else
+                  fprintf(src, "SetTypeByOid(*%s.%s);\n", defByNamedType->type->cxxTypeRefInfo->fieldName, nt->fieldName);
+           }
+           fprintf(src, "      break;\n");
+
+        }
+        fprintf(src, "  }\n");
+     }
+}
+
+
+static char *
+LookupNamespace PARAMS ((t, mods),
+    Type *t _AND_
+    ModuleList *mods)
+{
+    char *pszNamespace=NULL;
+    Module *mTmp=NULL;
+    TypeDef *ptTmp=NULL;
+    BasicType *pbtTmp2=NULL;
+
+    //RWC; HANDLE namespace designations of specific modules on declarations,
+    //      if necessary.  (May have to lookup module name to get namespace).
+    pbtTmp2 = t->basicType;
+    if (pbtTmp2->choiceId == BASICTYPE_SEQUENCEOF || 
+        pbtTmp2->choiceId == BASICTYPE_SETOF)
+        pbtTmp2 = pbtTmp2->a.sequenceOf->basicType;  // Burrow 1 more layer down for SequenceOf/SetOf
+    if (pbtTmp2->choiceId == BASICTYPE_IMPORTTYPEREF)
+    {                     // RWC; IF IMPORTED, then we need to check for 
+                          //       optional namespace designation (only in .h)
+            FOR_EACH_LIST_ELMT (mTmp, mods)
+            {
+                ptTmp = LookupType(mTmp->typeDefs, 
+                          pbtTmp2->a.importTypeRef->typeName); //WHAT we are looking for...
+                if (ptTmp != NULL)
+                    break;      //FOUND the MODULE that contains our defninition...
+            }       // END FOR each module.
+            if (ptTmp != NULL && mTmp != NULL && mTmp->namespaceToUse)  // FOUND our MODULE...
+            {
+                pszNamespace = mTmp->namespaceToUse;    // DO NOT DELETE...
+            }    
+            //LookupType PARAMS ((typeDefList, typeName),
+    }           // IF BASICTYPE_IMPORTTYPEREF
+
+    return(pszNamespace);
+}       /* END LookupNamespace(...)*/
+
+
+void PrintPySeqSetPrintFunction(FILE* src, FILE* hdr, MyString className,
+								 BasicType *pBasicType)
+{
+    int allOpt;
+	int inTailOptElmts;
+	NamedTypeList* pElmtList;
+	NamedType *e;
+
+	fprintf(src, "void %s::Print(std::ostream& os, unsigned short indent) const\n",
+		className);
+	fprintf(src, "{\n");
+
+	if (pBasicType->choiceId == BASICTYPE_SEQUENCE)
+	{
+		fprintf(src, "\tos << \"{ -- SEQUENCE --\" << std::endl;\n");
+		pElmtList = pBasicType->a.sequence;
+	}
+	else if (pBasicType->choiceId == BASICTYPE_SET)
+	{
+		fprintf(src, "\tos << \"{ -- SET --\" << std::endl;\n");
+		pElmtList = pBasicType->a.set;
+	}
+	else
+		abort();
+
+	allOpt = AllElmtsOptional(pElmtList);
+	if (allOpt)
+		fprintf(src, "\tint nonePrinted = true;\n");
+
+	fprintf(src, "++indent;\n\n");
+
+	FOR_EACH_LIST_ELMT (e, pElmtList)
+	{
+		inTailOptElmts = IsTailOptional(pElmtList);
+
+		if (e->type->cxxTypeRefInfo->isPtr)
+		{
+			fprintf(src, "\tif (%s (%s))\n",
+				e->type->cxxTypeRefInfo->optTestRoutineName,
+				e->type->cxxTypeRefInfo->fieldName);
+			fprintf (src, "\t{\n");
+
+			if (allOpt)
+			{
+				if (e != FIRST_LIST_ELMT (pElmtList))
+				{
+					fprintf(src, "\t\tif (!nonePrinted)\n");
+					fprintf(src, "\t\t\tos << \",\" << std::endl;\n");
+				}
+				fprintf(src, "\t\tnonePrinted = false;\n");
+			}
+			/* cannot be first elmt ow allOpt is true */
+			else if (inTailOptElmts) 
+				fprintf (src, "\t\tos << \",\"<< std::endl;\n");
+
+			fprintf(src, "\t\tIndent(os, indent);\n");
+
+			if (e->fieldName != NULL)
+				fprintf(src, "\t\tos << \"%s \";\n", e->fieldName);
+
+			fprintf(src, "\t\t%s->Print(os, indent);\n",
+				e->type->cxxTypeRefInfo->fieldName);
+
+			fprintf(src, "\t}\n");
+		}
+		else
+		{
+			fprintf(src, "\tIndent(os, indent);\n");
+
+			if (e->fieldName != NULL)
+				fprintf(src, "\tos << \"%s \";\n", e->fieldName);
+
+			fprintf(src, "\t%s.Print(os, indent);\n",
+				e->type->cxxTypeRefInfo->fieldName);
+
+			if (e != LAST_LIST_ELMT (pElmtList))
+				fprintf(src, "\tos << ',' << std::endl;\n");
+		}
+
+		fprintf (src, "\n");
+
+		if (e == LAST_LIST_ELMT (pElmtList))
+			fprintf(src, "\tos << std::endl;\n");
+	}
+
+	fprintf(src, "\t--indent;\n");
+	fprintf(src, "\tIndent(os, indent);\n");
+	fprintf(src, "\tos << \"}\\n\";\n");
+	fprintf (src, "} // end of %s::Print()\n\n", className);
+} /* end of PrintPySeqSetPrintFunction() */
+
+
+/*
+ * RWC;   */
+static void
+PrintPyDefCode_SetSeqPEREncode (FILE *src, FILE *hdr, PyRules *r, TypeDef *td, 
+    NamedType **pSetElementNamedType,
+    int iElementCount)      /* IN, ELEMENT Count to process in array*/
+{
+	NamedType *e;
+	char *varName;
+	CxxTRI *cxxtri=NULL;
+	enum BasicTypeChoiceId tmpTypeId;
+	NamedType *defByNamedType;
+    int extensionsExist = FALSE;
+	
+	// DEFINE PER encode/decode tmp vars.
+	int ii=0;
+	long lOptional_Default_ElmtCount=0;
+    const char* tabAndlenVar = "\tl";
+		
+	//fprintf(hdr, "\t%s\t\tP%s(AsnBufBits &_b) const;\n", lenTypeNameG,
+    //        r->encodeBaseName);
+      /*RWC; {AsnLen len; len = 1;return len;};\n");
+		RWC; MUST sort the results by tag; usually explicit except for 
+		RWC;  untagged Choices which can be nested.  We must determine which 
+		RWC;  tag can go 1st from any Choice, potentially nested. 
+	RWC;  (FORWARD ENCODING FOR PER!)*/
+	
+	fprintf(src, "%s %s::P%s(AsnBufBits &_b) const\n", lenTypeNameG,
+		td->cxxTypeDefInfo->className, r->encodeBaseName);
+	fprintf(src, "{\n\t%s l = 0;\n", lenTypeNameG);
+
+	/* SECOND, determine ahead of time the bit count for OPTIONAL/DEFAULT values. */
+	for (ii=0; ii < iElementCount; ii++)
+	{
+		e = pSetElementNamedType[ii];
+		
+		//RWC; ALSO, count any OPTIONAL/DEFAULT ASN.1 elements.
+		if ( (e->type->optional || e->type->defaultVal != NULL) && (!e->type->extensionAddition))
+			lOptional_Default_ElmtCount++;
+	}
+	
+	/* NEXT, decode this number of bits, if any, to determine the 
+	presence/absence of OPTIONAL/DEFAULT elements.*/
+	if (lOptional_Default_ElmtCount)
+	{	/* NOW, load PER encoding flag to indicate what OPTIONAL/DEFAULT
+		fields are actually present.*/
+		/* FOR PER ENCODING OF Set, we must load a bitfield of length 
+		"lOptional_Default_ElmtCount", indicating presence of optional 
+		or default field data. */
+		int iOptional_Default_ElementIndex=0;
+		fprintf(src, "\n\t// Build and encode preamble");
+		fprintf(src, "\n\tAsnBits SnaccOptionalDefaultBits(%ld);\n", lOptional_Default_ElmtCount);
+		for (ii=0; ii < iElementCount; ii++)
+		{
+			e = pSetElementNamedType[ii];
+			if ( (e->type->optional || e->type->defaultVal != NULL) && (!e->type->extensionAddition))
+			{
+				fprintf (src, "\tif (%s != NULL)\n",
+					e->type->cxxTypeRefInfo->fieldName);
+				fprintf (src, "\t\tSnaccOptionalDefaultBits.SetBit(%d);\n",
+					iOptional_Default_ElementIndex++);
+			}		/* END IF OPTIONAL/DEFAULT */
+		}	/* END FOR each element. */
+		fprintf (src, "\t_b.PutBits(SnaccOptionalDefaultBits.data(), %ld);\n",
+			lOptional_Default_ElmtCount);
+		fprintf (src, "\tl += %ld;\n", lOptional_Default_ElmtCount);
+       
+	}		/* END IF lOptional_Default_ElmtCount */
+	
+	/* NEXT, process each element of the Set/Sequence for decoding. */
+	fprintf(src, "\n\t// Encode the elements of the SEQUENCE\n");
+	for (ii=0; ii < iElementCount; ii++)
+	{
+		e = pSetElementNamedType[ii];
+        if(!e->type->extensionAddition)
+        {
+
+
+		    if ( (e->type->optional || e->type->defaultVal != NULL) && (!e->type->extensionAddition))
+		    {
+			    fprintf(src, "\tif (%s != NULL)\t// Optional OR Default\n",
+				    e->type->cxxTypeRefInfo->fieldName);
+			    tabAndlenVar = "\t\tl";
+		    }
+		    
+		    cxxtri =  e->type->cxxTypeRefInfo;
+		    varName = cxxtri->fieldName;
+		    
+		    /* encode tag(s), not UNIV but APL, CNTX or PRIV tags ONLY for PER */
+		    
+		    /*RWC;TBD; UPDATE to reflect PER encoding rules for encoding length, no tags
+		    RWC;TBD;  unless explicit (probably need to write a PER version, checking type).*/
+		    
+		    //RWC;NOT FOR PER;PrintPyTagAndLenEncodingCode (src, td, e->type, "l", "(*iBuf)");
+		    
+		    /* encode content */
+		    tmpTypeId = GetBuiltinType (e->type);
+		    if (tmpTypeId == BASICTYPE_ANYDEFINEDBY)
+		    {
+			    //RWC;TBD; we may have to investigate individual types here to 
+			    //RWC;TBD;	restrict which codes are printed for PER...
+			    defByNamedType = e->type->basicType->a.anyDefinedBy->link;
+			    PrintPySetTypeByCode(defByNamedType, cxxtri, src);
+			    
+			    fprintf(src, "%s += %s", tabAndlenVar, varName);
+			    if (cxxtri->isPtr)
+				    fprintf (src, "->");
+			    else
+				    fprintf (src, ".");
+			    fprintf (src, "P%s(_b);\n", r->encodeBaseName);
+		    }
+		    else if (tmpTypeId == BASICTYPE_ANY)
+		    {
+			    //RWC;NOTE:  we will assume here that the ANY buffer is already
+			    //RWC;NOTE:    properly PER encoder; we have no way of checking.
+			    fprintf(src, "%s += %s", tabAndlenVar, varName);
+			    if (cxxtri->isPtr)
+				    fprintf (src, "->");
+			    else
+				    fprintf (src, ".");
+			    
+			    fprintf (src, "P%s(_b);\n", r->encodeBaseName);
+		    }
+		    else if ( (tmpTypeId == BASICTYPE_OCTETCONTAINING) ||
+			    (tmpTypeId == BASICTYPE_BITCONTAINING))
+		    {
+			    PrintPyPEREncodeContaining(e->type, r, src);
+			    //RWC;TBD; THIS CALL WILL NOT UPDATE THE COUNT VALUE PROPERLY; must reflect
+			    //RWC;TBD;	PER encoding forward, l+=, instead of l=
+		    }
+		    else
+		    {
+			    fprintf(src, "%s += %s", tabAndlenVar, varName);
+			    if (cxxtri->isPtr)
+				    fprintf (src, "->");
+			    else
+				    fprintf (src, ".");
+			    
+			    fprintf (src, "P%s(_b);\n", r->encodeBaseName);/*RWC;r->encodeContentBaseName);*/
+		    }
+        }
+        else
+        {
+            extensionsExist = TRUE;
+        }
+	}			/* END FOR iElementCount */
+	
+
+    if(extensionsExist)
+    {
+        fprintf (src, " \t/*   WARNING:  PER does not yet support extensibility */\n");
+    }
+
+	fprintf(src, "\n\treturn l;\n");
+	fprintf(src, "}\t// %s::P%s\n\n\n", td->cxxTypeDefInfo->className,
+		r->encodeBaseName);
+} /* END PrintPyDefCode_SetSeqPEREncode(...) */
+
+
+/*
+ * RWC;  This method only handles the entire routine decode operations for both Set and Sequence PER Decode.
+ * element decodes, not the wrapping logic. */
+static void
+PrintPyDefCode_SetSeqPERDecode (FILE *src, FILE *hdr, PyRules *r, TypeDef *td, 
+    NamedType **pSetElementNamedType,
+    int iElementCount)      /* IN, ELEMENT Count to process in arrays */
+{
+	NamedType *e;
+	char *varName;
+	CxxTRI *cxxtri=NULL;
+	int elmtLevel=0;
+	int varCount, tmpVarCount;
+    enum BasicTypeChoiceId tmpTypeId;
+	NamedType *defByNamedType;
+
+    // DEFINE PER encode/decode tmp vars.
+	int ii=0;
+	int iOptional_Default_ElementIndex=0;
+	long lOptional_Default_ElmtCount=0;
+	
+	if (pSetElementNamedType == NULL)
+	{
+		printf("****** PrintPyDefCode_SetSeqPERDecode: MUST HAVE PER Encoders as well as PER Decoders! *****\n");
+		return;
+	}
+	
+	/***RWC; PERFORM PDec operations first... */
+	//fprintf(hdr, "\tvoid\t\tP%s(AsnBufBits& _b, %s& bitsDecoded);\n\n",
+    //r->decodeBaseName, lenTypeNameG);
+	
+	fprintf(src, "void %s::P%s(AsnBufBits& _b, %s& bitsDecoded)\n",
+		td->cxxTypeDefInfo->className, r->decodeBaseName, lenTypeNameG);
+	fprintf(src, "{\n");
+	fprintf(src, "\tClear();\n");
+
+	/* count max number of extra length var nec */
+	varCount = 0;
+	
+    /*	decode tag/length pair (s) */
+	elmtLevel = 0;
+	
+	for (ii=0; ii < iElementCount; ii++)
+		//FOR_EACH_LIST_ELMT (e, set->basicType->a.set)
+	{
+		e = pSetElementNamedType[ii];
+		tmpVarCount = CxxCountVariableLevels (e->type);
+		if (tmpVarCount > varCount)
+			varCount = tmpVarCount;
+		if ( (e->type->optional || e->type->defaultVal != NULL) && (!e->type->extensionAddition))
+		{
+			lOptional_Default_ElmtCount++;
+		}
+	}
+	
+	/* NEXT, decode this number of bits, if any, to determine the 
+	presence/absence of OPTIONAL/DEFAULT elements.	MUST BE DONE BEFORE 
+	TAGs.*/
+	if (lOptional_Default_ElmtCount)
+	{
+		fprintf(src, "\n\t// Decode the preamble\n");
+		fprintf(src, "\tAsnBits SnaccOptionalDefaultBits;\n");
+		fprintf(src, "\tbitsDecoded += _b.GetBits(SnaccOptionalDefaultBits, %ld);\n",
+			lOptional_Default_ElmtCount);
+	}
+	
+	//******************
+	/****RWC; PERFORM PDecContent operations here... ***/
+	/* print content local vars */
+    //	fprintf (src, "  unsigned int mandatoryElmtsDecoded = 0;\n");
+	
+	//******************
+	/* write extra length vars */
+    //	fprintf (src, "{\n");		// RWC; Temporary until I figure out the local var names from combining PDec with PDecContent
+    //	for (i = 1; i <= varCount; i++)
+    //		fprintf (src, "  %s elmtLen%d = 0; //RWC;default to infinite for now.\n", lenTypeNameG, i);
+    //	fprintf (src, "\n");
+	
+	/* handle empty set */
+	//RWC;if ((set->basicType->a.set == NULL) || LIST_EMPTY (set->basicType->a.set))
+	if (iElementCount == 0)
+	{
+		// RWC; Allow for "{" editing...
+		/*fprintf (src, "    throw EXCEPT(\"Expected an empty sequence\", DECODE_ERROR);\n");
+		fprintf (src, "  }\n");*/
+	}
+	else
+	{
+		fprintf(src, "\n\t// Decode each of the elements\n");
+		for (ii=0; ii < iElementCount; ii++)
+		{
+			const char* tabStr = "\t";
+			e = pSetElementNamedType[ii];
+
+            if(!e->type->extensionAddition)
+            {
+			    cxxtri =  e->type->cxxTypeRefInfo;
+			    if (e->type->optional || (e->type->defaultVal != NULL))
+			    {
+				    tabStr = "\t\t";
+				    fprintf(src, "\tif (SnaccOptionalDefaultBits.GetBit(%d))\n",
+					    iOptional_Default_ElementIndex++);
+				    fprintf(src, "\t{\n");
+			    }
+			    
+			    varName = cxxtri->fieldName;
+			    
+			    /* decode content */
+			    if (cxxtri->isPtr)
+			    {
+				    //fprintf(src, "%sif(%s)\n", tabStr, varName);
+                    //fprintf(src, "%s%sdelete %s;\n", tabStr, tabStr, varName);
+			    
+				    fprintf(src, "%s%s = new %s;\n", tabStr, varName,
+						    cxxtri->className);
+					     /* END IF subtypes, PER-Visible */
+			    }
+			    
+			    /* decode content */
+			    tmpTypeId = GetBuiltinType (e->type);
+			    if ((tmpTypeId == BASICTYPE_OCTETCONTAINING) ||
+				    (tmpTypeId == BASICTYPE_BITCONTAINING))
+			    {
+				    PrintPyPERDecodeContaining(e->type, r, src);
+			    }
+			    else
+			    {
+				    if (tmpTypeId == BASICTYPE_ANYDEFINEDBY)
+				    {
+					    elmtLevel++;
+				    
+					    defByNamedType = e->type->basicType->a.anyDefinedBy->link;
+					    PrintPySetTypeByCode(defByNamedType, cxxtri, src);
+				    }
+				    else if (tmpTypeId == BASICTYPE_ANY)
+				    {
+					    elmtLevel++;
+				    }
+
+				    if (cxxtri->isPtr)
+					    fprintf(src, "%s%s->", tabStr, varName);
+				    else
+					    fprintf(src, "%s%s.", tabStr, varName);
+				    fprintf(src, "P%s(_b, bitsDecoded);\n",	r->decodeBaseName);
+			    }
+			    
+			    if (e->type->optional || (e->type->defaultVal != NULL))
+				    fprintf (src, "\t}\n\n");
+            }				
+		} /* for each elmt */
+    } /* if not empty set clause */
+
+	fprintf (src, "} // %s::P%s()\n\n", td->cxxTypeDefInfo->className,
+		r->decodeBaseName);
+		
+}		/* END PrintPyDefCode_SetSeqPERDecode(...) */
+
+/*** This routine handles sorting of groups of NameType element(s) based on the
+ *   Set and Choice sorting rules.
+ */
+static void
+PrintPyDefCode_PERSort (
+    NamedType ***pppElementNamedType, /* OUT, array of sorted NameType(s) */
+    int **ppElementTag,      /* OUT, actual tag for sorted. */
+    AsnList *pElementList)   /* IN, actual eSNACC defs for NameType(s). */
+{
+    NamedType **pElementNamedType;
+    int *pElementTag;
+    NamedType *e;
+    NamedType *pnamedTypeTmp;
+    Tag *tag;
+    TagList *tags;
+    int tagTmp;
+    int stoleChoiceTags;
+    int ii=0, iii;
+
+        /*
+         * FIRST, determine encode order by looking at each element tag/type.
+         *  (careful with untagged Choice elements, may be nested).
+         *  If not tagged in the ASN.1 syntax, then we sort based on the IMPLICIT
+         *  tag, even though it may not be encoded for PER.
+         * pElementList->count total elements for PER encode sorting.*/
+        pElementTag = *ppElementTag = (int *)calloc(pElementList->count, sizeof(int));
+        pElementNamedType = *pppElementNamedType = 
+            (NamedType **)calloc(pElementList->count, sizeof(NamedType *));
+        FOR_EACH_LIST_ELMT (e, pElementList)
+        {
+            /*RWC;SEE tag-utils.c, line 175 for example of looking at nested
+             *RWC;  untagged Choice(s).  For PER, NEED to return lowest tag
+             *RWC;  value in nested untagged Choice for sorting.
+             *RWC;  The call to GetTags will only return tags with non-tagged
+             *RWC;  "Choice" elements if present (flagged by "stoleChoiceTags").*/
+            tags = GetTags (e->type, &stoleChoiceTags);
+
+            if (LIST_EMPTY (tags))
+            {
+                pElementTag[ii] = 0;
+                /* RWC; IGNORE; for now */
+            }       /* END IF (LIST_EMPTY (tags))*/
+            else if (stoleChoiceTags)
+            {
+                /* FOR untagged Choice, determine lowest possible tag for
+                 *  PER sorting order.*/
+                pElementTag[ii] = 9999;
+                FOR_EACH_LIST_ELMT (tag, tags)
+                {
+                    if (tag->code < pElementTag[ii])
+                       pElementTag[ii] = tag->code;  /* ONLY 1st element for sorting.*/
+                }
+            }
+            else
+            {
+                tag = (Tag*)FIRST_LIST_ELMT (tags);
+                pElementTag[ii] = tag->code;  // ONLY 1st element for sorting.
+            }
+            pElementNamedType[ii] = e;
+            ii++;
+        }       // END FOR each element.
+
+        // SECOND, sort this group of elements based on these tags.
+        for (ii=0; ii < pElementList->count-1; ii++)
+        {
+            for (iii=ii+1; iii < pElementList->count; iii++)
+            {   // LOCATE smallest tag value
+                if (pElementTag[iii] < pElementTag[ii])
+                {   // THEN switch them.
+                    tagTmp = pElementTag[ii];
+                    pnamedTypeTmp = pElementNamedType[ii];
+                    pElementTag[ii] = pElementTag[iii];
+                    pElementNamedType[ii] = pElementNamedType[iii];
+                    pElementTag[iii] = tagTmp;
+                    pElementNamedType[iii] = pnamedTypeTmp;
+                }
+            }   // END for remaining elements (for sorting)
+        }       // END FOR each element
+}       /* END PrintPyDefCode_PERSort(...) */
+
+void PrintPySimpleDefMeta_1(FILE * hdr, FILE* src, TypeDef* td, int hasNamedElmts, CNamedElmt *n, Module* m)
+{
+
+}
+
+void PrintPySimpleDefMeta_2(FILE * hdr, FILE* src, TypeDef* td, int hasNamedElmts, CNamedElmt *n, Module* m, PyRules *r)
+{
+
+}
+
+void PrintPyChoiceDefCodeMeta_1(FILE* hdr, FILE* src, TypeDef* td, Type* choice, Module* m, NamedType* e)
+{
+
+}
+
+void PrintPySeqDefCodeMeta_1(FILE* hdr, FILE* src, TypeDef* td, Type* seq, Module* m, NamedType* e)
+{
+
+}
+
+void PrintPySetDefCodeMeta_1(FILE* hdr, FILE* src, TypeDef* td, Type* set, Module* m, NamedType* e)
+{
+
+}
+/* EOF gen-code.c (for back-ends/c++-gen) */
+
diff --git a/compiler/back-ends/py-gen/rules.c b/compiler/back-ends/py-gen/rules.c
new file mode 100644
index 0000000..3c79068
--- /dev/null
+++ b/compiler/back-ends/py-gen/rules.c
@@ -0,0 +1,569 @@
+/*
+ * compiler/back-ends/py-gen/rules.c - initialized rule structure
+ *           inits a table that contains info about
+ *           converting each ASN.1 type to a python class
+ *
+ * Copyright (C) 2016 Aaron Conole
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include "asn-incl.h"
+#include "asn1module.h"
+#include "rules.h"
+
+PyRules pyRulesG =
+{
+   4,
+   "choiceId",
+   "ChoiceIdEnum",
+   "a",
+   "ChoiceUnion",
+   FALSE,
+   "Enc",
+   "Dec",
+   "EncContent",
+   "DecContent",
+   "EncPdu",
+   "DecPdu",
+   {
+      {  /* 0 */
+         BASICTYPE_UNKNOWN, 
+         "???",
+         FALSE,
+         FALSE,
+         FALSE,
+         TRUE,
+         TRUE,
+         TRUE,
+         TRUE,
+         "None",
+         "unknown"
+      },
+      { /* 1 */
+         BASICTYPE_BOOLEAN, /* 1 */
+         "asn_bool.AsnBool",
+         FALSE,
+         TRUE,
+         FALSE,
+         TRUE,
+         TRUE,
+         FALSE,
+         TRUE,
+         "None",
+         "bool"
+      },
+      {  /* 2 */
+         BASICTYPE_INTEGER, /* 2 */
+         "asn_ints.AsnInt",
+         FALSE,
+         TRUE,
+         FALSE,
+         TRUE,
+         TRUE,
+         FALSE,
+         TRUE,
+         "None",
+         "integer"
+      },
+      { /* 3 */
+         BASICTYPE_BITSTRING,
+         "asn_octs.AsnBits",
+         FALSE,
+         TRUE,
+         FALSE,
+         TRUE,
+         TRUE,
+         FALSE,
+         TRUE,
+         "None",
+         "bits"
+      },
+      {/* 4 */
+         BASICTYPE_OCTETSTRING,
+         "asn_octs.AsnOcts",
+         FALSE,
+         TRUE,
+         FALSE,
+         TRUE,
+         TRUE,
+         FALSE,
+         TRUE,
+         "None",
+         "octs"
+      },
+      {/* 5 */
+         BASICTYPE_NULL,
+         "asn_base.AsnNull",
+         FALSE,
+         TRUE,
+         FALSE,
+         TRUE,
+         TRUE,
+         FALSE,
+         TRUE,
+         "None",
+         "null"
+      },
+      { /* 6 */
+         BASICTYPE_OID,
+         "asn_oid.AsnOid",
+         FALSE,
+         TRUE,
+         FALSE,
+         TRUE,
+         TRUE,
+         FALSE,
+         TRUE,
+         "None",
+         "oid"
+      },
+      { /* 7 */
+         BASICTYPE_REAL,
+         "asn_ints.AsnReal",
+         FALSE,
+         TRUE,
+         FALSE,
+         TRUE,
+         TRUE,
+         FALSE,
+         TRUE,
+         "None",
+         "real"
+      },
+      {/* 8 */
+         BASICTYPE_ENUMERATED,
+         "asn_ints.AsnEnum",
+         FALSE,
+         TRUE,
+         FALSE,
+         TRUE,
+         TRUE,
+         FALSE,
+         TRUE,
+         "None",
+         "enumeration"
+      },
+      {/* 9 */
+         BASICTYPE_SEQUENCE,
+         NULL,
+         FALSE,
+         TRUE,
+         FALSE,
+         TRUE,
+         TRUE,
+         FALSE,
+         TRUE,
+         "None",
+         "seq"
+      },
+      {/* 10 */
+         BASICTYPE_SEQUENCEOF,
+         "asn_list.AsnSequenceOf",
+         FALSE,
+         TRUE,
+         FALSE,
+         TRUE,
+         TRUE,
+         FALSE,
+         TRUE,
+         "None",
+         "seqOf"
+      },
+      {/* 11 */
+         BASICTYPE_SET,
+         NULL,
+         FALSE,
+         TRUE,
+         FALSE,
+         TRUE,
+         TRUE,
+         FALSE,
+         FALSE,
+         "None",
+         "set"
+      },
+      {/* 12 */
+         BASICTYPE_SETOF,
+         "asn_list.AsnSetOf",
+         FALSE,
+         TRUE,
+         FALSE,
+         TRUE,
+         TRUE,
+         FALSE,
+         TRUE,
+         "None",
+         "setOf"
+      },
+      {/* 13 */
+         BASICTYPE_CHOICE,
+         NULL,
+         FALSE,
+         TRUE,
+         FALSE,
+         TRUE,
+         TRUE,
+         FALSE,
+         FALSE,
+         "None",
+         "choice"
+      },
+      {/* 14 */
+         BASICTYPE_SELECTION,
+         NULL,
+         FALSE,
+         TRUE,
+         FALSE,
+         TRUE,
+         TRUE,
+         FALSE,
+         TRUE,
+         "None",
+         "foo"
+      },
+      {/* 15 */
+         BASICTYPE_COMPONENTSOF,
+         NULL,
+         FALSE,
+         TRUE,
+         FALSE,
+         TRUE,
+         TRUE,
+         FALSE,
+         TRUE,
+         "None",
+         "bar"
+      },
+      {/* 16 */
+         BASICTYPE_ANY,
+         "asn_base.AsnAny",
+         FALSE,
+         TRUE,
+         FALSE,
+         TRUE,
+         TRUE,
+         FALSE,
+         TRUE,
+         "None",
+         "any"
+      },
+      {/* 17 */
+         BASICTYPE_ANYDEFINEDBY,
+         "AsnAnyDefinedBy",
+         FALSE,
+         TRUE,
+         FALSE,
+         TRUE,
+         TRUE,
+         FALSE,
+         TRUE,
+         "None",
+         "anyDefBy"
+      },
+      {/* 18 */
+         BASICTYPE_LOCALTYPEREF,
+         NULL,
+         FALSE,
+         TRUE,
+         FALSE,
+         TRUE,
+         TRUE,
+         FALSE,
+         TRUE,
+         "None",
+         "foo"
+      },
+      {/* 19 */
+         BASICTYPE_IMPORTTYPEREF,
+         NULL,
+         FALSE,
+         TRUE,
+         FALSE,
+         TRUE,
+         TRUE,
+         FALSE,
+         TRUE,
+         "None",
+         "bar"
+      },
+      {/* 20 */
+         BASICTYPE_MACROTYPE,
+         NULL,
+         FALSE,
+         FALSE,
+         FALSE,
+         TRUE,
+         TRUE,
+         FALSE,
+         TRUE,
+         "None",
+         "foo"
+      },
+      {/* 21 */
+         BASICTYPE_MACRODEF,
+         NULL,
+         FALSE,
+         FALSE,
+         FALSE,
+         TRUE,
+         TRUE,
+         FALSE,
+         TRUE,
+         "None",
+         "foo"
+      },
+      {/* 22 */
+         BASICTYPE_NUMERIC_STR,
+         "asn_useful.NumericString",
+         FALSE,
+         TRUE,
+         FALSE,
+         TRUE,
+         TRUE,
+         FALSE,
+         TRUE,
+         "None",
+         "numericString"
+      },
+      {/* 23 */
+         BASICTYPE_PRINTABLE_STR,
+         "asn_useful.PrintableString",
+         FALSE,
+         TRUE,
+         FALSE,
+         TRUE,
+         TRUE,
+         FALSE,
+         TRUE,
+         "None",
+         "printableString"
+      },
+      {/* 24 */
+         BASICTYPE_UNIVERSAL_STR,
+         "asn_useful.UniversalString",
+         FALSE,
+         TRUE,
+         FALSE,
+         TRUE,
+         TRUE,
+         FALSE,
+         TRUE,
+         "None",
+         "universalString"
+      },
+      {/* 25 */
+         BASICTYPE_IA5_STR,
+         "asn_useful.IA5String",
+         FALSE,
+         TRUE,
+         FALSE,
+         TRUE,
+         TRUE,
+         FALSE,
+         TRUE,
+         "None",
+         "ia5String"
+      },            
+      {/* 26 */
+         BASICTYPE_BMP_STR,
+         "asn_useful.BMPString",
+         FALSE,
+         TRUE,
+         FALSE,
+         TRUE,
+         TRUE,
+         FALSE,
+         TRUE,
+         "None",
+         "bmpString"
+      },            
+      {/* 27 */
+         BASICTYPE_UTF8_STR,
+         "asn_useful.UTF8String",
+         FALSE,
+         TRUE,
+         FALSE,
+         TRUE,
+         TRUE,
+         FALSE,
+         TRUE,
+         "None",
+         "utf8String"
+      },
+      {/* 28 */
+         BASICTYPE_UTCTIME, /* 23 */
+         "asn_useful.UTCTime",
+         FALSE,
+         TRUE,
+         FALSE,
+         TRUE,
+         TRUE,
+         FALSE,
+         TRUE,
+         "None",
+         "utcTime"
+      },
+      {/* 29 */
+         BASICTYPE_GENERALIZEDTIME, /* 24 */
+         "asn_useful.GeneralizedTime",
+         FALSE,
+         TRUE,
+         FALSE,
+         TRUE,
+         TRUE,
+         FALSE,
+         TRUE,
+         "None",
+         "generalizedTime"
+      },
+      {/* 30 */
+         BASICTYPE_GRAPHIC_STR, /* 25 */
+         "asn_useful.GraphicString",
+         FALSE,
+         TRUE,
+         FALSE,
+         TRUE,
+         TRUE,
+         FALSE,
+         TRUE,
+         "None",
+         "graphicString"
+      },
+      {/* 31 */
+         BASICTYPE_VISIBLE_STR, /* 26 */
+         "asn_useful.VisibleString",
+         FALSE,
+         TRUE,
+         FALSE,
+         TRUE,
+         TRUE,
+         FALSE,
+         TRUE,
+         "None",
+         "visibleString"
+      },
+      {/* 32 */
+         BASICTYPE_GENERAL_STR, /* 27 */
+         "asn_useful.GeneralString",
+         FALSE,
+         TRUE,
+         FALSE,
+         TRUE,
+         TRUE,
+         FALSE,
+         TRUE,
+         "None",
+         "generalString"
+      },
+      {/* 33 */
+         BASICTYPE_OBJECTDESCRIPTOR,
+         "asn_useful.ObjectDescriptor",
+         FALSE,
+         TRUE,
+         FALSE,
+         TRUE,
+         TRUE,
+         FALSE,
+         TRUE,
+         "None",
+         "objectDescriptor"
+      } ,
+      {/* 34 */
+         BASICTYPE_VIDEOTEX_STR,
+         "asn_useful.VideotexString",
+         FALSE,
+         TRUE,
+         FALSE,
+         TRUE,
+         TRUE,
+         FALSE,
+         TRUE,
+         "None",
+         "videotexString"
+      } ,           
+      {/* 35 */
+         BASICTYPE_T61_STR,
+         "asn_useful.T61String",
+         FALSE,
+         TRUE,
+         FALSE,
+         TRUE,
+         TRUE,
+         FALSE,
+         TRUE,
+         "None",
+         "t61String"
+      },            
+      {/* 36 */
+         BASICTYPE_EXTERNAL,
+         "asn_useful.EXTERNAL",
+         FALSE,
+         TRUE,
+         FALSE,
+         TRUE,
+         TRUE,
+         TRUE,
+         TRUE,
+         "None",
+         "external"
+      },            
+      {/* 37 */
+         BASICTYPE_OCTETCONTAINING,
+         NULL,
+         FALSE,
+         TRUE,
+         FALSE,
+         TRUE,
+         TRUE,
+         FALSE,
+         TRUE,
+         "None",
+         "octetContainer"
+		},
+      {/* 38 */
+         BASICTYPE_BITCONTAINING,
+         NULL,
+         FALSE,
+         TRUE,
+         FALSE,
+         TRUE,
+         TRUE,
+         FALSE,
+         TRUE,
+         "None",
+         "bitContainer"
+		},
+        { /* 39 */
+         BASICTYPE_RELATIVE_OID,
+         "AsnRelativeOid",
+         FALSE,
+         TRUE,
+         FALSE,
+         TRUE,
+         TRUE,
+         FALSE,
+         TRUE,
+         "None",
+         "relativeOid"
+        },
+        { /* 40 */
+         BASICTYPE_EXTENSION,
+         "asn_base.AsnExtension",
+         FALSE,
+         TRUE,
+         FALSE,
+         TRUE,
+         TRUE,
+         FALSE,
+         TRUE,
+         "None",
+         "extension"
+        }
+
+   }
+};
diff --git a/compiler/back-ends/py-gen/rules.h b/compiler/back-ends/py-gen/rules.h
new file mode 100644
index 0000000..e5d61bf
--- /dev/null
+++ b/compiler/back-ends/py-gen/rules.h
@@ -0,0 +1,36 @@
+/*
+ * compiler/back-ends/py-gen/rules.h
+ *
+ * Copyright (C) 2016 Aaron Conole
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#ifndef PY_RulesInclude
+#define PY_RulesInclude
+/* see asn1module.h for CxxTDI (C++ type def info) */
+
+typedef struct PyRules
+{
+    int  maxDigitsToAppend;
+    char *choiceIdFieldName;   /* name of choiceId field */
+    char *choiceIdEnumName;  /* name (tag) for choiceId enum def name */
+    char *choiceUnionFieldName; /* what the name of the choice's union is */
+    char *choiceUnionName;  /* name (tag) for choice union def name */
+    int   capitalizeNamedElmts;
+    char *encodeBaseName;
+    char *decodeBaseName;
+    char *encodeContentBaseName;
+    char *decodeContentBaseName;
+    char *encodePduBaseName;
+    char *decodePduBaseName;
+    CxxTDI typeConvTbl[BASICTYPE_EXTENSION + 1];
+}  PyRules;
+
+extern PyRules pyRulesG;
+
+#endif
diff --git a/compiler/back-ends/py-gen/types.c b/compiler/back-ends/py-gen/types.c
new file mode 100644
index 0000000..a6a7f3b
--- /dev/null
+++ b/compiler/back-ends/py-gen/types.c
@@ -0,0 +1,529 @@
+/*
+ * compiler/back-ends/py-gen/types.c  - fills in python type information
+ *
+ * Copyright (C) 2016 Aaron Conole
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <ctype.h>
+#include <string.h>
+#include "asn-incl.h"
+#include "asn1module.h"
+#include "snacc-util.h"
+#include "str-util.h"
+#include "rules.h"
+
+static DefinedObj *definedNamesG;
+
+/* unexported prototypes */
+
+void FillPyTypeDefInfo PROTO ((PyRules *r, Module *m, TypeDef *td));
+static void FillPyFieldNames PROTO ((PyRules *r,
+                                      NamedTypeList *firstSibling));
+static void FillPyTypeRefInfo PROTO ((PyRules *r, Module *m,
+                                       TypeDef *head, Type *parent, Type *t));
+static void FillPyStructElmts PROTO ((PyRules *r, Module *m,
+                                       TypeDef *head, Type *parent,
+                                       NamedTypeList *t));
+static void FillPyChoiceElmts PROTO ((PyRules *r, Module *m, TypeDef *head,
+                                       Type *parent, NamedTypeList *first));
+static int IsPyNone PROTO ((PyRules *r, TypeDef *td, Type *parent, Type *t));
+void FillPyTDIDefaults PROTO ((PyRules *r, CxxTDI *ctdi, TypeDef *td));
+
+
+static char *pykwds[] = {
+    "False", 	"class", 	"finally", 	"is", 	"return",
+    "None", 	"continue", 	"for", 	"lambda", 	"try",
+    "True", 	"def", 	"from", 	"nonlocal", 	"while",
+    "and", 	"del", 	"global", 	"not", 	"with",
+    "as", 	"elif", 	"if", 	"or", 	"yield",
+    "assert", 	"else", 	"import", 	"pass",
+    "break", 	"except", 	"in", 	"raise", NULL
+};
+
+
+/*
+ * returns non-zero if the given str is a C++ key word
+ */
+int
+IsPyKeyWord PARAMS ((str),
+    char *str)
+{
+    size_t i;
+
+    for (i=0; pykwds[i] != NULL && strcmp(pykwds[i], str); i++);
+
+    return pykwds[i] != NULL;
+}
+
+
+/*
+ *  allocates and fills all the cxxTypeInfos
+ *  in the type trees for every module in the list
+ */
+void
+FillPyTypeInfo PARAMS ((r, modList),
+    PyRules *r _AND_
+    ModuleList *modList)
+{
+    TypeDef *td;
+    Module *m;
+
+    /*
+     * go through each module's type defs and fill
+     * in the C type and enc/dec routines etc
+     */
+    definedNamesG = NULL;
+
+    FOR_EACH_LIST_ELMT (m, modList) {
+        FOR_EACH_LIST_ELMT (td, m->typeDefs)
+            FillPyTypeDefInfo (r, m, td);
+    }
+
+    /*
+     * now that type def info is filled in
+     * set up set/seq/list/choice elements that ref
+     * those definitions
+     */
+    FOR_EACH_LIST_ELMT (m, modList) {
+        FOR_EACH_LIST_ELMT (td, m->typeDefs)
+            FillPyTypeRefInfo (r, m, td, NULL, td->type);
+    }
+
+    /* done with checking for name conflicts */
+    FreeDefinedObjs (&definedNamesG);
+    definedNamesG = NULL;
+
+}
+
+
+/*
+ *  allocates and fills structure holding C type definition information
+ *  fo the given ASN.1 type definition.  Does not fill CTRI for contained
+ *  types etc.
+ */
+void
+FillPyTypeDefInfo PARAMS ((r, m, td),
+    PyRules *r _AND_
+    Module *m _AND_
+    TypeDef *td)
+{
+    char *tmpName;
+    CxxTDI *cxxtdi;
+
+    /*
+     * if CxxTDI is present this type def has already been 'filled'
+     */
+    if (td->cxxTypeDefInfo != NULL)
+        return;
+
+
+    cxxtdi = MT (CxxTDI);
+    td->cxxTypeDefInfo = cxxtdi;
+
+    /* get default type def attributes from table for type on rhs of ::= */
+
+    FillPyTDIDefaults (r, cxxtdi, td);
+
+
+    /*
+     * if defined by a ref to another type definition fill in that type
+     * def's CxxTDI so can inherit (actully completly replace default
+     * attributes) from it
+     */
+    if ((td->type->basicType->choiceId == BASICTYPE_LOCALTYPEREF) ||
+        (td->type->basicType->choiceId == BASICTYPE_IMPORTTYPEREF))
+    {
+        /*
+         * Fill in CxxTDI for defining type if nec.
+         * this works for importTypeRef as well since both a.localTypeRef
+         * and a.importTypeRef are of type TypeRef
+         */
+        FillPyTypeDefInfo(r, td->type->basicType->a.localTypeRef->module,
+                          td->type->basicType->a.localTypeRef->link);
+
+        tmpName = cxxtdi->className; /* save className */
+        /* copy all type def info and restore name related stuff - hack*/
+        *cxxtdi = *td->type->basicType->a.localTypeRef->link->cxxTypeDefInfo;
+        cxxtdi->className = tmpName; /* restore className */
+    }
+}  /* FillCxxTypeDefInfo */
+
+
+static void
+FillPyTypeRefInfo PARAMS ((r, m, head, parent, t),
+    PyRules *r _AND_
+    Module *m _AND_
+    TypeDef *head _AND_
+    Type *parent _AND_
+    Type *t)
+{
+    CxxTRI *cxxtri;
+    CxxTDI *tmpCxxtdi;
+    ValueDef *namedElmt;
+    CNamedElmt *cne;
+    CNamedElmt **cneHndl;
+    char       *elmtName;
+    int         len;
+    enum BasicTypeChoiceId basicTypeId;
+
+    /*
+     * you must check for cycles yourself before calling this
+     */
+    if (t->cxxTypeRefInfo == NULL) {
+        cxxtri = MT (CxxTRI);
+        t->cxxTypeRefInfo = cxxtri;
+    } else
+        cxxtri = t->cxxTypeRefInfo;
+
+    basicTypeId = t->basicType->choiceId;
+
+    tmpCxxtdi = &r->typeConvTbl[basicTypeId];
+
+    /* get base type def info from the conversion table in the rules */
+    cxxtri->isEnc = tmpCxxtdi->isEnc;
+    if ((basicTypeId == BASICTYPE_OCTETCONTAINING) ||
+        (basicTypeId == BASICTYPE_BITCONTAINING)) {
+        cxxtri->className =
+            r->typeConvTbl[t->basicType->a.stringContaining->basicType->
+                           choiceId].className;
+    } else
+        cxxtri->className = tmpCxxtdi->className;
+
+    cxxtri->optTestRoutineName = tmpCxxtdi->optTestRoutineName;
+
+
+    /*
+     * convert named elmts to C++ names.
+     * check for name conflict with other defined Types/Names/Values
+     */
+    if (((basicTypeId == BASICTYPE_INTEGER) ||
+         (basicTypeId == BASICTYPE_ENUMERATED) ||
+         (basicTypeId == BASICTYPE_BITSTRING)) &&
+        (!(LIST_EMPTY (t->basicType->a.integer)))) {
+        cxxtri->namedElmts = AsnListNew (sizeof (void*));
+
+        FOR_EACH_LIST_ELMT (namedElmt, t->basicType->a.integer) {
+            cneHndl = (CNamedElmt**)AsnListAppend (cxxtri->namedElmts);
+            cne = *cneHndl = MT(CNamedElmt);
+            elmtName = Asn1ValueName2CValueName(namedElmt->definedName);
+            cne->name = elmtName; /* not very efficient */
+
+            if (namedElmt->value->basicValue->choiceId == BASICVALUE_INTEGER)
+                cne->value = namedElmt->value->basicValue->a.integer;
+            else {
+                fprintf (errFileG, "Warning: unlinked defined value. Using -9999999\n");
+                cne->value = -9999999;
+            }
+
+            if (r->capitalizeNamedElmts)
+                Str2UCase(cne->name, len);
+
+            /*
+             * append digits if enum value name is a keyword
+             */
+            MakePyStrUnique(definedNamesG, cne->name, r->maxDigitsToAppend, 1);
+        }
+    }
+
+    /* fill in rest of type info depending on the type */
+    switch (basicTypeId)
+    {
+    default:
+    case BASICTYPE_UNKNOWN:
+    case BASICTYPE_MACRODEF:
+    case BASICTYPE_MACROTYPE:
+        /* do nothing */
+    case BASICTYPE_BOOLEAN:  /* library types */
+    case BASICTYPE_INTEGER:
+    case BASICTYPE_BITSTRING:
+    case BASICTYPE_OCTETSTRING:
+    case BASICTYPE_NULL:
+    case BASICTYPE_OID:
+    case BASICTYPE_RELATIVE_OID:
+    case BASICTYPE_REAL:
+    case BASICTYPE_ENUMERATED:
+    case BASICTYPE_ANY:
+    case BASICTYPE_ANYDEFINEDBY:  /* ANY types */
+        /* don't need to do anything else */
+        break;
+
+    case BASICTYPE_SEQUENCEOF:  /* list types */
+    case BASICTYPE_SETOF:
+        /* fill in component type */
+        FillPyTypeRefInfo (r, m, head, t, t->basicType->a.setOf);
+        break;
+
+    case BASICTYPE_IMPORTTYPEREF:  /* type references */
+    case BASICTYPE_LOCALTYPEREF:
+        /*
+         * grab class name from link (link is the def of the
+         * the ref'd type)
+         */
+        if (t->basicType->a.localTypeRef->link != NULL) {
+            /* inherit attributes from referenced type */
+            tmpCxxtdi=  t->basicType->a.localTypeRef->link->cxxTypeDefInfo;
+            cxxtri->className = tmpCxxtdi->className;
+            cxxtri->isEnc = tmpCxxtdi->isEnc;
+            cxxtri->optTestRoutineName = tmpCxxtdi->optTestRoutineName;
+        }
+        break;  /* these are handled now */
+
+    case BASICTYPE_CHOICE:
+        /*
+         * must fill field names BEFORE filling choice elmts
+         * (allows better naming for choice ids)
+         */
+        FillPyFieldNames(r, t->basicType->a.choice);
+        FillPyChoiceElmts(r, m, head, t, t->basicType->a.choice);
+        break;
+
+    case BASICTYPE_SET:
+    case BASICTYPE_SEQUENCE:
+        FillPyStructElmts (r, m, head, t, t->basicType->a.set);
+        FillPyFieldNames (r, t->basicType->a.set);
+        break;
+
+    case BASICTYPE_COMPONENTSOF:
+    case BASICTYPE_SELECTION:
+        fprintf(errFileG,
+                "Compiler error - COMPONENTS OF or SELECTION type slipped through normalizing phase.\n");
+        exit(-1);
+        break;
+    }
+
+    /*
+     * figure out whether this is a ptr based on the enclosing
+     * type (if any) and optionality/default
+     */
+    cxxtri->isPtr = (unsigned char)IsPyNone(r, head, parent, t);
+}  /* FillCxxTypeRefInfo */
+
+
+
+static void
+FillPyStructElmts PARAMS ((r, m, head, parent, elmts),
+    PyRules *r _AND_
+    Module *m _AND_
+    TypeDef *head _AND_
+    Type *parent _AND_
+    NamedTypeList *elmts)
+{
+    NamedType *et;
+
+    FOR_EACH_LIST_ELMT (et, elmts) {
+        FillPyTypeRefInfo(r, m, head, parent, et->type);
+    }
+}
+
+/*
+ *  Figures out non-conflicting enum names for the
+ *  choice id's
+ */
+static void
+FillPyChoiceElmts PARAMS ((r, m, head, parent, elmts),
+    PyRules *r _AND_
+    Module *m _AND_
+    TypeDef *head _AND_
+    Type *parent _AND_
+    NamedTypeList *elmts)
+{
+    NamedType *et;
+    int idCount = 0;
+    CxxTRI *cxxtri;
+    int   len;
+
+    /*
+     * fill in type info for elmt types first
+     */
+    FOR_EACH_LIST_ELMT (et, elmts)
+        FillPyTypeRefInfo (r, m, head, parent, et->type);
+
+    FOR_EACH_LIST_ELMT (et, elmts) {
+        cxxtri =  et->type->cxxTypeRefInfo;
+
+        if (cxxtri == NULL)
+            continue; /* wierd type */
+
+        cxxtri->choiceIdValue = idCount++;
+
+        len = strlen (cxxtri->fieldName);
+        cxxtri->choiceIdSymbol = Malloc (len + 4);
+        strcpy (cxxtri->choiceIdSymbol, cxxtri->fieldName);
+        strcat (cxxtri->choiceIdSymbol, "Cid");
+
+        if (r->capitalizeNamedElmts)
+            Str2UCase (cxxtri->choiceIdSymbol, len);
+    }
+}
+
+/*
+ * takes a list of "sibling" (eg same level in a structure)
+ * ElmtTypes and fills sets up the c field names in
+ * the CxxTRI struct
+ */
+static void
+FillPyFieldNames PARAMS ((r, elmts),
+    PyRules *r _AND_
+    NamedTypeList *elmts)
+{
+    NamedType  *et;
+    CxxTRI *cxxtri;
+    DefinedObj *fieldNames;
+    int        len;
+    char      *tmpName;
+    char      *asn1FieldName;
+    char      *cFieldName = NULL;
+
+    /*
+     * Initialize fieldname data
+     * allocate (if nec) and fill in CTRI fieldname if poss
+     * from asn1 field name.  leave blank otherwise
+     */
+    fieldNames = NewObjList();
+    FOR_EACH_LIST_ELMT (et, elmts) {
+        cxxtri = et->type->cxxTypeRefInfo;
+        if (cxxtri == NULL) {
+            cxxtri = MT(CxxTRI);
+            et->type->cxxTypeRefInfo = cxxtri;
+        }
+
+        if (et->fieldName != NULL) {
+            /*
+             * can assume that the field names are
+             * distinct because they have passed the
+             * error checking step.
+             * However, still call MakeStrUnique
+             * to change any field names that
+             * conflict with C++ keywords
+             */
+            asn1FieldName = et->fieldName;
+            cxxtri->fieldName = Asn1FieldName2CFieldName(asn1FieldName);
+            MakePyStrUnique(fieldNames, cxxtri->fieldName,
+                            r->maxDigitsToAppend, 1);
+            DefineObj(&fieldNames, cxxtri->fieldName);
+        }
+
+        /*
+         * generate field names for those without them
+         */
+        cFieldName = cxxtri->fieldName;
+        if (cxxtri->fieldName == NULL) {
+            if ((et->type->basicType->choiceId == BASICTYPE_LOCALTYPEREF) ||
+                (et->type->basicType->choiceId == BASICTYPE_IMPORTTYPEREF)) {
+                /*
+                 * take ref'd type name as field name
+                 * convert first let to lower case
+                 */
+                tmpName = et->type->basicType->a.localTypeRef->link->
+                    cxxTypeDefInfo->className;
+                tmpName = Asn1TypeName2CTypeName(tmpName);
+            } else {
+                /*
+                 * get default field name for this type
+                 */
+                tmpName = Strdup(r->typeConvTbl[et->type->basicType->choiceId].
+                                 defaultFieldName);
+            }
+            cFieldName = tmpName;
+            if (isupper(cFieldName[0]))
+                cFieldName[0] = (char)tolower(cFieldName[0]);
+
+            len = strlen(cFieldName);
+
+            /*
+             * try to use just the type name (with lower case first char).
+             * if that is already used in this type or a C++ keyword,
+             * append ascii digits to field name until unique
+             * in this type
+             */
+            MakePyStrUnique(fieldNames, cFieldName, r->maxDigitsToAppend, 1);
+            DefineObj(&fieldNames, cFieldName);
+            cxxtri->fieldName = cFieldName;
+        }
+    }
+    FreeDefinedObjs (&fieldNames);
+}
+
+/*
+ * returns true if this c type for this type should be
+ * be ref'd as a ptr
+ */
+static int
+IsPyNone PARAMS ((r, td, parent, t),
+    PyRules *r _AND_
+    TypeDef *td _AND_
+    Type *parent _AND_
+    Type *t)
+{
+    CxxTDI *cxxtdi;
+    int retVal = FALSE;
+
+    /*
+     * inherit ptr attriubutes from ref'd type if any
+     * otherwise grab lib c type def from the PyRules
+     */
+    if ((t->basicType->choiceId == BASICTYPE_LOCALTYPEREF) ||
+        (t->basicType->choiceId == BASICTYPE_IMPORTTYPEREF)) {
+        cxxtdi = t->basicType->a.localTypeRef->link->cxxTypeDefInfo;
+    } else
+        cxxtdi = &r->typeConvTbl[GetBuiltinType (t)];
+
+    /* no parent means t is the root of a typedef */
+    if ((parent == NULL) && (cxxtdi->isPtrForTypeDef))
+        retVal = TRUE;
+    else if ((parent != NULL) &&
+             ((parent->basicType->choiceId == BASICTYPE_SET) ||
+             (parent->basicType->choiceId == BASICTYPE_SEQUENCE)) &&
+             (cxxtdi->isPtrInSetAndSeq))
+        retVal = TRUE;
+    else if ((parent != NULL) &&
+             ((parent->basicType->choiceId == BASICTYPE_SETOF) ||
+             (parent->basicType->choiceId == BASICTYPE_SEQUENCEOF)) &&
+             (cxxtdi->isPtrInList))
+        retVal = TRUE;
+    else if ((parent != NULL) &&
+             (parent->basicType->choiceId == BASICTYPE_CHOICE) &&
+             (cxxtdi->isPtrInChoice))
+        retVal = TRUE;
+    else if (((t->optional) || (t->defaultVal != NULL)) && (cxxtdi->isPtrForOpt))
+        retVal = TRUE;
+
+    return retVal;
+}
+
+/* fill given cxxtdi with defaults from table for given typedef */
+void
+FillPyTDIDefaults PARAMS ((r, cxxtdi, td),
+    PyRules *r _AND_
+    CxxTDI *cxxtdi _AND_
+    TypeDef *td)
+{
+    CxxTDI *tblCxxtdi;
+    int typeIndex;
+    char *tmpName;
+
+    typeIndex = GetBuiltinType (td->type);
+
+    if (typeIndex < 0)
+        return;
+
+    tblCxxtdi = &r->typeConvTbl[typeIndex];
+
+    memcpy (cxxtdi, tblCxxtdi, sizeof (CxxTDI));
+
+    /* make sure class name is unique wrt to previously defined classes */
+    tmpName = Asn1TypeName2CTypeName (td->definedName);
+    cxxtdi->className = Malloc (strlen (tmpName) + r->maxDigitsToAppend +1);
+    strcpy (cxxtdi->className, tmpName);
+    Free (tmpName);
+
+    MakePyStrUnique (definedNamesG, cxxtdi->className, r->maxDigitsToAppend, 1);
+    DefineObj (&definedNamesG, cxxtdi->className);
+
+}
diff --git a/compiler/back-ends/str-util.c b/compiler/back-ends/str-util.c
index 073a4f1..b8c6dfb 100644
--- a/compiler/back-ends/str-util.c
+++ b/compiler/back-ends/str-util.c
@@ -90,6 +90,7 @@
 
 int IsCKeyWord PROTO ((char *str));
 int IsCxxKeyWord PROTO ((char *str));
+int IsPyKeyWord PROTO ((char *str));
 
 
 int	keepbaseG = TRUE;
@@ -127,9 +128,8 @@ Asn1FieldName2CFieldName PARAMS ((aName),
     if (aName == NULL)
         return NULL;
 
-    retVal = Malloc (strlen (aName) + 1);
-    strcpy (retVal, aName);
-    Dash2Underscore (retVal, strlen (retVal));
+    retVal = Strdup(aName);
+    Dash2Underscore(retVal, strlen(retVal));
 
     return retVal;
 }  /* Asn1FieldName2CFieldName */
@@ -262,8 +262,7 @@ Dash2Underscore PARAMS ((str, len),
     int len)
 {
     int i;
-    for (i=0; i < len; i++)
-    {
+    for (i=0; i < len; i++) {
         if (str[i] == '-')
             str[i] = '_';
     }
@@ -377,6 +376,34 @@ MakeCxxStrUnique PARAMS ((nameList, str, maxDigits, startingDigit),
     }
 }  /* MakeCxxStrUnique */
 
+
+/*
+ * same as MakeCStrUnique except checks against C++ keywords
+ */
+void
+MakePyStrUnique PARAMS ((nameList, str, maxDigits, startingDigit),
+    DefinedObj *nameList _AND_
+    char *str _AND_
+    int maxDigits _AND_
+    int startingDigit)
+{
+    int digit, len, maxDigitVal;
+
+    if (ObjIsDefined(nameList, str, StrObjCmp) || IsPyKeyWord (str)) {
+        for (maxDigitVal = 1; maxDigits > 0; maxDigits--)
+            maxDigitVal *= 10;
+
+        len = strlen(str);
+        digit = startingDigit;
+        do
+        {
+            str[len] = '\0';
+            AppendDigit (str, digit++);
+        } while (ObjIsDefined (nameList, str, StrObjCmp) &&
+                 (digit < maxDigitVal));
+    }
+}  /* MakeCxxStrUnique */
+
 static char *OutputDirectoryName;
 
 void StoreOutputDirectory PARAMS ((directory),
@@ -596,6 +623,17 @@ MakeCxxSrcFileName PARAMS ((refName),
 	return MakeFileName (refName, ".cpp");
 }
 
+char *
+MakePySrcFileName PARAMS ((refName),
+    const char *refName)
+{
+    char *name = Strdup(refName);
+    Dash2Underscore(name, strlen(refName));
+    char *ret = MakeFileName(name, ".py");
+    Free(name);
+    return ret;
+}
+
 #if IDL
 char *
 MakeIDLFileName PARAMS ((refName),
diff --git a/compiler/back-ends/str-util.h b/compiler/back-ends/str-util.h
index d3a0b54..b758c44 100644
--- a/compiler/back-ends/str-util.h
+++ b/compiler/back-ends/str-util.h
@@ -72,6 +72,7 @@ char *MakeCHdrFileName PROTO ((const char *moduleName));
 char *MakeCSrcFileName PROTO ((const char *moduleName));
 char *MakeCxxHdrFileName PROTO ((const char *moduleName));
 char *MakeCxxSrcFileName PROTO ((const char *moduleName));
+char *MakePySrcFileName PROTO ((const char *moduleName));
 #if IDL
 char *MakeIDLFileName PROTO ((const char *moduleName));
 #endif
diff --git a/compiler/core/define.c b/compiler/core/define.c
index 5d4d92d..3583a19 100644
--- a/compiler/core/define.c
+++ b/compiler/core/define.c
@@ -176,8 +176,7 @@ UndefineObj PARAMS ((objListHndl, obj, cmpRoutine),
 int
 ObjIsDefined (DefinedObj *objListPtr, void *obj, CmpObjsRoutine cmpRoutine)
 {
-    for ( ; objListPtr != NULL; objListPtr = objListPtr->next)
-    {
+    for ( ; objListPtr != NULL; objListPtr = objListPtr->next) {
         if (cmpRoutine (objListPtr->obj, obj))
             return TRUE;
     }
diff --git a/compiler/core/snacc.c b/compiler/core/snacc.c
index cb0cba8..407394b 100644
--- a/compiler/core/snacc.c
+++ b/compiler/core/snacc.c
@@ -81,6 +81,8 @@ char *bVDAGlobalDLLExport=(char *)0;
 
 #include "c++-gen/rules.h"		/* for c++ file generation */
 
+#include "py-gen/rules.h"
+
 #if IDL
 #include "idl-gen/rules.h"		/* for idl file generation */
 #endif
@@ -126,6 +128,12 @@ void PrintCxxCode (FILE *src, FILE *hdr, if_META (MetaNameStyle genMeta COMMA
 				   int printTypes, int printValues, int printEncoders,
 				   int printDecoders, int printPrinters, int printFree,
 				   if_TCL (int printTcl COMMA) int novolatilefuncs);
+void PrintPyCode (FILE *src, FILE *hdr, if_META (MetaNameStyle genMeta COMMA
+				   const Meta *meta COMMA MetaPDU *metapdus COMMA)
+				   ModuleList *mods, Module *m, CxxRules *r, long longJmpVal,
+				   int printTypes, int printValues, int printEncoders,
+				   int printDecoders, int printPrinters, int printFree,
+				   if_TCL (int printTcl COMMA) int novolatilefuncs);
 void PrintIDLCode PROTO ((FILE *idl, ModuleList *mods, Module *m, IDLRules *r,
 						 long int longJmpVal, int printValues));
 void ProcessMacros PROTO ((Module *m));
@@ -143,6 +151,11 @@ static void GenCxxCode PROTO ((ModuleList *allMods, long longJmpVal,
 							 int genPrinters, int genValues, int genFree,
 							 if_META (MetaNameStyle genMeta COMMA MetaPDU *meta_pdus COMMA)
 							 if_TCL (int genTcl COMMA) int novolatilefuncs));
+static void GenPyCode PROTO ((ModuleList *allMods, long longJmpVal,
+							 int genTypes, int genEncoders, int genDecoders,
+							 int genPrinters, int genValues, int genFree,
+							 if_META (MetaNameStyle genMeta COMMA MetaPDU *meta_pdus COMMA)
+							 if_TCL (int genTcl COMMA) int novolatilefuncs));
 static void GenIDLCode PROTO ((ModuleList *allMods, long longJmpVal, int genTypes,
 							 int genPrinters, int genValues, int genFree));
 static int ModNamesUnique PROTO ((ModuleList *m));
@@ -317,6 +330,7 @@ int main PARAMS ((argc, argv),
     int         genCCode = FALSE;        /* defaults to C if neither specified */
     int         genCxxCode = FALSE;
     int         genIDLCode = FALSE;
+    int         genPyCode = FALSE;
     long        longJmpVal = -100;
     int         novolatilefuncs = FALSE;
     char*       dirName;                    /* REN -- 6/2/03 -- added */
@@ -432,7 +446,11 @@ int main PARAMS ((argc, argv),
                 break;
 
             case 'p':
-                genPrintCode = TRUE;
+                if (argv[currArg][2] == 'y') {
+                    genPyCode = TRUE;
+                } else {
+                    genPrintCode = TRUE;
+                }
                 currArg++;
                 break;
 
@@ -693,15 +711,15 @@ error:
         genFreeCode = TRUE;
         genPrintCode = TRUE;
     }
-    else if (genCCode + genCxxCode + genTypeTbls + genIDLCode > 1)
+    else if (genCCode + genPyCode + genCxxCode + genTypeTbls + genIDLCode > 1)
     {
-        fprintf (stderr, "%s: ERROR---Choose only one of the -c -C or -T options\n",
+        fprintf (stderr, "%s: ERROR---Choose only one of the -py, -p py, -c, -C or -T options\n",
             argv[0]);
         Usage (argv[0], stderr);
         return 1;
     }
 
-    if (!genCCode && !genCxxCode && !genTypeTbls && !genIDLCode)
+    if (!genCCode && !genCxxCode && !genPyCode && !genTypeTbls && !genIDLCode)
         genCCode = TRUE;  /* default to C if neither specified */
 
     /* Set the encoding rules to BER if not set */
@@ -714,11 +732,9 @@ error:
     allMods = (ModuleList *)AsnListNew (sizeof (void*));
     
     tmpLst = srcList;
-    while (tmpLst != NULL)
-    {
+    while (tmpLst != NULL) {
         // Only do if not NULL 
-        if (tmpLst->fileName)
-        {
+        if (tmpLst->fileName) {
             currMod = ParseAsn1File (tmpLst->fileName,
                                      tmpLst->ImportFileFlag);
         
@@ -738,8 +754,7 @@ error:
     /*
      * Check that the module names/oids are unique
      */
-    if (!ModNamesUnique (allMods))
-    {
+    if (!ModNamesUnique (allMods)) {
         fprintf (errFileG, "\nConflicting module names, cannot proceed.\n");
         return 1;
     }
@@ -750,8 +765,7 @@ error:
      * Now that all files have been parsed,
      * link local and locatable import type refs
      */
-    if (LinkTypeRefs (allMods) < 0)
-    {
+    if (LinkTypeRefs (allMods) < 0) {
         fprintf (errFileG, "\nType linking errors---cannot proceed\n");
         return 2;
     }
@@ -763,8 +777,7 @@ error:
      * and have been linked.  Need type info to be able to
      * parse values easily (elimitate ambiguity).
      */
-    FOR_EACH_LIST_ELMT (currMod, allMods)
-    {
+    FOR_EACH_LIST_ELMT (currMod, allMods) {
         if (ParseValues (allMods, currMod) != 0)
             fprintf (errFileG, "WARNING: Value parsing error (s), attempting to continue\n");
     }
@@ -775,8 +788,7 @@ error:
      * Value parsing may have defined some new values
      * so can link local and locatable import value refs now.
      */
-    if (LinkValueRefs (allMods) < 0)
-    {
+    if (LinkValueRefs (allMods) < 0) {
         fprintf (errFileG, "\nValue linking errors---cannot proceed\n");
         return 4;
     }
@@ -790,8 +802,8 @@ error:
      *     so they are put in the id to ANY type hash tbl.
      */
     semErr = 0;
-    FOR_EACH_LIST_ELMT (currMod, allMods)
-    {   // For Macors, New TypeDefs are added here, if required
+    FOR_EACH_LIST_ELMT (currMod, allMods) {
+        // For Macros, New TypeDefs are added here, if required
         ProcessMacros (currMod);
         if (currMod->status == MOD_ERROR)
             semErr = 1;
@@ -808,8 +820,8 @@ error:
      * boil down values into simplest rep. (eg OID -> ENC_OID)
      */
     semErr = 0;
-    FOR_EACH_LIST_ELMT (currMod, allMods)
-    {   // New TypeDefs are added here, if required
+    FOR_EACH_LIST_ELMT (currMod, allMods) {
+        // New TypeDefs are added here, if required
         NormalizeModule (currMod);
         if (currMod->status == MOD_ERROR)
             semErr = 1;
@@ -823,8 +835,7 @@ error:
      * Mark recusive types.  Currently the recursive information is
      * not used elsewhere.
      */
-    FOR_EACH_LIST_ELMT (currMod, allMods)
-    {
+    FOR_EACH_LIST_ELMT (currMod, allMods) {
         MarkRecursiveTypes (currMod);
     }
 
@@ -835,8 +846,7 @@ error:
      * Check all modules and exit if errors were found
      */
     semErr = 0;
-    FOR_EACH_LIST_ELMT (currMod, allMods)
-    {
+    FOR_EACH_LIST_ELMT (currMod, allMods) {
         ErrChkModule (currMod);
         if (currMod->status == MOD_ERROR)
             semErr = 1;
@@ -851,23 +861,20 @@ error:
      * production but should not affect the other processing/error
      * checking steps.  This allows full display of errors.
      */
-    if (smallErrG)
-    {
+    if (smallErrG) {
         /*
          * for debugging show "parsed" version of ASN.1 module if
          * the print flag is set.
          * Dumps each module to stdout. Printed from Module data struct
          * print here before exiting otherwise print after sorting
          */
-        if (printModuleFlag)
-        {
-            FOR_EACH_LIST_ELMT (currMod, allMods)
-            {
+        if (printModuleFlag) {
+            FOR_EACH_LIST_ELMT (currMod, allMods) {
                 printf ("\n\n");
                 PrintModule (stdout, currMod);
             }
         }
-        
+
         return 8;
     }
 
@@ -893,6 +900,8 @@ error:
         FillIDLTypeInfo (&idlRulesG, allMods);
 #endif
 
+    else if (genPyCode)
+        FillPyTypeInfo(&pyRulesG, allMods);
 
     /*
      * STEP 10
@@ -911,10 +920,8 @@ error:
      * dumps each module to stdout. Printed from Module data struct
      * Shows the results of normalization and sorting.
      */
-    if (printModuleFlag)
-    {
-        FOR_EACH_LIST_ELMT (currMod, allMods)
-        {
+    if (printModuleFlag) {
+        FOR_EACH_LIST_ELMT (currMod, allMods) {
             printf ("\n\n");
             PrintModule (stdout, currMod);
         }
@@ -944,6 +951,12 @@ error:
             genPrintCode, genFreeCode);
 #endif
 
+    else if (genPyCode)
+        GenPyCode(allMods, longJmpVal, genTypeCode, genValueCode,
+                  genEncodeCode, genDecodeCode, genPrintCode, genFreeCode,
+                  if_META (genMetaCode COMMA meta_pdus COMMA)
+                  if_TCL (genTclCode COMMA) novolatilefuncs);
+
     tmpLst = srcList;
     while(tmpLst) {
         SRC_FILE *tmp;
@@ -1159,6 +1172,92 @@ GenCCode PARAMS ((allMods, longJmpVal, genTypes, genValues, genEncoders, genDeco
 }  /* GenCCode */
 
 
+void
+GenPyCode PARAMS ((allMods, longJmpVal, genTypes, genValues, genEncoders, genDecoders, genPrinters, genFree, if_META (genMeta COMMA meta_pdus COMMA) if_TCL (genTcl COMMA) novolatilefuncs),
+    ModuleList *allMods _AND_
+    long longJmpVal _AND_
+    int genTypes _AND_
+    int genValues _AND_
+    int genEncoders _AND_
+    int genDecoders _AND_
+    int genPrinters _AND_
+    int genFree _AND_
+    if_META (MetaNameStyle genMeta _AND_)
+    if_META (MetaPDU *meta_pdus _AND_)
+    if_TCL (int genTcl _AND_)
+    int novolatilefuncs)
+{
+    Module      *currMod;
+	AsnListNode *saveMods;
+    char        *modBaseFileName;
+    FILE        *hdrFilePtr;
+    FILE        *srcFilePtr;
+    DefinedObj  *fNames;
+    int         fNameConflict = FALSE;
+
+    /*
+     * Make names for each module's encoder/decoder src and hdr files
+     * so import references can be made via include files
+     * check for truncation --> name conflicts & exit if nec
+     */
+    fNames = NewObjList();
+
+    FOR_EACH_LIST_ELMT (currMod, allMods) {
+        modBaseFileName = MakeBaseFileName (keepbaseG
+                                            ? currMod->asn1SrcFileName
+                                            : currMod->modId->name);
+        currMod->cxxHdrFileName = "";
+        currMod->cxxSrcFileName = MakePySrcFileName(modBaseFileName);
+        if (ObjIsDefined (fNames, currMod->cxxHdrFileName, StrObjCmp) ||
+            ObjIsDefined (fNames, currMod->cxxSrcFileName, StrObjCmp)) {
+            fprintf(errFileG,
+                    "ERROR: file name conflict for generated source files with names `%s' and `%s'.\n\n",
+                    currMod->cxxHdrFileName, currMod->cxxSrcFileName);
+            fprintf(errFileG,
+                    "This usually means the max file name length is truncating the file names.\n");
+            fprintf(errFileG,
+                    "Try re-naming the modules with shorter names or increasing the argument to -mf option (if you are using it).\n");
+            fprintf(errFileG,
+                    "This error can also be caused by 2 modules have the same names but different OBJECT IDENTIFIERs.");
+            fprintf(errFileG,
+                    "  Try renaming the modules to correct this.\n");
+            fNameConflict = TRUE;
+        } else {
+            DefineObj (&fNames, currMod->cxxHdrFileName);
+            DefineObj (&fNames, currMod->cxxSrcFileName);
+        }
+        Free (modBaseFileName);
+
+        if (fNameConflict)
+            return;
+
+        FreeDefinedObjs (&fNames);
+    }
+
+    FOR_EACH_LIST_ELMT (currMod, allMods) {
+        if (currMod->ImportedFlag == FALSE) {
+            /*
+             * create and fill .h file for module's data structs
+             */
+            srcFilePtr = fopen (currMod->cxxSrcFileName, "wt");
+
+            if (srcFilePtr == NULL) {
+                perror ("fopen");
+            } else {
+                saveMods = allMods->curr;
+                PrintPyCode (srcFilePtr, hdrFilePtr,
+                             if_META (genMeta COMMA &meta COMMA meta_pdus COMMA)
+                             allMods, currMod, &cxxRulesG, longJmpVal,
+                             genTypes, genValues, genEncoders, genDecoders,
+                             genPrinters, genFree,
+                             if_TCL (genTcl COMMA) novolatilefuncs);
+                allMods->curr = saveMods;
+                fclose (srcFilePtr);
+            }
+        }
+    }
+}
+
 /*
  * Given the list of parsed, linked, normalized, error-checked and sorted
  * modules, and some code generation flags, generates C++ code and
@@ -1345,7 +1444,7 @@ GenCxxCode PARAMS ((allMods, longJmpVal, genTypes, genValues, genEncoders, genDe
 	fclose (meta.srcfp);
     
 #endif
-	}
+        }
 	}
 }  /* GenCxxCode */
 
-- 
2.7.4




More information about the dev mailing list