@@ -7,6 +7,8 @@ Future
* documentation: Developer's guides
* esnacc-logo: A mascot (and CC-BY license) was added for esnacc
* py-lib: Introduce a first cut at a python back-end
+* py-gen: Add python backend, which supports only basic explicit tagging, no
+ extensions, and BER only.
1.80
@@ -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
new file mode 100644
@@ -0,0 +1,265 @@
+/*
+ * 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;
+ enum BasicTypeChoiceId typeId;
+ ValueDef *vd;
+ Type *t;
+ BasicValue *bv;
+ char anyId[512];
+ char *typeName = NULL;
+
+ 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");
+ 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 {
+ /* Else if the syntax of this any is either a locally
+ defined type or an imported type, get the name from
+ the this type's ref info. */
+ 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);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ 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");
+} /* PrintAnyHashInitRoutine */
+
+
+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;
+ }
+ return NULL;*/
+
+} /* GetTypeDef */
new file mode 100644
@@ -0,0 +1,929 @@
+/*
+ * 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));
+static char *
+LookupNamespace PROTO ((Type *t, ModuleList *mods));
+
+/* 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;
+
+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;
+}
+
+/* Prints the default instantiation for a typedefined object */
+static void PrintPyTypeDefDefault PARAMS((src, td),
+ FILE* src _AND_
+ TypeDef* td)
+{
+ fprintf(src,
+ "%s=%s\n\n",
+
+ td->cxxTypeDefInfo->className ?
+ td->cxxTypeDefInfo->className :
+ "ERROR__",
+
+ td->type->cxxTypeRefInfo->className ?
+ td->type->cxxTypeRefInfo->className :
+ "BAD__");
+}
+
+
+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");
+ /* TODO: import modules */
+ fprintf(src, "\n");
+} /* PrintSrcIncludes */
+
+/*
+ * 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);
+}
+
+/*
+ * 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_TAG)\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 */
+
+
+/*
+ * 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 ((src, td),
+ FILE *src _AND_
+ TypeDef *td)
+{
+ Tag *tag;
+ TagList *tags;
+ char *formStr;
+ char *classStr;
+ CNamedElmt *n;
+ int stoleChoiceTags;
+
+ if (IsNewType (td->type)) {
+ int hasNamedElmts;
+
+ fprintf(src, "class %s(%s):\n",
+ td->cxxTypeDefInfo->className,
+ td->type->cxxTypeRefInfo->className);
+
+ if ((hasNamedElmts = HasNamedElmts (td->type)) != 0) {
+ int count = 0;
+ fprintf(src, " # ENUMERATIONS\n");
+ FOR_EACH_LIST_ELMT (n, td->type->cxxTypeRefInfo->namedElmts) {
+ fprintf(src, " %s = %d\n", n->name, n->value);
+ count++;
+ }
+ fprintf(src, "\n");
+ }
+
+ /*
+ * must explicitly call constructors for base class
+ */
+ PrintDerivedConstructors (src, td);
+
+ 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;
+ 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_TAG = %s\n", ptr);
+ }
+ FreeTags(tags);
+ fprintf(src, "\n\n");
+ }
+ } else {
+ /* For now, we don't handle constrained values in primitive types */
+ PrintPyTypeDefDefault(src, td);
+ }
+}
+
+static void
+PrintPyChoiceDefCode(FILE *src, FILE *hdr, ModuleList *mods, Module *m,
+ PyRules *r, TypeDef *td,Type *parent, Type *choice,
+ int novolatilefuncs)
+{
+ fprintf(src, "# WARNING : Choice code not implemented.\n");
+ fprintf(src, "# This ASN.1 file will not load properly.\n");
+}
+
+static char *
+PyDetermineCode(Tag *tag, int *ptagLen, int bJustIntegerFlag)
+{
+ static char retstring[256];
+ char *codeStr=NULL;
+ int iValue=500;
+ 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;
+ } 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;
+ }
+ } 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 ESNACC_UNUSED,
+ ModuleList *mods ESNACC_UNUSED,
+ Module *m ESNACC_UNUSED,
+ PyRules *r ESNACC_UNUSED,
+ TypeDef *td,
+ Type *parent ESNACC_UNUSED,
+ Type *seq, int novolatilefuncs ESNACC_UNUSED,
+ int isSequence)
+{
+ NamedType *e;
+ char *classStr;
+ char *codeStr;
+ Tag *tag;
+
+ fprintf(src, "class %s%s:\n\n", td->cxxTypeDefInfo->className,
+ baseClassesG);
+
+ tag = seq->tags->first->data;
+ classStr = Class2ClassStr (tag->tclass);
+ 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");
+ }
+
+ fprintf(src, " def typename(self):\n");
+ fprintf(src, " return \"%s\"\n\n", td->cxxTypeDefInfo->className);
+ /* constructor */
+ fprintf(src, " def __init__(self");
+ FOR_EACH_LIST_ELMT(e, seq->basicType->a.sequence) {
+ if (e->type->extensionAddition)
+ continue;
+
+ 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(%d)",
+ 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) {
+ if (e->type->extensionAddition)
+ continue;
+
+ 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) {
+ if (e->type->extensionAddition)
+ continue;
+
+ fprintf(src, " ");
+ char *indent = " ";
+ if (e->type->cxxTypeRefInfo->isPtr) {
+ fprintf(src, "if self.%s is not None:\n",
+ e->type->cxxTypeRefInfo->fieldName);
+ indent = " ";
+ } else {
+ fprintf(src, "if self.%s is None:\n "
+ "raise UnboundLocalError('Populate %s before encoding')\n",
+ e->type->cxxTypeRefInfo->fieldName,
+ e->type->cxxTypeRefInfo->fieldName);
+ }
+ if (e->type->tags->count) {
+ fprintf(src, "%s# %d tags to encode\n", indent,
+ e->type->tags->count);
+ fprintf(src, "%ssafe_buf = asnbuf\n", indent);
+ fprintf(src, "%ssafe_len = asnlen\n", indent);
+ fprintf(src, "%sasnlen = 0\n", indent);
+ fprintf(src, "%sasnbuf = %s()\n", indent, bufTypeNameG);
+ }
+ fprintf(src, "%sasnlen += self.%s.BEnc(asnbuf)\n", indent,
+ e->type->cxxTypeRefInfo->fieldName);
+ /* this will only be entered if the above check for count is true */
+ FOR_EACH_LIST_ELMT(tag, e->type->tags) {
+ fprintf(src, "%snewbuf = %s()\n", indent, bufTypeNameG);
+ fprintf(src, "%stagCode = asn_base.BERConsts.MakeTag(asn_base.BERConsts.%s, asn_base.BERConsts.%s, %d)\n",
+ indent, Class2ClassStr(tag->tclass),
+ Form2FormStr(tag->form), tag->code);
+ fprintf(src, "%sasnlen += asn_buffer.BEncDefLen(asnbuf, asnlen)\n",
+ indent);
+ fprintf(src, "%sasnlen += asnbuf.PutBufReverse(tagCode)\n",
+ indent);
+ fprintf(src, "%snewbuf.PutBuf(asnbuf.buf)\n", indent);
+ fprintf(src, "%sasnbuf = newbuf\n", indent);
+ }
+ if (e->type->tags->count) {
+ fprintf(src, "%ssafe_buf.PutBuf(asnbuf.buf)\n", indent);
+ fprintf(src, "%sasnbuf = safe_buf\n", indent);
+ fprintf(src, "%sasnlen = asnlen + safe_len\n", indent);
+ }
+ }
+ 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) {
+ if (e->type->extensionAddition)
+ continue;
+
+ int i = 0;
+ Tag *lastTag = NULL;
+ fprintf(src, " # tags: %d\n", e->type->tags->count);
+ FOR_EACH_LIST_ELMT(tag, e->type->tags) {
+ char *formStr = Form2FormStr(tag->form);
+ lastTag = tag;
+ if (i) {
+ fprintf(src, " bufTag, al = self.BDecTag(asnbuf, asnlen)\n");
+ fprintf(src, " if bufTag != TAG_CODE_EXPECTED:\n");
+ fprintf(src, " raise Exception('ahh: %%x vs %%x' %% (bufTag, TAG_CODE_EXPECTED))\n");
+ fprintf(src, " asnlen += al\n"
+ " asnbuf.swallow(al)\n");
+ fprintf(src, " tagTotalLen, totalBytesLen = asn_buffer.BDecDefLen(asnbuf)\n");
+ fprintf(src, " asnlen += tagTotalLen\n");
+ } else {
+ i = 1;
+ }
+ if (tag->tclass == CNTX)
+ formStr = Form2FormStr(CONS);
+ fprintf(src,
+ " TAG_CODE_EXPECTED = asn_base.BERConsts.MakeTag(asn_base.BERConsts.%s, asn_base.BERConsts.%s, %d)\n",
+ Class2ClassStr(tag->tclass), formStr, 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, al = self.BDecTag(asnbuf, asnlen)\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");
+ if (e->type->tags->count == 1 && lastTag && lastTag->tclass == CNTX) {
+ fprintf(src, " asnbuf.swallow(al)\n");
+ fprintf(src, " tagTotalLen, totalBytesLen = asn_buffer.BDecDefLen(asnbuf)\n");
+ fprintf(src, " asnlen += tagTotalLen\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");
+
+ fprintf(src, " def __str__(self):\n");
+ fprintf(src, " s = \"%%s = {\" %% self.typename()\n");
+ FOR_EACH_LIST_ELMT(e, seq->basicType->a.sequence) {
+ fprintf(src, " s += \"%s = \"\n",
+ e->type->cxxTypeRefInfo->fieldName);
+ fprintf(src, " if self.%s is not None:\n",
+ e->type->cxxTypeRefInfo->fieldName);
+ fprintf(src, " s += str(self.%s)\n",
+ e->type->cxxTypeRefInfo->fieldName);
+ fprintf(src, " else:\n");
+ fprintf(src, " s += \"None\"\n");
+ fprintf(src, " s += \"\\n\"\n");
+ }
+ fprintf(src, " s += \"}\"\n");
+ fprintf(src, " return s;\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 */
+
+
+static void
+PrintPyListClass(FILE *src, TypeDef *td, Type *lst, Module* m)
+{
+ struct NamedType p_etemp;
+ NamedType* p_e;
+ char *lcn; /* list class name */
+ char *ecn; /* (list) elmt class name */
+
+ 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);
+
+ if (td->type->subtypes != NULL) {
+ 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, m, td, setOf),
+ FILE *src _AND_
+ Module *m _AND_
+ TypeDef *td _AND_
+ Type *setOf)
+{
+ /* do class */
+ PrintPyListClass(src, td, setOf, m);
+
+} /* 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(src, td);
+ break;
+ case BASICTYPE_SEQUENCEOF: /* list types */
+ case BASICTYPE_SETOF:
+ PrintPySetOfDefCode(src, m, td, td->type);
+ 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(src, 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 ESNACC_UNUSED _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;
+
+ 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) {
+ /* PrintPyValueDef(src, r, vd); */
+ }
+ 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 */
+
+static char *
+LookupNamespace PARAMS ((t, mods),
+ Type *t _AND_
+ ModuleList *mods)
+{
+ char *pszNamespace = NULL;
+ Module *mTmp = NULL;
+ TypeDef *ptTmp = NULL;
+ BasicType *pbtTmp2 = NULL;
+
+ 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) {
+ 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...
+ }
+
+ if (ptTmp != NULL && mTmp != NULL && mTmp->namespaceToUse) {
+ pszNamespace = mTmp->namespaceToUse;
+ }
+ }
+
+ return(pszNamespace);
+}
new file mode 100644
@@ -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,
+ "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"
+ }
+
+ }
+};
new file mode 100644
@@ -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
new file mode 100644
@@ -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);
+
+}
@@ -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),
@@ -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
@@ -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;
}
@@ -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 */
This is a simple python backend for generating code. It currently doesn't handle constraints, implicit tagging, or non-BER forms of serialization. Signed-off-by: Aaron Conole <aconole@bytheb.org> --- NEWS | 2 + compiler/automake.mk | 5 + compiler/back-ends/py-gen/gen-any.c | 265 ++++++++++ compiler/back-ends/py-gen/gen-code.c | 929 +++++++++++++++++++++++++++++++++++ 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 +++++-- 11 files changed, 2515 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