diff options
author | Guy Harris <guy@alum.mit.edu> | 2004-10-01 19:54:46 +0000 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2004-10-01 19:54:46 +0000 |
commit | 6aad0b0543480ffbb4a089fecd873a895922e28c (patch) | |
tree | ba1e56acf5a0553217a6758e15f2b618cc79d6dd /tools | |
parent | 017d788da09a70cd6fea59403f8126f05a809ed1 (diff) |
From Tomas Kukosa:
- fix for protocol registration (register_dissector() does not return
handle)
- new directive REGISTER which can register PDU more than once
- implicit tagging environment is supported
svn path=/trunk/; revision=12177
Diffstat (limited to 'tools')
-rw-r--r-- | tools/asn2eth.py | 141 |
1 files changed, 86 insertions, 55 deletions
diff --git a/tools/asn2eth.py b/tools/asn2eth.py index 85870429a2..174b155c04 100644 --- a/tools/asn2eth.py +++ b/tools/asn2eth.py @@ -17,7 +17,7 @@ # http://www.pobox.com/~asl2/software/PyZ3950/ # (ASN.1 to Python compiler functionality is broken but not removed, it could be revived if necessary) # -# It requires Dave Beazley's PLY parsing package licensed under the LGPL (tested with version 1.3.1) +# It requires Dave Beazley's PLY parsing package licensed under the LGPL (tested with version 1.5) # http://systems.cs.uchicago.edu/ply/ # # @@ -1040,10 +1040,9 @@ class EthCtx: dis = self.proto if (pdu['reg'] != '.'): dis += '.' + pdu['reg'] - ret = '' + fx.write(' register_dissector("%s", dissect_%s, proto_%s);\n' % (dis, f, self.eproto)) if (not pdu['hidden']): - ret = '%s_handle = ' % (asn2c(dis)) - fx.write(' %sregister_dissector("%s", dissect_%s, proto_%s);\n' % (ret, dis, f, self.eproto)) + fx.write(' %s_handle = find_dissector("%s");\n' % (asn2c(dis), dis)) fempty = False fx.write('\n') self.output.file_close(fx, discard=fempty) @@ -1052,22 +1051,27 @@ class EthCtx: def eth_output_dis_tab(self): fx = self.output.file_open('dis-tab') fempty = True - for f in self.eth_hfpdu_ord: - pdu = self.eth_hf[f]['pdu'] - if (pdu and pdu.has_key('rtype')): - if (pdu['rtype'] in ('NUM', 'STR')): - rstr = '' - if (pdu['rtype'] == 'STR'): rstr = '_string' - if (pdu and pdu['reg'] and not pdu['hidden']): - dis = self.proto - if (pdu['reg'] != '.'): dis += '.' + pdu['reg'] + for k in self.conform.get_order('REGISTER'): + reg = self.conform.use_item('REGISTER', k) + if not self.field.has_key(reg['pdu']): continue + f = self.field[reg['pdu']]['ethname'] + pdu = self.eth_hf[f]['pdu'] + if (reg['rtype'] in ('NUM', 'STR')): + rstr = '' + if (reg['rtype'] == 'STR'): rstr = '_string' + if (pdu['reg']): + dis = self.proto + if (pdu['reg'] != '.'): dis += '.' + pdu['reg'] + if (not pdu['hidden']): hnd = '%s_handle' % (asn2c(dis)) else: - hnd = 'create_dissector_handle(dissect_%s, proto_%s)' % (f, self.eproto) - fx.write(' dissector_add%s("%s", %s, %s);\n' % (rstr, pdu['rtable'], pdu['rport'], hnd)) - elif (pdu['rtype'] in ('BER', 'PER')): - fx.write(' register_%s_oid_dissector(%s, dissect_%s, proto_%s, %s);\n' % (pdu['rtype'].lower(), pdu['roid'], f, self.eproto, pdu['roidname'])) - fempty = False + hnd = 'find_dissector("%s")' % (dis) + else: + hnd = 'create_dissector_handle(dissect_%s, proto_%s)' % (f, self.eproto) + fx.write(' dissector_add%s("%s", %s, %s);\n' % (rstr, reg['rtable'], reg['rport'], hnd)) + elif (reg['rtype'] in ('BER', 'PER')): + fx.write(' register_%s_oid_dissector(%s, dissect_%s, proto_%s, %s);\n' % (reg['rtype'].lower(), reg['roid'], f, self.eproto, reg['roidname'])) + fempty = False fx.write('\n') self.output.file_close(fx, discard=fempty) @@ -1103,10 +1107,12 @@ class EthCnf: def __init__(self): self.tblcfg = {} self.table = {} + self.order = {} self.fn = {} # 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['PDU'] = { '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 } self.tblcfg['MODULE_IMPORT'] = { 'val_nm' : 'proto', 'val_dflt' : None, 'chk_dup' : True, 'chk_use' : True } @@ -1123,6 +1129,7 @@ class EthCnf: for k in self.tblcfg.keys() : self.table[k] = {} + self.order[k] = [] def add_item(self, table, key, fn, lineno, **kw): if self.tblcfg[table]['chk_dup'] and self.table[table].has_key(key): @@ -1132,6 +1139,10 @@ class EthCnf: return self.table[table][key] = {'fn' : fn, 'lineno' : lineno, 'used' : False} self.table[table][key].update(kw) + self.order[table].append(key) + + def get_order(self, table): + return self.order[table] def check_item(self, table, key): return self.table[table].has_key(key) @@ -1167,6 +1178,39 @@ class EthCnf: return ''; return self.fn[name][ctx]['text'] + def add_pdu(self, par, fn, lineno): + #print "add_pdu(par=%s, %s, %d)" % (str(par), fn, lineno) + (reg, hidden) = (None, False) + if (len(par) > 1): reg = par[1] + if (reg and reg[0]=='@'): (reg, hidden) = (reg[1:], True) + attr = {'reg' : reg, 'hidden' : hidden} + self.add_item('PDU', par[0], attr=attr, fn=fn, lineno=lineno) + return + + def add_register(self, pdu, par, fn, lineno): + #print "add_pdu(pdu=%s, par=%s, %s, %d)" % (pdu, str(par), fn, lineno) + if (par[0] in ('N', 'NUM')): rtype = 'NUM'; (pmin, pmax) = (2, 2) + elif (par[0] in ('S', 'STR')): rtype = 'STR'; (pmin, pmax) = (2, 2) + elif (par[0] in ('B', 'BER')): rtype = 'BER'; (pmin, pmax) = (1, 2) + elif (par[0] in ('P', 'PER')): rtype = 'PER'; (pmin, pmax) = (1, 2) + else: warnings.warn_explicit("Unknown registration type '%s'" % (par[2]), UserWarning, fn, lineno); return + if ((len(par)-1) < pmin): + warnings.warn_explicit("Too few parameters for %s registration type. At least %d parameters are required" % (rtype, pmin), UserWarning, fn, lineno) + return + if ((len(par)-1) > pmax): + warnings.warn_explicit("Too many parameters for %s registration type. Only %d parameters are allowed" % (rtype, pmax), UserWarning, fn, lineno) + attr = {'pdu' : pdu, 'rtype' : rtype} + if (rtype in ('NUM', 'STR')): + attr['rtable'] = par[1] + attr['rport'] = par[2] + rkey = '/'.join([rtype, attr['rtable'], attr['rport']]) + elif (rtype in ('BER', 'PER')): + attr['roid'] = par[1] + attr['roidname'] = '""' + if (len(par)>=3): attr['roidname'] = par[2] + rkey = '/'.join([rtype, attr['roid']]) + self.add_item('REGISTER', rkey, attr=attr, fn=fn, lineno=lineno) + def read(self, fn): def get_par(line, pmin, pmax, fn, lineno): par = line.split(None, pmax) @@ -1243,7 +1287,7 @@ class EthCnf: if comment.search(line): continue result = directive.search(line) if result: # directive - if result.group('name') in ('EXPORTS', 'PDU', 'USER_DEFINED', 'NO_EMIT', 'MODULE_IMPORT', 'OMIT_ASSIGNMENT', + if result.group('name') in ('EXPORTS', 'PDU', 'REGISTER', 'USER_DEFINED', 'NO_EMIT', 'MODULE_IMPORT', 'OMIT_ASSIGNMENT', 'TYPE_RENAME', 'FIELD_RENAME', 'IMPORT_TAG', 'TYPE_ATTR', 'ETYPE_ATTR', 'FIELD_ATTR', 'EFIELD_ATTR'): ctx = result.group('name') @@ -1293,32 +1337,16 @@ class EthCnf: if empty.match(line): continue par = get_par(line, 1, 5, fn=fn, lineno=lineno) if not par: continue - (reg, hidden) = (None, False) - if (len(par) > 1): reg = par[1] - if (reg and reg[0]=='@'): (reg, hidden) = (reg[1:], True) - attr = {'reg' : reg, 'hidden' : hidden} - rtype = None + self.add_pdu(par[0:2], fn, lineno) if (len(par)>=3): - if (par[2] in ('N', 'NUM')): rtype = 'NUM'; (pmin, pmax) = (2, 2) - elif (par[2] in ('S', 'STR')): rtype = 'STR'; (pmin, pmax) = (2, 2) - elif (par[2] in ('B', 'BER')): rtype = 'BER'; (pmin, pmax) = (1, 2) - elif (par[2] in ('P', 'PER')): rtype = 'PER'; (pmin, pmax) = (1, 2) - else: warnings.warn_explicit("Unknown registration type '%s'" % (par[2]), UserWarning, fn, lineno) - if (rtype and ((len(par)-3) < pmin)): - warnings.warn_explicit("Too few parameters for %s registration type. At least %d parameters are required" % (rtype, pmin), UserWarning, fn, lineno) - rtype = None - if (rtype and ((len(par)-3) > pmax)): - warnings.warn_explicit("Too many parameters for %s registration type. Only %d parameters are allowed" % (rtype, pmax), UserWarning, fn, lineno) - if (rtype): - attr['rtype'] = rtype - if (rtype in ('NUM', 'STR')): - attr['rtable'] = par[3] - attr['rport'] = par[4] - elif (rtype in ('BER', 'PER')): - attr['roid'] = par[3] - attr['roidname'] = '""' - if (len(par)>=5): attr['roidname'] = par[4] - self.add_item('PDU', par[0], attr=attr, fn=fn, lineno=lineno) + self.add_register(par[0], par[2:5], fn, lineno) + elif ctx == 'REGISTER': + if empty.match(line): continue + par = get_par(line, 3, 4, fn=fn, lineno=lineno) + if not par: continue + if not self.check_item('PDU', par[0]): + self.add_pdu(par[0:1], fn, lineno) + self.add_register(par[0], par[1:4], fn, lineno) elif ctx == 'MODULE_IMPORT': if empty.match(line): continue par = get_par(line, 2, 2, fn=fn, lineno=lineno) @@ -1501,7 +1529,7 @@ class Node: l.append (x.str_depth (depth+1)) else: l.append (indent + " " + str(x) + "\n") - return keystr + "[\n" + ''.join (l) + indent + "]\n" + return keystr + "[\n" + ''.join(l) + indent + "]\n" else: return keystr + str (child) + "\n" def str_depth (self, depth): # ugh @@ -1551,8 +1579,10 @@ class Type (Node): def HasOwnTag(self): return self.__dict__.has_key('tag') - def HasImplicitTag(self): - return self.HasOwnTag() and (self.tag.mode == 'IMPLICIT') + def HasImplicitTag(self, ectx): + return (self.HasOwnTag() and + ((self.tag.mode == 'IMPLICIT') or + ((self.tag.mode == 'default') and (ectx.tag_def == 'IMPLICIT')))) def IndetermTag(self, ectx): return False @@ -1615,7 +1645,7 @@ class Type (Node): if self.type == 'Type_Ref': ectx.eth_reg_type(nm, self) if (ectx.conform.check_item('PDU', nm)): - ectx.eth_reg_field(nm, nm, impl=self.HasImplicitTag(), pdu=ectx.conform.use_item('PDU', nm)) + ectx.eth_reg_field(nm, nm, impl=self.HasImplicitTag(ectx), pdu=ectx.conform.use_item('PDU', nm)) if self.type == 'Type_Ref': if ectx.conform.check_item('TYPE_RENAME', nm) or ectx.conform.get_fn_presence(nm): ectx.eth_reg_type(nm, self) # new type @@ -1626,9 +1656,9 @@ class Type (Node): ectx.eth_reg_type(nm, self) if ident: if self.type == 'Type_Ref': - ectx.eth_reg_field(nm, trnm, idx=idx, parent=parent, impl=self.HasImplicitTag()) + ectx.eth_reg_field(nm, trnm, idx=idx, parent=parent, impl=self.HasImplicitTag(ectx)) else: - ectx.eth_reg_field(nm, nm, idx=idx, parent=parent, impl=self.HasImplicitTag()) + ectx.eth_reg_field(nm, nm, idx=idx, parent=parent, impl=self.HasImplicitTag(ectx)) self.eth_reg_sub(nm, ectx) def eth_get_size_constr(self, ): @@ -1709,6 +1739,7 @@ class Module (Node): def to_eth (self, ectx): if (not ectx.proto): ectx.proto = self.ident.val + ectx.tag_def = self.tag_def.dfl_tag self.body.to_eth(ectx) class Module_Body (Node): @@ -1830,7 +1861,7 @@ class SqType (Type): efd = ef if (ectx.OBer() and ectx.field[f]['impl']): efd += '_impl' - if (ectx.encoding == 'ber'): + 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) opt = '' @@ -1839,7 +1870,7 @@ class SqType (Type): if (not val.HasOwnTag()): if (opt): opt += '|' opt += 'BER_FLAGS_NOOWNTAG' - elif (val.HasImplicitTag()): + elif (val.HasImplicitTag(ectx)): if (opt): opt += '|' opt += 'BER_FLAGS_IMPLTAG' if (val.IndetermTag(ectx)): @@ -2072,7 +2103,7 @@ class SequenceType (SqType): for e in (self.ext_list): f = fname + '/' + e.val.name out += self.out_item(f, e.val, e.optional, 'ASN1_NOT_EXTENSION_ROOT', ectx) - if (ectx.encoding == 'ber'): + if (ectx.Ber()): out += " { 0, 0, 0, NULL }\n};\n" else: out += " { NULL, 0, 0, NULL }\n};\n" @@ -2248,7 +2279,7 @@ class ChoiceType (Type): efd = ef if (ectx.field[f]['impl']): efd += '_impl' - if (ectx.encoding == 'ber'): + if (ectx.Ber()): opt = '' if (not e.HasOwnTag()): opt = 'BER_FLAGS_NOOWNTAG' @@ -2305,7 +2336,7 @@ class ChoiceType (Type): else: val = str(cnt) out += out_item(val, e, 'ASN1_NOT_EXTENSION_ROOT', ectx) cnt += 1 - if (ectx.encoding == 'ber'): + if (ectx.Ber()): out += " { 0, 0, 0, 0, NULL }\n};\n" else: out += " { 0, NULL, 0, NULL }\n};\n" |