From Xiao Xiangquan:
[obnox/wireshark/wip.git] / tools / asn2wrs.py
index 45343f08d1cf0fbcd5e35b5b8568de715c44c9f3..18fe4d12bf895ad60fbbc19ed861a7ba22c67919 100755 (executable)
@@ -142,6 +142,9 @@ oid_names = {
   '2/upu' : 40,
 }
 
+ITEM_FIELD_NAME = '_item'
+UNTAG_TYPE_NAME = '_untag'
+
 def asn2c(id):
   return id.replace('-', '_').replace('.', '_').replace('&', '_')
 
@@ -205,8 +208,8 @@ static_tokens = {
   r'::='    : 'ASSIGNMENT',  # 11.16 Assignment lexical item
   r'\.\.'   : 'RANGE',       # 11.17 Range separator
   r'\.\.\.' : 'ELLIPSIS',    # 11.18 Ellipsis
-  #r'\[\['   : 'LVERBRACK',   # 11.19 Left version brackets
-  #r'\]\]'   : 'RVERBRACK',   # 11.20 Right version brackets
+  r'\[\['   : 'LVERBRACK',   # 11.19 Left version brackets
+  r'\]\]'   : 'RVERBRACK',   # 11.20 Right version brackets
   # 11.26 Single character lexical items
   r'\{' : 'LBRACE',
   r'\}' : 'RBRACE',
@@ -443,7 +446,7 @@ class Ctx:
         if ident in self.assignments:
             raise DuplicateError("assignment", ident)
         if ident in self.defined_dict:
-            raise "cross-module duplicates for " + ident
+            raise Exception("cross-module duplicates for %s" % ident)
         self.defined_dict [ident] = 1
         self.assignments[ident] = val
         self.dependencies [ident] = dependencies
@@ -557,6 +560,16 @@ def dependency_compute(items, dependency, map_fn = lambda t: t, ignore_fn = lamb
         x[e] = True
   return (item_ord, item_cyc)
 
+# Given a filename, return a relative path from epan/dissectors
+def rel_dissector_path(filename):
+  path_parts = os.path.abspath(filename).split(os.sep)
+  while (len(path_parts) > 3 and path_parts[0] != 'asn1'):
+    path_parts.pop(0)
+  path_parts.insert(0, '..')
+  path_parts.insert(0, '..')
+  return '/'.join(path_parts)
+
+
 #--- EthCtx -------------------------------------------------------------------
 class EthCtx:
   def __init__(self, conform, output, indent = 0):
@@ -571,6 +584,7 @@ class EthCtx:
     self.default_containing_variant = '_pdu_new'
     self.default_embedded_pdv_cb = None
     self.default_external_type_cb = None
+    self.remove_prefix = None
     self.srcdir = None
     self.emitted_pdu = {}
     self.module = {}
@@ -588,7 +602,7 @@ class EthCtx:
   def Ber(self): return self.encoding == 'ber'
   def Aligned(self): return self.aligned
   def Unaligned(self): return not self.aligned
-  def Tag(self): return self.tag_opt or self.Ber()
+  def NeedTags(self): return self.tag_opt or self.Ber()
   def NAPI(self): return False  # disable planned features
 
   def Module(self):  # current module name
@@ -665,7 +679,7 @@ class EthCtx:
       ttype = type
       while (val.type == 'TaggedType'):
         val = val.val
-        ttype += '/_untag'
+        ttype += '/' + UNTAG_TYPE_NAME
       if (val.type != 'Type_Ref'):
         if (type != ttype):
           types.append(ttype)
@@ -842,7 +856,7 @@ class EthCtx:
   def dummy_import_type(self, ident):
     # dummy imported
     if ident in self.type:
-        raise "Try to dummy import for existing type :" + ident
+        raise Exception("Try to dummy import for existing type :%s" % ident)
     ethtype = asn2c(ident)
     self.type[ident] = {'import'  : 'xxx', 'proto' : 'xxx',
                         'ethname' : ethtype }
@@ -910,6 +924,7 @@ class EthCtx:
         self.type_imp.remove(ident)
       else:
         raise DuplicateError("type", ident)
+    val.ident = ident
     self.type[ident] = { 'val' : val, 'import' : None }
     self.type[ident]['module'] = self.Module()
     self.type[ident]['proto'] = self.proto
@@ -919,6 +934,7 @@ class EthCtx:
       self.type[ident]['tname'] = asn2c(ident)
     self.type[ident]['export'] = self.conform.use_item('EXPORTS', ident)
     self.type[ident]['enum'] = self.conform.use_item('MAKE_ENUM', ident)
+    self.type[ident]['vals_ext'] = self.conform.use_item('USE_VALS_EXT', ident)
     self.type[ident]['user_def'] = self.conform.use_item('USER_DEFINED', ident)
     self.type[ident]['no_emit'] = self.conform.use_item('NO_EMIT', ident)
     self.type[ident]['tname'] = self.conform.use_item('TYPE_RENAME', ident, val_dflt=self.type[ident]['tname'])
@@ -986,7 +1002,10 @@ class EthCtx:
     self.field[ident] = {'type' : type, 'idx' : idx, 'impl' : impl, 'pdu' : pdu,
                          'modified' : '', 'attr' : {} }
     name = ident.split('/')[-1]
-    if len(ident.split('/')) > 1 and name == '_item':  # Sequence/Set of type
+    if self.remove_prefix and name.startswith(self.remove_prefix):
+        name = name[len(self.remove_prefix):]
+
+    if len(ident.split('/')) > 1 and name == ITEM_FIELD_NAME:  # Sequence/Set of type
       if len(self.field[ident]['type'].split('/')) > 1:
         self.field[ident]['attr']['NAME'] = '"%s item"' % ident.split('/')[-2]
         self.field[ident]['attr']['ABBREV'] = asn2c(ident.split('/')[-2] + name)
@@ -1007,6 +1026,10 @@ class EthCtx:
     if parent:
       self.eth_dep_add(parent, type)
 
+  def eth_dummy_eag_field_required(self):
+    if (not self.dummy_eag_field):
+      self.dummy_eag_field = 'dummy_eag_field'
+
   #--- eth_clean --------------------------------------------------------------
   def eth_clean(self):
     self.proto = self.proto_opt;
@@ -1056,6 +1079,7 @@ class EthCtx:
     self.eth_hf_ord = []
     self.eth_hfpdu_ord = []
     self.eth_hf_dupl = {}
+    self.dummy_eag_field = None
     #--- type dependencies -------------------
     self.eth_type_ord1 = []
     self.eth_dep_cycle = []
@@ -1120,25 +1144,35 @@ class EthCtx:
         self.type[tt]['val'].sel_req(t, self.sel_req[t]['sel'], self)
 
     #--- types -------------------
-    for t in self.type_imp:
+    for t in self.type_imp: # imported types
       nm = asn2c(t)
       self.eth_type[nm] = { 'import' : self.type[t]['import'],
                             'proto' : asn2c(self.type[t]['proto']),
                             'attr' : {}, 'ref' : []}
       self.eth_type[nm]['attr'].update(self.conform.use_item('ETYPE_ATTR', nm))
       self.type[t]['ethname'] = nm
+    for t in self.type_ord: # dummy import for missing type reference
+      tp = self.type[t]['val']
+      #print "X : %s %s " % (t, tp.type)
+      if isinstance(tp, TaggedType):
+        #print "%s : %s " % (tp.type, t)
+        tp = tp.val
+      if isinstance(tp, Type_Ref):
+        #print "%s : %s ::= %s " % (tp.type, t, tp.val)
+        if tp.val not in self.type:
+          self.dummy_import_type(tp.val)
     for t in self.type_ord:
       nm = self.type[t]['tname']
       if ((nm.find('#') >= 0) or
           ((len(t.split('/'))>1) and
            (self.conform.get_fn_presence(t) or self.conform.check_item('FN_PARS', t) or
-            self.conform.get_fn_presence('/'.join((t,'_item'))) or self.conform.check_item('FN_PARS', '/'.join((t,'_item')))) and
+            self.conform.get_fn_presence('/'.join((t,ITEM_FIELD_NAME))) or self.conform.check_item('FN_PARS', '/'.join((t,ITEM_FIELD_NAME)))) and
            not self.conform.check_item('TYPE_RENAME', t))):
-        if len(t.split('/')) == 2 and t.split('/')[1] == '_item':  # Sequence of type at the 1st level
+        if len(t.split('/')) == 2 and t.split('/')[1] == ITEM_FIELD_NAME:  # Sequence of type at the 1st level
           nm = t.split('/')[0] + t.split('/')[1]
-        elif t.split('/')[-1] == '_item':  # Sequence/Set of type at next levels
+        elif t.split('/')[-1] == ITEM_FIELD_NAME:  # Sequence/Set of type at next levels
           nm = 'T_' + self.conform.use_item('FIELD_RENAME', '/'.join(t.split('/')[0:-1]), val_dflt=t.split('/')[-2]) + t.split('/')[-1]
-        elif t.split('/')[-1] == '_untag':  # Untagged type
+        elif t.split('/')[-1] == UNTAG_TYPE_NAME:  # Untagged type
           nm = self.type['/'.join(t.split('/')[0:-1])]['ethname'] + '_U'
         else:
           nm = 'T_' + self.conform.use_item('FIELD_RENAME', t, val_dflt=t.split('/')[-1])
@@ -1153,7 +1187,7 @@ class EthCtx:
         self.eth_type[nm]['ref'].append(t)
       else:
         self.eth_type_ord.append(nm)
-        self.eth_type[nm] = { 'import' : None, 'proto' : self.eproto, 'export' : 0, 'enum' : 0,
+        self.eth_type[nm] = { 'import' : None, 'proto' : self.eproto, 'export' : 0, 'enum' : 0, 'vals_ext' : 0,
                               'user_def' : EF_TYPE|EF_VALS, 'no_emit' : EF_TYPE|EF_VALS,
                               'val' : self.type[t]['val'],
                               'attr' : {}, 'ref' : [t]}
@@ -1162,10 +1196,15 @@ class EthCtx:
         self.eth_export_ord.append(nm)
       self.eth_type[nm]['export'] |= self.type[t]['export']
       self.eth_type[nm]['enum'] |= self.type[t]['enum']
+      self.eth_type[nm]['vals_ext'] |= self.type[t]['vals_ext']
       self.eth_type[nm]['user_def'] &= self.type[t]['user_def']
       self.eth_type[nm]['no_emit'] &= self.type[t]['no_emit']
       if self.type[t]['attr'].get('STRINGS') == '$$':
-        self.eth_type[nm]['attr']['STRINGS'] = 'VALS(%s)' % (self.eth_vals_nm(nm))
+        use_ext = self.type[t]['vals_ext']
+        if (use_ext):
+          self.eth_type[nm]['attr']['STRINGS'] = '&%s_ext' % (self.eth_vals_nm(nm))
+        else:
+          self.eth_type[nm]['attr']['STRINGS'] = 'VALS(%s)' % (self.eth_vals_nm(nm))
       self.eth_type[nm]['attr'].update(self.conform.use_item('ETYPE_ATTR', nm))
     for t in self.eth_type_ord:
       bits = self.eth_type[t]['val'].eth_named_bits()
@@ -1228,7 +1267,7 @@ class EthCtx:
 
     #--- fields -------------------------
     for f in (self.pdu_ord + self.field_ord):
-      if len(f.split('/')) > 1 and f.split('/')[-1] == '_item':  # Sequence/Set of type
+      if len(f.split('/')) > 1 and f.split('/')[-1] == ITEM_FIELD_NAME:  # Sequence/Set of type
         nm = self.conform.use_item('FIELD_RENAME', '/'.join(f.split('/')[0:-1]), val_dflt=f.split('/')[-2]) + f.split('/')[-1]
       else:
         nm = f.split('/')[-1]
@@ -1275,11 +1314,16 @@ class EthCtx:
       if (self.NAPI() and 'NAME' in attr):
         attr['NAME'] += self.field[f]['idx']
       attr.update(self.conform.use_item('EFIELD_ATTR', nm))
+      use_vals_ext = self.eth_type[ethtype].get('vals_ext')
+      if (use_vals_ext):
+        attr['DISPLAY'] += '|BASE_EXT_STRING'
       self.eth_hf[nm] = {'fullname' : fullname, 'pdu' : self.field[f]['pdu'],
                          'ethtype' : ethtype, 'modified' : self.field[f]['modified'],
                          'attr' : attr.copy(),
                          'ref' : [f]}
       self.field[f]['ethname'] = nm
+    if (self.dummy_eag_field):
+      self.dummy_eag_field = 'hf_%s_%s' % (self.eproto, self.dummy_eag_field)
     #--- type dependencies -------------------
     (self.eth_type_ord1, self.eth_dep_cycle) = dependency_compute(self.type_ord, self.type_dep, map_fn = lambda t: self.type[t]['ethname'], ignore_fn = lambda t: self.type[t]['import'])
     i = 0
@@ -1334,6 +1378,9 @@ class EthCtx:
   def eth_vals(self, tname, vals):
     out = ""
     has_enum = self.eth_type[tname]['enum'] & EF_ENUM
+    use_ext = self.eth_type[tname]['vals_ext']
+    if (use_ext):
+      vals.sort(key=lambda vals_entry: int(vals_entry[0]))
     if (not self.eth_type[tname]['export'] & EF_VALS):
       out += 'static '
     if (self.eth_type[tname]['export'] & EF_VALS) and (self.eth_type[tname]['export'] & EF_TABLE):
@@ -1346,6 +1393,8 @@ class EthCtx:
         vval = val
       out += '  { %3s, "%s" },\n' % (vval, id)
     out += "  { 0, NULL }\n};\n"
+    if (use_ext):
+      out += "\nstatic value_string_ext %s_ext = VALUE_STRING_EXT_INIT(%s);\n" % (self.eth_vals_nm(tname), self.eth_vals_nm(tname))
     return out
 
   #--- eth_enum_prefix ------------------------------------------------------------
@@ -1506,6 +1555,8 @@ class EthCtx:
       fx.write('/* named bits */\n')
     for nb in self.named_bit:
       fx.write("static int %s = -1;\n" % (nb['ethname']))
+    if (self.dummy_eag_field):
+      fx.write("static int %s = -1; /* never registered */ \n" % (self.dummy_eag_field))
     self.output.file_close(fx)
 
   #--- eth_output_hf_arr ------------------------------------------------------
@@ -1514,6 +1565,8 @@ class EthCtx:
     fx = self.output.file_open('hfarr')
     for f in (self.eth_hfpdu_ord + self.eth_hf_ord):
       t = self.eth_hf[f]['ethtype']
+      if self.remove_prefix and t.startswith(self.remove_prefix):
+        t = t[len(self.remove_prefix):]
       name=self.eth_hf[f]['attr']['NAME']
       trantab=maketrans("- ", "__")
       name=name.translate(trantab)
@@ -1565,7 +1618,6 @@ class EthCtx:
 
   #--- eth_output_export ------------------------------------------------------
   def eth_output_export(self):
-    if (not len(self.eth_export_ord)): return
     fx = self.output.file_open('exp', ext='h')
     for t in self.eth_export_ord:  # vals
       if (self.eth_type[t]['export'] & EF_ENUM) and self.eth_type[t]['val'].eth_has_enum(t, self):
@@ -1803,7 +1855,10 @@ class EthCtx:
       if (pdu['new']): new_prefix = 'new_'
       if (reg['rtype'] in ('NUM', 'STR')):
         rstr = ''
-        if (reg['rtype'] == 'STR'): rstr = '_string'
+        if (reg['rtype'] == 'STR'):
+         rstr = 'string'
+        else:
+         rstr = 'uint'
         if (pdu['reg']):
           dis = self.proto
           if (pdu['reg'] != '.'): dis += '.' + pdu['reg']
@@ -1814,7 +1869,7 @@ class EthCtx:
         else:
           hnd = '%screate_dissector_handle(dissect_%s, proto_%s)' % (new_prefix, f, self.eproto)
         rport = self.value_get_eth(reg['rport'])
-        fx.write('  dissector_add%s("%s", %s, %s);\n' % (rstr, reg['rtable'], rport, hnd))
+        fx.write('  dissector_add_%s("%s", %s, %s);\n' % (rstr, reg['rtable'], rport, hnd))
       elif (reg['rtype'] in ('BER', 'PER')):
         roid = self.value_get_eth(reg['roid'])
         fx.write('  %sregister_%s_oid_dissector(%s, dissect_%s, proto_%s, %s);\n' % (new_prefix, reg['rtype'].lower(), roid, f, self.eproto, reg['roidname']))
@@ -1822,6 +1877,20 @@ class EthCtx:
     fx.write('\n')
     self.output.file_close(fx, discard=fempty)
 
+  #--- eth_output_syn_reg -----------------------------------------------------
+  def eth_output_syn_reg(self):
+    fx = self.output.file_open('syn-reg')
+    fempty = True
+    first_decl = True
+    for k in self.conform.get_order('SYNTAX'):
+      reg = self.conform.use_item('SYNTAX', k)
+      if first_decl:
+        fx.write('  /*--- Syntax registrations ---*/\n')
+        first_decl = False
+      fx.write('  register_ber_syntax_dissector(%s, proto_%s, dissect_%s_PDU);\n' % (k, self.eproto, reg['pdu']));
+      fempty=False
+    self.output.file_close(fx, discard=fempty)
+
   #--- eth_output_table -----------------------------------------------------
   def eth_output_table(self):
     for num in list(self.conform.report.keys()):
@@ -1984,6 +2053,7 @@ class EthCtx:
       self.eth_output_dis_hnd()
       self.eth_output_dis_reg()
       self.eth_output_dis_tab()
+      self.eth_output_syn_reg()
       self.eth_output_table()
     if self.expcnf:
       self.eth_output_expcnf()
@@ -2031,7 +2101,9 @@ class EthCnf:
     #                                   Value name             Default value       Duplicity check   Usage check
     self.tblcfg['EXPORTS']         = { 'val_nm' : 'flag',     'val_dflt' : 0,     'chk_dup' : True, 'chk_use' : True }
     self.tblcfg['MAKE_ENUM']       = { 'val_nm' : 'flag',     'val_dflt' : 0,     'chk_dup' : True, 'chk_use' : True }
+    self.tblcfg['USE_VALS_EXT']    = { 'val_nm' : 'flag',     'val_dflt' : 0,     'chk_dup' : True, 'chk_use' : True }
     self.tblcfg['PDU']             = { 'val_nm' : 'attr',     'val_dflt' : None,  'chk_dup' : True, 'chk_use' : True }
+    self.tblcfg['SYNTAX']             = { 'val_nm' : 'attr',     'val_dflt' : None,  'chk_dup' : True, 'chk_use' : True }
     self.tblcfg['REGISTER']        = { 'val_nm' : 'attr',     'val_dflt' : None,  'chk_dup' : True, 'chk_use' : True }
     self.tblcfg['USER_DEFINED']    = { 'val_nm' : 'flag',     'val_dflt' : 0,     'chk_dup' : True, 'chk_use' : True }
     self.tblcfg['NO_EMIT']         = { 'val_nm' : 'flag',     'val_dflt' : 0,     'chk_dup' : True, 'chk_use' : True }
@@ -2125,7 +2197,7 @@ class EthCnf:
     self.fn[name][ctx]['used'] = True
     out = self.fn[name][ctx]['text']
     if (not self.suppress_line):
-      out = '#line %u "%s"\n%s\n' % (self.fn[name][ctx]['lineno'], os.path.basename(self.fn[name][ctx]['fn']), out);
+      out = '#line %u "%s"\n%s\n' % (self.fn[name][ctx]['lineno'], rel_dissector_path(self.fn[name][ctx]['fn']), out);
     return out
 
   def add_pdu(self, par, is_new, fn, lineno):
@@ -2137,6 +2209,16 @@ class EthCnf:
     self.add_item('PDU', par[0], attr=attr, fn=fn, lineno=lineno)
     return
 
+  def add_syntax(self, par, fn, lineno):
+    #print "add_syntax(par=%s, %s, %d)" % (str(par), fn, lineno)
+    if( (len(par) >=2)):
+      name = par[1]
+    else:
+      name = '"'+par[0]+'"'
+    attr = { 'pdu' : par[0] }
+    self.add_item('SYNTAX', name, attr=attr, fn=fn, lineno=lineno)
+    return
+
   def add_register(self, pdu, par, fn, lineno):
     #print "add_register(pdu=%s, par=%s, %s, %d)" % (pdu, str(par), fn, lineno)
     if (par[0] in ('N', 'NUM')):   rtype = 'NUM'; (pmin, pmax) = (2, 2)
@@ -2266,7 +2348,7 @@ class EthCnf:
                                     'OMIT_ASSIGNMENT', 'NO_OMIT_ASSGN',
                                     'VIRTUAL_ASSGN', 'SET_TYPE', 'ASSIGN_VALUE_TO_TYPE',
                                     'TYPE_RENAME', 'FIELD_RENAME', 'TF_RENAME', 'IMPORT_TAG',
-                                    'TYPE_ATTR', 'ETYPE_ATTR', 'FIELD_ATTR', 'EFIELD_ATTR'):
+                                    'TYPE_ATTR', 'ETYPE_ATTR', 'FIELD_ATTR', 'EFIELD_ATTR', 'SYNTAX'):
           ctx = result.group('name')
         elif result.group('name') in ('OMIT_ALL_ASSIGNMENTS', 'OMIT_ASSIGNMENTS_EXCEPT',
                                       'OMIT_ALL_TYPE_ASSIGNMENTS', 'OMIT_TYPE_ASSIGNMENTS_EXCEPT',
@@ -2324,6 +2406,9 @@ class EthCnf:
             elif (par[i] == 'UPPER_CASE'):     default_flags |= EF_UCASE
             elif (par[i] == 'NO_UPPER_CASE'):  default_flags &= ~EF_UCASE
             else: warnings.warn_explicit("Unknown parameter value '%s'" % (par[i]), UserWarning, fn, lineno)
+        elif result.group('name') == 'USE_VALS_EXT':
+          ctx = result.group('name')
+          default_flags = 0xFF
         elif result.group('name') == 'FN_HDR':
           minp = 1
           if (ctx in ('FN_PARS',)) and name: minp = 0
@@ -2458,6 +2543,12 @@ class EthCnf:
           elif (par[i] == 'NO_UPPER_CASE'):  flags &= ~EF_UCASE
           else: warnings.warn_explicit("Unknown parameter value '%s'" % (par[i]), UserWarning, fn, lineno)
         self.add_item('MAKE_ENUM', par[0], flag=flags, fn=fn, lineno=lineno)
+      elif ctx == 'USE_VALS_EXT':
+        if empty.match(line): continue
+        par = get_par(line, 1, 1, fn=fn, lineno=lineno)
+        if not par: continue
+        flags = default_flags
+        self.add_item('USE_VALS_EXT', par[0], flag=flags, fn=fn, lineno=lineno)
       elif ctx in ('PDU', 'PDU_NEW'):
         if empty.match(line): continue
         par = get_par(line, 1, 5, fn=fn, lineno=lineno)
@@ -2467,6 +2558,13 @@ class EthCnf:
         self.add_pdu(par[0:2], is_new, fn, lineno)
         if (len(par)>=3):
           self.add_register(par[0], par[2:5], fn, lineno)
+      elif ctx in ('SYNTAX'):
+        if empty.match(line): continue
+        par = get_par(line, 1, 2, fn=fn, lineno=lineno)
+        if not par: continue
+        if not self.check_item('PDU', par[0]):
+          self.add_pdu(par[0:1], False, fn, lineno)
+        self.add_syntax(par, fn, lineno)
       elif ctx in ('REGISTER', 'REGISTER_NEW'):
         if empty.match(line): continue
         par = get_par(line, 3, 4, fn=fn, lineno=lineno)
@@ -2642,6 +2740,10 @@ class EthCnf:
       par = self.check_par(par, 1, 1, fn, lineno)
       if not par: return
       self.ectx.default_external_type_cb = par[0]
+    elif opt in ("-r",):
+      par = self.check_par(par, 1, 1, fn, lineno)
+      if not par: return
+      self.ectx.remove_prefix = par[0]
     else:
       warnings.warn_explicit("Unknown option %s" % (opt),
                              UserWarning, fn, lineno)
@@ -2715,12 +2817,9 @@ class EthOut:
       fn += '-' + ftype
     fn += '.' + ext
     return fn
-  #--- output_fullname -------------------------------------------------------
-  def output_fullname(self, ftype, ext='c'):
-    return os.path.join(self.outdir, self.output_fname(ftype, ext=ext))
   #--- file_open -------------------------------------------------------
   def file_open(self, ftype, ext='c'):
-    fn = self.output_fullname(ftype, ext=ext)
+    fn = self.output_fname(ftype, ext=ext)
     if self.created_file_exists(fn):
       fx = file(fn, 'a')
     else:
@@ -2775,11 +2874,11 @@ class EthOut:
   def make_single_file(self):
     if (not self.single_file): return
     in_nm = self.single_file + '.c'
-    out_nm = self.output_fullname('')
+    out_nm = os.path.join(self.outdir, self.output_fname(''))
     self.do_include(out_nm, in_nm)
     in_nm = self.single_file + '.h'
     if (os.path.exists(in_nm)):
-      out_nm = self.output_fullname('', ext='h')
+      out_nm = os.path.join(self.outdir, self.output_fname('', ext='h'))
       self.do_include(out_nm, in_nm)
     if (not self.keep):
       for fn in self.created_files_ord:
@@ -2798,7 +2897,7 @@ class EthOut:
     fout.write(self.fhdr(out_nm))
     fout.write('/* Input file: ' + os.path.basename(in_nm) +' */\n')
     fout.write('\n')
-    fout.write('#line %u "%s"\n' % (1, os.path.basename(in_nm)))
+    fout.write('#line %u "%s"\n' % (1, rel_dissector_path(in_nm)))
 
     include = re.compile(r'^\s*#\s*include\s+[<"](?P<fname>[^>"]+)[>"]', re.IGNORECASE)
 
@@ -2820,12 +2919,12 @@ class EthOut:
       if (ifile):
         fout.write('\n')
         fout.write('/*--- Included file: ' + ifile + ' ---*/\n')
-        fout.write('#line %u "%s"\n' % (1, os.path.basename(ifile)))
+        fout.write('#line %u "%s"\n' % (1, rel_dissector_path(ifile)))
         finc = file(ifile, "r")
         fout.write(finc.read())
         fout.write('\n')
         fout.write('/*--- End of included file: ' + ifile + ' ---*/\n')
-        fout.write('#line %u "%s"\n' % (cont_linenum+1, os.path.basename(in_nm)) )
+        fout.write('#line %u "%s"\n' % (cont_linenum+1, rel_dissector_path(in_nm)) )
         finc.close()
       else:
         fout.write(line)
@@ -2877,6 +2976,7 @@ class Node:
     def fld_obj_repr(self, ectx):
         return "/* TO DO %s */" % (str(self))
 
+
 #--- ValueAssignment -------------------------------------------------------------
 class ValueAssignment (Node):
   def __init__(self,*args, **kw) :
@@ -3010,6 +3110,9 @@ class Type (Node):
   def eth_strings(self):
     return 'NULL'
 
+  def eth_omit_field(self):
+    return False
+
   def eth_need_tree(self):
     return False
 
@@ -3043,7 +3146,7 @@ class Type (Node):
   def eth_reg(self, ident, ectx, tstrip=0, tagflag=False, selflag=False, idx='', parent=None):
     #print "eth_reg(): %s, ident=%s, tstrip=%d, tagflag=%s, selflag=%s, parent=%s" %(self.type, ident, tstrip, str(tagflag), str(selflag), str(parent))
     #print " ", self
-    if (ectx.Tag() and (len(self.tags) > tstrip)):
+    if (ectx.NeedTags() and (len(self.tags) > tstrip)):
       tagged_type = self
       for i in range(len(self.tags)-1, tstrip-1, -1):
         tagged_type = TaggedType(val=tagged_type, tstrip=i)
@@ -3090,7 +3193,7 @@ class Type (Node):
       self.eth_reg_sub(vnm, ectx)
     if parent and (ectx.type[parent]['val'].type == 'TaggedType'):
       ectx.type[parent]['val'].eth_set_val_name(parent, trnm, ectx)
-    if ident and not tagflag:
+    if ident and not tagflag and not self.eth_omit_field():
       ectx.eth_reg_field(nm, trnm, idx=idx, parent=parent, impl=self.HasImplicitTag(ectx))
     if ectx.conform.check_item('SET_TYPE', nm):
       virtual_tr.eth_reg_sub(nm, ectx)
@@ -3199,7 +3302,7 @@ class Type (Node):
       for k in list(pars.keys()):
         try:
           pars[k] = pars[k] % pars
-        except (TypeError):
+        except (ValueError,TypeError):
           raise sys.exc_info()[0], "%s\n%s" % (str(pars), sys.exc_info()[1])
     out = '\n'
     out += self.eth_type_default_table(ectx, tname) % pars
@@ -3265,7 +3368,7 @@ class Tag (Node):
                                                 self.tag.num),
                                     self.typ.to_python (ctx))
   def IsImplicit(self, ectx):
-    return ((self.mode == 'IMPLICIT') or ((self.mode == 'default') and (ectx.tag_def == 'IMPLICIT')))
+    return ((self.mode == 'IMPLICIT') or ((self.mode == 'default') and (ectx.tag_def != 'EXPLICIT')))
 
   def GetTag(self, ectx):
     tc = ''
@@ -3284,6 +3387,7 @@ class Tag (Node):
     return n + str(self.num)
 
 #--- Constraint ---------------------------------------------------------------
+constr_cnt = 0
 class Constraint (Node):
   def to_python (self, ctx):
     print "Ignoring constraint:", self.type
@@ -3423,7 +3527,7 @@ class Constraint (Node):
         if (int(val) < 0):
           return 'M' + str(-int(val))
         else:
-          return str(val)
+          return str(int(val))
       except (ValueError, TypeError):
         return asn2c(str(val))
 
@@ -3437,7 +3541,11 @@ class Constraint (Node):
     elif self.type == 'Size':
       return 'SIZE_' + self.subtype.eth_constrname() + ext
     else:
-      return 'CONSTR' + str(id(self)) + ext
+      if (not hasattr(self, 'constr_num')):
+        global constr_cnt
+        constr_cnt += 1
+        self.constr_num = constr_cnt
+      return 'CONSTR%03d%s' % (self.constr_num, ext)
 
 
 class Module (Node):
@@ -3686,7 +3794,7 @@ class TaggedType (Type):
     ectx.eth_dep_add(ident, self.val_name)
 
   def eth_reg_sub(self, ident, ectx):
-    self.val_name = ident + '/' + '_untag'
+    self.val_name = ident + '/' + UNTAG_TYPE_NAME
     self.val.eth_reg(self.val_name, ectx, tstrip=self.tstrip+1, tagflag=True, parent=ident)
 
   def GetTTag(self, ectx):
@@ -3721,11 +3829,13 @@ class TaggedType (Type):
 #--- SqType -----------------------------------------------------------
 class SqType (Type):
   def out_item(self, f, val, optional, ext, ectx):
-    ef = ectx.field[f]['ethname']
-    t = ectx.eth_hf[ef]['ethtype']
-    efd = ef
-    if (ectx.Ber() and ectx.field[f]['impl']):
-      efd += '_impl'
+    if (val.eth_omit_field()):
+      t = ectx.type[val.ident]['ethname']
+      fullname = ectx.dummy_eag_field
+    else:
+      ef = ectx.field[f]['ethname']
+      t = ectx.eth_hf[ef]['ethtype']
+      fullname = ectx.eth_hf[ef]['fullname']
     if (ectx.Ber()):
       #print "optional=%s, e.val.HasOwnTag()=%s, e.val.IndetermTag()=%s" % (str(e.optional), str(e.val.HasOwnTag()), str(e.val.IndetermTag(ectx)))
       #print val.str_depth(1)
@@ -3750,10 +3860,10 @@ class SqType (Type):
     if (ectx.Ber()):
       (tc, tn) = val.GetTag(ectx)
       out = '  { %-24s, %-13s, %s, %s, dissect_%s_%s },\n' \
-            % ('&'+ectx.eth_hf[ef]['fullname'], tc, tn, opt, ectx.eth_type[t]['proto'], t)
+            % ('&'+fullname, tc, tn, opt, ectx.eth_type[t]['proto'], t)
     elif (ectx.Per()):
       out = '  { %-24s, %-23s, %-17s, dissect_%s_%s },\n' \
-            % ('&'+ectx.eth_hf[ef]['fullname'], ext, opt, ectx.eth_type[t]['proto'], t)
+            % ('&'+fullname, ext, opt, ectx.eth_type[t]['proto'], t)
     else:
       out = ''
     return out
@@ -3761,12 +3871,16 @@ class SqType (Type):
 #--- SeqType -----------------------------------------------------------
 class SeqType (SqType):
 
-  def need_components(self):
+  def all_components(self):
     lst = self.elt_list[:]
     if hasattr(self, 'ext_list'):
       lst.extend(self.ext_list)
     if hasattr(self, 'elt_list2'):
       lst.extend(self.elt_list2)
+    return lst
+
+  def need_components(self):
+    lst = self.all_components()
     for e in (lst):
       if e.type == 'components_of':
         return True
@@ -3798,6 +3912,66 @@ class SeqType (SqType):
       lst.extend(self.elt_list2)
     return lst
 
+  def eth_reg_sub(self, ident, ectx, components_available=False):
+    # check if autotag is required
+    autotag = False
+    if (ectx.NeedTags() and (ectx.tag_def == 'AUTOMATIC')):
+      autotag = True
+      lst = self.all_components()
+      for e in (self.elt_list):
+        if e.val.HasOwnTag(): autotag = False; break;
+    # expand COMPONENTS OF
+    if self.need_components():
+      if components_available:
+        self.expand_components(ectx)
+      else:
+        ectx.eth_comp_req(ident)
+        return
+    # extension addition groups
+    if hasattr(self, 'ext_list'):
+      if (ectx.Per()):  # add names
+        eag_num = 1
+        for e in (self.ext_list):
+          if isinstance(e.val, ExtensionAdditionGroup):
+            e.val.parent_ident = ident
+            e.val.parent_tname = ectx.type[ident]['tname']
+            if (e.val.ver):
+              e.val.SetName("eag_v%s" % (e.val.ver))
+            else:
+              e.val.SetName("eag_%d" % (eag_num))
+              eag_num += 1;
+      else:  # expand
+        new_ext_list = []
+        for e in (self.ext_list):
+          if isinstance(e.val, ExtensionAdditionGroup):
+            new_ext_list.extend(e.val.elt_list)
+          else:
+            new_ext_list.append(e)
+        self.ext_list = new_ext_list
+    # do autotag
+    if autotag:
+      atag = 0
+      for e in (self.elt_list):
+        e.val.AddTag(Tag(cls = 'CONTEXT', num = str(atag), mode = 'IMPLICIT'))
+        atag += 1
+      if autotag and hasattr(self, 'elt_list2'):
+        for e in (self.elt_list2):
+          e.val.AddTag(Tag(cls = 'CONTEXT', num = str(atag), mode = 'IMPLICIT'))
+          atag += 1
+      if autotag and hasattr(self, 'ext_list'):
+        for e in (self.ext_list):
+          e.val.AddTag(Tag(cls = 'CONTEXT', num = str(atag), mode = 'IMPLICIT'))
+          atag += 1
+    # register components
+    for e in (self.elt_list):
+      e.val.eth_reg(ident, ectx, tstrip=1, parent=ident)
+    if hasattr(self, 'ext_list'):
+      for e in (self.ext_list):
+        e.val.eth_reg(ident, ectx, tstrip=1, parent=ident)
+    if hasattr(self, 'elt_list2'):
+      for e in (self.elt_list2):
+        e.val.eth_reg(ident, ectx, tstrip=1, parent=ident)
+
   def eth_type_default_table(self, ectx, tname):
     #print "eth_type_default_table(tname='%s')" % (tname)
     fname = ectx.eth_type[tname]['ref'][0]
@@ -3806,6 +3980,9 @@ class SeqType (SqType):
       ext = 'ASN1_EXTENSION_ROOT'
     else:
       ext = 'ASN1_NO_EXTENSIONS'
+    empty_ext_flag = '0'
+    if (len(self.elt_list)==0) and hasattr(self, 'ext_list') and (len(self.ext_list)==0) and (not hasattr(self, 'elt_list2') or (len(self.elt_list2)==0)):
+      empty_ext_flag = ext
     for e in (self.elt_list):
       f = fname + '/' + e.val.name
       table += self.out_item(f, e.val, e.optional, ext, ectx)
@@ -3820,7 +3997,7 @@ class SeqType (SqType):
     if (ectx.Ber()):
       table += "  { NULL, 0, 0, 0, NULL }\n};\n"
     else:
-      table += "  { NULL, 0, 0, NULL }\n};\n"
+      table += "  { NULL, %s, 0, NULL }\n};\n" % (empty_ext_flag)
     return table
 
 #--- SeqOfType -----------------------------------------------------------
@@ -3831,7 +4008,7 @@ class SeqOfType (SqType):
     if self.val.IsNamed ():
       f = fname + '/' + self.val.name
     else:
-      f = fname + '/' + '_item'
+      f = fname + '/' + ITEM_FIELD_NAME
     table = "static const %(ER)s_sequence_t %(TABLE)s[1] = {\n"
     table += self.out_item(f, self.val, False, 'ASN1_NO_EXTENSIONS', ectx)
     table += "};\n"
@@ -3852,7 +4029,7 @@ class SequenceOfType (SeqOfType):
   def eth_reg_sub(self, ident, ectx):
     itmnm = ident
     if not self.val.IsNamed ():
-      itmnm += '/' + '_item'
+      itmnm += '/' + ITEM_FIELD_NAME
     self.val.eth_reg(itmnm, ectx, tstrip=1, idx='[##]', parent=ident)
 
   def eth_tname(self):
@@ -3909,7 +4086,7 @@ class SetOfType (SeqOfType):
   def eth_reg_sub(self, ident, ectx):
     itmnm = ident
     if not self.val.IsNamed ():
-      itmnm += '/' + '_item'
+      itmnm += '/' + ITEM_FIELD_NAME
     self.val.eth_reg(itmnm, ectx, tstrip=1, idx='(##)', parent=ident)
 
   def eth_tname(self):
@@ -4015,22 +4192,6 @@ class SequenceType (SeqType):
       ctx.outdent ()
       return rv
 
-  def eth_reg_sub(self, ident, ectx, components_available=False):
-    if self.need_components():
-      if components_available:
-        self.expand_components(ectx)
-      else:
-        ectx.eth_comp_req(ident)
-        return
-    for e in (self.elt_list):
-        e.val.eth_reg(ident, ectx, tstrip=1, parent=ident)
-    if hasattr(self, 'ext_list'):
-        for e in (self.ext_list):
-            e.val.eth_reg(ident, ectx, tstrip=1, parent=ident)
-    if hasattr(self, 'elt_list2'):
-        for e in (self.elt_list2):
-            e.val.eth_reg(ident, ectx, tstrip=1, parent=ident)
-
   def eth_need_tree(self):
     return True
 
@@ -4055,21 +4216,43 @@ class SequenceType (SeqType):
       body = '#error Can not decode %s' % (tname)
     return body
 
-#--- SetType ------------------------------------------------------------------
-class SetType(SeqType):
+#--- ExtensionAdditionGroup ---------------------------------------------------
+class ExtensionAdditionGroup (SeqType):
+  def __init__(self,*args, **kw) :
+    self.parent_ident = None
+    self.parent_tname = None
+    SeqType.__init__ (self,*args, **kw)
 
-  def eth_reg_sub(self, ident, ectx, components_available=False):
-    if self.need_components():
-      if components_available:
-        self.expand_components(ectx)
-      else:
-        ectx.eth_comp_req(ident)
-        return
-    for e in (self.elt_list):
-      e.val.eth_reg(ident, ectx, tstrip=1, parent=ident)
-    if hasattr(self, 'ext_list'):
-      for e in (self.ext_list):
-        e.val.eth_reg(ident, ectx, tstrip=1, parent=ident)
+  def eth_omit_field(self):
+    return True
+
+  def eth_tname(self):
+    if (self.parent_tname and self.IsNamed()):
+      return self.parent_tname + "_" + self.name
+    else:
+      return SeqType.eth_tname(self)
+
+  def eth_reg_sub(self, ident, ectx):
+    ectx.eth_dummy_eag_field_required()
+    ectx.eth_dep_add(self.parent_ident, ident)
+    SeqType.eth_reg_sub(self, ident, ectx)
+
+  def eth_type_default_pars(self, ectx, tname):
+    pars = Type.eth_type_default_pars(self, ectx, tname)
+    pars['TABLE'] = '%(PROTOP)s%(TNAME)s_sequence'
+    return pars
+
+  def eth_type_default_body(self, ectx, tname):
+    if (ectx.Per()):
+      body = ectx.eth_fn_call('dissect_%(ER)s_sequence_eag', ret='offset',
+                              par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(TABLE)s',),))
+    else:
+      body = '#error Can not decode %s' % (tname)
+    return body
+
+
+#--- SetType ------------------------------------------------------------------
+class SetType (SeqType):
 
   def eth_need_tree(self):
     return True
@@ -4136,6 +4319,25 @@ class ChoiceType (Type):
 
   def eth_reg_sub(self, ident, ectx):
     #print "eth_reg_sub(ident='%s')" % (ident)
+    # check if autotag is required
+    autotag = False
+    if (ectx.NeedTags() and (ectx.tag_def == 'AUTOMATIC')):
+      autotag = True
+      for e in (self.elt_list):
+        if e.HasOwnTag(): autotag = False; break;
+      if autotag and hasattr(self, 'ext_list'):
+        for e in (self.ext_list):
+          if e.HasOwnTag(): autotag = False; break;
+    # do autotag
+    if autotag:
+      atag = 0
+      for e in (self.elt_list):
+        e.AddTag(Tag(cls = 'CONTEXT', num = str(atag), mode = 'IMPLICIT'))
+        atag += 1
+      if autotag and hasattr(self, 'ext_list'):
+        for e in (self.ext_list):
+          e.AddTag(Tag(cls = 'CONTEXT', num = str(atag), mode = 'IMPLICIT'))
+          atag += 1
     for e in (self.elt_list):
         e.eth_reg(ident, ectx, tstrip=1, parent=ident)
         if ectx.conform.check_item('EXPORTS', ident + '.' + e.name):
@@ -4279,9 +4481,6 @@ class ChoiceType (Type):
       f = fname + '/' + e.name
       ef = ectx.field[f]['ethname']
       t = ectx.eth_hf[ef]['ethtype']
-      efd = ef
-      if (ectx.field[f]['impl']):
-        efd += '_impl'
       if (ectx.Ber()):
         opt = ''
         if (not e.HasOwnTag()):
@@ -4310,6 +4509,9 @@ class ChoiceType (Type):
       ext = 'ASN1_EXTENSION_ROOT'
     else:
       ext = 'ASN1_NO_EXTENSIONS'
+    empty_ext_flag = '0'
+    if (len(self.elt_list)==0) and hasattr(self, 'ext_list') and (len(self.ext_list)==0):
+      empty_ext_flag = ext
     for e in (self.elt_list):
       if (tagval): val = e.GetTag(ectx)[1]
       else: val = str(cnt)
@@ -4324,7 +4526,7 @@ class ChoiceType (Type):
     if (ectx.Ber()):
       table += "  { 0, NULL, 0, 0, 0, NULL }\n};\n"
     else:
-      table += "  { 0, NULL, 0, NULL }\n};\n"
+      table += "  { 0, NULL, %s, NULL }\n};\n" % (empty_ext_flag)
     return table
 
   def eth_type_default_body(self, ectx, tname):
@@ -5295,6 +5497,8 @@ class HStringValue (Value):
     vv = '0x'
     vv += self.val[1:-2]
     return vv
+  def __int__(self):
+    return int(self.val[1:-2], 16)
 
 #--- FieldSpec ----------------------------------------------------------------
 class FieldSpec (Node):
@@ -5393,8 +5597,8 @@ def p_ModuleBegin (t):
 
 def p_TagDefault_1 (t):
   '''TagDefault : EXPLICIT TAGS
-  | IMPLICIT TAGS
-  | AUTOMATIC TAGS'''
+                | IMPLICIT TAGS
+                | AUTOMATIC TAGS '''
   t[0] = Default_Tags (dfl_tag = t[1])
 
 def p_TagDefault_2 (t):
@@ -5881,7 +6085,7 @@ def p_SequenceType_2 (t):
   if 'ext_list' in t[3]:
     t[0].ext_list = t[3]['ext_list']
   if 'elt_list2' in t[3]:
-    t[0].ext_list = t[3]['elt_list2']
+    t[0].elt_list2 = t[3]['elt_list2']
 
 def p_ExtensionAndException_1 (t):
   'ExtensionAndException : ELLIPSIS'
@@ -5923,33 +6127,36 @@ def p_ComponentTypeLists_7 (t):
     'ComponentTypeLists : ExtensionAndException ExtensionAdditionList OptionalExtensionMarker'
     t[0] = {'elt_list' : [], 'ext_list' : t[2]}
 
-#def p_RootComponentTypeList (t):
-#    'RootComponentTypeList : ComponentTypeList'
-#    t[0] = t[1]
-
 def p_ExtensionEndMarker (t):
   'ExtensionEndMarker : COMMA ELLIPSIS'
   pass
 
-#def p_extension_additions_1 (t):
-#    'extension_additions : extension_addition_list'
-#    t[0] = t[1]
-
-#def p_extension_additions_2 (t):
-#    'extension_additions : '
-#    t[0] = []
-
 def p_ExtensionAdditionList_1 (t):
-  'ExtensionAdditionList : COMMA extension_addition'
+  'ExtensionAdditionList : COMMA ExtensionAddition'
   t[0] = [t[2]]
 
 def p_ExtensionAdditionList_2 (t):
-  'ExtensionAdditionList : ExtensionAdditionList COMMA extension_addition'
+  'ExtensionAdditionList : ExtensionAdditionList COMMA ExtensionAddition'
   t[0] = t[1] + [t[3]]
 
-def p_extension_addition_1 (t):
-    'extension_addition : ComponentType'
-    t[0] = t[1]
+def p_ExtensionAddition_1 (t):
+  'ExtensionAddition : ExtensionAdditionGroup'
+  t[0] = Node ('elt_type', val = t[1], optional = 0)
+
+def p_ExtensionAddition_2 (t):
+  'ExtensionAddition : ComponentType'
+  t[0] = t[1]
+
+def p_ExtensionAdditionGroup (t):
+  'ExtensionAdditionGroup : LVERBRACK VersionNumber ComponentTypeList RVERBRACK'
+  t[0] = ExtensionAdditionGroup (ver = t[2], elt_list = t[3])
+
+def p_VersionNumber_1 (t):
+  'VersionNumber : '
+
+def p_VersionNumber_2 (t):
+  'VersionNumber : NUMBER COLON'
+  t[0] = t[1]
 
 def p_ComponentTypeList_1 (t):
   'ComponentTypeList : ComponentType'
@@ -6028,10 +6235,11 @@ def p_SetType_1 (t):
 
 def p_SetType_2 (t):
   'SetType : SET LBRACE ComponentTypeLists RBRACE'
+  t[0] = SetType (elt_list = t[3]['elt_list'])
   if 'ext_list' in t[3]:
-    t[0] = SetType (elt_list = t[3]['elt_list'], ext_list = t[3]['ext_list'])
-  else:
-    t[0] = SetType (elt_list = t[3]['elt_list'])
+    t[0].ext_list = t[3]['ext_list']
+  if 'elt_list2' in t[3]:
+    t[0].elt_list2 = t[3]['elt_list2']
 
 
 # 27 Notation for set-of types ------------------------------------------------
@@ -6046,46 +6254,54 @@ def p_SetOfType (t):
 
 # 28.1
 def p_ChoiceType (t):
-    'ChoiceType : CHOICE LBRACE alternative_type_lists RBRACE'
+    'ChoiceType : CHOICE LBRACE AlternativeTypeLists RBRACE'
     if 'ext_list' in t[3]:
         t[0] = ChoiceType (elt_list = t[3]['elt_list'], ext_list = t[3]['ext_list'])
     else:
         t[0] = ChoiceType (elt_list = t[3]['elt_list'])
 
-def p_alternative_type_lists_1 (t):
-    'alternative_type_lists : alternative_type_list'
+def p_AlternativeTypeLists_1 (t):
+    'AlternativeTypeLists : AlternativeTypeList'
     t[0] = {'elt_list' : t[1]}
 
-def p_alternative_type_lists_2 (t):
-    '''alternative_type_lists : alternative_type_list COMMA ExtensionAndException extension_addition_alternatives OptionalExtensionMarker'''
+def p_AlternativeTypeLists_2 (t):
+    'AlternativeTypeLists : AlternativeTypeList COMMA ExtensionAndException ExtensionAdditionAlternatives OptionalExtensionMarker'
     t[0] = {'elt_list' : t[1], 'ext_list' : t[4]}
 
-def p_extension_addition_alternatives_1 (t):
-    'extension_addition_alternatives : extension_addition_alternatives_list'
+def p_ExtensionAdditionAlternatives_1 (t):
+    'ExtensionAdditionAlternatives : ExtensionAdditionAlternativesList'
     t[0] = t[1]
 
-def p_extension_addition_alternatives_2 (t):
-    'extension_addition_alternatives : '
+def p_ExtensionAdditionAlternatives_2 (t):
+    'ExtensionAdditionAlternatives : '
     t[0] = []
 
-def p_extension_addition_alternatives_list_1 (t):
-    'extension_addition_alternatives_list : COMMA extension_addition_alternative'
-    t[0] = [t[2]]
+def p_ExtensionAdditionAlternativesList_1 (t):
+    'ExtensionAdditionAlternativesList : COMMA ExtensionAdditionAlternative'
+    t[0] = t[2]
 
-def p_extension_addition_alternatives_list_2 (t):
-    'extension_addition_alternatives_list : extension_addition_alternatives_list COMMA extension_addition_alternative'
-    t[0] = t[1] + [t[3]]
+def p_ExtensionAdditionAlternativesList_2 (t):
+    'ExtensionAdditionAlternativesList : ExtensionAdditionAlternativesList COMMA ExtensionAdditionAlternative'
+    t[0] = t[1] + t[3]
 
-def p_extension_addition_alternative_1 (t):
-    'extension_addition_alternative : NamedType'
+def p_ExtensionAdditionAlternative_1 (t):
+    'ExtensionAdditionAlternative : NamedType'
+    t[0] = [t[1]]
+
+def p_ExtensionAdditionAlternative_2 (t):
+    'ExtensionAdditionAlternative : ExtensionAdditionAlternativesGroup'
     t[0] = t[1]
 
-def p_alternative_type_list_1 (t):
-    'alternative_type_list : NamedType'
+def p_ExtensionAdditionAlternativesGroup (t):
+  'ExtensionAdditionAlternativesGroup : LVERBRACK VersionNumber AlternativeTypeList RVERBRACK'
+  t[0] = t[3]
+
+def p_AlternativeTypeList_1 (t):
+    'AlternativeTypeList : NamedType'
     t[0] = [t[1]]
 
-def p_alternative_type_list_2 (t):
-    'alternative_type_list : alternative_type_list COMMA NamedType'
+def p_AlternativeTypeList_2 (t):
+    'AlternativeTypeList : AlternativeTypeList COMMA NamedType'
     t[0] = t[1] + [t[3]]
 
 # 28.10
@@ -7546,7 +7762,7 @@ asn2wrs [-h|?] [-d dbg] [-b] [-p proto] [-c cnf_file] [-e] input_file(s) ...
   -p proto      : Protocol name (implies -S). Default is module-name
                   from input_file (renamed by #.MODULE if present)
   -o name       : Output files name core (default is <proto>)
-  -O dir        : Output directory
+  -O dir        : Output directory for dissector
   -c cnf_file   : Conformance file
   -I path       : Path for conformance file includes
   -e            : Create conformance file for exported types
@@ -7558,6 +7774,7 @@ asn2wrs [-h|?] [-d dbg] [-b] [-p proto] [-c cnf_file] [-e] input_file(s) ...
   -L            : Suppress #line directive from .cnf file
   -D dir        : Directory for input_file(s) (default: '.')
   -C            : Add check for SIZE constraints
+  -r prefix     : Remove the prefix from type names
 
   input_file(s) : Input ASN.1 file(s)
 
@@ -7579,7 +7796,7 @@ def eth_main():
   global lexer
   print "ASN.1 to Wireshark dissector compiler";
   try:
-    opts, args = getopt.getopt(sys.argv[1:], "h?d:D:buXp:FTo:O:c:I:eESs:kLC");
+    opts, args = getopt.getopt(sys.argv[1:], "h?d:D:buXp:FTo:O:c:I:eESs:kLCr:");
   except getopt.GetoptError:
     eth_usage(); sys.exit(2)
   if len(args) < 1: