kimgr / asn1ate

A Python library for translating ASN.1 into other forms.
Other
69 stars 41 forks source link

default vales for enums need to be strings #45

Open aholtzma opened 8 years ago

aholtzma commented 8 years ago

Using this module definition:

Class-definitions DEFINITIONS AUTOMATIC TAGS ::=

BEGIN

  Myenum ::= ENUMERATED { zero, one, two }

  Mysequence-with-enum  ::=      SEQUENCE 
  {
    foo Myenum DEFAULT two
  }

END

the output isn't valid python:

...
Mysequence_with_enum.componentType = namedtype.NamedTypes(
    namedtype.DefaultedNamedType('foo', Myenum().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0)).subtype(value=two))
)
...

The default values for enums need to be quoted.

aholtzma commented 8 years ago

There are actually two cases, one where the default is for a defined type, and one for an inline enum.

  Mysequence-with-enum  ::=      SEQUENCE
  {
    foo Myenum DEFAULT two,
    bar ENUMERATED { a, b, c} DEFAULT c
  }

I can fix the latter, but not the former.

--- a/asn1ate/pyasn1gen.py
+++ b/asn1ate/pyasn1gen.py
@@ -419,6 +419,8 @@ class Pyasn1Backend(object):
         if t.optional:
             return "namedtype.OptionalNamedType('%s', %s)" % (t.identifier, self.generate_expr(t.type_decl))
         elif t.default_value is not None:
+            if _translate_type(t.type_decl.type_name) == 'univ.Enumerated':
+                t.default_value = '\'%s\'' % t.default_value
             type_expr = self.generate_expr(t.type_decl)
             type_expr += '.subtype(value=%s)' % _translate_value(t.default_value)

How to resolve a defined type to a single basic type?

kimgr commented 8 years ago

I think you may be looking for sema.Module.resolve_type_decl. That unravels a chain of declarations back to the built-in type.

aholtzma commented 8 years ago

I had some trouble making resolve_type_decl work. It turns out it doesn't unwrap objects that are tagged. I was able to work around this by manually unwrapping the tag (with .type_decl.type_decl), but it's not clear to me what the right way to do this is.

--- a/asn1ate/pyasn1gen.py
+++ b/asn1ate/pyasn1gen.py
@@ -419,6 +419,9 @@ class Pyasn1Backend(object):
         if t.optional:
             return "namedtype.OptionalNamedType('%s', %s)" % (t.identifier, self.generate_expr(t.type_decl))
         elif t.default_value is not None:
+            xx = self.sema_module.resolve_type_decl(t.type_decl.type_decl, self.referenced_modules)
+            if _translate_type(xx.type_name) == 'univ.Enumerated':
+                t.default_value = '\'%s\'' % t.default_value
             type_expr = self.generate_expr(t.type_decl)
             type_expr += '.subtype(value=%s)' % _translate_value(t.default_value)
kimgr commented 8 years ago

Hmm. It's not clear to me why you end up in inline_component_type rather than inline_tagged_type. Or is this code called from inline_tagged_type? It's been too long since I thought about this code to be sure what's going on.

But your patch as-is will definitely break things for non-tagged types, I don't think any other sema-types have two levels of type_decl members.