added missing dependency in tagged type
[obnox/wireshark/wip.git] / tools / asn2wrs.py
1 #!/usr/bin/env python
2
3 #
4 # asn2wrs.py
5 # ASN.1 to Wireshark dissector compiler
6 # 2004 Tomas Kukosa 
7 #
8 # $Id$
9 #
10
11 """ASN.1 to Wireshark dissector compiler"""
12
13 #
14 # Compiler from ASN.1 specification to the Wireshark dissector
15 #
16 # Based on ASN.1 to Python compiler from Aaron S. Lav's PyZ3950 package licensed under the X Consortium license
17 # http://www.pobox.com/~asl2/software/PyZ3950/
18 # (ASN.1 to Python compiler functionality is broken but not removed, it could be revived if necessary)
19 #
20 # It requires Dave Beazley's PLY parsing package licensed under the LGPL (tested with version 2.3)
21 # http://www.dabeaz.com/ply/
22
23
24 # ITU-T Recommendation X.680 (07/2002), 
25 #   Information technology - Abstract Syntax Notation One (ASN.1): Specification of basic notation
26 #
27 # ITU-T Recommendation X.681 (07/2002), 
28 #   Information technology - Abstract Syntax Notation One (ASN.1): Information object specification
29 #
30 # ITU-T Recommendation X.682 (07/2002), 
31 #   Information technology - Abstract Syntax Notation One (ASN.1): Constraint specification
32 #
33 # ITU-T Recommendation X.683 (07/2002), 
34 #   Information technology - Abstract Syntax Notation One (ASN.1): Parameterization of ASN.1 specifications
35 #
36
37 from __future__ import nested_scopes
38
39 import warnings
40
41 import re
42 import sys
43 import os
44 import os.path
45 import time
46 import getopt
47
48 import __main__ # XXX blech!
49 import lex
50 import yacc
51
52 # OID name -> number conversion table
53 oid_names = {
54   '/itu-t' : 0,
55   '/itu'   : 0,
56   '/ccitt' : 0,
57   '/itu-r' : 0,
58   '0/recommendation' : 0,
59   '0.0/a' : 1,
60   '0.0/b' : 2,
61   '0.0/c' : 3,
62   '0.0/d' : 4,
63   '0.0/e' : 5,
64   '0.0/f' : 6,
65   '0.0/g' : 7,
66   '0.0/h' : 8,
67   '0.0/i' : 9,
68   '0.0/j' : 10,
69   '0.0/k' : 11,
70   '0.0/l' : 12,
71   '0.0/m' : 13,
72   '0.0/n' : 14,
73   '0.0/o' : 15,
74   '0.0/p' : 16,
75   '0.0/q' : 17,
76   '0.0/r' : 18,
77   '0.0/s' : 19,
78   '0.0/t' : 20,
79   '0.0/tseries' : 20,
80   '0.0/u' : 21,
81   '0.0/v' : 22,
82   '0.0/w' : 23,
83   '0.0/x' : 24,
84   '0.0/y' : 25,
85   '0.0/z' : 26,
86   '0/question' : 1,
87   '0/administration' : 2,
88   '0/network-operator' : 3,
89   '0/identified-organization' : 4,
90   '0/r-recommendation' : 5,
91   '0/data' : 9,
92   '/iso' : 1,
93   '1/standard' : 0,
94   '1/registration-authority' : 1,
95   '1/member-body' : 2,
96   '1/identified-organization' : 3,
97   '/joint-iso-itu-t' : 2,
98   '/joint-iso-ccitt' : 2,
99   '2/presentation' : 0,
100   '2/asn1' : 1,
101   '2/association-control' : 2,
102   '2/reliable-transfer' : 3,
103   '2/remote-operations' : 4,
104   '2/ds' : 5,
105   '2/directory' : 5,
106   '2/mhs' : 6,
107   '2/mhs-motis' : 6,
108   '2/ccr' : 7,
109   '2/oda' : 8,
110   '2/ms' : 9,
111   '2/osi-management' : 9,
112   '2/transaction-processing' : 10,
113   '2/dor' : 11,
114   '2/distinguished-object-reference' : 11,
115   '2/reference-data-transfe' : 12,
116   '2/network-layer' : 13,
117   '2/network-layer-management' : 13,
118   '2/transport-layer' : 14,
119   '2/transport-layer-management' : 14,
120   '2/datalink-layer' : 15,
121   '2/datalink-layer-managemen' : 15,
122   '2/datalink-layer-management-information' : 15,
123   '2/country' : 16,
124   '2/registration-procedures' : 17,
125   '2/registration-procedure' : 17,
126   '2/physical-layer' : 18,
127   '2/physical-layer-management' : 18,
128   '2/mheg' : 19,
129   '2/genericULS' : 20,
130   '2/generic-upper-layers-security' : 20,
131   '2/guls' : 20,
132   '2/transport-layer-security-protocol' : 21,
133   '2/network-layer-security-protocol' : 22,
134   '2/international-organizations' : 23,
135   '2/internationalRA' : 23,
136   '2/sios' : 24,
137   '2/uuid' : 25,
138   '2/odp' : 26,
139   '2/upu' : 40,
140 }
141
142 def asn2c(id):
143   return id.replace('-', '_').replace('.', '_')
144
145 class LexError(Exception): pass
146 class ParseError(Exception): pass
147
148 # 11 ASN.1 lexical items
149
150 static_tokens = {
151   r'::='    : 'ASSIGNMENT',  # 11.16 Assignment lexical item
152   r'\.\.'   : 'RANGE',       # 11.17 Range separator
153   r'\.\.\.' : 'ELLIPSIS',    # 11.18 Ellipsis
154   #r'\[\['   : 'LVERBRACK',   # 11.19 Left version brackets
155   #r'\]\]'   : 'RVERBRACK',   # 11.20 Right version brackets
156   # 11.26 Single character lexical items
157   r'\{' : 'LBRACE',
158   r'\}' : 'RBRACE',
159   r'<'  : 'LT',
160   #r'>'  : 'GT',
161   r','  : 'COMMA',
162   r'\.' : 'DOT',
163   r'\(' : 'LPAREN',
164   r'\)' : 'RPAREN',
165   r'\[' : 'LBRACK',
166   r'\]' : 'RBRACK',
167   r'-'  : 'MINUS',
168   r':'  : 'COLON',
169   #r'='  : 'EQ',
170   #r'"'  : 'QUOTATION',
171   #r"'"  : 'APOSTROPHE',
172   r';'  : 'SEMICOLON',
173   #r'@'  : 'AT',
174   #r'\!' : 'EXCLAMATION',
175   r'\^' : 'CIRCUMFLEX',
176   r'\&' : 'AMPERSAND'
177 }
178
179 # 11.27 Reserved words
180
181 # all keys in reserved_words must start w/ upper case
182 reserved_words = {
183     'TAGS' : 'TAGS',
184     'BOOLEAN' : 'BOOLEAN',
185     'INTEGER' : 'INTEGER',
186     'BIT'     : 'BIT',
187     'CHARACTER' : 'CHARACTER',
188     'STRING'  : 'STRING',
189     'OCTET'   : 'OCTET',
190     'NULL'    : 'NULL',
191     'SEQUENCE': 'SEQUENCE',
192     'OF'      : 'OF',
193     'SET'     : 'SET',
194     'IMPLICIT': 'IMPLICIT',
195     'CHOICE'  : 'CHOICE',
196     'ANY'     : 'ANY',
197 #    'EXTERNAL' : 'EXTERNAL', # XXX added over base
198     'OPTIONAL':'OPTIONAL',
199     'DEFAULT' : 'DEFAULT',
200     'COMPONENTS': 'COMPONENTS',
201     'UNIVERSAL' : 'UNIVERSAL',
202     'APPLICATION' : 'APPLICATION',
203     'PRIVATE'   : 'PRIVATE',
204     'TRUE' : 'TRUE',
205     'FALSE' : 'FALSE',
206     'BEGIN' : 'BEGIN',
207     'END' : 'END',
208     'DEFINITIONS' : 'DEFINITIONS',
209     'EXPLICIT' : 'EXPLICIT',
210     'ENUMERATED' : 'ENUMERATED',
211     'EXPORTS' : 'EXPORTS',
212     'IMPORTS' : 'IMPORTS',
213     'REAL'    : 'REAL',
214     'INCLUDES': 'INCLUDES',
215     'MIN'     : 'MIN',
216     'MAX'     : 'MAX',
217     'SIZE'    : 'SIZE',
218     'FROM'    : 'FROM',
219     'INTERSECTION' : 'INTERSECTION',
220 #    'UNION'   : 'UNION',
221     'PATTERN'    : 'PATTERN',
222     'WITH'    : 'WITH',
223     'COMPONENT': 'COMPONENT',
224     'PRESENT'  : 'PRESENT',
225     'ABSENT'   : 'ABSENT',
226 #    'DEFINED'  : 'DEFINED',
227     'CONSTRAINED' : 'CONSTRAINED',
228     'BY'       : 'BY',
229     'PLUS-INFINITY'   : 'PLUS_INFINITY',
230     'MINUS-INFINITY'  : 'MINUS_INFINITY',
231     'GeneralizedTime' : 'GeneralizedTime',
232     'UTCTime'         : 'UTCTime',
233     'ObjectDescriptor': 'ObjectDescriptor',
234     'AUTOMATIC': 'AUTOMATIC',
235     'OBJECT': 'OBJECT',
236     'IDENTIFIER': 'IDENTIFIER',
237     'TYPE-IDENTIFIER' : 'TYPE_IDENTIFIER',
238     'ABSTRACT-SYNTAX' : 'ABSTRACT_SYNTAX',
239 #      'OPERATION'       : 'OPERATION',
240 #      'ARGUMENT'        : 'ARGUMENT',
241 #      'RESULT'          : 'RESULT',
242 #      'ERRORS'          : 'ERRORS',
243 #      'LINKED'          : 'LINKED',
244 #      'ERROR'           : 'ERROR',
245 #      'PARAMETER'       : 'PARAMETER',
246 #      'BIND'            : 'BIND',
247 #      'BIND-ERROR'      : 'BIND_ERROR',
248 #      'UNBIND'          : 'UNBIND',
249 #      'APPLICATION-CONTEXT' : 'AC',
250 #      'APPLICATON-SERVICE-ELEMENTS' : 'ASES',
251 #      'REMOTE' : 'REMOTE',
252 #      'INITIATOR' : 'INITIATOR',
253 #      'RESPONDER' : 'RESPONDER',
254 #      'APPLICATION-SERVICE-ELEMENT' : 'ASE',
255 #      'OPERATIONS' : None,
256 #      'EXTENSION-ATTRIBUTE' : 'EXTENSION_ATTRIBUTE',
257 #      'EXTENSIONS' : None,
258 #      'CHOSEN' : None,
259 #      'EXTENSION' : None,
260 #      'CRITICAL': None,
261 #      'FOR' : None,
262 #      'SUBMISSION' : None,
263 #      'DELIVERY' : None,
264 #      'TRANSFER' : None,
265 #      'OBJECT' : None,
266 #      'PORTS' : None,
267 #      'PORT'  : None,
268 #      r'ABSTRACT\s*OPERATIONS' : 'ABSTR_OPS',
269 #      'REFINE' : None,
270 #      'AS' : None,
271 #      'RECURRING' : None
272     }
273
274 for k in static_tokens.keys ():
275     if static_tokens [k] == None:
276         static_tokens [k] = k
277
278 StringTypes = ['Numeric', 'Printable', 'IA5', 'BMP', 'Universal', 'UTF8',
279                'Teletex', 'T61', 'Videotex', 'Graphic', 'ISO646', 'Visible',
280                'General']
281
282 for s in StringTypes:
283   reserved_words[s + 'String'] = s + 'String'
284
285 tokens = static_tokens.values() \
286          + reserved_words.values() \
287          + ['BSTRING', 'HSTRING', 'QSTRING',
288             'UCASE_IDENT', 'LCASE_IDENT',
289             'NUMBER', 'PYQUOTE']
290
291
292 for (k, v) in static_tokens.items ():
293   __main__.__dict__['t_' + v] = k
294
295 # 11.10 Binary strings
296 def t_BSTRING (t):
297     r"'[01]*'B"
298     return t
299
300 # 11.12 Hexadecimal strings
301 def t_HSTRING (t):
302     r"'[0-9A-Fa-f]*'H"
303     return t
304
305 def t_QSTRING (t):
306     r'"([^"]|"")*"'
307     return t # XXX might want to un-""
308
309 def t_UCASE_IDENT (t):
310     r"[A-Z](-[a-zA-Z0-9]|[a-zA-Z0-9])*" # can't end w/ '-'
311     t.type = reserved_words.get(t.value, "UCASE_IDENT")
312     return t
313
314 def t_LCASE_IDENT (t):
315     r"[a-z](-[a-zA-Z0-9]|[a-zA-Z0-9])*" # can't end w/ '-'
316     return t
317
318 # 11.8 Numbers
319 def t_NUMBER (t):
320     r"0|([1-9][0-9]*)"
321     return t
322
323 # 11.9 Real numbers
324 # not supported yet
325
326 # 11.6 Comments
327 pyquote_str = 'PYQUOTE'
328 def t_COMMENT(t):
329     r"--(-[^\-\n]|[^\-\n])*(--|\n|-\n|$|-$)"
330     if (t.value.find("\n") >= 0) : t.lineno += 1
331     if t.value[2:2+len (pyquote_str)] == pyquote_str:
332         t.value = t.value[2+len(pyquote_str):]
333         t.value = t.value.lstrip ()
334         t.type = pyquote_str
335         return t
336     return None
337
338 t_ignore = " \t\r"
339
340 def t_NEWLINE(t):
341     r'\n+'
342     t.lineno += t.value.count("\n")
343
344 def t_error(t):
345     print "Error", t.value[:100], t.lineno
346     raise LexError
347
348     
349
350 class Ctx:
351     def __init__ (self, defined_dict, indent = 0):
352         self.tags_def = 'EXPLICIT' # default = explicit
353         self.indent_lev = 0
354         self.assignments = {}
355         self.dependencies = {}
356         self.pyquotes = []
357         self.defined_dict = defined_dict
358         self.name_ctr = 0
359     def spaces (self):
360         return " " * (4 * self.indent_lev)
361     def indent (self):
362         self.indent_lev += 1
363     def outdent (self):
364         self.indent_lev -= 1
365         assert (self.indent_lev >= 0)
366     def register_assignment (self, ident, val, dependencies):
367         if self.assignments.has_key (ident):
368             raise "Duplicate assignment for " + ident
369         if self.defined_dict.has_key (ident):
370             raise "cross-module duplicates for " + ident
371         self.defined_dict [ident] = 1
372         self.assignments[ident] = val
373         self.dependencies [ident] = dependencies
374         return ""
375     #        return "#%s depends on %s" % (ident, str (dependencies))
376     def register_pyquote (self, val):
377         self.pyquotes.append (val)
378         return ""
379     def output_assignments (self):
380         already_output = {}
381         text_list = []
382         assign_keys = self.assignments.keys()
383         to_output_count = len (assign_keys)
384         while 1:
385             any_output = 0
386             for (ident, val) in self.assignments.iteritems ():
387                 if already_output.has_key (ident):
388                     continue
389                 ok = 1
390                 for d in self.dependencies [ident]:
391                     if (not already_output.has_key (d) and
392                         d in assign_keys):
393                         ok = 0
394                 if ok:
395                     text_list.append ("%s=%s" % (ident,
396                                                 self.assignments [ident]))
397                     already_output [ident] = 1
398                     any_output = 1
399                     to_output_count -= 1
400                     assert (to_output_count >= 0)
401             if not any_output:
402                 if to_output_count == 0:
403                     break
404                 # OK, we detected a cycle
405                 cycle_list = []
406                 for ident in self.assignments.iterkeys ():
407                     if not already_output.has_key (ident):
408                         depend_list = [d for d in self.dependencies[ident] if d in assign_keys]
409                         cycle_list.append ("%s(%s)" % (ident, ",".join (depend_list)))
410                         
411                 text_list.append ("# Cycle XXX " + ",".join (cycle_list))
412                 for (ident, val) in self.assignments.iteritems ():
413                     if not already_output.has_key (ident):
414                         text_list.append ("%s=%s" % (ident, self.assignments [ident]))
415                 break
416
417         return "\n".join (text_list)
418     def output_pyquotes (self):
419         return "\n".join (self.pyquotes)
420     def make_new_name (self):
421         self.name_ctr += 1
422         return "_compiler_generated_name_%d" % (self.name_ctr,)
423
424 #--- Flags for EXPORT, USER_DEFINED, NO_EMIT, MAKE_ENUM -------------------------------
425 EF_TYPE    = 0x01
426 EF_VALS    = 0x02
427 EF_ENUM    = 0x04
428 EF_WS_VAR  = 0x08
429 EF_NO_PROT = 0x10
430 EF_NO_TYPE = 0x20
431 EF_UCASE   = 0x40
432 EF_DEFINE  = 0x80
433
434 #--- EthCtx -------------------------------------------------------------------
435 class EthCtx:
436   def __init__(self, conform, output, indent = 0):
437     self.conform = conform
438     self.output = output
439
440   def encp(self):  # encoding protocol
441     encp = self.encoding
442     return encp
443
444   # Encoding
445   def Per(self): return self.encoding == 'per'
446   def Ber(self): return self.encoding == 'ber'
447   def Aligned(self): return self.aligned
448   def Unaligned(self): return not self.aligned
449   def Fld(self): return self.fld_opt or self.Ber()
450   def Tag(self): return self.tag_opt # or self.Ber() - temporary comment out (experimental feature)
451   def NAPI(self): return False  # disable planned features
452
453   def dbg(self, d):
454     if (self.dbgopt.find(d) >= 0):
455       return True
456     else:
457       return False
458
459   def eth_get_type_attr(self, type):
460     types = [type]
461     while (not self.type[type]['import'] 
462            and self.type[type]['val'].type == 'Type_Ref'):
463       type = self.type[type]['val'].val
464       types.append(type)
465     attr = {}
466     while len(types):
467       t = types.pop()
468       attr.update(self.type[t]['attr'])
469       attr.update(self.eth_type[self.type[t]['ethname']]['attr'])
470     return attr
471
472   #--- eth_reg_assign ---------------------------------------------------------
473   def eth_reg_assign(self, ident, val, virt=False):
474     #print "eth_reg_assign(ident='%s')" % (ident)
475     if self.assign.has_key(ident):
476       raise "Duplicate assignment for " + ident
477     self.assign[ident] = { 'val' : val , 'virt' : virt }
478     self.assign_ord.append(ident)
479
480   #--- eth_reg_vassign --------------------------------------------------------
481   def eth_reg_vassign(self, vassign):
482     ident = vassign.ident
483     #print "eth_reg_vassign(ident='%s')" % (ident)
484     if self.vassign.has_key(ident):
485       raise "Duplicate value assignment for " + ident
486     self.vassign[ident] = vassign
487     self.vassign_ord.append(ident)
488
489   #--- eth_import_type --------------------------------------------------------
490   def eth_import_type(self, ident, mod, proto):
491     #print "eth_import_type(ident='%s', mod='%s', prot='%s')" % (ident, mod, prot)
492     if self.type.has_key(ident):
493       raise "Duplicate type for " + ident
494     self.type[ident] = {'import'  : mod, 'proto' : proto,
495                         'ethname' : '' }
496     self.type[ident]['attr'] = { 'TYPE' : 'FT_NONE', 'DISPLAY' : 'BASE_NONE',
497                                  'STRINGS' : 'NULL', 'BITMASK' : '0' }
498     self.type[ident]['attr'].update(self.conform.use_item('TYPE_ATTR', ident))
499     self.type_imp.append(ident)
500
501   #--- eth_import_value -------------------------------------------------------
502   def eth_import_value(self, ident, mod, proto):
503     #print "eth_import_value(ident='%s', mod='%s', prot='%s')" % (ident, mod, prot)
504     if self.type.has_key(ident):
505       raise "Duplicate value for " + ident
506     self.value[ident] = {'import'  : mod, 'proto' : proto,
507                          'ethname' : ''}
508     self.value_imp.append(ident)
509
510   #--- eth_dep_add ------------------------------------------------------------
511   def eth_dep_add(self, type, dep):
512     if self.type_dep.has_key(type):
513       self.type_dep[type].append(dep)
514     else:
515       self.type_dep[type] = [dep]
516
517   #--- eth_reg_type -----------------------------------------------------------
518   def eth_reg_type(self, ident, val):
519     #print "eth_reg_type(ident='%s', type='%s')" % (ident, val.type)
520     if self.type.has_key(ident):
521       raise "Duplicate type for " + ident
522     self.type[ident] = { 'val' : val, 'import' : None }
523     if len(ident.split('/')) > 1:
524       self.type[ident]['tname'] = val.eth_tname()
525     else:
526       self.type[ident]['tname'] = asn2c(ident)
527     self.type[ident]['export'] = self.conform.use_item('EXPORTS', ident)
528     self.type[ident]['enum'] = self.conform.use_item('MAKE_ENUM', ident)
529     self.type[ident]['user_def'] = self.conform.use_item('USER_DEFINED', ident)
530     self.type[ident]['no_emit'] = self.conform.use_item('NO_EMIT', ident)
531     self.type[ident]['tname'] = self.conform.use_item('TYPE_RENAME', ident, val_dflt=self.type[ident]['tname'])
532     self.type[ident]['ethname'] = ''
533     if val.type == 'Type_Ref':
534       self.type[ident]['attr'] = {}
535     else:
536       (ftype, display) = val.eth_ftype(self)
537       self.type[ident]['attr'] = { 'TYPE' : ftype, 'DISPLAY' : display,
538                                    'STRINGS' : val.eth_strings(), 'BITMASK' : '0' }
539     self.type[ident]['attr'].update(self.conform.use_item('TYPE_ATTR', ident))
540     self.type_ord.append(ident)
541
542   #--- eth_reg_value ----------------------------------------------------------
543   def eth_reg_value(self, ident, type, value):
544     #print "eth_reg_value(ident='%s')" % (ident)
545     if self.value.has_key(ident):
546       raise "Duplicate value for " + ident
547     self.value[ident] = { 'import' : None, 'proto' : self.proto,
548                           'type' : type, 'value' : value }
549     self.value[ident]['export'] = self.conform.use_item('EXPORTS', ident)
550     self.value[ident]['ethname'] = ''
551     self.value_ord.append(ident)
552
553   #--- eth_reg_field ----------------------------------------------------------
554   def eth_reg_field(self, ident, type, idx='', parent=None, impl=False, pdu=None):
555     #print "eth_reg_field(ident='%s', type='%s')" % (ident, type)
556     if self.field.has_key(ident):
557       raise "Duplicate field for " + ident
558     self.field[ident] = {'type' : type, 'idx' : idx, 'impl' : impl, 'pdu' : pdu,
559                          'modified' : '', 'attr' : {} }
560     name = ident.split('/')[-1]
561     if len(ident.split('/')) > 1 and name == '_item':  # Sequnce/Set of type
562       self.field[ident]['attr']['NAME'] = '"Item"'
563       self.field[ident]['attr']['ABBREV'] = asn2c(ident.split('/')[-2] + name)
564     else:
565       self.field[ident]['attr']['NAME'] = '"%s"' % name
566       self.field[ident]['attr']['ABBREV'] = asn2c(name)
567     if self.conform.check_item('FIELD_ATTR', ident):
568       self.field[ident]['modified'] = '#' + str(id(self))
569       self.field[ident]['attr'].update(self.conform.use_item('FIELD_ATTR', ident))
570     if (pdu):
571       self.pdu_ord.append(ident)
572     else:
573       self.field_ord.append(ident)
574     if parent: self.eth_dep_add(parent, type)
575
576   #--- eth_clean --------------------------------------------------------------
577   def eth_clean(self):
578     self.proto = self.proto_opt;
579     #--- ASN.1 tables ----------------
580     self.assign = {}
581     self.assign_ord = []
582     self.field = {}
583     self.pdu_ord = []
584     self.field_ord = []
585     self.type = {}
586     self.type_ord = []
587     self.type_imp = []
588     self.type_dep = {}
589     self.vassign = {}
590     self.vassign_ord = []
591     self.value = {}
592     self.value_ord = []
593     self.value_imp = []
594     #--- Modules ------------
595     self.modules = []
596     #--- types -------------------
597     self.eth_type = {}
598     self.eth_type_ord = []
599     self.eth_export_ord = []
600     self.eth_type_dupl = {}
601     self.named_bit = []
602     #--- value dependencies -------------------
603     self.value_dep = {}
604     #--- values -------------------
605     self.eth_value = {}
606     self.eth_value_ord = []
607     #--- fields -------------------------
608     self.eth_hf = {}
609     self.eth_hf_ord = []
610     self.eth_hfpdu_ord = []
611     self.eth_hf_dupl = {}
612     #--- type dependencies -------------------
613     self.eth_type_ord1 = []
614     self.eth_dep_cycle = []
615     self.dep_cycle_eth_type = {}
616     #--- value dependencies and export -------------------
617     self.eth_value_ord1 = []
618     self.eth_vexport_ord = []
619
620   #--- eth_prepare ------------------------------------------------------------
621   def eth_prepare(self):
622     self.eproto = asn2c(self.proto)
623
624     #--- dummy types/fields for PDU registration ---
625     nm = 'NULL'
626     if (self.conform.check_item('PDU', nm)):
627       self.eth_reg_type('_dummy/'+nm, NullType())
628       self.eth_reg_field(nm, '_dummy/'+nm, pdu=self.conform.use_item('PDU', nm))
629
630     #--- types -------------------
631     for t in self.type_imp:
632       nm = asn2c(t)
633       self.eth_type[nm] = { 'import' : self.type[t]['import'], 
634                             'proto' : asn2c(self.type[t]['proto']),
635                             'attr' : {}, 'ref' : []}
636       self.type[t]['ethname'] = nm
637     for t in self.type_ord:
638       nm = self.type[t]['tname']
639       if ((nm.find('#') >= 0) or 
640           ((len(t.split('/'))>1) and 
641            (self.conform.get_fn_presence(t) or self.conform.check_item('FN_PARS', t)) and 
642            not self.conform.check_item('TYPE_RENAME', t))):
643         if len(t.split('/')) == 2 and t.split('/')[1] == '_item':  # Sequnce of type at the 1st level
644           nm = t.split('/')[0] + t.split('/')[1]
645         elif t.split('/')[-1] == '_item':  # Sequnce/Set of type at next levels
646           nm = 'T_' + self.conform.use_item('FIELD_RENAME', '/'.join(t.split('/')[0:-1]), val_dflt=t.split('/')[-2]) + t.split('/')[-1]
647         elif t.split('/')[-1] == '_untag':  # Untagged type
648           nm = self.type['/'.join(t.split('/')[0:-1])]['ethname'] + '_U'
649         else:
650           nm = 'T_' + self.conform.use_item('FIELD_RENAME', t, val_dflt=t.split('/')[-1])
651         nm = asn2c(nm)
652         if self.eth_type.has_key(nm):
653           if self.eth_type_dupl.has_key(nm):
654             self.eth_type_dupl[nm].append(t)
655           else:
656             self.eth_type_dupl[nm] = [self.eth_type[nm]['ref'][0], t]
657           nm += str(len(self.eth_type_dupl[nm])-1)
658       if self.eth_type.has_key(nm):
659         self.eth_type[nm]['ref'].append(t)
660       else:
661         self.eth_type_ord.append(nm)
662         self.eth_type[nm] = { 'import' : None, 'proto' : self.eproto, 'export' : 0, 'enum' : 0,
663                               'user_def' : EF_TYPE|EF_VALS, 'no_emit' : EF_TYPE|EF_VALS, 
664                               'val' : self.type[t]['val'], 
665                               'attr' : {}, 
666                               'ref' : [t]}
667         self.eth_type[nm]['attr'].update(self.conform.use_item('ETYPE_ATTR', nm))
668       self.type[t]['ethname'] = nm
669       if (not self.eth_type[nm]['export'] and self.type[t]['export']):  # new export
670         self.eth_export_ord.append(nm)
671       self.eth_type[nm]['export'] |= self.type[t]['export']
672       self.eth_type[nm]['enum'] |= self.type[t]['enum']
673       self.eth_type[nm]['user_def'] &= self.type[t]['user_def']
674       self.eth_type[nm]['no_emit'] &= self.type[t]['no_emit']
675       if self.type[t]['attr'].get('STRINGS') == '$$':
676         self.eth_type[nm]['attr']['STRINGS'] = 'VALS(%s)' % (self.eth_vals_nm(nm))
677     for t in self.eth_type_ord:
678       bits = self.eth_type[t]['val'].eth_named_bits()
679       if (bits):
680         for (val, id) in bits:
681           self.named_bit.append({'name' : id, 'val' : val,
682                                  'ethname' : 'hf_%s_%s_%s' % (self.eproto, t, asn2c(id)),
683                                  'ftype'   : 'FT_BOOLEAN', 'display' : '8',
684                                  'strings' : 'NULL',
685                                  'bitmask' : '0x'+('80','40','20','10','08','04','02','01')[val%8]})
686       if self.eth_type[t]['val'].eth_need_tree():
687         self.eth_type[t]['tree'] = "ett_%s_%s" % (self.eth_type[t]['proto'], t)
688       else:
689         self.eth_type[t]['tree'] = None
690
691     #--- value dependencies -------------------
692     for v in self.value_ord:
693       if isinstance (self.value[v]['value'], Value):
694         dep = self.value[v]['value'].get_dep()
695       else:
696         dep = self.value[v]['value']
697       if dep and self.value.has_key(dep):
698         self.value_dep.setdefault(v, []).append(dep)
699     
700     #--- exports all necessary values
701     for v in self.value_ord:
702       if not self.value[v]['export']: continue
703       deparr = self.value_dep.get(v, [])
704       while deparr:
705         d = deparr.pop()
706         if not self.value[d]['import']:
707           if not self.value[d]['export']:
708             self.value[d]['export'] = EF_TYPE
709             deparr.extend(self.value_dep.get(d, []))
710
711     #--- values -------------------
712     for v in self.value_imp:
713       nm = asn2c(v)
714       self.eth_value[nm] = { 'import' : self.value[v]['import'], 
715                              'proto' : asn2c(self.value[v]['proto']), 
716                              'ref' : []}
717       self.value[v]['ethname'] = nm
718     for v in self.value_ord:
719       nm = asn2c(v)
720       self.eth_value[nm] = { 'import' : None, 
721                              'proto' : asn2c(self.value[v]['proto']),
722                              'export' : self.value[v]['export'], 'ref' : [v] }
723       if isinstance (self.value[v]['value'], Value):
724         self.eth_value[nm]['value'] = self.value[v]['value'].to_str()
725       else:
726         self.eth_value[nm]['value'] = self.value[v]['value']
727       self.eth_value_ord.append(nm)
728       self.value[v]['ethname'] = nm
729
730     #--- fields -------------------------
731     for f in (self.pdu_ord + self.field_ord):
732       if len(f.split('/')) > 1 and f.split('/')[-1] == '_item':  # Sequnce/Set of type
733         nm = self.conform.use_item('FIELD_RENAME', '/'.join(f.split('/')[0:-1]), val_dflt=f.split('/')[-2]) + f.split('/')[-1]
734       else:
735         nm = f.split('/')[-1]
736       nm = self.conform.use_item('FIELD_RENAME', f, val_dflt=nm)
737       nm = asn2c(nm)
738       if (self.field[f]['pdu']): 
739         nm += '_PDU'
740       t = self.field[f]['type']
741       if self.type.has_key(t):
742         ethtype = self.type[t]['ethname']
743       else:  # undefined type
744         # dummy imported
745         print "Dummy imported: ", t
746         self.type[t] = {'import'  : 'xxx', 'proto' : 'xxx',
747                         'ethname' : t }
748         self.type[t]['attr'] = { 'TYPE' : 'FT_NONE', 'DISPLAY' : 'BASE_NONE',
749                                  'STRINGS' : 'NULL', 'BITMASK' : '0' }
750         self.eth_type[t] = { 'import' : 'xxx', 'proto' : 'xxx' , 'attr' : {}, 'ref' : []}
751         ethtype = t
752       ethtypemod = ethtype + self.field[f]['modified']
753       if self.eth_hf.has_key(nm):
754         if self.eth_hf_dupl.has_key(nm):
755           if self.eth_hf_dupl[nm].has_key(ethtypemod):
756             nm = self.eth_hf_dupl[nm][ethtypemod]
757             self.eth_hf[nm]['ref'].append(f)
758             self.field[f]['ethname'] = nm
759             continue
760           else:
761             nmx = nm + str(len(self.eth_hf_dupl[nm]))
762             self.eth_hf_dupl[nm][ethtype] = nmx
763             nm = nmx
764         else:
765           if (self.eth_hf[nm]['ethtype']+self.eth_hf[nm]['modified']) == ethtypemod:
766             self.eth_hf[nm]['ref'].append(f)
767             self.field[f]['ethname'] = nm
768             continue
769           else:
770             self.eth_hf_dupl[nm] = {self.eth_hf[nm]['ethtype']+self.eth_hf[nm]['modified'] : nm, \
771                                     ethtypemod : nm+'1'}
772             nm += '1'
773       if (self.field[f]['pdu']):
774         self.eth_hfpdu_ord.append(nm)
775       else:
776         self.eth_hf_ord.append(nm)
777       fullname = "hf_%s_%s" % (self.eproto, nm)
778       attr = self.eth_get_type_attr(self.field[f]['type']).copy()
779       attr.update(self.field[f]['attr'])
780       if (self.NAPI() and attr.has_key('NAME')):
781         attr['NAME'] += self.field[f]['idx']
782       attr.update(self.conform.use_item('EFIELD_ATTR', nm))
783       self.eth_hf[nm] = {'fullname' : fullname, 'pdu' : self.field[f]['pdu'],
784                          'ethtype' : ethtype, 'modified' : self.field[f]['modified'],
785                          'attr' : attr.copy(), 'ref' : [f]}
786       self.field[f]['ethname'] = nm
787     #--- type dependencies -------------------
788     x = {}  # already emitted
789     #print '# Dependency computation'
790     for t in self.type_ord:
791       if x.has_key(self.type[t]['ethname']):
792         #print 'Continue: %s : %s' % (t, self.type[t]['ethname'])
793         continue
794       stack = [t]
795       stackx = {t : self.type_dep.get(t, [])[:]}
796       #print 'Push: %s : %s' % (t, str(stackx[t]))
797       while stack:
798         if stackx[stack[-1]]:  # has dependencies
799           d = stackx[stack[-1]].pop(0)
800           if x.has_key(self.type[d]['ethname']) or self.type[d]['import']:
801             continue
802           if stackx.has_key(d):  # cyclic dependency
803             c = stack[:]
804             c.reverse()
805             c = [d] + c[0:c.index(d)+1]
806             c.reverse()
807             self.eth_dep_cycle.append(c)
808             #print 'Cyclic: %s ' % (' -> '.join(c))
809             continue
810           stack.append(d)
811           stackx[d] = self.type_dep.get(d, [])[:]
812           #print 'Push: %s : %s' % (d, str(stackx[d]))
813         else:
814           #print 'Pop: %s' % (stack[-1])
815           del stackx[stack[-1]]
816           e = self.type[stack.pop()]['ethname']
817           if x.has_key(e):
818             continue
819           #print 'Add: %s' % (e)
820           self.eth_type_ord1.append(e)
821           x[e] = True
822     i = 0
823     while i < len(self.eth_dep_cycle):
824       t = self.type[self.eth_dep_cycle[i][0]]['ethname']
825       self.dep_cycle_eth_type.setdefault(t, []).append(i)
826       i += 1
827
828     #--- value dependencies and export -------------------
829     for v in self.eth_value_ord:
830       if self.eth_value[v]['export']:
831         self.eth_vexport_ord.append(v)
832       else:
833         self.eth_value_ord1.append(v)
834
835   #--- eth_vals_nm ------------------------------------------------------------
836   def eth_vals_nm(self, tname):
837     out = ""
838     if (not self.eth_type[tname]['export'] & EF_NO_PROT):
839       out += "%s_" % (self.eproto)
840     out += "%s_vals" % (tname)
841     return out
842
843   #--- eth_vals ---------------------------------------------------------------
844   def eth_vals(self, tname, vals):
845     out = ""
846     has_enum = self.eth_type[tname]['enum'] & EF_ENUM
847     if (not self.eth_type[tname]['export'] & EF_VALS):
848       out += "static "
849     out += "const value_string %s[] = {\n" % (self.eth_vals_nm(tname))
850     for (val, id) in vals:
851       if (has_enum):
852         vval = self.eth_enum_item(tname, id)
853       else:
854         vval = val
855       out += '  { %3s, "%s" },\n' % (vval, id)
856     out += "  { 0, NULL }\n};\n"
857     return out
858
859   #--- eth_enum_prefix ------------------------------------------------------------
860   def eth_enum_prefix(self, tname):
861     out = ""
862     if (self.eth_type[tname]['export'] & EF_ENUM):
863       no_prot = self.eth_type[tname]['export'] & EF_NO_PROT
864     else:
865       no_prot = self.eth_type[tname]['enum'] & EF_NO_PROT
866     if (not no_prot):
867       out += self.eproto
868     if (not self.eth_type[tname]['enum'] & EF_NO_TYPE):
869       if (out): out += '_'
870       out += tname
871     if (self.eth_type[tname]['enum'] & EF_UCASE):
872       out = out.upper()
873     return out
874
875   #--- eth_enum_nm ------------------------------------------------------------
876   def eth_enum_nm(self, tname):
877     out = self.eth_enum_prefix(tname)
878     out += "_enum"
879     return out
880
881   #--- eth_enum_item ---------------------------------------------------------------
882   def eth_enum_item(self, tname, ident):
883     out = self.eth_enum_prefix(tname)
884     out += '_' + asn2c(ident)
885     if (self.eth_type[tname]['enum'] & EF_UCASE):
886       out = out.upper()
887     return out
888
889   #--- eth_enum ---------------------------------------------------------------
890   def eth_enum(self, tname, vals):
891     out = ""
892     if (self.eth_type[tname]['enum'] & EF_DEFINE):
893       out += "/* enumerated values for %s */\n" % (tname)
894       for (val, id) in vals:
895         out += '#define %-12s %3s\n' % (self.eth_enum_item(tname, id), val)
896     else:
897       out += "typedef enum _%s {\n" % (self.eth_enum_nm(tname))
898       for (val, id) in vals:
899         out += '  %-12s %3s,\n' % (self.eth_enum_item(tname, id), val)
900       out += "} %s;\n" % (self.eth_enum_nm(tname))
901     return out
902
903   #--- eth_bits ---------------------------------------------------------------
904   def eth_bits(self, tname, bits):
905     out = ""
906     out += "static const "
907     out += "asn_namedbit %(TABLE)s[] = {\n"
908     for (val, id) in bits:
909       out += '  { %2d, &hf_%s_%s_%s, -1, -1, "%s", NULL },\n' % (val, self.eproto, tname, asn2c(id), id)
910     out += "  { 0, NULL, 0, 0, NULL, NULL }\n};\n"
911     return out
912
913   #--- eth_type_fn_h ----------------------------------------------------------
914   def eth_type_fn_h(self, tname):
915     out = ""
916     if (not self.eth_type[tname]['export'] & EF_TYPE):
917       out += "static "
918     out += "int "
919     if (self.Ber()):
920       out += "dissect_%s_%s(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *tree _U_, int hf_index _U_)" % (self.eth_type[tname]['proto'], tname)
921     elif (self.Per()):
922       out += "dissect_%s_%s(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_)" % (self.eth_type[tname]['proto'], tname)
923     out += ";\n"
924     return out
925
926   #--- eth_fn_call ------------------------------------------------------------
927   def eth_fn_call(self, fname, ret=None, indent=2, par=None):
928     out = indent * ' '
929     if (ret):
930       if (ret == 'return'):
931         out += 'return '
932       else:
933         out += ret + ' = '
934     out += fname + '('
935     ind = len(out)
936     for i in range(len(par)):
937       if (i>0): out += ind * ' '
938       out += ', '.join(par[i])
939       if (i<(len(par)-1)): out += ',\n'
940     out += ');\n'
941     return out
942
943   #--- eth_type_fn_hdr --------------------------------------------------------
944   def eth_type_fn_hdr(self, tname):
945     out = '\n'
946     if (not self.eth_type[tname]['export'] & EF_TYPE):
947       out += "static "
948     out += "int\n"
949     if (self.Ber()):
950       out += "dissect_%s_%s(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *tree _U_, int hf_index _U_) {\n" % (self.eth_type[tname]['proto'], tname)
951     elif (self.Per()):
952       out += "dissect_%s_%s(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {\n" % (self.eth_type[tname]['proto'], tname)
953     if self.conform.get_fn_presence(tname):
954       out += self.conform.get_fn_text(tname, 'FN_HDR')
955     elif self.conform.get_fn_presence(self.eth_type[tname]['ref'][0]):
956       out += self.conform.get_fn_text(self.eth_type[tname]['ref'][0], 'FN_HDR')
957     return out
958
959   #--- eth_type_fn_ftr --------------------------------------------------------
960   def eth_type_fn_ftr(self, tname):
961     out = '\n'
962     if self.conform.get_fn_presence(tname):
963       out += self.conform.get_fn_text(tname, 'FN_FTR')
964     elif self.conform.get_fn_presence(self.eth_type[tname]['ref'][0]):
965       out += self.conform.get_fn_text(self.eth_type[tname]['ref'][0], 'FN_FTR')
966     out += "  return offset;\n"
967     out += "}\n"
968     return out
969
970   #--- eth_type_fn_body -------------------------------------------------------
971   def eth_type_fn_body(self, tname, body, pars=None):
972     out = body
973     if self.conform.get_fn_body_presence(tname):
974       out = self.conform.get_fn_text(tname, 'FN_BODY')
975     elif self.conform.get_fn_body_presence(self.eth_type[tname]['ref'][0]):
976       out = self.conform.get_fn_text(self.eth_type[tname]['ref'][0], 'FN_BODY')
977     if pars:
978       try:
979         out = out % pars
980       except (TypeError):
981         pass
982     return out
983
984   #--- eth_output_hf ----------------------------------------------------------
985   def eth_output_hf (self):
986     if not len(self.eth_hf_ord) and not len(self.eth_hfpdu_ord) and not len(self.named_bit): return
987     fx = self.output.file_open('hf')
988     for f in (self.eth_hfpdu_ord + self.eth_hf_ord):
989       fx.write("%-50s/* %s */\n" % ("static int %s = -1;  " % (self.eth_hf[f]['fullname']), self.eth_hf[f]['ethtype']))
990     if (self.named_bit):
991       fx.write('/* named bits */\n')
992     for nb in self.named_bit:
993       fx.write("static int %s = -1;\n" % (nb['ethname']))
994     self.output.file_close(fx)
995     
996   #--- eth_output_hf_arr ------------------------------------------------------
997   def eth_output_hf_arr (self):
998     if not len(self.eth_hf_ord) and not len(self.eth_hfpdu_ord) and not len(self.named_bit): return
999     fx = self.output.file_open('hfarr')
1000     for f in (self.eth_hfpdu_ord + self.eth_hf_ord):
1001       t = self.eth_hf[f]['ethtype']
1002       blurb = '"%s.%s"' % (self.eth_type[t]['proto'], t)
1003       attr = self.eth_hf[f]['attr'].copy()
1004       attr['ABBREV'] = '"%s.%s"' % (self.proto, attr['ABBREV'])
1005       if not attr.has_key('BLURB'):
1006         attr['BLURB'] = blurb
1007       fx.write('    { &%s,\n' % (self.eth_hf[f]['fullname']))
1008       fx.write('      { %(NAME)s, %(ABBREV)s,\n' % attr)
1009       fx.write('        %(TYPE)s, %(DISPLAY)s, %(STRINGS)s, %(BITMASK)s,\n' % attr)
1010       fx.write('        %(BLURB)s, HFILL }},\n' % attr)
1011     for nb in self.named_bit:
1012       blurb = ''
1013       fx.write('    { &%s,\n' % (nb['ethname']))
1014       fx.write('      { "%s", "%s.%s",\n' % (nb['name'], self.proto, nb['name']))
1015       fx.write('        %s, %s, %s, %s,\n' % (nb['ftype'], nb['display'], nb['strings'], nb['bitmask']))
1016       fx.write('        "%s", HFILL }},\n' % (blurb))
1017     self.output.file_close(fx)
1018
1019   #--- eth_output_ett ---------------------------------------------------------
1020   def eth_output_ett (self):
1021     fx = self.output.file_open('ett')
1022     fempty = True
1023     #fx.write("static gint ett_%s = -1;\n" % (self.eproto))
1024     for t in self.eth_type_ord:
1025       if self.eth_type[t]['tree']:
1026         fx.write("static gint %s = -1;\n" % (self.eth_type[t]['tree']))
1027         fempty = False
1028     self.output.file_close(fx, discard=fempty)
1029
1030   #--- eth_output_ett_arr -----------------------------------------------------
1031   def eth_output_ett_arr(self):
1032     fx = self.output.file_open('ettarr')
1033     fempty = True
1034     #fx.write("    &ett_%s,\n" % (self.eproto))
1035     for t in self.eth_type_ord:
1036       if self.eth_type[t]['tree']:
1037         fx.write("    &%s,\n" % (self.eth_type[t]['tree']))
1038         fempty = False
1039     self.output.file_close(fx, discard=fempty)
1040
1041   #--- eth_output_export ------------------------------------------------------
1042   def eth_output_export(self):
1043     if (not len(self.eth_export_ord)): return
1044     fx = self.output.file_open('exp', ext='h')
1045     for t in self.eth_export_ord:  # vals
1046       if (self.eth_type[t]['export'] & EF_ENUM) and self.eth_type[t]['val'].eth_has_enum(t, self):
1047         fx.write(self.eth_type[t]['val'].eth_type_enum(t, self))
1048       if (self.eth_type[t]['export'] & EF_VALS) and self.eth_type[t]['val'].eth_has_vals():
1049         if self.eth_type[t]['export'] & EF_WS_VAR:
1050           fx.write("WS_VAR_IMPORT ")
1051         else:
1052           fx.write("extern ")
1053         fx.write("const value_string %s[];\n" % (self.eth_vals_nm(t)))
1054     for t in self.eth_export_ord:  # functions
1055       if (self.eth_type[t]['export'] & EF_TYPE):
1056         fx.write(self.eth_type_fn_h(t))
1057     self.output.file_close(fx)
1058
1059   #--- eth_output_expcnf ------------------------------------------------------
1060   def eth_output_expcnf(self):
1061     fx = self.output.file_open('exp', ext='cnf')
1062     fx.write('#.MODULE\n')
1063     maxw = 0
1064     for (m, p) in self.modules:
1065       if (len(m) > maxw): maxw = len(m)
1066     for (m, p) in self.modules:
1067       fx.write("%-*s  %s\n" % (maxw, m, p))
1068     fx.write('#.END\n\n')
1069     if self.Ber():
1070       fx.write('#.IMPORT_TAG\n')
1071       for t in self.eth_export_ord:  # tags
1072         if (self.eth_type[t]['export'] & EF_TYPE):
1073           fx.write('%-24s ' % self.eth_type[t]['ref'][0])
1074           fx.write('%s %s\n' % self.eth_type[t]['val'].GetTag(self))
1075       fx.write('#.END\n\n')
1076     fx.write('#.TYPE_ATTR\n')
1077     for t in self.eth_export_ord:  # attributes
1078       if (self.eth_type[t]['export'] & EF_TYPE):
1079         fx.write('%-24s ' % self.eth_type[t]['ref'][0])
1080         attr = self.eth_get_type_attr(self.eth_type[t]['ref'][0]).copy()
1081         fx.write('TYPE = %(TYPE)-9s  DISPLAY = %(DISPLAY)-9s  STRINGS = %(STRINGS)s  BITMASK = %(BITMASK)s\n' % attr)
1082     fx.write('#.END\n\n')
1083     self.output.file_close(fx, keep_anyway=True)
1084
1085   #--- eth_output_val ------------------------------------------------------
1086   def eth_output_val(self):
1087     if (not len(self.eth_value_ord1)): return
1088     fx = self.output.file_open('val', ext='h')
1089     for v in self.eth_value_ord1:
1090       fx.write("#define %-30s %s\n" % (v, self.eth_value[v]['value']))
1091     self.output.file_close(fx)
1092
1093   #--- eth_output_valexp ------------------------------------------------------
1094   def eth_output_valexp(self):
1095     if (not len(self.eth_vexport_ord)): return
1096     fx = self.output.file_open('valexp', ext='h')
1097     for v in self.eth_vexport_ord:
1098       fx.write("#define %-30s %s\n" % (v, self.eth_value[v]['value']))
1099     self.output.file_close(fx)
1100
1101   #--- eth_output_types -------------------------------------------------------
1102   def eth_output_types(self):
1103     def out_field(f):
1104       t = self.eth_hf[f]['ethtype']
1105       if (self.Ber()):
1106         x = {}
1107         for r in self.eth_hf[f]['ref']:
1108           x[self.field[r]['impl']] = self.field[r]['impl']
1109       else:
1110         x = {False : False}
1111       x = x.values()
1112       x.sort()
1113       out = ''
1114       for i in x:
1115         if (i):
1116           postfix = '_impl'
1117           impl = 'TRUE'
1118         else:
1119           postfix = ''
1120           impl = 'FALSE'
1121         if (self.Ber()):
1122           if (i): postfix = '_impl'; impl = 'TRUE'
1123           else:   postfix = '';      impl = 'FALSE'
1124           out += 'static int dissect_'+f+postfix+'(packet_info *pinfo _U_, proto_tree *tree _U_, tvbuff_t *tvb _U_, int offset _U_) {\n'
1125           par=((impl, 'tvb', 'offset', 'pinfo', 'tree', self.eth_hf[f]['fullname']),)
1126         else:
1127           out += 'static int dissect_'+f+'(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_) {\n'
1128           par=(('tvb', 'offset', 'actx', 'tree', self.eth_hf[f]['fullname']),)
1129         out += self.eth_fn_call('dissect_%s_%s' % (self.eth_type[t]['proto'], t), ret='return',
1130                                 par=par)
1131         out += '}\n'
1132       return out
1133     #end out_field()
1134     def out_pdu(f):
1135       t = self.eth_hf[f]['ethtype']
1136       is_new = self.eth_hf[f]['pdu']['new']
1137       if self.field[self.eth_hf[f]['ref'][0]]['impl']:
1138         impl = 'TRUE'
1139       else:
1140         impl = 'FALSE'
1141       out = 'static '
1142       if (is_new):
1143         out += 'int'
1144       else:
1145         out += 'void'
1146       out += ' dissect_'+f+'(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_) {\n'
1147       if (self.Per()):
1148         if (self.Aligned()):
1149           aligned = 'TRUE'
1150         else:
1151           aligned = 'FALSE'
1152         out += "  asn1_ctx_t asn1_ctx;\n"
1153         out += self.eth_fn_call('asn1_ctx_init', par=(('&asn1_ctx', 'ASN1_ENC_PER', aligned, 'pinfo'),))
1154       if (self.Ber()):
1155         par=((impl, 'tvb', '0', 'pinfo', 'tree', self.eth_hf[f]['fullname']),)
1156       elif (self.Per()):
1157         par=(('tvb', '0', '&asn1_ctx', 'tree', self.eth_hf[f]['fullname']),)
1158       else:
1159         par=((),)
1160       ret = None
1161       if (is_new): ret = 'return'
1162       out += self.eth_fn_call('dissect_%s_%s' % (self.eth_type[t]['proto'], t), ret=ret, par=par)
1163       out += '}\n'
1164       return out
1165     #end out_pdu()
1166     fx = self.output.file_open('fn')
1167     pos = fx.tell()
1168     if self.eth_dep_cycle:
1169       fx.write('/*--- Cyclic dependencies ---*/\n\n')
1170       i = 0
1171       while i < len(self.eth_dep_cycle):
1172         t = self.type[self.eth_dep_cycle[i][0]]['ethname']
1173         if self.dep_cycle_eth_type[t][0] != i: i += 1; continue
1174         fx.write(''.join(map(lambda i: '/* %s */\n' % ' -> '.join(self.eth_dep_cycle[i]), self.dep_cycle_eth_type[t])))
1175         fx.write(self.eth_type_fn_h(t))
1176         if (self.Fld()):
1177           fx.write('\n')
1178           for f in self.eth_hf_ord:
1179             if (self.eth_hf[f]['ethtype'] == t):
1180               fx.write(out_field(f))
1181         fx.write('\n')
1182         i += 1
1183       fx.write('\n')
1184     if (self.Fld()):  # fields for imported types
1185       fx.write('/*--- Fields for imported types ---*/\n\n')
1186       for f in self.eth_hf_ord:
1187         if (self.eth_type[self.eth_hf[f]['ethtype']]['import']):
1188           fx.write(out_field(f))
1189       fx.write('\n')
1190     for t in self.eth_type_ord1:
1191       if self.eth_type[t]['import']:
1192         continue
1193       if self.eth_type[t]['val'].eth_has_enum(t, self) and not (self.eth_type[t]['export'] & EF_ENUM):
1194         fx.write(self.eth_type[t]['val'].eth_type_enum(t, self))
1195       if self.eth_type[t]['val'].eth_has_vals():
1196         if self.eth_type[t]['no_emit'] & EF_VALS:
1197           pass
1198         elif self.eth_type[t]['user_def'] & EF_VALS:
1199           fx.write("extern const value_string %s[];\n" % (self.eth_vals_nm(t)))
1200         else:
1201           fx.write(self.eth_type[t]['val'].eth_type_vals(t, self))
1202       if self.eth_type[t]['no_emit'] & EF_TYPE:
1203         pass
1204       elif self.eth_type[t]['user_def'] & EF_TYPE:
1205         fx.write(self.eth_type_fn_h(t))
1206       else:
1207         fx.write(self.eth_type[t]['val'].eth_type_fn(self.eth_type[t]['proto'], t, self))
1208       if (self.Fld() and not self.dep_cycle_eth_type.has_key(t)):
1209         for f in self.eth_hf_ord:
1210           if (self.eth_hf[f]['ethtype'] == t):
1211             fx.write(out_field(f))
1212       fx.write('\n')
1213     if (len(self.eth_hfpdu_ord)):
1214       fx.write('/*--- PDUs ---*/\n\n')
1215       for f in self.eth_hfpdu_ord:
1216         if (self.eth_hf[f]['pdu']):
1217           fx.write(out_pdu(f))
1218       fx.write('\n')
1219     fempty = pos == fx.tell()
1220     self.output.file_close(fx, discard=fempty)
1221
1222   #--- eth_output_dis_hnd -----------------------------------------------------
1223   def eth_output_dis_hnd(self):
1224     fx = self.output.file_open('dis-hnd')
1225     fempty = True
1226     for f in self.eth_hfpdu_ord:
1227       pdu = self.eth_hf[f]['pdu']
1228       if (pdu and pdu['reg'] and not pdu['hidden']):
1229         dis = self.proto
1230         if (pdu['reg'] != '.'):
1231           dis += '.' + pdu['reg']
1232         fx.write('static dissector_handle_t %s_handle;\n' % (asn2c(dis)))
1233         fempty = False
1234     fx.write('\n')
1235     self.output.file_close(fx, discard=fempty)
1236
1237   #--- eth_output_dis_reg -----------------------------------------------------
1238   def eth_output_dis_reg(self):
1239     fx = self.output.file_open('dis-reg')
1240     fempty = True
1241     for f in self.eth_hfpdu_ord:
1242       pdu = self.eth_hf[f]['pdu']
1243       if (pdu and pdu['reg']):
1244         new_prefix = ''
1245         if (pdu['new']): new_prefix = 'new_'
1246         dis = self.proto
1247         if (pdu['reg'] != '.'): dis += '.' + pdu['reg']
1248         fx.write('  %sregister_dissector("%s", dissect_%s, proto_%s);\n' % (new_prefix, dis, f, self.eproto))
1249         if (not pdu['hidden']):
1250           fx.write('  %s_handle = find_dissector("%s");\n' % (asn2c(dis), dis))
1251         fempty = False
1252     fx.write('\n')
1253     self.output.file_close(fx, discard=fempty)
1254
1255   #--- eth_output_dis_tab -----------------------------------------------------
1256   def eth_output_dis_tab(self):
1257     fx = self.output.file_open('dis-tab')
1258     fempty = True
1259     for k in self.conform.get_order('REGISTER'):
1260       reg = self.conform.use_item('REGISTER', k)
1261       if not self.field.has_key(reg['pdu']): continue
1262       f = self.field[reg['pdu']]['ethname']
1263       pdu = self.eth_hf[f]['pdu'] 
1264       new_prefix = ''
1265       if (pdu['new']): new_prefix = 'new_'
1266       if (reg['rtype'] in ('NUM', 'STR')):
1267         rstr = ''
1268         if (reg['rtype'] == 'STR'): rstr = '_string'
1269         if (pdu['reg']):
1270           dis = self.proto
1271           if (pdu['reg'] != '.'): dis += '.' + pdu['reg']
1272           if  (not pdu['hidden']):
1273             hnd = '%s_handle' % (asn2c(dis))
1274           else:
1275             hnd = 'find_dissector("%s")' % (dis)
1276         else:
1277           hnd = '%screate_dissector_handle(dissect_%s, proto_%s)' % (new_prefix, f, self.eproto)
1278         fx.write('  dissector_add%s("%s", %s, %s);\n' % (rstr, reg['rtable'], reg['rport'], hnd))
1279       elif (reg['rtype'] in ('BER', 'PER')):
1280         fx.write('  %sregister_%s_oid_dissector(%s, dissect_%s, proto_%s, %s);\n' % (new_prefix, reg['rtype'].lower(), reg['roid'], f, self.eproto, reg['roidname']))
1281       fempty = False
1282     fx.write('\n')
1283     self.output.file_close(fx, discard=fempty)
1284
1285   #--- dupl_report -----------------------------------------------------
1286   def dupl_report(self):
1287     # types
1288     tmplist = self.eth_type_dupl.keys()
1289     tmplist.sort()
1290     for t in tmplist:
1291       msg = "The same type names for different types. Explicit type renaming is recommended.\n"
1292       msg += t + "\n"
1293       x = ''
1294       for tt in self.eth_type_dupl[t]:
1295         msg += " %-20s %s\n" % (t+str(x), tt)
1296         if not x: x = 1
1297         else: x += 1
1298       warnings.warn_explicit(msg, UserWarning, '', '')
1299     # fields
1300     tmplist = self.eth_hf_dupl.keys()
1301     tmplist.sort()
1302     for f in tmplist:
1303       msg = "The same field names for different types. Explicit field renaming is recommended.\n"
1304       msg += f + "\n"
1305       for tt in self.eth_hf_dupl[f].keys():
1306         msg += " %-20s %-20s " % (self.eth_hf_dupl[f][tt], tt)
1307         msg += ", ".join(self.eth_hf[self.eth_hf_dupl[f][tt]]['ref'])
1308         msg += "\n"
1309       warnings.warn_explicit(msg, UserWarning, '', '')
1310
1311   #--- eth_do_output ------------------------------------------------------------
1312   def eth_do_output(self):
1313     if self.dbg('a'):
1314       print "\n# Assignments"
1315       for a in self.assign_ord:
1316         v = ' '
1317         if (self.assign[a]['virt']): v = '*'
1318         print v, a
1319       print "\n# Value assignments"
1320       print "\n".join(self.vassign_ord)
1321     if self.dbg('t'):
1322       print "\n# Imported Types"
1323       print "%-40s %-24s %-24s" % ("ASN.1 name", "Module", "Protocol")
1324       print "-" * 100
1325       for t in self.type_imp:
1326         print "%-40s %-24s %-24s" % (t, self.type[t]['import'], self.type[t]['proto'])
1327       print "\n# Imported Values"
1328       print "%-40s %-24s %-24s" % ("ASN.1 name", "Module", "Protocol")
1329       print "-" * 100
1330       for t in self.value_imp:
1331         print "%-40s %-24s %-24s" % (t, self.value[t]['import'], self.value[t]['proto'])
1332       print "\n# Exported Types"
1333       print "%-31s %s" % ("Wireshark type", "Export Flag")
1334       print "-" * 100
1335       for t in self.eth_export_ord:
1336         print "%-31s 0x%02X" % (t, self.eth_type[t]['export'])
1337       print "\n# Exported Values"
1338       print "%-40s %s" % ("Wireshark name", "Value")
1339       print "-" * 100
1340       for v in self.eth_vexport_ord:
1341         print "%-40s %s" % (v, self.eth_value[v]['value'])
1342       print "\n# ASN.1 Types"
1343       print "%-49s %-24s %-24s" % ("ASN.1 unique name", "'tname'", "Wireshark type")
1344       print "-" * 100
1345       for t in self.type_ord:
1346         print "%-49s %-24s %-24s" % (t, self.type[t]['tname'], self.type[t]['ethname'])
1347       print "\n# Wireshark Types"
1348       print "Wireshark type                   References (ASN.1 types)"
1349       print "-" * 100
1350       for t in self.eth_type_ord:
1351         print "%-31s %d" % (t, len(self.eth_type[t]['ref'])),
1352         print ', '.join(self.eth_type[t]['ref'])
1353       print "\n# ASN.1 Values"
1354       print "%-40s %-18s %s" % ("ASN.1 unique name", "Type", "Value")
1355       print "-" * 100
1356       for v in self.value_ord:
1357         if isinstance (self.value[v]['value'], Value):
1358           print "%-40s %-18s %s" % (v, self.value[v]['type'].eth_tname(), self.value[v]['value'].to_str())
1359         else:
1360           print "%-40s %-18s %s" % (v, self.value[v]['type'].eth_tname(), self.value[v]['value'])
1361       print "\n# Wireshark Values"
1362       print "%-40s %s" % ("Wireshark name", "Value")
1363       print "-" * 100
1364       for v in self.eth_value_ord:
1365         print "%-40s %s" % (v, self.eth_value[v]['value'])
1366       print "\n# ASN.1 Fields"
1367       print "ASN.1 unique name                        Wireshark name        ASN.1 type"
1368       print "-" * 100
1369       for f in (self.pdu_ord + self.field_ord):
1370         print "%-40s %-20s %s" % (f, self.field[f]['ethname'], self.field[f]['type'])
1371       print "\n# Wireshark Fields"
1372       print "Wireshark name                  Wireshark type        References (ASN.1 fields)"
1373       print "-" * 100
1374       for f in (self.eth_hfpdu_ord + self.eth_hf_ord):
1375         print "%-30s %-20s %s" % (f, self.eth_hf[f]['ethtype'], len(self.eth_hf[f]['ref'])),
1376         print ', '.join(self.eth_hf[f]['ref'])
1377       #print "\n# Order after dependencies"
1378       #print '\n'.join(self.eth_type_ord1)
1379       print "\n# Cyclic dependencies"
1380       for c in self.eth_dep_cycle:
1381         print ' -> '.join(c)
1382     self.dupl_report()
1383     self.output.outnm = self.outnm_opt
1384     if (not self.output.outnm):
1385       self.output.outnm = self.proto
1386     self.eth_output_hf()
1387     self.eth_output_ett()
1388     self.eth_output_types()
1389     self.eth_output_hf_arr()
1390     self.eth_output_ett_arr()
1391     self.eth_output_export()
1392     if self.expcnf:
1393       self.eth_output_expcnf()
1394     self.eth_output_val()
1395     self.eth_output_valexp()
1396     self.eth_output_dis_hnd()
1397     self.eth_output_dis_reg()
1398     self.eth_output_dis_tab()
1399
1400 #--- EthCnf -------------------------------------------------------------------
1401 class EthCnf:
1402   def __init__(self):
1403     self.tblcfg = {}
1404     self.table = {}
1405     self.order = {}
1406     self.fn = {}
1407     self.suppress_line = False
1408     #                                   Value name             Default value       Duplicity check   Usage check
1409     self.tblcfg['EXPORTS']         = { 'val_nm' : 'flag',     'val_dflt' : 0,     'chk_dup' : True, 'chk_use' : True }
1410     self.tblcfg['MAKE_ENUM']       = { 'val_nm' : 'flag',     'val_dflt' : 0,     'chk_dup' : True, 'chk_use' : True }
1411     self.tblcfg['PDU']             = { 'val_nm' : 'attr',     'val_dflt' : None,  'chk_dup' : True, 'chk_use' : True }
1412     self.tblcfg['REGISTER']        = { 'val_nm' : 'attr',     'val_dflt' : None,  'chk_dup' : True, 'chk_use' : True }
1413     self.tblcfg['USER_DEFINED']    = { 'val_nm' : 'flag',     'val_dflt' : 0,     'chk_dup' : True, 'chk_use' : True }
1414     self.tblcfg['NO_EMIT']         = { 'val_nm' : 'flag',     'val_dflt' : 0,     'chk_dup' : True, 'chk_use' : True }
1415     self.tblcfg['MODULE']          = { 'val_nm' : 'proto',    'val_dflt' : None,  'chk_dup' : True, 'chk_use' : False }
1416     self.tblcfg['OMIT_ASSIGNMENT'] = { 'val_nm' : 'omit',     'val_dflt' : False, 'chk_dup' : True, 'chk_use' : True }
1417     self.tblcfg['VIRTUAL_ASSGN']   = { 'val_nm' : 'name',     'val_dflt' : None,  'chk_dup' : True, 'chk_use' : True }
1418     self.tblcfg['SET_TYPE']        = { 'val_nm' : 'type',     'val_dflt' : None,  'chk_dup' : True, 'chk_use' : True }
1419     self.tblcfg['TYPE_RENAME']     = { 'val_nm' : 'eth_name', 'val_dflt' : None,  'chk_dup' : True, 'chk_use' : True }
1420     self.tblcfg['FIELD_RENAME']    = { 'val_nm' : 'eth_name', 'val_dflt' : None,  'chk_dup' : True, 'chk_use' : True }
1421     self.tblcfg['IMPORT_TAG']      = { 'val_nm' : 'ttag',     'val_dflt' : (),    'chk_dup' : True, 'chk_use' : False }
1422     self.tblcfg['FN_PARS']         = { 'val_nm' : 'pars',     'val_dflt' : {},    'chk_dup' : True, 'chk_use' : True }
1423     self.tblcfg['TYPE_ATTR']       = { 'val_nm' : 'attr',     'val_dflt' : {},    'chk_dup' : True, 'chk_use' : False }
1424     self.tblcfg['ETYPE_ATTR']      = { 'val_nm' : 'attr',     'val_dflt' : {},    'chk_dup' : True, 'chk_use' : False }
1425     self.tblcfg['FIELD_ATTR']      = { 'val_nm' : 'attr',     'val_dflt' : {},    'chk_dup' : True, 'chk_use' : True }
1426     self.tblcfg['EFIELD_ATTR']     = { 'val_nm' : 'attr',     'val_dflt' : {},    'chk_dup' : True, 'chk_use' : True }
1427
1428
1429     for k in self.tblcfg.keys() :
1430       self.table[k] = {}
1431       self.order[k] = []
1432
1433   def add_item(self, table, key, fn, lineno, **kw):
1434     if self.tblcfg[table]['chk_dup'] and self.table[table].has_key(key):
1435       warnings.warn_explicit("Duplicated %s for %s. Previous one is at %s:%d" % 
1436                              (table, key, self.table[table][key]['fn'], self.table[table][key]['lineno']), 
1437                              UserWarning, fn, lineno)
1438       return
1439     self.table[table][key] = {'fn' : fn, 'lineno' : lineno, 'used' : False}
1440     self.table[table][key].update(kw)
1441     self.order[table].append(key)
1442
1443   def get_order(self, table):
1444     return self.order[table]
1445
1446   def check_item(self, table, key):
1447     return self.table[table].has_key(key)
1448
1449   def check_item_value(self, table, key, **kw):
1450     return self.table[table].has_key(key) and self.table[table][key].has_key(kw.get('val_nm', self.tblcfg[table]['val_nm']))
1451
1452   def use_item(self, table, key, **kw):
1453     vdflt = kw.get('val_dflt', self.tblcfg[table]['val_dflt'])
1454     if not self.table[table].has_key(key): return vdflt
1455     vname = kw.get('val_nm', self.tblcfg[table]['val_nm'])
1456     #print "use_item() - set used for %s %s" % (table, key)
1457     self.table[table][key]['used'] = True
1458     return self.table[table][key].get(vname, vdflt)
1459
1460   def add_fn_line(self, name, ctx, line, fn, lineno):
1461     if not self.fn.has_key(name):
1462       self.fn[name] = {'FN_HDR' : None, 'FN_FTR' : None, 'FN_BODY' : None}
1463     if (self.fn[name][ctx]):
1464       self.fn[name][ctx]['text'] += line
1465     else:
1466       self.fn[name][ctx] = {'text' : line, 'used' : False,
1467                              'fn' : fn, 'lineno' : lineno}
1468   def get_fn_presence(self, name):
1469     #print "get_fn_presence('%s'):%s" % (name, str(self.fn.has_key(name)))
1470     #if self.fn.has_key(name): print self.fn[name]
1471     return self.fn.has_key(name)
1472   def get_fn_body_presence(self, name):
1473     return self.fn.has_key(name) and self.fn[name]['FN_BODY']
1474   def get_fn_text(self, name, ctx):
1475     if (not self.fn.has_key(name)):
1476       return '';
1477     if (not self.fn[name][ctx]):
1478       return '';
1479     self.fn[name][ctx]['used'] = True
1480     out = self.fn[name][ctx]['text']
1481     if (not self.suppress_line): 
1482       out = '#line %u "%s"\n%s\n' % (self.fn[name][ctx]['lineno'], self.fn[name][ctx]['fn'], out);
1483     return out
1484
1485   def add_pdu(self, par, is_new, fn, lineno):
1486     #print "add_pdu(par=%s, %s, %d)" % (str(par), fn, lineno)
1487     (reg, hidden) = (None, False)
1488     if (len(par) > 1): reg = par[1]
1489     if (reg and reg[0]=='@'): (reg, hidden) = (reg[1:], True)
1490     attr = {'new' : is_new, 'reg' : reg, 'hidden' : hidden}
1491     self.add_item('PDU', par[0], attr=attr, fn=fn, lineno=lineno)
1492     return
1493
1494   def add_register(self, pdu, par, fn, lineno):
1495     #print "add_register(pdu=%s, par=%s, %s, %d)" % (pdu, str(par), fn, lineno)
1496     if (par[0] in ('N', 'NUM')):   rtype = 'NUM'; (pmin, pmax) = (2, 2)
1497     elif (par[0] in ('S', 'STR')): rtype = 'STR'; (pmin, pmax) = (2, 2)
1498     elif (par[0] in ('B', 'BER')): rtype = 'BER'; (pmin, pmax) = (1, 2)
1499     elif (par[0] in ('P', 'PER')): rtype = 'PER'; (pmin, pmax) = (1, 2)
1500     else: warnings.warn_explicit("Unknown registration type '%s'" % (par[2]), UserWarning, fn, lineno); return
1501     if ((len(par)-1) < pmin):
1502       warnings.warn_explicit("Too few parameters for %s registration type. At least %d parameters are required" % (rtype, pmin), UserWarning, fn, lineno)
1503       return
1504     if ((len(par)-1) > pmax):
1505       warnings.warn_explicit("Too many parameters for %s registration type. Only %d parameters are allowed" % (rtype, pmax), UserWarning, fn, lineno)
1506     attr = {'pdu' : pdu, 'rtype' : rtype}
1507     if (rtype in ('NUM', 'STR')): 
1508       attr['rtable'] = par[1]
1509       attr['rport'] = par[2]
1510       rkey = '/'.join([rtype, attr['rtable'], attr['rport']])
1511     elif (rtype in ('BER', 'PER')): 
1512       attr['roid'] = par[1]
1513       attr['roidname'] = '""'
1514       if (len(par)>=3): attr['roidname'] = par[2]
1515       rkey = '/'.join([rtype, attr['roid']])
1516     self.add_item('REGISTER', rkey, attr=attr, fn=fn, lineno=lineno)
1517
1518   def read(self, fn):
1519     def get_par(line, pmin, pmax, fn, lineno):
1520       par = line.split(None, pmax)
1521       for i in range(len(par)):
1522         if par[i] == '-':
1523           par[i] = None
1524           continue
1525         if par[i][0] == '#':
1526           par[i:] = []
1527           break
1528       if len(par) < pmin:
1529         warnings.warn_explicit("Too few parameters. At least %d parameters are required" % (pmin), UserWarning, fn, lineno)
1530         return None
1531       if (pmax >= 0) and (len(par) > pmax):
1532         warnings.warn_explicit("Too many parameters. Only %d parameters are allowed" % (pmax), UserWarning, fn, lineno)
1533         return par[0:pmax]
1534       return par
1535
1536     def get_par_nm(line, pmin, pmax, fn, lineno):
1537       if pmax:
1538         par = line.split(None, pmax)
1539       else:
1540         par = [line,]
1541       for i in range(len(par)):
1542         if par[i][0] == '#':
1543           par[i:] = []
1544           break
1545       if len(par) < pmin:
1546         warnings.warn_explicit("Too few parameters. At least %d parameters are required" % (pmin), UserWarning, fn, lineno)
1547         return None
1548       if len(par) > pmax:
1549         nmpar = par[pmax]
1550       else:
1551         nmpar = ''
1552       nmpars = {}
1553       nmpar_first = re.compile(r'^\s*(?P<attr>[_A-Z][_A-Z0-9]*)\s*=\s*')
1554       nmpar_next = re.compile(r'\s+(?P<attr>[_A-Z][_A-Z0-9]*)\s*=\s*')
1555       nmpar_end = re.compile(r'\s*$')
1556       result = nmpar_first.search(nmpar)
1557       pos = 0
1558       while result:
1559         k = result.group('attr')
1560         pos = result.end()
1561         result = nmpar_next.search(nmpar, pos)
1562         p1 = pos
1563         if result:
1564           p2 = result.start()
1565         else:
1566           p2 = nmpar_end.search(nmpar, pos).start()
1567         v = nmpar[p1:p2]
1568         nmpars[k] = v
1569       if len(par) > pmax:
1570         par[pmax] = nmpars
1571       return par
1572
1573     f = open(fn, "r")
1574     directive = re.compile(r'^\s*#\.(?P<name>[A-Z_]+)\s+')
1575     comment = re.compile(r'^\s*#[^.]')
1576     empty = re.compile(r'^\s*$')
1577     lineno = 0
1578     ctx = None
1579     name = ''
1580     default_flags = 0x00
1581     stack = []
1582     while 1:
1583       line = f.readline()
1584       lineno += 1
1585       if not line:
1586         f.close()
1587         if stack:
1588           frec = stack.pop()
1589           fn, f, lineno = frec['fn'], frec['f'], frec['lineno']
1590           continue
1591         else: 
1592           break
1593       if comment.search(line): continue
1594       result = directive.search(line)
1595       if result:  # directive
1596         if result.group('name') in ('PDU', 'PDU_NEW', 'REGISTER', 'REGISTER_NEW', 
1597                                     'MODULE', 'MODULE_IMPORT', 
1598                                     'OMIT_ASSIGNMENT', 'VIRTUAL_ASSGN', 'SET_TYPE',
1599                                     'TYPE_RENAME', 'FIELD_RENAME', 'TF_RENAME', 'IMPORT_TAG',
1600                                     'TYPE_ATTR', 'ETYPE_ATTR', 'FIELD_ATTR', 'EFIELD_ATTR'):
1601           ctx = result.group('name')
1602         elif result.group('name') in ('EXPORTS', 'USER_DEFINED', 'NO_EMIT'):
1603           ctx = result.group('name')
1604           default_flags = EF_TYPE|EF_VALS
1605           if ctx == 'EXPORTS':
1606             par = get_par(line[result.end():], 0, 4, fn=fn, lineno=lineno)
1607           else:
1608             par = get_par(line[result.end():], 0, 1, fn=fn, lineno=lineno)
1609           if not par: continue
1610           p = 1
1611           if (par[0] == 'WITH_VALS'):      default_flags |= EF_TYPE|EF_VALS
1612           elif (par[0] == 'WITHOUT_VALS'): default_flags |= EF_TYPE; default_flags &= ~EF_TYPE
1613           elif (par[0] == 'ONLY_VALS'):    default_flags &= ~EF_TYPE; default_flags |= EF_VALS
1614           elif (ctx == 'EXPORTS'): p = 0
1615           else: warnings.warn_explicit("Unknown parameter value '%s'" % (par[0]), UserWarning, fn, lineno)
1616           for i in range(p, len(par)):
1617             if (par[i] == 'ONLY_ENUM'):   default_flags &= ~(EF_TYPE|EF_VALS); default_flags |= EF_ENUM
1618             elif (par[i] == 'WITH_ENUM'): default_flags |= EF_ENUM
1619             elif (par[i] == 'WS_VAR'):    default_flags |= EF_WS_VAR
1620             elif (par[i] == 'NO_PROT_PREFIX'): default_flags |= EF_NO_PROT
1621             else: warnings.warn_explicit("Unknown parameter value '%s'" % (par[i]), UserWarning, fn, lineno)
1622         elif result.group('name') in ('MAKE_ENUM', 'MAKE_DEFINES'):
1623           ctx = result.group('name')
1624           default_flags = EF_ENUM
1625           if ctx == 'MAKE_ENUM': default_flags |= EF_NO_PROT
1626           if ctx == 'MAKE_DEFINES': default_flags |= EF_DEFINE|EF_UCASE
1627           par = get_par(line[result.end():], 0, 3, fn=fn, lineno=lineno)
1628           for i in range(0, len(par)):
1629             if (par[i] == 'NO_PROT_PREFIX'):   default_flags |= EF_NO_PROT
1630             elif (par[i] == 'NO_TYPE_PREFIX'): default_flags |= EF_NO_TYPE
1631             elif (par[i] == 'UPPER_CASE'):     default_flags |= EF_UCASE
1632             elif (par[i] == 'NO_UPPER_CASE'):  default_flags &= ~EF_UCASE
1633             else: warnings.warn_explicit("Unknown parameter value '%s'" % (par[i]), UserWarning, fn, lineno)
1634         elif result.group('name') in ('FN_HDR', 'FN_FTR'):
1635           par = get_par(line[result.end():], 1, 1, fn=fn, lineno=lineno)
1636           if not par: continue
1637           ctx = result.group('name')
1638           name = par[0]
1639         elif result.group('name') == 'FN_BODY':
1640           par = get_par_nm(line[result.end():], 1, 1, fn=fn, lineno=lineno)
1641           if not par: continue
1642           ctx = result.group('name')
1643           name = par[0]
1644           if len(par) > 1:
1645             self.add_item('FN_PARS', name, pars=par[1], fn=fn, lineno=lineno)
1646         elif result.group('name') == 'FN_PARS':
1647           par = get_par_nm(line[result.end():], 0, 1, fn=fn, lineno=lineno)
1648           ctx = result.group('name')
1649           if not par:
1650             name = None
1651           else:
1652             name = par[0]
1653           if len(par) > 1:
1654             self.add_item(ctx, name, pars=par[1], fn=fn, lineno=lineno)
1655             ctx = None
1656             name = None
1657         elif result.group('name') == 'INCLUDE':
1658           par = get_par(line[result.end():], 1, 1, fn=fn, lineno=lineno)
1659           if not par: 
1660             warnings.warn_explicit("INCLUDE requires parameter", UserWarning, fn, lineno)
1661             continue
1662           fname = os.path.join(os.path.split(fn)[0], par[0])
1663           if (not os.path.exists(fname)):
1664             fname = par[0]
1665           fnew = open(fname, "r")
1666           stack.append({'fn' : fn, 'f' : f, 'lineno' : lineno})
1667           fn, f, lineno = par[0], fnew, 0
1668         elif result.group('name') == 'END':
1669           ctx = None
1670         else:
1671           warnings.warn_explicit("Unknown directive '%s'" % (result.group('name')), UserWarning, fn, lineno)
1672         continue
1673       if not ctx:
1674         if not empty.match(line):
1675           warnings.warn_explicit("Non-empty line in empty context", UserWarning, fn, lineno)
1676       elif ctx in ('EXPORTS', 'USER_DEFINED', 'NO_EMIT'):
1677         if empty.match(line): continue
1678         if ctx == 'EXPORTS':
1679           par = get_par(line, 1, 4, fn=fn, lineno=lineno)
1680         else:
1681           par = get_par(line, 1, 2, fn=fn, lineno=lineno)
1682         if not par: continue
1683         flags = default_flags
1684         p = 2
1685         if (len(par)>=2):
1686           if (par[1] == 'WITH_VALS'):      flags |= EF_TYPE|EF_VALS
1687           elif (par[1] == 'WITHOUT_VALS'): flags |= EF_TYPE; flags &= ~EF_TYPE
1688           elif (par[1] == 'ONLY_VALS'):    flags &= ~EF_TYPE; flags |= EF_VALS
1689           elif (ctx == 'EXPORTS'): p = 1
1690           else: warnings.warn_explicit("Unknown parameter value '%s'" % (par[1]), UserWarning, fn, lineno)
1691         for i in range(p, len(par)):
1692           if (par[i] == 'ONLY_ENUM'):        flags &= ~(EF_TYPE|EF_VALS); flags |= EF_ENUM
1693           elif (par[i] == 'WITH_ENUM'):      flags |= EF_ENUM
1694           elif (par[i] == 'WS_VAR'):         flags |= EF_WS_VAR
1695           elif (par[i] == 'NO_PROT_PREFIX'): flags |= EF_NO_PROT
1696           else: warnings.warn_explicit("Unknown parameter value '%s'" % (par[i]), UserWarning, fn, lineno)
1697         self.add_item(ctx, par[0], flag=flags, fn=fn, lineno=lineno)
1698       elif ctx in ('MAKE_ENUM', 'MAKE_DEFINES'):
1699         if empty.match(line): continue
1700         par = get_par(line, 1, 4, fn=fn, lineno=lineno)
1701         if not par: continue
1702         flags = default_flags
1703         for i in range(1, len(par)):
1704           if (par[i] == 'NO_PROT_PREFIX'):   flags |= EF_NO_PROT
1705           elif (par[i] == 'NO_TYPE_PREFIX'): flags |= EF_NO_TYPE
1706           elif (par[i] == 'UPPER_CASE'):     flags |= EF_UCASE
1707           elif (par[i] == 'NO_UPPER_CASE'):  flags &= ~EF_UCASE
1708           else: warnings.warn_explicit("Unknown parameter value '%s'" % (par[i]), UserWarning, fn, lineno)
1709         self.add_item('MAKE_ENUM', par[0], flag=flags, fn=fn, lineno=lineno)
1710       elif ctx in ('PDU', 'PDU_NEW'):
1711         if empty.match(line): continue
1712         par = get_par(line, 1, 5, fn=fn, lineno=lineno)
1713         if not par: continue
1714         is_new = False
1715         if (ctx == 'PDU_NEW'): is_new = True
1716         self.add_pdu(par[0:2], is_new, fn, lineno)
1717         if (len(par)>=3):
1718           self.add_register(par[0], par[2:5], fn, lineno)
1719       elif ctx in ('REGISTER', 'REGISTER_NEW'):
1720         if empty.match(line): continue
1721         par = get_par(line, 3, 4, fn=fn, lineno=lineno)
1722         if not par: continue
1723         if not self.check_item('PDU', par[0]):
1724           is_new = False
1725           if (ctx == 'REGISTER_NEW'): is_new = True
1726           self.add_pdu(par[0:1], is_new, fn, lineno)
1727         self.add_register(par[0], par[1:4], fn, lineno)
1728       elif ctx in ('MODULE', 'MODULE_IMPORT'):
1729         if empty.match(line): continue
1730         par = get_par(line, 2, 2, fn=fn, lineno=lineno)
1731         if not par: continue
1732         self.add_item('MODULE', par[0], proto=par[1], fn=fn, lineno=lineno)
1733       elif ctx == 'IMPORT_TAG':
1734         if empty.match(line): continue
1735         par = get_par(line, 3, 3, fn=fn, lineno=lineno)
1736         if not par: continue
1737         self.add_item('IMPORT_TAG', par[0], ttag=(par[1], par[2]), fn=fn, lineno=lineno)
1738       elif ctx == 'OMIT_ASSIGNMENT':
1739         if empty.match(line): continue
1740         par = get_par(line, 1, 1, fn=fn, lineno=lineno)
1741         if not par: continue
1742         self.add_item('OMIT_ASSIGNMENT', par[0], omit=True, fn=fn, lineno=lineno)
1743       elif ctx == 'VIRTUAL_ASSGN':
1744         if empty.match(line): continue
1745         par = get_par(line, 2, -1, fn=fn, lineno=lineno)
1746         if not par: continue
1747         if (len(par[1].split('/')) > 1) and not self.check_item('SET_TYPE', par[1]):
1748           self.add_item('SET_TYPE', par[1], type=par[0], fn=fn, lineno=lineno)
1749         self.add_item('VIRTUAL_ASSGN', par[1], name=par[0], fn=fn, lineno=lineno)
1750         for nm in par[2:]:
1751           self.add_item('SET_TYPE', nm, type=par[0], fn=fn, lineno=lineno)
1752         if not par[0][0].isupper():
1753           warnings.warn_explicit("Virtual assignment should have uppercase name (%s)" % (par[0]),
1754                                   UserWarning, fn, lineno)
1755       elif ctx == 'SET_TYPE':
1756         if empty.match(line): continue
1757         par = get_par(line, 2, 2, fn=fn, lineno=lineno)
1758         if not par: continue
1759         if not self.check_item('VIRTUAL_ASSGN', par[0]):
1760           self.add_item('SET_TYPE', par[0], type=par[1], fn=fn, lineno=lineno)
1761         if not par[1][0].isupper():
1762           warnings.warn_explicit("Set type should have uppercase name (%s)" % (par[1]),
1763                                   UserWarning, fn, lineno)
1764       elif ctx == 'TYPE_RENAME':
1765         if empty.match(line): continue
1766         par = get_par(line, 2, 2, fn=fn, lineno=lineno)
1767         if not par: continue
1768         self.add_item('TYPE_RENAME', par[0], eth_name=par[1], fn=fn, lineno=lineno)
1769         if not par[1][0].isupper():
1770           warnings.warn_explicit("Type should be renamed to uppercase name (%s)" % (par[1]),
1771                                   UserWarning, fn, lineno)
1772       elif ctx == 'FIELD_RENAME':
1773         if empty.match(line): continue
1774         par = get_par(line, 2, 2, fn=fn, lineno=lineno)
1775         if not par: continue
1776         self.add_item('FIELD_RENAME', par[0], eth_name=par[1], fn=fn, lineno=lineno)
1777         if not par[1][0].islower():
1778           warnings.warn_explicit("Field should be renamed to lowercase name (%s)" % (par[1]),
1779                                   UserWarning, fn, lineno)
1780       elif ctx == 'TF_RENAME':
1781         if empty.match(line): continue
1782         par = get_par(line, 2, 2, fn=fn, lineno=lineno)
1783         if not par: continue
1784         tmpu = par[1][0].upper() + par[1][1:]
1785         tmpl = par[1][0].lower() + par[1][1:]
1786         self.add_item('TYPE_RENAME', par[0], eth_name=tmpu, fn=fn, lineno=lineno)
1787         if not tmpu[0].isupper():
1788           warnings.warn_explicit("Type should be renamed to uppercase name (%s)" % (par[1]),
1789                                   UserWarning, fn, lineno)
1790         self.add_item('FIELD_RENAME', par[0], eth_name=tmpl, fn=fn, lineno=lineno)
1791         if not tmpl[0].islower():
1792           warnings.warn_explicit("Field should be renamed to lowercase name (%s)" % (par[1]),
1793                                   UserWarning, fn, lineno)
1794       elif ctx in ('TYPE_ATTR', 'ETYPE_ATTR', 'FIELD_ATTR', 'EFIELD_ATTR'):
1795         if empty.match(line): continue
1796         par = get_par_nm(line, 1, 1, fn=fn, lineno=lineno)
1797         if not par: continue
1798         self.add_item(ctx, par[0], attr=par[1], fn=fn, lineno=lineno)
1799       elif ctx == 'FN_PARS':
1800         if empty.match(line): continue
1801         if name:
1802           par = get_par_nm(line, 0, 0, fn=fn, lineno=lineno)
1803         else:
1804           par = get_par_nm(line, 1, 1, fn=fn, lineno=lineno)
1805         if not par: continue
1806         if name:
1807           self.add_item(ctx, name, pars=par[0], fn=fn, lineno=lineno)
1808         else:
1809           self.add_item(ctx, par[0], pars=par[1], fn=fn, lineno=lineno)
1810       elif ctx in ('FN_HDR', 'FN_FTR', 'FN_BODY'):
1811         self.add_fn_line(name, ctx, line, fn=fn, lineno=lineno)
1812
1813   def dbg_print(self):
1814     print "\n# Conformance values"
1815     print "%-15s %-4s %-15s %-20s %s" % ("File", "Line", "Table", "Key", "Value")
1816     print "-" * 100
1817     tbls = self.table.keys()
1818     tbls.sort()
1819     for t in tbls:
1820       keys = self.table[t].keys()
1821       keys.sort()
1822       for k in keys:
1823         print "%-15s %4s %-15s %-20s %s" % (
1824               self.table[t][k]['fn'], self.table[t][k]['lineno'], t, k, str(self.table[t][k][self.tblcfg[t]['val_nm']]))
1825
1826   def unused_report(self):
1827     tbls = self.table.keys()
1828     tbls.sort()
1829     for t in tbls:
1830       if not self.tblcfg[t]['chk_use']: continue
1831       keys = self.table[t].keys()
1832       keys.sort()
1833       for k in keys:
1834         if not self.table[t][k]['used']:
1835           warnings.warn_explicit("Unused %s for %s" % (t, k),
1836                                   UserWarning, self.table[t][k]['fn'], self.table[t][k]['lineno'])
1837     fnms = self.fn.keys()
1838     fnms.sort()
1839     for f in fnms:
1840       keys = self.fn[f].keys()
1841       keys.sort()
1842       for k in keys:
1843         if not self.fn[f][k]: continue
1844         if not self.fn[f][k]['used']:
1845           warnings.warn_explicit("Unused %s for %s" % (k, f),
1846                                   UserWarning, self.fn[f][k]['fn'], self.fn[f][k]['lineno'])
1847
1848 #--- EthOut -------------------------------------------------------------------
1849 class EthOut:
1850   def __init__(self):
1851     self.outnm = None
1852     self.outdir = '.'
1853     self.single_file = None
1854     self.created_files = []
1855     self.unique_created_files = []
1856     self.keep = False
1857   #--- output_fname -------------------------------------------------------
1858   def output_fname(self, ftype, ext='c'):
1859     fn = ''
1860     if not ext in ('cnf',):
1861       fn += 'packet-' 
1862     fn += self.outnm
1863     if (ftype):
1864       fn += '-' + ftype
1865     fn += '.' + ext
1866     return fn
1867   #--- output_fullname -------------------------------------------------------
1868   def output_fullname(self, ftype, ext='c'):
1869     return os.path.join(self.outdir, self.output_fname(ftype, ext=ext))
1870   #--- file_open -------------------------------------------------------
1871   def file_open(self, ftype, ext='c'):
1872     fn = self.output_fullname(ftype, ext=ext)
1873     fx = file(fn, 'w')
1874     if ext in ('cnf',):
1875       fx.write(self.fhdr(fn, comment = '#'))
1876     else:
1877       if (not self.single_file):
1878         fx.write(self.fhdr(fn))
1879     return fx
1880   #--- file_close -------------------------------------------------------
1881   def file_close(self, fx, discard=False, keep_anyway=False):
1882     fx.close()
1883     if (discard): 
1884       os.unlink(fx.name)
1885     elif (not keep_anyway):
1886       self.created_files.append(os.path.normcase(os.path.abspath(fx.name)))
1887   #--- fhdr -------------------------------------------------------
1888   def fhdr(self, fn, comment=None):
1889     def outln(ln):
1890       if comment:
1891         return '# %s\n' % (ln)
1892       else:
1893         return '/* %-74s */\n' % (ln)
1894     out = ''
1895     out += outln('Do not modify this file.')
1896     out += outln('It is created automatically by the ASN.1 to Wireshark dissector compiler')
1897     out += outln(fn)
1898     out += outln(' '.join(sys.argv))
1899     out += '\n'
1900     return out
1901
1902   #--- dbg_print -------------------------------------------------------
1903   def dbg_print(self):
1904     print "\n# Output files"
1905     print "\n".join(self.created_files)
1906     print "\n"
1907
1908   #--- make_single_file -------------------------------------------------------
1909   def make_single_file(self):
1910     if (not self.single_file): return
1911     in_nm = self.single_file + '.c'
1912     out_nm = self.output_fullname('')
1913     self.do_include(out_nm, in_nm)
1914     in_nm = self.single_file + '.h'
1915     if (os.path.exists(in_nm)):
1916       out_nm = self.output_fullname('', ext='h')
1917       self.do_include(out_nm, in_nm)
1918     if (not self.keep):
1919       self.unique_created_files = []
1920       [self.unique_created_files.append(wrd) for wrd in self.created_files if not self.unique_created_files.count(wrd)]
1921       for fn in self.unique_created_files:
1922         os.unlink(fn)
1923
1924   #--- do_include -------------------------------------------------------
1925   def do_include(self, out_nm, in_nm):
1926     def check_file(fn, fnlist):
1927       fnfull = os.path.normcase(os.path.abspath(fn))
1928       if ((fnfull in fnlist) and os.path.exists(fnfull)):
1929         return os.path.normpath(fn)
1930       return None
1931     fin = file(in_nm, "r")
1932     fout = file(out_nm, "w")
1933     fout.write(self.fhdr(out_nm))
1934     fout.write('/* Input file: ' + in_nm +' */\n')
1935     fout.write('\n')
1936     fout.write('#line 1 "%s"\n' % (in_nm))
1937
1938     include = re.compile(r'^\s*#\s*include\s+[<"](?P<fname>[^>"]+)[>"]', re.IGNORECASE)
1939
1940     cont_linenum = 0;
1941
1942     while (True):
1943       cont_linenum = cont_linenum + 1;
1944       line = fin.readline()
1945       if (line == ''): break
1946       ifile = None
1947       result = include.search(line)
1948       #if (result): print os.path.normcase(os.path.abspath(result.group('fname')))
1949       if (result):
1950         ifile = check_file(os.path.join(os.path.split(in_nm)[0], result.group('fname')), self.created_files)
1951         if (not ifile):
1952           ifile = check_file(os.path.join(self.outdir, result.group('fname')), self.created_files)
1953         if (not ifile):
1954           ifile = check_file(result.group('fname'), self.created_files)
1955       if (ifile):
1956         fout.write('\n')
1957         fout.write('/*--- Included file: ' + ifile + ' ---*/\n')
1958         fout.write('#line 1 "' + ifile + '"\n')
1959         finc = file(ifile, "r")
1960         fout.write(finc.read())
1961         fout.write('\n')
1962         fout.write('/*--- End of included file: ' + ifile + ' ---*/\n')
1963         fout.write('#line %i "%s"\n' % (cont_linenum+1,in_nm) )
1964         finc.close()
1965       else:
1966         fout.write(line)
1967
1968     fout.close()
1969     fin.close()
1970
1971
1972 #--- Node ---------------------------------------------------------------------
1973 class Node:
1974     def __init__(self,*args, **kw):
1975         if len (args) == 0:
1976             self.type = self.__class__.__name__
1977         else:
1978             assert (len(args) == 1)
1979             self.type = args[0]
1980         self.__dict__.update (kw)
1981     def str_child (self, key, child, depth):
1982         indent = " " * (2 * depth)
1983         keystr = indent + key + ": "
1984         if key == 'type': # already processed in str_depth
1985             return ""
1986         if isinstance (child, Node): # ugh
1987             return keystr + "\n" + child.str_depth (depth+1)
1988         if type (child) == type ([]):
1989             l = []
1990             for x in child:
1991               if isinstance (x, Node):
1992                 l.append (x.str_depth (depth+1))
1993               else:
1994                 l.append (indent + "  " + str(x) + "\n")
1995             return keystr + "[\n" + ''.join(l) + indent + "]\n"
1996         else:
1997             return keystr + str (child) + "\n"
1998     def str_depth (self, depth): # ugh
1999         indent = " " * (2 * depth)
2000         l = ["%s%s" % (indent, self.type)]
2001         l.append ("".join (map (lambda (k,v): self.str_child (k, v, depth + 1),
2002                                 self.__dict__.items ())))
2003         return "\n".join (l)
2004     def __str__(self):
2005         return "\n" + self.str_depth (0)
2006     def to_python (self, ctx):
2007         return self.str_depth (ctx.indent_lev)
2008
2009     def eth_reg(self, ident, ectx):
2010         pass
2011
2012 #--- value_assign -------------------------------------------------------------
2013 class value_assign (Node):
2014   def __init__(self,*args, **kw) :
2015     Node.__init__ (self,*args, **kw)
2016
2017   def eth_reg(self, ident, ectx):
2018     if ectx.conform.use_item('OMIT_ASSIGNMENT', self.ident): return # Assignment to omit
2019     ectx.eth_reg_vassign(self)
2020     ectx.eth_reg_value(self.ident, self.typ, self.val)
2021
2022
2023 #--- Type ---------------------------------------------------------------------
2024 class Type (Node):
2025   def __init__(self,*args, **kw) :
2026     self.name = None
2027     self.constr = None
2028     self.tags = []
2029     Node.__init__ (self,*args, **kw)
2030
2031   def IsNamed(self):
2032     if self.name is None :
2033       return False
2034     else:
2035       return True
2036
2037   def HasConstraint(self):
2038     if self.constr is None :
2039       return False
2040     else :
2041       return True
2042
2043   def HasOwnTag(self):
2044     return len(self.tags) > 0
2045
2046   def HasImplicitTag(self, ectx):
2047     return (self.HasOwnTag() and self.tags[0].IsImplicit(ectx))
2048
2049   def IndetermTag(self, ectx):
2050     return False
2051
2052   def AddTag(self, tag):
2053     self.tags[0:0] = [tag]
2054
2055   def GetTag(self, ectx):
2056     #print "GetTag(%s)\n" % self.name;
2057     if (self.HasOwnTag()):
2058       return self.tags[0].GetTag(ectx)
2059     else:
2060       return self.GetTTag(ectx)
2061
2062   def GetTTag(self, ectx):
2063     print "#Unhandled  GetTTag() in %s" % (self.type)
2064     print self.str_depth(1)
2065     return ('BER_CLASS_unknown', 'TAG_unknown')
2066
2067   def SetName(self, name):
2068     self.name = name
2069
2070   def AddConstraint(self, constr):
2071     if not self.HasConstraint():
2072       self.constr = constr
2073     else:
2074       self.constr = Constraint(type = 'Intersection', subtype = [self.constr, constr])
2075
2076   def eth_tname(self):
2077     return '#' + self.type + '_' + str(id(self))
2078
2079   def eth_ftype(self, ectx):
2080     return ('FT_NONE', 'BASE_NONE')
2081
2082   def eth_strings(self):
2083     return 'NULL'
2084
2085   def eth_need_tree(self):
2086     return False
2087
2088   def eth_has_vals(self):
2089     return False
2090
2091   def eth_has_enum(self, tname, ectx):
2092     return self.eth_has_vals() and (ectx.eth_type[tname]['enum'] & EF_ENUM)
2093
2094   def eth_named_bits(self):
2095     return None
2096
2097   def eth_reg_sub(self, ident, ectx):
2098     pass
2099
2100   def eth_reg(self, ident, ectx, tstrip=0, tagflag=False, idx='', parent=None):
2101     if (ectx.Tag() and (len(self.tags) > tstrip)):
2102       tagged_type = TaggedType(val=self, tstrip=tstrip)
2103       tagged_type.AddTag(self.tags[tstrip])
2104       if not tagflag:  # 1st tagged level
2105         if self.IsNamed():
2106           tagged_type.SetName(self.name)
2107           #self.SetName(None)
2108       tagged_type.eth_reg(ident, ectx, tstrip=1, tagflag=tagflag, idx=idx, parent=parent)
2109       return
2110     nm = ''
2111     if ident and self.IsNamed() and not tagflag:
2112       nm = ident + '/' + self.name
2113     elif ident:
2114       nm = ident
2115     elif self.IsNamed():
2116       nm = self.name
2117     if not ident and ectx.conform.use_item('OMIT_ASSIGNMENT', nm): return # Assignment to omit
2118     if not ident:  # Assignment
2119       ectx.eth_reg_assign(nm, self)
2120       if self.type == 'Type_Ref':
2121         ectx.eth_reg_type(nm, self)
2122       if (ectx.conform.check_item('PDU', nm)):
2123         ectx.eth_reg_field(nm, nm, impl=self.HasImplicitTag(ectx), pdu=ectx.conform.use_item('PDU', nm))
2124     virtual_tr = Type_Ref(val=ectx.conform.use_item('SET_TYPE', nm))
2125     if (self.type == 'Type_Ref') or ectx.conform.check_item('SET_TYPE', nm):
2126       if ectx.conform.check_item('TYPE_RENAME', nm) or ectx.conform.get_fn_presence(nm):
2127         if ectx.conform.check_item('SET_TYPE', nm):
2128           ectx.eth_reg_type(nm, virtual_tr)  # dummy Type Reference
2129         else:
2130           ectx.eth_reg_type(nm, self)  # new type
2131         trnm = nm
2132       elif ectx.conform.check_item('SET_TYPE', nm):
2133         trnm = ectx.conform.use_item('SET_TYPE', nm)
2134       else:
2135         trnm = self.val
2136     else:
2137       ectx.eth_reg_type(nm, self)
2138     if ectx.conform.check_item('VIRTUAL_ASSGN', nm):
2139       vnm = ectx.conform.use_item('VIRTUAL_ASSGN', nm)
2140       ectx.eth_reg_assign(vnm, self, virt=True)
2141       ectx.eth_reg_type(vnm, self)
2142       self.eth_reg_sub(vnm, ectx)
2143     if ident and not tagflag:
2144       if (self.type == 'Type_Ref') or ectx.conform.check_item('SET_TYPE', nm):
2145         ectx.eth_reg_field(nm, trnm, idx=idx, parent=parent, impl=self.HasImplicitTag(ectx))
2146       else:
2147         ectx.eth_reg_field(nm, nm, idx=idx, parent=parent, impl=self.HasImplicitTag(ectx))
2148     if ectx.conform.check_item('SET_TYPE', nm):
2149       virtual_tr.eth_reg_sub(nm, ectx)
2150     else:
2151       self.eth_reg_sub(nm, ectx)
2152
2153   def eth_get_size_constr(self):
2154     (minv, maxv, ext) = ('NO_BOUND', 'NO_BOUND', 'FALSE')
2155     if not self.HasConstraint():
2156       (minv, maxv, ext) = ('NO_BOUND', 'NO_BOUND', 'FALSE')
2157     elif self.constr.IsSize():
2158       (minv, maxv, ext) = self.constr.GetSize()
2159     elif (self.constr.type == 'Intersection'):
2160       if self.constr.subtype[0].IsSize():
2161         (minv, maxv, ext) = self.constr.subtype[0].GetSize()
2162       elif self.constr.subtype[1].IsSize():
2163         (minv, maxv, ext) = self.constr.subtype[1].GetSize()
2164     return (minv, maxv, ext)
2165
2166   def eth_get_value_constr(self):
2167     (minv, maxv, ext) = ('NO_BOUND', 'NO_BOUND', 'FALSE')
2168     if not self.HasConstraint():
2169       (minv, maxv, ext) = ('NO_BOUND', 'NO_BOUND', 'FALSE')
2170     elif self.constr.IsValue():
2171       (minv, maxv, ext) = self.constr.GetValue()
2172     return (minv, maxv, ext)
2173
2174   def eth_type_vals(self, tname, ectx):
2175     if self.eth_has_vals():
2176       print "#Unhandled  eth_type_vals('%s') in %s" % (tname, self.type)
2177       print self.str_depth(1)
2178     return ''
2179
2180   def eth_type_enum(self, tname, ectx):
2181     if self.eth_has_enum(tname, ectx):
2182       print "#Unhandled  eth_type_enum('%s') in %s" % (tname, self.type)
2183       print self.str_depth(1)
2184     return ''
2185
2186   def eth_type_default_table(self, ectx, tname):
2187     return ''
2188
2189   def eth_type_default_body(self, ectx):
2190     print "#Unhandled  eth_type_default_body() in %s" % (self.type)
2191     print self.str_depth(1)
2192     return ''
2193
2194   def eth_type_default_pars(self, ectx, tname):
2195     pars = {
2196       'TNAME' : tname,
2197       'ER' : ectx.encp(),
2198       'FN_VARIANT' : '',
2199       'TREE' : 'tree', 
2200       'TVB' : 'tvb', 
2201       'OFFSET' : 'offset',
2202       'ACTX' : 'actx',
2203       'HF_INDEX' : 'hf_index',
2204       'VAL_PTR' : 'NULL',
2205       'IMPLICIT_TAG' : 'implicit_tag',
2206     }
2207     if (ectx.eth_type[tname]['tree']):
2208       pars['ETT_INDEX'] = ectx.eth_type[tname]['tree']
2209     if (not ectx.Per()):
2210       pars['PINFO'] = 'pinfo'
2211     return pars
2212
2213   def eth_type_fn(self, proto, tname, ectx):
2214     body = self.eth_type_default_body(ectx, tname)
2215     pars = self.eth_type_default_pars(ectx, tname)
2216     if ectx.conform.check_item('FN_PARS', tname):
2217       pars.update(ectx.conform.use_item('FN_PARS', tname))
2218     elif ectx.conform.check_item('FN_PARS', ectx.eth_type[tname]['ref'][0]):
2219       pars.update(ectx.conform.use_item('FN_PARS', ectx.eth_type[tname]['ref'][0]))
2220     pars['DEFAULT_BODY'] = body
2221     for i in range(4):
2222       for k in pars.keys(): pars[k] = pars[k] % pars
2223     out = '\n'
2224     out += self.eth_type_default_table(ectx, tname) % pars
2225     out += ectx.eth_type_fn_hdr(tname)
2226     out += ectx.eth_type_fn_body(tname, body, pars=pars)
2227     out += ectx.eth_type_fn_ftr(tname)
2228     return out
2229
2230 #--- Value --------------------------------------------------------------------
2231 class Value (Node):
2232   def __init__(self,*args, **kw) :
2233     self.name = None
2234     Node.__init__ (self,*args, **kw)
2235
2236   def SetName(self, name) :
2237     self.name = name
2238
2239   def to_str(self):
2240     return str(self)
2241
2242   def get_dep(self):
2243     return None
2244
2245 #--- Tag ---------------------------------------------------------------
2246 class Tag (Node):
2247   def to_python (self, ctx):
2248     return 'asn1.TYPE(%s,%s)' % (mk_tag_str (ctx, self.tag.cls,
2249                                                 self.tag_typ,
2250                                                 self.tag.num),
2251                                     self.typ.to_python (ctx))
2252   def IsImplicit(self, ectx):
2253     return ((self.mode == 'IMPLICIT') or ((self.mode == 'default') and (ectx.tag_def == 'IMPLICIT')))
2254
2255   def GetTag(self, ectx):
2256     tc = ''
2257     if (self.cls == 'UNIVERSAL'): tc = 'BER_CLASS_UNI'
2258     elif (self.cls == 'APPLICATION'): tc = 'BER_CLASS_APP'
2259     elif (self.cls == 'CONTEXT'): tc = 'BER_CLASS_CON'
2260     elif (self.cls == 'PRIVATE'): tc = 'BER_CLASS_PRI'
2261     return (tc, self.num)
2262
2263   def eth_tname(self):
2264     n = ''
2265     if (self.cls == 'UNIVERSAL'): n = 'U'
2266     elif (self.cls == 'APPLICATION'): n = 'A'
2267     elif (self.cls == 'CONTEXT'): n = 'C'
2268     elif (self.cls == 'PRIVATE'): n = 'P'
2269     return n + str(self.num)
2270  
2271 #--- Constraint ---------------------------------------------------------------
2272 class Constraint (Node):
2273   def to_python (self, ctx):
2274     print "Ignoring constraint:", self.type
2275     return self.subtype.typ.to_python (ctx)
2276   def __str__ (self):
2277     return "Constraint: type=%s, subtype=%s" % (self.type, self.subtype)
2278
2279   def IsSize(self):
2280     return self.type == 'Size' and (self.subtype.type == 'SingleValue' or self.subtype.type == 'ValueRange')
2281
2282   def GetSize(self):
2283     minv = 'NO_BOUND'
2284     maxv = 'NO_BOUND'
2285     ext = 'FALSE'
2286     if self.IsSize():
2287       if self.subtype.type == 'SingleValue':
2288         minv = self.subtype.subtype
2289         maxv = self.subtype.subtype
2290       else:
2291         minv = self.subtype.subtype[0]
2292         maxv = self.subtype.subtype[1]
2293       if hasattr(self.subtype, 'ext') and self.subtype.ext:
2294         ext = 'TRUE'
2295       else:
2296         ext = 'FALSE'
2297     return (minv, maxv, ext)
2298
2299   def IsValue(self):
2300     return self.type == 'SingleValue' or self.type == 'ValueRange'
2301
2302   def GetValue(self):
2303     minv = 'NO_BOUND'
2304     maxv = 'NO_BOUND'
2305     ext = 'FALSE'
2306     if self.IsValue():
2307       if self.type == 'SingleValue':
2308         minv = self.subtype
2309         maxv = self.subtype
2310       else:
2311         if self.subtype[0] == 'MIN':
2312           minv = 'NO_BOUND'
2313         else:
2314           minv = self.subtype[0]
2315         if self.subtype[1] == 'MAX':
2316           maxv = 'NO_BOUND'
2317         else:
2318           maxv = self.subtype[1]
2319       if str(minv).isdigit(): minv += 'U'
2320       if str(maxv).isdigit(): maxv += 'U'
2321       if hasattr(self, 'ext') and self.ext:
2322         ext = 'TRUE'
2323       else:
2324         ext = 'FALSE'
2325     return (minv, maxv, ext)
2326
2327   def IsNegativ(self):
2328     def is_neg(sval):
2329       return sval[0] == '-'
2330     if self.type == 'SingleValue':
2331       return is_neg(self.subtype)
2332     elif self.type == 'ValueRange':
2333       if self.subtype[0] == 'MIN': return True
2334       return is_neg(self.subtype[0])
2335     return FALSE
2336
2337   def IsPermAlph(self):
2338     return self.type == 'From' and self.subtype.type == 'SingleValue'
2339
2340   def eth_constrname(self):
2341     def int2str(val):
2342       try:
2343         if (int(val) < 0):
2344           return 'M' + str(-int(val))
2345         else:
2346           return str(val)
2347       except (ValueError, TypeError):
2348         return str(val)
2349
2350     ext = ''
2351     if hasattr(self, 'ext') and self.ext:
2352       ext = '_'
2353     if self.type == 'SingleValue':
2354       return int2str(self.subtype) + ext
2355     elif self.type == 'ValueRange':
2356       return int2str(self.subtype[0]) + '_' + int2str(self.subtype[1]) + ext
2357     elif self.type == 'Size':
2358       return 'SIZE_' + self.subtype.eth_constrname() + ext
2359     else:
2360       return 'CONSTR' + str(id(self)) + ext
2361
2362
2363 class Module (Node):
2364   def to_python (self, ctx):
2365     ctx.tag_def = self.tag_def.dfl_tag
2366     return """#%s
2367 %s""" % (self.ident, self.body.to_python (ctx))
2368
2369   def to_eth (self, ectx):
2370     ectx.tags_def = 'EXPLICIT' # default = explicit
2371     if (not ectx.proto):
2372       ectx.proto = ectx.conform.use_item('MODULE', self.ident.val, val_dflt=self.ident.val)
2373     ectx.tag_def = self.tag_def.dfl_tag
2374     ectx.modules.append((self.ident.val, ectx.proto))
2375     self.body.to_eth(ectx)
2376
2377 class Module_Body (Node):
2378     def to_python (self, ctx):
2379         # XXX handle exports, imports.
2380         l = map (lambda x: x.to_python (ctx), self.assign_list)
2381         l = [a for a in l if a <> '']
2382         return "\n".join (l)
2383
2384     def to_eth(self, ectx):
2385         for i in self.imports:
2386           mod = i.module.val
2387           proto = ectx.conform.use_item('MODULE', mod, val_dflt=mod)
2388           for s in i.symbol_list:
2389             if isinstance(s, Type_Ref):
2390               ectx.eth_import_type(s.val, mod, proto)
2391             else:
2392               ectx.eth_import_value(s, mod, proto)
2393         for a in self.assign_list:
2394           a.eth_reg('', ectx)
2395
2396 class Default_Tags (Node):
2397     def to_python (self, ctx): # not to be used directly
2398         assert (0)
2399
2400 # XXX should just calculate dependencies as we go along.
2401 def calc_dependencies (node, dict, trace = 0):
2402     if not hasattr (node, '__dict__'):
2403         if trace: print "#returning, node=", node
2404         return
2405     if isinstance (node, Type_Ref):
2406         dict [node.val] = 1
2407         if trace: print "#Setting", node.val
2408         return
2409     for (a, val) in node.__dict__.items ():
2410         if trace: print "# Testing node ", node, "attr", a, " val", val
2411         if a[0] == '_':
2412             continue
2413         elif isinstance (val, Node):
2414             calc_dependencies (val, dict, trace)
2415         elif isinstance (val, type ([])):
2416             for v in val:
2417                 calc_dependencies (v, dict, trace)
2418     
2419                           
2420 class Type_Assign (Node):
2421     def __init__ (self, *args, **kw):
2422         Node.__init__ (self, *args, **kw)
2423         if isinstance (self.val, Tag): # XXX replace with generalized get_typ_ignoring_tag (no-op for Node, override in Tag)
2424             to_test = self.val.typ
2425         else:
2426             to_test = self.val
2427         if isinstance (to_test, SequenceType):
2428             to_test.sequence_name = self.name.name
2429             
2430     def to_python (self, ctx):
2431         dep_dict = {}
2432         calc_dependencies (self.val, dep_dict, 0)
2433         depend_list = dep_dict.keys ()
2434         return ctx.register_assignment (self.name.name,
2435                                         self.val.to_python (ctx),
2436                                         depend_list)
2437
2438 class PyQuote (Node):
2439     def to_python (self, ctx):
2440         return ctx.register_pyquote (self.val)
2441
2442 #--- Type_Ref -----------------------------------------------------------------
2443 class Type_Ref (Type):
2444   def to_python (self, ctx):
2445     return self.val
2446
2447   def eth_reg_sub(self, ident, ectx):
2448     ectx.eth_dep_add(ident, self.val)
2449
2450   def eth_tname(self):
2451     return asn2c(self.val)
2452
2453   def GetTTag(self, ectx):
2454     #print "GetTTag(%s)\n" % self.val;
2455     if (ectx.type[self.val]['import']):
2456       if not ectx.type[self.val].has_key('ttag'):
2457         if not ectx.conform.check_item('IMPORT_TAG', self.val):
2458           msg = 'Missing tag information for imported type %s from %s (%s)' % (self.val, ectx.type[self.val]['import'], ectx.type[self.val]['proto'])
2459           warnings.warn_explicit(msg, UserWarning, '', '')
2460         ectx.type[self.val]['ttag'] = ectx.conform.use_item('IMPORT_TAG', self.val, val_dflt=('-1 /*imported*/', '-1 /*imported*/'))
2461       return ectx.type[self.val]['ttag']
2462     else:
2463       return ectx.type[self.val]['val'].GetTag(ectx)
2464
2465   def IndetermTag(self, ectx):
2466     if (ectx.type[self.val]['import']):
2467       return False
2468     else:
2469       return ectx.type[self.val]['val'].IndetermTag(ectx)
2470
2471   def eth_type_default_pars(self, ectx, tname):
2472     pars = Type.eth_type_default_pars(self, ectx, tname)
2473     t = ectx.type[self.val]['ethname']
2474     pars['TYPE_REF_PROTO'] = ectx.eth_type[t]['proto']
2475     pars['TYPE_REF_TNAME'] = t
2476     pars['TYPE_REF_FN'] = 'dissect_%(TYPE_REF_PROTO)s_%(TYPE_REF_TNAME)s'
2477     return pars
2478
2479   def eth_type_default_body(self, ectx, tname):
2480     if (ectx.Ber()):
2481       body = ectx.eth_fn_call('%(TYPE_REF_FN)s', ret='offset',
2482                               par=(('%(IMPLICIT_TAG)s', '%(TVB)s', '%(OFFSET)s', '%(PINFO)s', '%(TREE)s', '%(HF_INDEX)s'),))
2483     elif (ectx.Per()):
2484       body = ectx.eth_fn_call('%(TYPE_REF_FN)s', ret='offset',
2485                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),))
2486     else:
2487       body = '#error Can not decode %s' % (tname)
2488     return body
2489
2490 #--- TaggedType -----------------------------------------------------------------
2491 class TaggedType (Type):
2492   def eth_tname(self):
2493     tn = ''
2494     for i in range(self.tstrip, len(self.val.tags)):
2495       tn += self.val.tags[i].eth_tname()
2496       tn += '_'
2497     tn += self.val.eth_tname()
2498     return tn
2499
2500   def eth_reg_sub(self, ident, ectx):
2501     self.val_name = ident + '/' + '_untag'
2502     ectx.eth_dep_add(ident, self.val_name)
2503     self.val.eth_reg(self.val_name, ectx, tstrip=self.tstrip+1, tagflag=True, parent=ident)
2504
2505   def eth_ftype(self, ectx):
2506     return self.val.eth_ftype(ectx)
2507
2508   def eth_type_default_pars(self, ectx, tname):
2509     pars = Type.eth_type_default_pars(self, ectx, tname)
2510     t = ectx.type[self.val_name]['ethname']
2511     pars['TYPE_REF_PROTO'] = ectx.eth_type[t]['proto']
2512     pars['TYPE_REF_TNAME'] = t
2513     pars['TYPE_REF_FN'] = 'dissect_%(TYPE_REF_PROTO)s_%(TYPE_REF_TNAME)s'
2514     (pars['TAG_CLS'], pars['TAG_TAG']) = self.GetTag(ectx)
2515     if self.HasImplicitTag(ectx):
2516       pars['TAG_IMPL'] = 'TRUE'
2517     else:
2518       pars['TAG_IMPL'] = 'FALSE'
2519     return pars
2520
2521   def eth_type_default_body(self, ectx, tname):
2522     if (ectx.Ber()):
2523       body = ectx.eth_fn_call('dissect_%(ER)s_tagged_type', ret='offset',
2524                               par=(('%(IMPLICIT_TAG)s', '%(PINFO)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s'),
2525                                    ('%(HF_INDEX)s', '%(TAG_CLS)s', '%(TAG_TAG)s', '%(TAG_IMPL)s', '%(TYPE_REF_FN)s',),))
2526     else:
2527       body = '#error Can not decode %s' % (tname)
2528     return body
2529
2530 #--- SqType -----------------------------------------------------------
2531 class SqType (Type):
2532   def out_item(self, f, val, optional, ext, ectx):
2533     ef = ectx.field[f]['ethname']
2534     t = ectx.eth_hf[ef]['ethtype']
2535     efd = ef
2536     if (ectx.Ber() and ectx.field[f]['impl']):
2537       efd += '_impl'
2538     if (ectx.Ber()):
2539       #print "optional=%s, e.val.HasOwnTag()=%s, e.val.IndetermTag()=%s" % (str(e.optional), str(e.val.HasOwnTag()), str(e.val.IndetermTag(ectx)))
2540       #print val.str_depth(1)
2541       opt = ''
2542       if (optional):
2543         opt = 'BER_FLAGS_OPTIONAL'
2544       if (not val.HasOwnTag()):
2545         if (opt): opt += '|'
2546         opt += 'BER_FLAGS_NOOWNTAG'
2547       elif (val.HasImplicitTag(ectx)):
2548         if (opt): opt += '|'
2549         opt += 'BER_FLAGS_IMPLTAG'
2550       if (val.IndetermTag(ectx)):
2551         if (opt): opt += '|'
2552         opt += 'BER_FLAGS_NOTCHKTAG'
2553       if (not opt): opt = '0'
2554     else:
2555       if optional:
2556         opt = 'ASN1_OPTIONAL'
2557       else:
2558         opt = 'ASN1_NOT_OPTIONAL'
2559     if (ectx.Ber()):
2560       (tc, tn) = val.GetTag(ectx)
2561       out = '  { %-13s, %s, %s, dissect_%s },\n' \
2562             % (tc, tn, opt, efd)
2563     elif (ectx.Per()):
2564       out = '  { %-24s, %-23s, %-17s, dissect_%s_%s },\n' \
2565             % ('&'+ectx.eth_hf[ef]['fullname'], ext, opt, ectx.eth_type[t]['proto'], t)
2566     else:
2567       out = ''
2568     return out   
2569
2570 #--- SeqType -----------------------------------------------------------
2571 class SeqType (SqType):
2572   def eth_type_default_table(self, ectx, tname):
2573     #print "eth_type_default_table(tname='%s')" % (tname)
2574     fname = ectx.eth_type[tname]['ref'][0]
2575     table = "static const %(ER)s_sequence_t %(TABLE)s[] = {\n"
2576     if hasattr(self, 'ext_list'):
2577       ext = 'ASN1_EXTENSION_ROOT'
2578     else:
2579       ext = 'ASN1_NO_EXTENSIONS'
2580     for e in (self.elt_list):
2581       f = fname + '/' + e.val.name
2582       table += self.out_item(f, e.val, e.optional, ext, ectx)
2583     if hasattr(self, 'ext_list'):
2584       for e in (self.ext_list):
2585         f = fname + '/' + e.val.name
2586         table += self.out_item(f, e.val, e.optional, 'ASN1_NOT_EXTENSION_ROOT', ectx)
2587     if (ectx.Ber()):
2588       table += "  { 0, 0, 0, NULL }\n};\n"
2589     else:
2590       table += "  { NULL, 0, 0, NULL }\n};\n"
2591     return table
2592
2593 #--- SeqOfType -----------------------------------------------------------
2594 class SeqOfType (SqType):
2595   def eth_type_default_table(self, ectx, tname):
2596     #print "eth_type_default_table(tname='%s')" % (tname)
2597     fname = ectx.eth_type[tname]['ref'][0]
2598     if self.val.IsNamed ():
2599       f = fname + '/' + self.val.name
2600     else:
2601       f = fname + '/' + '_item'
2602     table = "static const %(ER)s_sequence_t %(TABLE)s[1] = {\n"
2603     table += self.out_item(f, self.val, False, 'ASN1_NO_EXTENSIONS', ectx)
2604     table += "};\n"
2605     return table
2606
2607 #--- SequenceOfType -----------------------------------------------------------
2608 class SequenceOfType (SeqOfType):
2609   def to_python (self, ctx):
2610     # name, tag (None for no tag, EXPLICIT() for explicit), typ)
2611     # or '' + (1,) for optional
2612     sizestr = ''
2613     if self.size_constr <> None:
2614         print "#Ignoring size constraint:", self.size_constr.subtype
2615     return "%sasn1.SEQUENCE_OF (%s%s)" % (ctx.spaces (),
2616                                           self.val.to_python (ctx),
2617                                           sizestr)
2618
2619   def eth_reg_sub(self, ident, ectx):
2620     itmnm = ident
2621     if not self.val.IsNamed ():
2622       itmnm += '/' + '_item'
2623     self.val.eth_reg(itmnm, ectx, tstrip=1, idx='[##]', parent=ident)
2624
2625   def eth_tname(self):
2626     if self.val.type != 'Type_Ref':
2627       return '#' + self.type + '_' + str(id(self))
2628     if not self.HasConstraint():
2629       return "SEQUENCE_OF_" + self.val.eth_tname()
2630     elif self.constr.IsSize():
2631       return 'SEQUENCE_' + self.constr.eth_constrname() + '_OF_' + self.val.eth_tname()
2632     else:
2633       return '#' + self.type + '_' + str(id(self))
2634
2635   def eth_ftype(self, ectx):
2636     return ('FT_UINT32', 'BASE_DEC')
2637
2638   def eth_need_tree(self):
2639     return True
2640
2641   def GetTTag(self, ectx):
2642     return ('BER_CLASS_UNI', 'BER_UNI_TAG_SEQUENCE')
2643
2644   def eth_type_default_pars(self, ectx, tname):
2645     pars = Type.eth_type_default_pars(self, ectx, tname)
2646     (pars['MIN_VAL'], pars['MAX_VAL'], pars['EXT']) = self.eth_get_size_constr()
2647     pars['TABLE'] = '%(TNAME)s_sequence_of'
2648     return pars
2649
2650   def eth_type_default_body(self, ectx, tname):
2651     if (ectx.Ber()):
2652       body = ectx.eth_fn_call('dissect_%(ER)s_sequence_of', ret='offset',
2653                               par=(('%(IMPLICIT_TAG)s', '%(PINFO)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s'),
2654                                    ('%(TABLE)s', '%(HF_INDEX)s', '%(ETT_INDEX)s',),))
2655     elif (ectx.Per() and not self.HasConstraint()):
2656       body = ectx.eth_fn_call('dissect_%(ER)s_sequence_of', ret='offset',
2657                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
2658                                    ('%(ETT_INDEX)s', '%(TABLE)s',),))
2659     elif (ectx.Per() and self.constr.type == 'Size'):
2660       body = ectx.eth_fn_call('dissect_%(ER)s_constrained_sequence_of', ret='offset',
2661                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
2662                                    ('%(ETT_INDEX)s', '%(TABLE)s',),
2663                                    ('%(MIN_VAL)s', '%(MAX_VAL)s',),))
2664     else:
2665       body = '#error Can not decode %s' % (tname)
2666     return body
2667
2668
2669 #--- SetOfType ----------------------------------------------------------------
2670 class SetOfType (SeqOfType):
2671   def eth_reg_sub(self, ident, ectx):
2672     itmnm = ident
2673     if not self.val.IsNamed ():
2674       itmnm += '/' + '_item'
2675     self.val.eth_reg(itmnm, ectx, tstrip=1, idx='(##)', parent=ident)
2676
2677   def eth_tname(self):
2678     if self.val.type != 'Type_Ref':
2679       return '#' + self.type + '_' + str(id(self))
2680     if not self.HasConstraint():
2681       return "SET_OF_" + self.val.eth_tname()
2682     elif self.constr.IsSize():
2683       return 'SET_' + self.constr.eth_constrname() + '_OF_' + self.val.eth_tname()
2684     else:
2685       return '#' + self.type + '_' + str(id(self))
2686
2687   def eth_ftype(self, ectx):
2688     return ('FT_UINT32', 'BASE_DEC')
2689
2690   def eth_need_tree(self):
2691     return True
2692
2693   def GetTTag(self, ectx):
2694     return ('BER_CLASS_UNI', 'BER_UNI_TAG_SET')
2695
2696   def eth_type_default_pars(self, ectx, tname):
2697     pars = Type.eth_type_default_pars(self, ectx, tname)
2698     (pars['MIN_VAL'], pars['MAX_VAL'], pars['EXT']) = self.eth_get_size_constr()
2699     pars['TABLE'] = '%(TNAME)s_set_of'
2700     return pars
2701
2702   def eth_type_default_body(self, ectx, tname):
2703     if (ectx.Ber()):
2704       body = ectx.eth_fn_call('dissect_%(ER)s_set_of', ret='offset',
2705                               par=(('%(IMPLICIT_TAG)s', '%(PINFO)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s'),
2706                                    ('%(TABLE)s', '%(HF_INDEX)s', '%(ETT_INDEX)s',),))
2707     elif (ectx.Per() and not self.HasConstraint()):
2708       body = ectx.eth_fn_call('dissect_%(ER)s_set_of', ret='offset',
2709                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
2710                                    ('%(ETT_INDEX)s', '%(TABLE)s',),))
2711     elif (ectx.Per() and self.constr.type == 'Size'):
2712       body = ectx.eth_fn_call('dissect_%(ER)s_constrained_set_of', ret='offset',
2713                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
2714                                    ('%(ETT_INDEX)s', '%(TABLE)s',),
2715                                    ('%(MIN_VAL)s', '%(MAX_VAL)s',),))
2716     else:
2717       body = '#error Can not decode %s' % (tname)
2718     return body
2719
2720 def mk_tag_str (ctx, cls, typ, num):
2721
2722     # XXX should do conversion to int earlier!
2723     val = int (num)
2724     typ = typ.upper()
2725     if typ == 'DEFAULT':
2726         typ = ctx.tags_def
2727     return 'asn1.%s(%d,cls=asn1.%s_FLAG)' % (typ, val, cls) # XXX still ned
2728
2729 #--- SequenceType -------------------------------------------------------------
2730 class SequenceType (SeqType):
2731   def to_python (self, ctx):
2732       # name, tag (None for no tag, EXPLICIT() for explicit), typ)
2733       # or '' + (1,) for optional
2734       # XXX should also collect names for SEQUENCE inside SEQUENCE or
2735       # CHOICE or SEQUENCE_OF (where should the SEQUENCE_OF name come
2736       # from?  for others, element or arm name would be fine)
2737       seq_name = getattr (self, 'sequence_name', None)
2738       if seq_name == None:
2739           seq_name = 'None'
2740       else:
2741           seq_name = "'" + seq_name + "'"
2742       if self.__dict__.has_key('ext_list'):
2743         return "%sasn1.SEQUENCE ([%s], ext=[%s], seq_name = %s)" % (ctx.spaces (), 
2744                                  self.elts_to_py (self.elt_list, ctx),
2745                                  self.elts_to_py (self.ext_list, ctx), seq_name)
2746       else:
2747         return "%sasn1.SEQUENCE ([%s]), seq_name = %s" % (ctx.spaces (), 
2748                                  self.elts_to_py (self.elt_list, ctx), seq_name)
2749   def elts_to_py (self, list, ctx):
2750       # we have elt_type, val= named_type, maybe default=, optional=
2751       # named_type node: either ident = or typ =
2752       # need to dismember these in order to generate Python output syntax.
2753       ctx.indent ()
2754       def elt_to_py (e):
2755           assert (e.type == 'elt_type')
2756           nt = e.val
2757           optflag = e.optional
2758           #assert (not hasattr (e, 'default')) # XXX add support for DEFAULT!
2759           assert (nt.type == 'named_type')
2760           tagstr = 'None'
2761           identstr = nt.ident
2762           if hasattr (nt.typ, 'type') and nt.typ.type == 'tag': # ugh
2763               tagstr = mk_tag_str (ctx,nt.typ.tag.cls,
2764                                    nt.typ.tag.tag_typ,nt.typ.tag.num)
2765       
2766
2767               nt = nt.typ
2768           return "('%s',%s,%s,%d)" % (identstr, tagstr,
2769                                     nt.typ.to_python (ctx), optflag)
2770       indentstr = ",\n" + ctx.spaces ()
2771       rv = indentstr.join ([elt_to_py (e) for e in list])
2772       ctx.outdent ()
2773       return rv
2774
2775   def eth_reg_sub(self, ident, ectx):
2776       for e in (self.elt_list):
2777           e.val.eth_reg(ident, ectx, tstrip=1, parent=ident)
2778       if hasattr(self, 'ext_list'):
2779           for e in (self.ext_list):
2780               e.val.eth_reg(ident, ectx, tstrip=1, parent=ident)
2781
2782   def eth_need_tree(self):
2783     return True
2784
2785   def GetTTag(self, ectx):
2786     return ('BER_CLASS_UNI', 'BER_UNI_TAG_SEQUENCE')
2787
2788   def eth_type_default_pars(self, ectx, tname):
2789     pars = Type.eth_type_default_pars(self, ectx, tname)
2790     pars['TABLE'] = '%(TNAME)s_sequence'
2791     return pars
2792
2793   def eth_type_default_body(self, ectx, tname):
2794     if (ectx.Ber()):
2795       body = ectx.eth_fn_call('dissect_%(ER)s_sequence', ret='offset',
2796                               par=(('%(IMPLICIT_TAG)s', '%(PINFO)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s'),
2797                                    ('%(TABLE)s', '%(HF_INDEX)s', '%(ETT_INDEX)s',),))
2798     elif (ectx.Per()):
2799       body = ectx.eth_fn_call('dissect_%(ER)s_sequence', ret='offset',
2800                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
2801                                    ('%(ETT_INDEX)s', '%(TABLE)s',),))
2802     else:
2803       body = '#error Can not decode %s' % (tname)
2804     return body
2805
2806 #--- SetType ------------------------------------------------------------------
2807 class SetType(SeqType):
2808   def eth_reg_sub(self, ident, ectx):
2809     for e in (self.elt_list):
2810       e.val.eth_reg(ident, ectx, tstrip=1, parent=ident)
2811     if hasattr(self, 'ext_list'):
2812       for e in (self.ext_list):
2813         e.val.eth_reg(ident, ectx, tstrip=1, parent=ident)
2814
2815   def eth_need_tree(self):
2816     return True
2817
2818   def GetTTag(self, ectx):
2819     return ('BER_CLASS_UNI', 'BER_UNI_TAG_SET')
2820
2821   def eth_type_default_pars(self, ectx, tname):
2822     pars = Type.eth_type_default_pars(self, ectx, tname)
2823     pars['TABLE'] = '%(TNAME)s_set'
2824     return pars
2825
2826   def eth_type_default_body(self, ectx, tname):
2827     if (ectx.Ber()):
2828       body = ectx.eth_fn_call('dissect_%(ER)s_set', ret='offset',
2829                               par=(('%(IMPLICIT_TAG)s', '%(PINFO)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s'),
2830                                    ('%(TABLE)s', '%(HF_INDEX)s', '%(ETT_INDEX)s',),))
2831     elif (ectx.Per()):
2832       body = ectx.eth_fn_call('dissect_%(ER)s_set', ret='offset',
2833                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
2834                                    ('%(ETT_INDEX)s', '%(TABLE)s',),))
2835     else:
2836       body = '#error Can not decode %s' % (tname)
2837     return body
2838
2839 #--- ChoiceType ---------------------------------------------------------------
2840 class ChoiceType (Type):
2841   def to_python (self, ctx):
2842       # name, tag (None for no tag, EXPLICIT() for explicit), typ)
2843       # or '' + (1,) for optional
2844       if self.__dict__.has_key('ext_list'):
2845         return "%sasn1.CHOICE ([%s], ext=[%s])" % (ctx.spaces (), 
2846                                self.elts_to_py (self.elt_list, ctx),
2847                                self.elts_to_py (self.ext_list, ctx))
2848       else:
2849         return "%sasn1.CHOICE ([%s])" % (ctx.spaces (), self.elts_to_py (self.elt_list, ctx))
2850   def elts_to_py (self, list, ctx):
2851       ctx.indent ()
2852       def elt_to_py (nt):
2853           assert (nt.type == 'named_type')
2854           tagstr = 'None'
2855           if hasattr (nt, 'ident'):
2856               identstr = nt.ident
2857           else:
2858               if hasattr (nt.typ, 'val'):
2859                   identstr = nt.typ.val # XXX, making up name
2860               elif hasattr (nt.typ, 'name'):
2861                   identstr = nt.typ.name
2862               else:
2863                   identstr = ctx.make_new_name ()
2864
2865           if hasattr (nt.typ, 'type') and nt.typ.type == 'tag': # ugh
2866               tagstr = mk_tag_str (ctx,nt.typ.tag.cls,
2867                                    nt.typ.tag.tag_typ,nt.typ.tag.num)
2868       
2869
2870               nt = nt.typ
2871           return "('%s',%s,%s)" % (identstr, tagstr,
2872                                     nt.typ.to_python (ctx))
2873       indentstr = ",\n" + ctx.spaces ()
2874       rv =  indentstr.join ([elt_to_py (e) for e in list])
2875       ctx.outdent ()
2876       return rv
2877
2878   def eth_reg_sub(self, ident, ectx):
2879       #print "eth_reg_sub(ident='%s')" % (ident)
2880       for e in (self.elt_list):
2881           e.eth_reg(ident, ectx, tstrip=1, parent=ident)
2882       if hasattr(self, 'ext_list'):
2883           for e in (self.ext_list):
2884               e.eth_reg(ident, ectx, tstrip=1, parent=ident)
2885
2886   def eth_ftype(self, ectx):
2887     return ('FT_UINT32', 'BASE_DEC')
2888
2889   def eth_strings(self):
2890     return '$$'
2891
2892   def eth_need_tree(self):
2893     return True
2894
2895   def eth_has_vals(self):
2896     return True
2897
2898   def GetTTag(self, ectx):
2899     lst = self.elt_list
2900     cls = 'BER_CLASS_ANY/*choice*/'
2901     #if hasattr(self, 'ext_list'):
2902     #  lst.extend(self.ext_list)
2903     #if (len(lst) > 0):
2904     #  cls = lst[0].GetTag(ectx)[0]
2905     #for e in (lst):
2906     #  if (e.GetTag(ectx)[0] != cls):
2907     #    cls = '-1/*choice*/'
2908     return (cls, '-1/*choice*/')
2909
2910   def IndetermTag(self, ectx):
2911     #print "Choice IndetermTag()=%s" % (str(not self.HasOwnTag()))
2912     return not self.HasOwnTag()
2913
2914   def get_vals(self, ectx):
2915     tagval = False
2916     if (ectx.Ber()):
2917       lst = self.elt_list
2918       if hasattr(self, 'ext_list'):
2919         lst.extend(self.ext_list)
2920       if (len(lst) > 0):
2921         t = lst[0].GetTag(ectx)[0]
2922         tagval = True
2923       if (t == 'BER_CLASS_UNI'):
2924         tagval = False
2925       for e in (lst):
2926         if (e.GetTag(ectx)[0] != t):
2927           tagval = False
2928     vals = []
2929     cnt = 0
2930     for e in (self.elt_list):
2931       if (tagval): val = e.GetTag(ectx)[1]
2932       else: val = str(cnt)
2933       vals.append((val, e.name))
2934       cnt += 1
2935     if hasattr(self, 'ext_list'):
2936       for e in (self.ext_list):
2937         if (tagval): val = e.GetTag(ectx)[1]
2938         else: val = str(cnt)
2939         vals.append((val, e.name))
2940         cnt += 1
2941     return vals
2942
2943   def eth_type_vals(self, tname, ectx):
2944     out = '\n'
2945     vals = self.get_vals(ectx)
2946     out += ectx.eth_vals(tname, vals)
2947     return out
2948
2949   def eth_type_enum(self, tname, ectx):
2950     out = '\n'
2951     vals = self.get_vals(ectx)
2952     out += ectx.eth_enum(tname, vals)
2953     return out
2954
2955   def eth_type_default_pars(self, ectx, tname):
2956     pars = Type.eth_type_default_pars(self, ectx, tname)
2957     pars['TABLE'] = '%(TNAME)s_choice'
2958     return pars
2959
2960   def eth_type_default_table(self, ectx, tname):
2961     def out_item(val, e, ext, ectx):
2962       has_enum = ectx.eth_type[tname]['enum'] & EF_ENUM
2963       if (has_enum):
2964         vval = ectx.eth_enum_item(tname, e.name)
2965       else:
2966         vval = val
2967       f = fname + '/' + e.name
2968       ef = ectx.field[f]['ethname']
2969       t = ectx.eth_hf[ef]['ethtype']
2970       efd = ef
2971       if (ectx.field[f]['impl']):
2972         efd += '_impl'
2973       if (ectx.Ber()):
2974         opt = ''
2975         if (not e.HasOwnTag()):
2976           opt = 'BER_FLAGS_NOOWNTAG'
2977         elif (e.HasImplicitTag(ectx)):
2978           if (opt): opt += '|'
2979           opt += 'BER_FLAGS_IMPLTAG'
2980         if (not opt): opt = '0'
2981       if (ectx.Ber()):
2982         (tc, tn) = e.GetTag(ectx)
2983         out = '  { %3s, %-13s, %s, %s, dissect_%s },\n' \
2984               % (vval, tc, tn, opt, efd)
2985       elif (ectx.Per()):
2986         out = '  { %3s, %-24s, %-23s, dissect_%s_%s },\n' \
2987               % (vval, '&'+ectx.eth_hf[ef]['fullname'], ext, ectx.eth_type[t]['proto'], t)
2988       else:
2989         out = ''
2990       return out   
2991     # end out_item()
2992     #print "eth_type_default_table(tname='%s')" % (tname)
2993     fname = ectx.eth_type[tname]['ref'][0]
2994     tagval = False
2995     if (ectx.Ber()):
2996       lst = self.elt_list
2997       if hasattr(self, 'ext_list'):
2998         lst.extend(self.ext_list)
2999       if (len(lst) > 0):
3000         t = lst[0].GetTag(ectx)[0]
3001         tagval = True
3002       if (t == 'BER_CLASS_UNI'):
3003         tagval = False
3004       for e in (lst):
3005         if (e.GetTag(ectx)[0] != t):
3006           tagval = False
3007     table = "static const %(ER)s_choice_t %(TABLE)s[] = {\n"
3008     cnt = 0
3009     if hasattr(self, 'ext_list'):
3010       ext = 'ASN1_EXTENSION_ROOT'
3011     else:
3012       ext = 'ASN1_NO_EXTENSIONS'
3013     for e in (self.elt_list):
3014       if (tagval): val = e.GetTag(ectx)[1]
3015       else: val = str(cnt)
3016       table += out_item(val, e, ext, ectx)
3017       cnt += 1
3018     if hasattr(self, 'ext_list'):
3019       for e in (self.ext_list):
3020         if (tagval): val = e.GetTag(ectx)[1]
3021         else: val = str(cnt)
3022         table += out_item(val, e, 'ASN1_NOT_EXTENSION_ROOT', ectx)
3023         cnt += 1
3024     if (ectx.Ber()):
3025       table += "  { 0, 0, 0, 0, NULL }\n};\n"
3026     else:
3027       table += "  { 0, NULL, 0, NULL }\n};\n"
3028     return table
3029
3030   def eth_type_default_body(self, ectx, tname):
3031     if (ectx.Ber()):
3032       body = ectx.eth_fn_call('dissect_%(ER)s_choice', ret='offset',
3033                               par=(('%(PINFO)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s'),
3034                                    ('%(TABLE)s', '%(HF_INDEX)s', '%(ETT_INDEX)s'),
3035                                    ('%(VAL_PTR)s',),))
3036     elif (ectx.Per()):
3037       body = ectx.eth_fn_call('dissect_%(ER)s_choice', ret='offset',
3038                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
3039                                    ('%(ETT_INDEX)s', '%(TABLE)s',),
3040                                    ('%(VAL_PTR)s',),))
3041     else:
3042       body = '#error Can not decode %s' % (tname)
3043     return body
3044    
3045 #--- EnumeratedType -----------------------------------------------------------
3046 class EnumeratedType (Type):
3047   def to_python (self, ctx):
3048     def strify_one (named_num):
3049       return "%s=%s" % (named_num.ident, named_num.val)
3050     return "asn1.ENUM(%s)" % ",".join (map (strify_one, self.val))
3051
3052   def eth_ftype(self, ectx):
3053     return ('FT_UINT32', 'BASE_DEC')
3054
3055   def eth_strings(self):
3056     return '$$'
3057
3058   def eth_has_vals(self):
3059     return True
3060
3061   def GetTTag(self, ectx):
3062     return ('BER_CLASS_UNI', 'BER_UNI_TAG_ENUMERATED')
3063
3064   def get_vals_etc(self, ectx):
3065     vals = []
3066     lastv = 0
3067     used = {}
3068     maxv = 0
3069     root_num = 0
3070     ext_num = 0
3071     map_table = []
3072     for e in (self.val):
3073       if e.type == 'NamedNumber':
3074         used[int(e.val)] = True
3075     for e in (self.val):
3076       if e.type == 'NamedNumber':
3077         val = int(e.val)
3078       else:
3079         while used.has_key(lastv):
3080           lastv += 1
3081         val = lastv
3082         used[val] = True
3083       vals.append((val, e.ident))
3084       map_table.append(val)
3085       root_num += 1
3086       if val > maxv:
3087         maxv = val
3088     if self.ext is not None:
3089       for e in (self.ext):
3090         if e.type == 'NamedNumber':
3091           used[int(e.val)] = True
3092       for e in (self.ext):
3093         if e.type == 'NamedNumber':
3094           val = int(e.val)
3095         else:
3096           while used.has_key(lastv):
3097             lastv += 1
3098           val = lastv
3099           used[val] = True
3100         vals.append((val, e.ident))
3101         map_table.append(val)
3102         ext_num += 1
3103         if val > maxv:
3104           maxv = val
3105     need_map = False
3106     for i in range(len(map_table)):
3107       need_map = need_map or (map_table[i] != i)
3108     if (not need_map):
3109       map_table = None
3110     return (vals, root_num, ext_num, map_table)
3111
3112   def eth_type_vals(self, tname, ectx):
3113     out = '\n'
3114     vals = self.get_vals_etc(ectx)[0]
3115     out += ectx.eth_vals(tname, vals)
3116     return out
3117
3118   def eth_type_enum(self, tname, ectx):
3119     out = '\n'
3120     vals = self.get_vals_etc(ectx)[0]
3121     out += ectx.eth_enum(tname, vals)
3122     return out
3123
3124   def eth_type_default_pars(self, ectx, tname):
3125     pars = Type.eth_type_default_pars(self, ectx, tname)
3126     (root_num, ext_num, map_table) = self.get_vals_etc(ectx)[1:]
3127     if (self.ext != None):
3128       ext = 'TRUE'
3129     else:
3130       ext = 'FALSE'
3131     pars['ROOT_NUM'] = str(root_num)
3132     pars['EXT'] = ext
3133     pars['EXT_NUM'] = str(ext_num)
3134     if (map_table):
3135       pars['TABLE'] = '%(TNAME)s_value_map'
3136     else:
3137       pars['TABLE'] = 'NULL'
3138     return pars
3139
3140   def eth_type_default_table(self, ectx, tname):
3141     if (not ectx.Per()): return ''
3142     map_table = self.get_vals_etc(ectx)[3]
3143     if (map_table == None): return ''
3144     table = "static guint32 %(TABLE)s[%(ROOT_NUM)s+%(EXT_NUM)s] = {"
3145     table += ", ".join([str(v) for v in map_table])
3146     table += "};\n"
3147     return table
3148
3149   def eth_type_default_body(self, ectx, tname):
3150     if (ectx.Ber()):
3151       body = ectx.eth_fn_call('dissect_%(ER)s_integer', ret='offset',
3152                               par=(('%(IMPLICIT_TAG)s', '%(PINFO)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s', '%(HF_INDEX)s'),
3153                                    ('%(VAL_PTR)s',),))
3154     elif (ectx.Per()):
3155       body = ectx.eth_fn_call('dissect_%(ER)s_enumerated', ret='offset',
3156                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
3157                                    ('%(ROOT_NUM)s', '%(VAL_PTR)s', '%(EXT)s', '%(EXT_NUM)s', '%(TABLE)s',),))
3158     else:
3159       body = '#error Can not decode %s' % (tname)
3160     return body
3161
3162 #--- OpenType -----------------------------------------------------------
3163 class OpenType (Type):
3164   def to_python (self, ctx):
3165     return "asn1.ANY"
3166
3167   def single_type(self):
3168     if (self.HasConstraint() and 
3169         self.constr.type == 'Type' and 
3170         self.constr.subtype.type == 'Type_Ref'):
3171       return self.constr.subtype.val
3172     return None
3173
3174   def eth_reg_sub(self, ident, ectx):
3175     t = self.single_type()
3176     if t:
3177       ectx.eth_dep_add(ident, t)
3178
3179   def eth_tname(self):
3180     t = self.single_type()
3181     if t:
3182       return 'OpenType_' + t
3183     else:
3184       return Type.eth_tname(self)
3185
3186   def eth_ftype(self, ectx):
3187     return ('FT_NONE', 'BASE_NONE')
3188
3189   def GetTTag(self, ectx):
3190     return ('BER_CLASS_ANY', '0')
3191
3192   def eth_type_default_pars(self, ectx, tname):
3193     pars = Type.eth_type_default_pars(self, ectx, tname)
3194     t = self.single_type()
3195     if t:
3196       t = ectx.type[t]['ethname']
3197       pars['TYPE_REF_PROTO'] = ectx.eth_type[t]['proto']
3198       pars['TYPE_REF_TNAME'] = t
3199       pars['TYPE_REF_FN'] = 'dissect_%(TYPE_REF_PROTO)s_%(TYPE_REF_TNAME)s'
3200     else:
3201       pars['TYPE_REF_FN'] = 'NULL'
3202     return pars
3203
3204   def eth_type_default_body(self, ectx, tname):
3205     if (ectx.Per()):
3206       body = ectx.eth_fn_call('dissect_%(ER)s_open_type', ret='offset',
3207                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s', '%(TYPE_REF_FN)s',),))
3208     else:
3209       body = '#error Can not decode %s' % (tname)
3210     return body
3211
3212 #--- AnyType -----------------------------------------------------------
3213 class AnyType (Type):
3214   def to_python (self, ctx):
3215     return "asn1.ANY"
3216
3217   def eth_ftype(self, ectx):
3218     return ('FT_NONE', 'BASE_NONE')
3219
3220   def GetTTag(self, ectx):
3221     return ('BER_CLASS_ANY', '0')
3222
3223   def eth_type_default_body(self, ectx, tname):
3224     body = '#error Can not decode %s' % (tname)
3225     return body
3226
3227 class Literal (Node):
3228     def to_python (self, ctx):
3229         return self.val
3230
3231 #--- NullType -----------------------------------------------------------------
3232 class NullType (Type):
3233   def to_python (self, ctx):
3234     return 'asn1.NULL'
3235
3236   def eth_tname(self):
3237     return 'NULL'
3238
3239   def GetTTag(self, ectx):
3240     return ('BER_CLASS_UNI', 'BER_UNI_TAG_NULL')
3241
3242   def eth_type_default_body(self, ectx, tname):
3243     if (ectx.Ber()):
3244       body = ectx.eth_fn_call('dissect_%(ER)s_null', ret='offset',
3245                               par=(('%(IMPLICIT_TAG)s', '%(PINFO)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s', '%(HF_INDEX)s'),))
3246     elif (ectx.Per()):
3247       body = ectx.eth_fn_call('dissect_%(ER)s_null', ret='offset',
3248                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),))
3249     else:
3250       body = '#error Can not decode %s' % (tname)
3251     return body
3252
3253 #--- RealType -----------------------------------------------------------------
3254 class RealType (Type):
3255   def to_python (self, ctx):
3256     return 'asn1.REAL'
3257
3258   def eth_tname(self):
3259     return 'REAL'
3260
3261   def eth_type_default_body(self, ectx, tname):
3262     body = '#error Can not decode %s' % (tname)
3263     return body
3264
3265 #--- BooleanType --------------------------------------------------------------
3266 class BooleanType (Type):
3267   def to_python (self, ctx):
3268     return 'asn1.BOOLEAN'
3269
3270   def eth_tname(self):
3271     return 'BOOLEAN'
3272
3273   def GetTTag(self, ectx):
3274     return ('BER_CLASS_UNI', 'BER_UNI_TAG_BOOLEAN')
3275
3276   def eth_ftype(self, ectx):
3277     return ('FT_BOOLEAN', '8')
3278
3279   def eth_type_default_body(self, ectx, tname):
3280     if (ectx.Ber()):
3281       body = ectx.eth_fn_call('dissect_%(ER)s_boolean', ret='offset',
3282                               par=(('%(IMPLICIT_TAG)s', '%(PINFO)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s', '%(HF_INDEX)s'),))
3283     elif (ectx.Per()):
3284       body = ectx.eth_fn_call('dissect_%(ER)s_boolean', ret='offset',
3285                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s', '%(VAL_PTR)s',),))
3286     else:
3287       body = '#error Can not decode %s' % (tname)
3288     return body
3289
3290 #--- OctetStringType ----------------------------------------------------------
3291 class OctetStringType (Type):
3292   def to_python (self, ctx):
3293     return 'asn1.OCTSTRING'
3294
3295   def eth_tname(self):
3296     if not self.HasConstraint():
3297       return 'OCTET_STRING'
3298     elif self.constr.IsSize():
3299       return 'OCTET_STRING' + '_' + self.constr.eth_constrname()
3300     else:
3301       return '#' + self.type + '_' + str(id(self))
3302
3303   def eth_ftype(self, ectx):
3304     return ('FT_BYTES', 'BASE_HEX')
3305
3306   def GetTTag(self, ectx):
3307     return ('BER_CLASS_UNI', 'BER_UNI_TAG_OCTETSTRING')
3308
3309   def eth_type_default_pars(self, ectx, tname):
3310     pars = Type.eth_type_default_pars(self, ectx, tname)
3311     (pars['MIN_VAL'], pars['MAX_VAL'], pars['EXT']) = self.eth_get_size_constr()
3312     return pars
3313
3314   def eth_type_default_body(self, ectx, tname):
3315     if (ectx.Ber()):
3316       body = ectx.eth_fn_call('dissect_%(ER)s_octet_string', ret='offset',
3317                               par=(('%(IMPLICIT_TAG)s', '%(PINFO)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s', '%(HF_INDEX)s'),
3318                                    ('%(VAL_PTR)s',),))
3319     elif (ectx.Per()):
3320       body = ectx.eth_fn_call('dissect_%(ER)s_octet_string', ret='offset',
3321                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
3322                                    ('%(MIN_VAL)s', '%(MAX_VAL)s', '%(VAL_PTR)s',),))
3323     else:
3324       body = '#error Can not decode %s' % (tname)
3325     return body
3326
3327 #--- CharacterStringType ------------------------------------------------------
3328 class CharacterStringType (Type):
3329   def eth_tname(self):
3330     if not self.HasConstraint():
3331       return self.eth_tsname()
3332     elif self.constr.IsSize():
3333       return self.eth_tsname() + '_' + self.constr.eth_constrname()
3334     else:
3335       return '#' + self.type + '_' + str(id(self))
3336
3337   def eth_ftype(self, ectx):
3338     return ('FT_STRING', 'BASE_NONE')
3339
3340 class RestrictedCharacterStringType (CharacterStringType):
3341   def to_python (self, ctx):
3342     return 'asn1.' + self.eth_tsname()
3343
3344   def GetTTag(self, ectx):
3345     return ('BER_CLASS_UNI', 'BER_UNI_TAG_' + self.eth_tsname())
3346
3347   def HasPermAlph(self):
3348     return (self.HasConstraint() and 
3349             (self.constr.IsPermAlph() or 
3350              (self.constr.type == 'Intersection' and (self.constr.subtype[0].IsPermAlph() or self.constr.subtype[1].IsPermAlph()))
3351             )
3352            )
3353
3354   def eth_type_default_pars(self, ectx, tname):
3355     pars = Type.eth_type_default_pars(self, ectx, tname)
3356     (pars['MIN_VAL'], pars['MAX_VAL'], pars['EXT']) = self.eth_get_size_constr()
3357     (pars['STRING_TYPE'], pars['STRING_TAG']) = (self.eth_tsname(), self.GetTTag(ectx)[1])
3358     (pars['ALPHABET'], pars['ALPHABET_LEN']) = ('NULL', '0')
3359     if self.HasPermAlph():
3360       if self.constr.IsPermAlph():
3361         pars['ALPHABET'] = self.constr.subtype.subtype
3362       elif self.constr.subtype[0].IsPermAlph():
3363         pars['ALPHABET'] = self.constr.subtype[0].subtype.subtype
3364       elif self.constr.subtype[1].IsPermAlph():
3365         pars['ALPHABET'] = self.constr.subtype[1].subtype.subtype
3366       pars['ALPHABET_LEN'] = 'strlen(%(ALPHABET)s)'
3367     return pars
3368
3369   def eth_type_default_body(self, ectx, tname):
3370     if (ectx.Ber()):
3371       body = ectx.eth_fn_call('dissect_%(ER)s_restricted_string', ret='offset',
3372                               par=(('%(IMPLICIT_TAG)s', '%(STRING_TAG)s'),
3373                                    ('%(PINFO)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s', '%(HF_INDEX)s'),
3374                                    ('%(VAL_PTR)s',),))
3375     elif (ectx.Per() and self.HasPermAlph()):
3376       body = ectx.eth_fn_call('dissect_%(ER)s_restricted_character_string', ret='offset',
3377                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
3378                                    ('%(MIN_VAL)s', '%(MAX_VAL)s', '%(ALPHABET)s', '%(ALPHABET_LEN)s'),
3379                                    ('%(VAL_PTR)s',),))
3380     elif (ectx.Per()):
3381       if (self.eth_tsname() == 'GeneralString'):
3382         body = ectx.eth_fn_call('dissect_%(ER)s_%(STRING_TYPE)s', ret='offset',
3383                                 par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),))
3384       elif (self.eth_tsname() == 'GeneralizedTime'):
3385         body = ectx.eth_fn_call('dissect_%(ER)s_VisibleString', ret='offset',
3386                                 par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
3387                                      ('%(MIN_VAL)s', '%(MAX_VAL)s',),))
3388       elif (self.eth_tsname() == 'UTCTime'):
3389         body = ectx.eth_fn_call('dissect_%(ER)s_VisibleString', ret='offset',
3390                                 par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
3391                                      ('%(MIN_VAL)s', '%(MAX_VAL)s',),))
3392       else:
3393         body = ectx.eth_fn_call('dissect_%(ER)s_%(STRING_TYPE)s', ret='offset',
3394                                 par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
3395                                      ('%(MIN_VAL)s', '%(MAX_VAL)s',),))
3396     else:
3397       body = '#error Can not decode %s' % (tname)
3398     return body
3399
3400 class BMPStringType (RestrictedCharacterStringType):
3401   def eth_tsname(self):
3402     return 'BMPString'
3403
3404 class GeneralStringType (RestrictedCharacterStringType):
3405   def eth_tsname(self):
3406     return 'GeneralString'
3407
3408 class GraphicStringType (RestrictedCharacterStringType):
3409   def eth_tsname(self):
3410     return 'GraphicString'
3411
3412 class IA5StringType (RestrictedCharacterStringType):
3413   def eth_tsname(self):
3414     return 'IA5String'
3415
3416 class NumericStringType (RestrictedCharacterStringType):
3417   def eth_tsname(self):
3418     return 'NumericString'
3419
3420 class PrintableStringType (RestrictedCharacterStringType):
3421   def eth_tsname(self):
3422     return 'PrintableString'
3423
3424 class TeletexStringType (RestrictedCharacterStringType):
3425   def eth_tsname(self):
3426     return 'TeletexString'
3427
3428 class T61StringType (RestrictedCharacterStringType):
3429   def eth_tsname(self):
3430     return 'T61String'
3431   def GetTTag(self, ectx):
3432     return ('BER_CLASS_UNI', 'BER_UNI_TAG_TeletexString')
3433
3434 class UniversalStringType (RestrictedCharacterStringType):
3435   def eth_tsname(self):
3436     return 'UniversalString'
3437
3438 class UTF8StringType (RestrictedCharacterStringType):
3439   def eth_tsname(self):
3440     return 'UTF8String'
3441
3442 class VideotexStringType (RestrictedCharacterStringType):
3443   def eth_tsname(self):
3444     return 'VideotexString'
3445
3446 class VisibleStringType (RestrictedCharacterStringType):
3447   def eth_tsname(self):
3448     return 'VisibleString'
3449
3450 class ISO646StringType (RestrictedCharacterStringType):
3451   def eth_tsname(self):
3452     return 'ISO646String'
3453   def GetTTag(self, ectx):
3454     return ('BER_CLASS_UNI', 'BER_UNI_TAG_VisibleString')
3455
3456 class UnrestrictedCharacterStringType (CharacterStringType):
3457   def to_python (self, ctx):
3458     return 'asn1.UnrestrictedCharacterString'
3459   def eth_tsname(self):
3460     return 'CHARACTER_STRING'
3461
3462 #--- UsefulType ---------------------------------------------------------------
3463 class GeneralizedTime (RestrictedCharacterStringType):
3464   def eth_tsname(self):
3465     return 'GeneralizedTime'
3466
3467   def eth_type_default_body(self, ectx, tname):
3468     if (ectx.Ber()):
3469       body = ectx.eth_fn_call('dissect_%(ER)s_%(STRING_TYPE)s', ret='offset',
3470                               par=(('%(IMPLICIT_TAG)s', '%(PINFO)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s', '%(HF_INDEX)s'),))
3471       return body
3472     else:
3473       return RestrictedCharacterStringType.eth_type_default_body(self, ectx, tname)
3474
3475 class UTCTime (RestrictedCharacterStringType):
3476   def eth_tsname(self):
3477     return 'UTCTime'
3478
3479 class ObjectDescriptor (RestrictedCharacterStringType):
3480   def eth_tsname(self):
3481     return 'ObjectDescriptor'
3482
3483
3484 #--- ObjectIdentifierType -----------------------------------------------------
3485 class ObjectIdentifierType (Type):
3486   def to_python (self, ctx):
3487     return 'asn1.OBJECT_IDENTIFIER'
3488
3489   def eth_tname(self):
3490     return 'OBJECT_IDENTIFIER'
3491
3492   def eth_ftype(self, ectx):
3493     return ('FT_OID', 'BASE_NONE')
3494
3495   def GetTTag(self, ectx):
3496     return ('BER_CLASS_UNI', 'BER_UNI_TAG_OID')
3497
3498   def eth_type_default_body(self, ectx, tname):
3499     if (ectx.Ber()):
3500       body = ectx.eth_fn_call('dissect_%(ER)s_object_identifier%(FN_VARIANT)s', ret='offset',
3501                               par=(('%(IMPLICIT_TAG)s', '%(PINFO)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s', '%(HF_INDEX)s', '%(VAL_PTR)s',),))
3502     elif (ectx.Per()):
3503       body = ectx.eth_fn_call('dissect_%(ER)s_object_identifier%(FN_VARIANT)s', ret='offset',
3504                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s', '%(VAL_PTR)s',),))
3505     else:
3506       body = '#error Can not decode %s' % (tname)
3507     return body
3508
3509 #--- ObjectIdentifierValue ----------------------------------------------------
3510 class ObjectIdentifierValue (Value):
3511   def get_num(self, path, val):
3512     return str(oid_names.get(path + '/' + val, val))
3513
3514   def to_str(self):
3515     out = ''
3516     path = ''
3517     first = True
3518     sep = ''
3519     for v in self.comp_list:
3520       if isinstance(v, Node) and (v.type == 'name_and_number'):
3521         vstr = v.number
3522       elif v.isdigit():
3523         vstr = v
3524       else:
3525         vstr = self.get_num(path, v)
3526       if first:
3527         if vstr.isdigit():
3528           out += '"' + vstr
3529         else:
3530           out += vstr + '"'
3531       else:
3532        out += sep + vstr
3533       path += sep + vstr
3534       first = False
3535       sep = '.'
3536     out += '"'
3537     return out
3538
3539   def get_dep(self):
3540     v = self.comp_list[0]
3541     if isinstance(v, Node) and (v.type == 'name_and_number'):
3542       return None
3543     elif v.isdigit():
3544       return None
3545     else:
3546       vstr = self.get_num('', v)
3547     if vstr.isdigit():
3548       return None
3549     else:
3550       return vstr
3551
3552 class NamedNumber (Node):
3553     def to_python (self, ctx):
3554         return "('%s',%s)" % (self.ident, self.val)
3555
3556 class NamedNumListBase(Node):
3557     def to_python (self, ctx):
3558         return "asn1.%s_class ([%s])" % (self.asn1_typ,",".join (
3559             map (lambda x: x.to_python (ctx), self.named_list)))
3560
3561 #--- IntegerType --------------------------------------------------------------
3562 class IntegerType (Type):
3563   def to_python (self, ctx):
3564         return "asn1.INTEGER_class ([%s])" % (",".join (
3565             map (lambda x: x.to_python (ctx), self.named_list)))
3566
3567   def eth_tname(self):
3568     if self.named_list:
3569       return Type.eth_tname(self)
3570     if not self.HasConstraint():
3571       return 'INTEGER'
3572     elif self.constr.type == 'SingleValue' or self.constr.type == 'ValueRange':
3573       return 'INTEGER' + '_' + self.constr.eth_constrname()
3574     else:
3575       return 'INTEGER' + '_' + self.constr.eth_tname()
3576
3577   def GetTTag(self, ectx):
3578     return ('BER_CLASS_UNI', 'BER_UNI_TAG_INTEGER')
3579
3580
3581   def eth_ftype(self, ectx):
3582     if self.HasConstraint():
3583       if not self.constr.IsNegativ():
3584         return ('FT_UINT32', 'BASE_DEC')
3585     return ('FT_INT32', 'BASE_DEC')
3586
3587   def eth_strings(self):
3588     if (self.named_list):
3589       return '$$'
3590     else:
3591       return 'NULL'
3592
3593   def eth_has_vals(self):
3594     if (self.named_list):
3595       return True
3596     else:
3597       return False
3598
3599   def get_vals(self, ectx):
3600     vals = []
3601     for e in (self.named_list):
3602       vals.append((int(e.val), e.ident))
3603     return vals
3604
3605   def eth_type_vals(self, tname, ectx):
3606     if not self.eth_has_vals(): return ''
3607     out = '\n'
3608     vals = self.get_vals(ectx)
3609     out += ectx.eth_vals(tname, vals)
3610     return out
3611
3612   def eth_type_enum(self, tname, ectx):
3613     if not self.eth_has_enum(tname, ectx): return ''
3614     out = '\n'
3615     vals = self.get_vals(ectx)
3616     out += ectx.eth_enum(tname, vals)
3617     return out
3618
3619   def eth_type_default_pars(self, ectx, tname):
3620     pars = Type.eth_type_default_pars(self, ectx, tname)
3621     if self.HasConstraint() and self.constr.IsValue():
3622       (pars['MIN_VAL'], pars['MAX_VAL'], pars['EXT']) = self.eth_get_value_constr()
3623     return pars
3624
3625   def eth_type_default_body(self, ectx, tname):
3626     if (ectx.Ber()):
3627       body = ectx.eth_fn_call('dissect_%(ER)s_integer', ret='offset',
3628                               par=(('%(IMPLICIT_TAG)s', '%(PINFO)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s', '%(HF_INDEX)s'),
3629                                    ('%(VAL_PTR)s',),))
3630     elif (ectx.Per() and not self.HasConstraint()):
3631       body = ectx.eth_fn_call('dissect_%(ER)s_integer', ret='offset',
3632                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s', '%(VAL_PTR)s'),))
3633     elif (ectx.Per() and ((self.constr.type == 'SingleValue') or (self.constr.type == 'ValueRange'))):
3634       body = ectx.eth_fn_call('dissect_%(ER)s_constrained_integer', ret='offset',
3635                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
3636                                    ('%(MIN_VAL)s', '%(MAX_VAL)s', '%(VAL_PTR)s', '%(EXT)s'),))
3637     else:
3638       body = '#error Can not decode %s' % (tname)
3639     return body
3640
3641 #--- BitStringType ------------------------------------------------------------
3642 class BitStringType (Type):
3643   def to_python (self, ctx):
3644         return "asn1.BITSTRING_class ([%s])" % (",".join (
3645             map (lambda x: x.to_python (ctx), self.named_list)))
3646
3647   def eth_tname(self):
3648     if self.named_list:
3649       return Type.eth_tname(self)
3650     elif not self.HasConstraint():
3651       return 'BIT_STRING'
3652     elif self.constr.IsSize():
3653       return 'BIT_STRING' + '_' + self.constr.eth_constrname()
3654     else:
3655       return '#' + self.type + '_' + str(id(self))
3656
3657   def GetTTag(self, ectx):
3658     return ('BER_CLASS_UNI', 'BER_UNI_TAG_BITSTRING')
3659
3660   def eth_ftype(self, ectx):
3661     return ('FT_BYTES', 'BASE_HEX')
3662
3663   def eth_need_tree(self):
3664     return self.named_list
3665
3666   def eth_named_bits(self):
3667     bits = []
3668     if (self.named_list):
3669       for e in (self.named_list):
3670         bits.append((int(e.val), e.ident))
3671     return bits
3672
3673   def eth_type_default_pars(self, ectx, tname):
3674     pars = Type.eth_type_default_pars(self, ectx, tname)
3675     (pars['MIN_VAL'], pars['MAX_VAL'], pars['EXT']) = self.eth_get_size_constr()
3676     if not pars.has_key('ETT_INDEX'):
3677       pars['ETT_INDEX'] = '-1'
3678     pars['TABLE'] = 'NULL'
3679     if self.eth_named_bits():
3680       pars['TABLE'] = '%(TNAME)s_bits'
3681     return pars
3682
3683   def eth_type_default_table(self, ectx, tname):
3684     #print "eth_type_default_table(tname='%s')" % (tname)
3685     table = ''
3686     bits = self.eth_named_bits()
3687     if (bits):
3688       table = ectx.eth_bits(tname, bits)
3689     return table
3690
3691   def eth_type_default_body(self, ectx, tname):
3692     if (ectx.Ber()):
3693       body = ectx.eth_fn_call('dissect_%(ER)s_bitstring', ret='offset',
3694                               par=(('%(IMPLICIT_TAG)s', '%(PINFO)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s'),
3695                                    ('%(TABLE)s', '%(HF_INDEX)s', '%(ETT_INDEX)s',),
3696                                    ('%(VAL_PTR)s',),))
3697     elif (ectx.Per()):
3698       body = ectx.eth_fn_call('dissect_%(ER)s_bit_string', ret='offset',
3699                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
3700                                    ('%(MIN_VAL)s', '%(MAX_VAL)s','%(EXT)s','%(VAL_PTR)s'),))
3701     else:
3702       body = '#error Can not decode %s' % (tname)
3703     return body
3704
3705
3706 #==============================================================================
3707     
3708 def p_module_list_1 (t):
3709     'module_list : module_list module_def'
3710     t[0] = t[1] + [t[2]]
3711
3712 def p_module_list_2 (t):
3713     'module_list : module_def'
3714     t[0] = [t[1]]
3715
3716
3717 #--- ITU-T Recommendation X.680 -----------------------------------------------
3718
3719
3720 # 11 ASN.1 lexical items --------------------------------------------------------
3721
3722 # 11.2 Type references
3723 def p_type_ref (t):
3724     'type_ref : UCASE_IDENT'
3725     t[0] = Type_Ref(val=t[1])
3726
3727 # 11.4 Value references
3728 def p_valuereference (t):
3729     'valuereference : LCASE_IDENT'
3730     t[0] = t[1]
3731
3732 # 11.5 Module references
3733 def p_modulereference (t):
3734     'modulereference : UCASE_IDENT'
3735     t[0] = t[1]
3736
3737
3738 # 12 Module definition --------------------------------------------------------
3739
3740 # 12.1
3741 def p_module_def (t):
3742     'module_def : ModuleIdentifier DEFINITIONS TagDefault ASSIGNMENT BEGIN module_body END'
3743     t[0] = Module (ident = t[1], tag_def = t[3], body = t[6])
3744
3745 def p_TagDefault_1 (t):
3746     '''TagDefault : EXPLICIT TAGS
3747     | IMPLICIT TAGS
3748     | AUTOMATIC TAGS'''
3749     t[0] = Default_Tags (dfl_tag = t[1])
3750
3751 def p_TagDefault_2 (t):
3752     'TagDefault : '
3753     # 12.2 The "TagDefault" is taken as EXPLICIT TAGS if it is "empty".
3754     t[0] = Default_Tags (dfl_tag = 'EXPLICIT') 
3755
3756 def p_ModuleIdentifier_1 (t):
3757   'ModuleIdentifier : modulereference DefinitiveIdentifier' # name, oid
3758   t [0] = Node('module_ident', val = t[1], ident = t[2])
3759
3760 def p_ModuleIdentifier_2 (t):
3761   'ModuleIdentifier : modulereference' # name, oid
3762   t [0] = Node('module_ident', val = t[1], ident = None)
3763
3764 def p_DefinitiveIdentifier (t):
3765   'DefinitiveIdentifier : ObjectIdentifierValue'
3766   t[0] = t[1]
3767
3768 # XXX originally we had both type_ref and module_ref, but that caused
3769 # a reduce/reduce conflict (because both were UCASE_IDENT).  Presumably
3770 # this didn't cause a problem in the original ESNACC grammar because it
3771 # was LALR(1) and PLY is (as of 1.1) only SLR.
3772
3773 #def p_module_ref (t):
3774 #    'module_ref : UCASE_IDENT'
3775 #    t[0] = t[1]
3776
3777 def p_assigned_ident_1 (t):
3778     'assigned_ident : ObjectIdentifierValue'
3779     t[0] = t[1]
3780
3781 def p_assigned_ident_2 (t):
3782     'assigned_ident : LCASE_IDENT'
3783     t[0] = t[1]
3784
3785 def p_assigned_ident_3 (t):
3786     'assigned_ident : '
3787     pass
3788
3789 def p_module_body_1 (t):
3790     'module_body : exports Imports AssignmentList'
3791     t[0] = Module_Body (exports = t[1], imports = t[2], assign_list = t[3])
3792
3793 def p_module_body_2 (t):
3794     'module_body : '
3795     t[0] = Node ('module_body', exports = [], imports = [],
3796                  assign_list = [])
3797
3798 def p_exports_1 (t):
3799     'exports : EXPORTS syms_exported SEMICOLON'
3800     t[0] = t[2]
3801
3802 def p_exports_2 (t):
3803     'exports : '
3804     t[0] = []
3805
3806 def p_syms_exported_1 (t):
3807     'syms_exported : exp_sym_list'
3808     t[0] = t[1]
3809
3810 def p_syms_exported_2 (t):
3811     'syms_exported : '
3812     t[0] = []
3813
3814 def p_exp_sym_list_1 (t):
3815     'exp_sym_list : Symbol'
3816     t[0] = [t[1]]
3817
3818 def p_exp_sym_list_2 (t):
3819     'exp_sym_list : exp_sym_list COMMA Symbol'
3820     t[0] = t[1] + [t[3]]
3821     
3822
3823 def p_Imports_1(t):
3824     'Imports : IMPORTS SymbolsImported SEMICOLON'
3825     t[0] = t[2]
3826
3827 def p_Imports_2 (t):
3828     'Imports : '
3829     t[0] = []
3830
3831 def p_SymbolsImported_1(t):
3832     'SymbolsImported : '
3833     t[0] = []
3834
3835 def p_SymbolsImported_2 (t):
3836     'SymbolsImported : SymbolsFromModuleList'
3837     t[0] = t[1]
3838
3839 def p_SymbolsFromModuleList_1 (t):
3840     'SymbolsFromModuleList : SymbolsFromModuleList SymbolsFromModule'
3841     t[0] = t[1] + [t[2]]
3842
3843 def p_SymbolsFromModuleList_2 (t):
3844     'SymbolsFromModuleList : SymbolsFromModule'
3845     t[0] = [t[1]]
3846
3847 def p_SymbolsFromModule (t):
3848     'SymbolsFromModule : SymbolList FROM GlobalModuleReference'
3849     t[0] = Node ('SymbolList', symbol_list = t[1], module = t[3])
3850
3851 def p_GlobalModuleReference (t):
3852   'GlobalModuleReference : modulereference assigned_ident'
3853   t [0] = Node('module_ident', val = t[1], ident = t[2])
3854
3855 def p_SymbolList_1 (t):
3856     'SymbolList : Symbol'
3857     t[0] = [t[1]]
3858
3859 def p_SymbolList_2 (t):
3860     'SymbolList : SymbolList COMMA Symbol'
3861     t[0] = t[1] + [t[3]]
3862
3863 def p_Symbol (t):
3864     '''Symbol : type_ref
3865               | ParameterizedReference
3866               | identifier''' # XXX omit DefinedMacroName
3867     t[0] = t[1]
3868
3869 def p_Reference (t):
3870     '''Reference : type_ref
3871                  | valuereference'''
3872     t[0] = t[1]
3873
3874 def p_AssignmentList_1 (t):
3875     'AssignmentList : AssignmentList Assignment'
3876     t[0] = t[1] + [t[2]]
3877
3878 def p_AssignmentList_2 (t):
3879     'AssignmentList : Assignment SEMICOLON'
3880     t[0] = [t[1]]
3881
3882 def p_AssignmentList_3 (t):
3883     'AssignmentList : Assignment'
3884     t[0] = [t[1]]
3885
3886 def p_Assignment (t):
3887     '''Assignment : TypeAssignment
3888                   | ValueAssignment
3889                   | pyquote
3890                   | ParameterizedTypeAssignment'''
3891     t[0] = t[1]
3892
3893 def p_pyquote (t):
3894     '''pyquote : PYQUOTE'''
3895     t[0] = PyQuote (val = t[1])
3896
3897
3898 # 13 Referencing type and value definitions -----------------------------------
3899
3900 # 13.1
3901 def p_DefinedType (t): 
3902   '''DefinedType : ext_type_ref
3903   | type_ref
3904   | ParameterizedType'''
3905   t[0] = t[1]
3906
3907 def p_DefinedValue(t):
3908   '''DefinedValue : ext_val_ref
3909                   | identifier'''
3910   t[0] = t[1]
3911
3912
3913 # 15 Assigning types and values -----------------------------------------------
3914
3915 # 15.1
3916 def p_TypeAssignment (t):
3917   'TypeAssignment : UCASE_IDENT ASSIGNMENT Type'
3918   t[0] = t[3]
3919   t[0].SetName(t[1])
3920
3921 # 15.2
3922 def p_ValueAssignment (t):
3923   'ValueAssignment : identifier Type ASSIGNMENT Value'
3924   t[0] = value_assign (ident = t[1], typ = t[2], val = t[4])
3925
3926
3927 # 16 Definition of types and values -------------------------------------------
3928
3929 # 16.1
3930 def p_Type (t):
3931   '''Type : BuiltinType
3932           | ReferencedType
3933           | ConstrainedType'''
3934   t[0] = t[1]
3935
3936 # 16.2
3937 def p_BuiltinType (t):
3938   '''BuiltinType : AnyType
3939                  | BitStringType
3940                  | BooleanType
3941                  | CharacterStringType
3942                  | ChoiceType
3943                  | EnumeratedType
3944                  | IntegerType
3945                  | NullType
3946                  | ObjectClassFieldType
3947                  | ObjectIdentifierType
3948                  | OctetStringType
3949                  | RealType
3950                  | SequenceType
3951                  | SequenceOfType
3952                  | SetType
3953                  | SetOfType
3954                  | selection_type
3955                  | TaggedType'''
3956   t[0] = t[1]
3957
3958 # 16.3
3959 def p_ReferencedType (t):
3960   '''ReferencedType : DefinedType
3961                     | UsefulType'''
3962   t[0] = t[1]
3963
3964 def p_ext_type_ref (t):
3965     'ext_type_ref : type_ref DOT type_ref'
3966     # XXX coerce 1st type_ref to module_ref
3967     t[0] = Node ('ext_type_ref', module = t[1], typ = t[3])
3968
3969 # 16.5
3970 def p_NamedType (t):
3971   'NamedType : identifier Type'
3972   t[0] = t[2]
3973   t[0].SetName (t[1]) 
3974
3975 # 16.7
3976 def p_Value (t):
3977   '''Value : BuiltinValue
3978            | ReferencedValue'''
3979   t[0] = t[1]
3980
3981 # 16.9
3982 def p_BuiltinValue (t):
3983   '''BuiltinValue : BooleanValue
3984                   | ObjectIdentifierValue
3985                   | special_real_val
3986                   | SignedNumber
3987                   | SequenceValue
3988                   | hex_string
3989                   | binary_string
3990                   | char_string''' # XXX we don't support {data} here
3991   t[0] = t[1]
3992
3993 # 16.11
3994 def p_ReferencedValue (t):
3995   '''ReferencedValue : DefinedValue'''
3996   t[0] = t[1]
3997
3998 # 16.13
3999 #def p_NamedValue (t):
4000 #  'NamedValue : identifier Value'
4001 #  t[0] = Node ('NamedValue', ident = t[1], value = t[2])
4002
4003
4004 # 17 Notation for the boolean type --------------------------------------------
4005
4006 # 17.1
4007 def p_BooleanType (t):
4008   'BooleanType : BOOLEAN'
4009   t[0] = BooleanType ()
4010
4011 # 17.2
4012 def p_BooleanValue (t):
4013   '''BooleanValue : TRUE
4014                   | FALSE'''
4015   t[0] = t[1]
4016
4017
4018 # 18 Notation for the integer type --------------------------------------------
4019
4020 # 18.1
4021 def p_IntegerType_1 (t):
4022   'IntegerType : INTEGER'
4023   t[0] = IntegerType (named_list = None)
4024
4025 def p_IntegerType_2 (t):
4026   'IntegerType : INTEGER LBRACE NamedNumberList RBRACE'
4027   t[0] = IntegerType (named_list = t[3])
4028
4029 def p_NamedNumberList_1 (t):
4030   'NamedNumberList : NamedNumber'
4031   t[0] = [t[1]]
4032
4033 def p_NamedNumberList_2 (t):
4034   'NamedNumberList : NamedNumberList COMMA NamedNumber'
4035   t[0] = t[1] + [t[3]]
4036
4037 def p_NamedNumber (t):
4038   '''NamedNumber : identifier LPAREN SignedNumber RPAREN
4039                  | identifier LPAREN DefinedValue RPAREN'''
4040   t[0] = NamedNumber (ident = t[1], val = t[3])
4041
4042 def p_SignedNumber_1 (t):
4043   'SignedNumber : NUMBER'
4044   t[0] = t [1]
4045
4046 def p_SignedNumber_2 (t):
4047   'SignedNumber : MINUS NUMBER'
4048   t[0] = '-' + t[2]
4049
4050
4051 # 19 Notation for the enumerated type -----------------------------------------
4052
4053 # 19.1
4054 def p_EnumeratedType (t):
4055     'EnumeratedType : ENUMERATED LBRACE Enumerations RBRACE'
4056     t[0] = EnumeratedType (val = t[3]['val'], ext = t[3]['ext'])
4057
4058 def p_Enumerations_1 (t):
4059     'Enumerations : Enumeration'
4060     t[0] = { 'val' : t[1], 'ext' : None }
4061
4062 def p_Enumerations_2 (t):
4063     'Enumerations : Enumeration COMMA ELLIPSIS ExceptionSpec'
4064     t[0] = { 'val' : t[1], 'ext' : [] }
4065
4066 def p_Enumerations_3 (t):
4067     'Enumerations : Enumeration COMMA ELLIPSIS ExceptionSpec COMMA Enumeration'
4068     t[0] = { 'val' : t[1], 'ext' : t[6] }
4069
4070 def p_Enumeration_1 (t):
4071     'Enumeration : EnumerationItem'
4072     t[0] = [t[1]]
4073
4074 def p_Enumeration_2 (t):
4075     'Enumeration : Enumeration COMMA EnumerationItem'
4076     t[0] = t[1] + [t[3]]
4077
4078 def p_EnumerationItem (t):
4079     '''EnumerationItem : Identifier
4080                        | NamedNumber'''
4081     t[0] = t[1]
4082
4083 def p_Identifier (t):
4084     'Identifier : identifier'
4085     t[0] = Node ('Identifier', ident = t[1])
4086
4087
4088 # 20 Notation for the real type -----------------------------------------------
4089
4090 # 20.1
4091 def p_RealType (t):
4092     'RealType : REAL'
4093     t[0] = RealType ()
4094
4095 # 21 Notation for the bitstring type ------------------------------------------
4096
4097 # 21.1
4098 def p_BitStringType_1 (t):
4099     'BitStringType : BIT STRING'
4100     t[0] = BitStringType (named_list = None)
4101
4102 def p_BitStringType_2 (t):
4103     'BitStringType : BIT STRING LBRACE NamedBitList RBRACE'
4104     t[0] = BitStringType (named_list = t[4])
4105
4106 def p_NamedBitList_1 (t):
4107     'NamedBitList : NamedBit'
4108     t[0] = [t[1]]
4109
4110 def p_NamedBitList_2 (t):
4111     'NamedBitList : NamedBitList COMMA NamedBit'
4112     t[0] = t[1] + [t[3]]
4113
4114 def p_NamedBit (t):
4115     '''NamedBit : identifier LPAREN NUMBER RPAREN
4116                 | identifier LPAREN DefinedValue RPAREN'''
4117     t[0] = NamedNumber (ident = t[1], val = t[3])
4118
4119
4120 # 22 Notation for the octetstring type ----------------------------------------
4121
4122 # 22.1
4123 def p_OctetStringType (t):
4124     'OctetStringType : OCTET STRING'
4125     t[0] = OctetStringType ()
4126
4127
4128 # 23 Notation for the null type -----------------------------------------------
4129
4130 # 23.1
4131 def p_NullType (t):
4132     'NullType : NULL'
4133     t[0] = NullType ()
4134
4135 # 23.3
4136 #def p_NullValue (t):
4137 #    'NullValue : NULL'
4138 #    t[0] = t[1]
4139
4140
4141 # 24 Notation for sequence types ----------------------------------------------
4142
4143 # 24.1
4144 def p_SequenceType_1 (t):
4145     'SequenceType : SEQUENCE LBRACE RBRACE'
4146     t[0] = SequenceType (elt_list = [])
4147
4148 def p_SequenceType_2 (t):
4149     'SequenceType : SEQUENCE LBRACE ComponentTypeLists RBRACE'
4150     if t[3].has_key('ext_list'):
4151         t[0] = SequenceType (elt_list = t[3]['elt_list'], ext_list = t[3]['ext_list'])
4152     else:
4153         t[0] = SequenceType (elt_list = t[3]['elt_list'])
4154
4155 def p_ExtensionAndException_1 (t):
4156     'ExtensionAndException : ELLIPSIS'
4157     t[0] = []
4158
4159 def p_OptionalExtensionMarker_1 (t):
4160     'OptionalExtensionMarker : COMMA ELLIPSIS'
4161     t[0] = True
4162
4163 def p_OptionalExtensionMarker_2 (t):
4164     'OptionalExtensionMarker : '
4165     t[0] = False
4166
4167 def p_ComponentTypeLists_1 (t):
4168     'ComponentTypeLists : element_type_list'
4169     t[0] = {'elt_list' : t[1]}
4170
4171 def p_ComponentTypeLists_2 (t):
4172     'ComponentTypeLists : element_type_list COMMA ExtensionAndException extension_additions OptionalExtensionMarker'
4173     t[0] = {'elt_list' : t[1], 'ext_list' : t[4]}
4174
4175 def p_ComponentTypeLists_3 (t):
4176     'ComponentTypeLists : ExtensionAndException extension_additions OptionalExtensionMarker'
4177     t[0] = {'elt_list' : [], 'ext_list' : t[2]}
4178
4179 def p_extension_additions_1 (t):
4180     'extension_additions : extension_addition_list'
4181     t[0] = t[1]
4182
4183 def p_extension_additions_2 (t):
4184     'extension_additions : '
4185     t[0] = []
4186
4187 def p_extension_addition_list_1 (t):
4188     'extension_addition_list : COMMA extension_addition'
4189     t[0] = [t[2]]
4190
4191 def p_extension_addition_list_2 (t):
4192     'extension_addition_list : extension_addition_list COMMA extension_addition'
4193     t[0] = t[1] + [t[3]]
4194
4195 def p_extension_addition_1 (t):
4196     'extension_addition : element_type'
4197     t[0] = t[1]
4198
4199 def p_element_type_list_1 (t):
4200     'element_type_list : element_type'
4201     t[0] = [t[1]]
4202
4203 def p_element_type_list_2 (t):
4204     'element_type_list : element_type_list COMMA element_type'
4205     t[0] = t[1] + [t[3]]
4206
4207 def p_element_type_1 (t):
4208     'element_type : NamedType'
4209     t[0] = Node ('elt_type', val = t[1], optional = 0)
4210
4211 def p_element_type_2 (t):
4212     'element_type : NamedType OPTIONAL'
4213     t[0] = Node ('elt_type', val = t[1], optional = 1)
4214
4215 def p_element_type_3 (t):
4216     'element_type : NamedType DEFAULT Value'
4217     t[0] = Node ('elt_type', val = t[1], optional = 1, default = t[3])
4218 #          /*
4219 #           * this rules uses NamedValue instead of Value
4220 #           * for the stupid choice value syntax (fieldname value)
4221 #           * it should be like a set/seq value (ie with
4222 #           * enclosing { }
4223 #           */
4224
4225 # XXX get to COMPONENTS later
4226
4227 # 24.17
4228 def p_SequenceValue_1 (t):
4229   'SequenceValue : LBRACE RBRACE'
4230   t[0] = []
4231
4232
4233 #def p_SequenceValue_2 (t):
4234 #  'SequenceValue : LBRACE ComponentValueList RBRACE'
4235 #  t[0] = t[2]
4236     
4237 #def p_ComponentValueList_1 (t):
4238 #    'ComponentValueList : NamedValue'
4239 #    t[0] = [t[1]]
4240
4241 #def p_ComponentValueList_2 (t):
4242 #    'ComponentValueList : ComponentValueList COMMA NamedValue'
4243 #    t[0] = t[1] + [t[3]]
4244
4245
4246 # 25 Notation for sequence-of types -------------------------------------------
4247
4248 # 25.1
4249 def p_SequenceOfType (t):
4250     '''SequenceOfType : SEQUENCE OF Type
4251                       | SEQUENCE OF NamedType'''
4252     t[0] = SequenceOfType (val = t[3], size_constr = None)
4253
4254
4255 # 26 Notation for set types ---------------------------------------------------
4256
4257 # 26.1
4258 def p_SetType_1 (t):
4259     'SetType : SET LBRACE RBRACE'
4260     if t[3].has_key('ext_list'):
4261         t[0] = SetType (elt_list = [])
4262
4263 def p_SetType_2 (t):
4264     'SetType : SET LBRACE ComponentTypeLists RBRACE'
4265     if t[3].has_key('ext_list'):
4266         t[0] = SetType (elt_list = t[3]['elt_list'], ext_list = t[3]['ext_list'])
4267     else:
4268         t[0] = SetType (elt_list = t[3]['elt_list'])
4269
4270
4271 # 27 Notation for set-of types ------------------------------------------------
4272
4273 # 27.1
4274 def p_SetOfType (t):
4275     '''SetOfType : SET OF Type
4276                  | SET OF NamedType'''
4277     t[0] = SetOfType (val = t[3])
4278
4279 # 28 Notation for choice types ------------------------------------------------
4280
4281 # 28.1
4282 def p_ChoiceType (t):
4283     'ChoiceType : CHOICE LBRACE alternative_type_lists RBRACE'
4284     if t[3].has_key('ext_list'):
4285         t[0] = ChoiceType (elt_list = t[3]['elt_list'], ext_list = t[3]['ext_list'])
4286     else:
4287         t[0] = ChoiceType (elt_list = t[3]['elt_list'])
4288
4289 def p_alternative_type_lists_1 (t):
4290     'alternative_type_lists : alternative_type_list'
4291     t[0] = {'elt_list' : t[1]}
4292
4293 def p_alternative_type_lists_2 (t):
4294     '''alternative_type_lists : alternative_type_list COMMA ExtensionAndException extension_addition_alternatives OptionalExtensionMarker'''
4295     t[0] = {'elt_list' : t[1], 'ext_list' : t[4]}
4296
4297 def p_extension_addition_alternatives_1 (t):
4298     'extension_addition_alternatives : extension_addition_alternatives_list'
4299     t[0] = t[1]
4300
4301 def p_extension_addition_alternatives_2 (t):
4302     'extension_addition_alternatives : '
4303     t[0] = []
4304
4305 def p_extension_addition_alternatives_list_1 (t):
4306     'extension_addition_alternatives_list : COMMA extension_addition_alternative'
4307     t[0] = [t[2]]
4308
4309 def p_extension_addition_alternatives_list_2 (t):
4310     'extension_addition_alternatives_list : extension_addition_alternatives_list COMMA extension_addition_alternative'
4311     t[0] = t[1] + [t[3]]
4312
4313 def p_extension_addition_alternative_1 (t):
4314     'extension_addition_alternative : NamedType'
4315     t[0] = t[1]
4316
4317 def p_alternative_type_list_1 (t):
4318     'alternative_type_list : NamedType'
4319     t[0] = [t[1]]
4320
4321 def p_alternative_type_list_2 (t):
4322     'alternative_type_list : alternative_type_list COMMA NamedType'
4323     t[0] = t[1] + [t[3]]
4324
4325 def p_selection_type (t): # XXX what is this?
4326     'selection_type : identifier LT Type'
4327     return Node ('seltype', ident = t[1], typ = t[3])
4328
4329 # 30 Notation for tagged types ------------------------------------------------
4330
4331 # 30.1
4332 def p_TaggedType_1 (t):
4333     'TaggedType : Tag Type'
4334     t[1].mode = 'default'
4335     t[0] = t[2]
4336     t[0].AddTag(t[1])
4337
4338 def p_TaggedType_2 (t):
4339     '''TaggedType : Tag IMPLICIT Type
4340                   | Tag EXPLICIT Type'''
4341     t[1].mode = t[2]
4342     t[0] = t[3]
4343     t[0].AddTag(t[1])
4344
4345 def p_Tag (t):
4346     'Tag : LBRACK Class ClassNumber RBRACK'
4347     t[0] = Tag(cls = t[2], num = t[3])
4348
4349 def p_ClassNumber_1 (t):
4350     'ClassNumber : number'
4351     t[0] = t[1]
4352
4353 def p_ClassNumber_2 (t):
4354     'ClassNumber : DefinedValue'
4355     t[0] = t[1]
4356
4357 def p_Class_1 (t):
4358     '''Class : UNIVERSAL
4359              | APPLICATION
4360              | PRIVATE'''
4361     t[0] = t[1]
4362
4363 def p_Class_2 (t):
4364     'Class :'
4365     t[0] = 'CONTEXT'
4366
4367
4368 def p_AnyType (t):
4369     'AnyType : ANY'
4370     t[0] = AnyType ()
4371
4372 #def p_any_type_2 (t):
4373 #    'any_type : ANY DEFINED BY identifier'
4374 #    t[0] = Literal (val='asn1.ANY_constr(def_by="%s")' % t[4]) # XXX
4375
4376
4377 # 31 Notation for the object identifier type ----------------------------------
4378
4379 # 31.1
4380 def p_ObjectIdentifierType (t):
4381   'ObjectIdentifierType : OBJECT IDENTIFIER'
4382   t[0] = ObjectIdentifierType()
4383
4384 # 31.3
4385 def p_ObjectIdentifierValue (t):
4386     'ObjectIdentifierValue : LBRACE oid_comp_list RBRACE'
4387     t[0] = ObjectIdentifierValue (comp_list=t[2])
4388
4389 def p_oid_comp_list_1 (t):
4390     'oid_comp_list : oid_comp_list oid_component'
4391     t[0] = t[1] + [t[2]]
4392
4393 def p_oid_comp_list_2 (t):
4394     'oid_comp_list : oid_component'
4395     t[0] = [t[1]]
4396
4397 def p_oid_component (t):
4398     '''oid_component : number_form
4399     | name_form
4400     | name_and_number_form'''
4401     t[0] = t[1]
4402
4403 def p_number_form (t):
4404     'number_form : NUMBER'
4405     t [0] = t[1]
4406
4407 # 36 Notation for character string types --------------------------------------
4408
4409 # 36.1
4410 def p_CharacterStringType (t):
4411     '''CharacterStringType : RestrictedCharacterStringType
4412     | UnrestrictedCharacterStringType'''
4413     t[0] = t[1]
4414
4415
4416 # 37 Definition of restricted character string types --------------------------
4417
4418 def p_RestrictedCharacterStringType_1 (t):
4419     'RestrictedCharacterStringType : BMPString'
4420     t[0] = BMPStringType ()
4421 def p_RestrictedCharacterStringType_2 (t):
4422     'RestrictedCharacterStringType : GeneralString'
4423     t[0] = GeneralStringType ()
4424 def p_RestrictedCharacterStringType_3 (t):
4425     'RestrictedCharacterStringType : GraphicString'
4426     t[0] = GraphicStringType ()
4427 def p_RestrictedCharacterStringType_4 (t):
4428     'RestrictedCharacterStringType : IA5String'
4429     t[0] = IA5StringType ()
4430 def p_RestrictedCharacterStringType_5 (t):
4431     'RestrictedCharacterStringType : ISO646String'
4432     t[0] = ISO646StringType ()
4433 def p_RestrictedCharacterStringType_6 (t):
4434     'RestrictedCharacterStringType : NumericString'
4435     t[0] = NumericStringType ()
4436 def p_RestrictedCharacterStringType_7 (t):
4437     'RestrictedCharacterStringType : PrintableString'
4438     t[0] = PrintableStringType ()
4439 def p_RestrictedCharacterStringType_8 (t):
4440     'RestrictedCharacterStringType : TeletexString'
4441     t[0] = TeletexStringType ()
4442 def p_RestrictedCharacterStringType_9 (t):
4443     'RestrictedCharacterStringType : T61String'
4444     t[0] = T61StringType ()
4445 def p_RestrictedCharacterStringType_10 (t):
4446     'RestrictedCharacterStringType : UniversalString'
4447     t[0] = UniversalStringType ()
4448 def p_RestrictedCharacterStringType_11 (t):
4449     'RestrictedCharacterStringType : UTF8String'
4450     t[0] = UTF8StringType ()
4451 def p_RestrictedCharacterStringType_12 (t):
4452     'RestrictedCharacterStringType : VideotexString'
4453     t[0] = VideotexStringType ()
4454 def p_RestrictedCharacterStringType_13 (t):
4455     'RestrictedCharacterStringType : VisibleString'
4456     t[0] = VisibleStringType ()
4457
4458
4459 # 40 Definition of unrestricted character string types ------------------------
4460
4461 # 40.1
4462 def p_UnrestrictedCharacterStringType (t):
4463     'UnrestrictedCharacterStringType : CHARACTER STRING'
4464     t[0] = UnrestrictedCharacterStringType ()
4465
4466
4467 # 41 Notation for types defined in clauses 42 to 44 ---------------------------
4468
4469 # 42 Generalized time ---------------------------------------------------------
4470
4471 def p_UsefulType_1 (t):
4472   'UsefulType : GeneralizedTime'
4473   t[0] = GeneralizedTime()
4474
4475 # 43 Universal time -----------------------------------------------------------
4476
4477 def p_UsefulType_2 (t):
4478   'UsefulType : UTCTime'
4479   t[0] = UTCTime()
4480
4481 # 44 The object descriptor type -----------------------------------------------
4482
4483 def p_UsefulType_3 (t):
4484   'UsefulType : ObjectDescriptor'
4485   t[0] = ObjectDescriptor()
4486
4487
4488 # 45 Constrained types --------------------------------------------------------
4489
4490 # 45.1
4491 def p_ConstrainedType_1 (t):
4492     'ConstrainedType : Type Constraint'
4493     t[0] = t[1]
4494     t[0].AddConstraint(t[2])
4495
4496 def p_ConstrainedType_2 (t):
4497     'ConstrainedType : TypeWithConstraint'
4498     t[0] = t[1]
4499
4500 # 45.5
4501 def p_TypeWithConstraint_1 (t):
4502     '''TypeWithConstraint : SET Constraint OF Type
4503                           | SET SizeConstraint OF Type'''
4504     t[0] = SetOfType (val = t[4], constr = t[2])
4505
4506 def p_TypeWithConstraint_2 (t):
4507     '''TypeWithConstraint : SEQUENCE Constraint OF Type
4508                           | SEQUENCE SizeConstraint OF Type'''
4509     t[0] = SequenceOfType (val = t[4], constr = t[2])
4510
4511 def p_TypeWithConstraint_3 (t):
4512     '''TypeWithConstraint : SET Constraint OF NamedType
4513                           | SET SizeConstraint OF NamedType'''
4514     t[0] = SetOfType (val = t[4], constr = t[2])
4515
4516 def p_TypeWithConstraint_4 (t):
4517     '''TypeWithConstraint : SEQUENCE Constraint OF NamedType
4518                           | SEQUENCE SizeConstraint OF NamedType'''
4519     t[0] = SequenceOfType (val = t[4], constr = t[2])
4520
4521 # 45.6
4522 # 45.7
4523 def p_Constraint (t):
4524     'Constraint : LPAREN ConstraintSpec ExceptionSpec RPAREN'
4525     t[0] = t[2]
4526
4527 def p_ConstraintSpec (t):
4528     '''ConstraintSpec : ElementSetSpecs
4529                       | GeneralConstraint'''
4530     t[0] = t[1]
4531
4532 # 46 Element set specification ------------------------------------------------
4533
4534 # 46.1
4535 def p_ElementSetSpecs_1 (t):
4536     'ElementSetSpecs : RootElementSetSpec'
4537     t[0] = t[1]
4538
4539 def p_ElementSetSpecs_2 (t):
4540     'ElementSetSpecs : RootElementSetSpec COMMA ELLIPSIS'
4541     t[0] = t[1]
4542     t[0].ext = True
4543
4544 def p_ElementSetSpecs_3 (t):
4545     'ElementSetSpecs : RootElementSetSpec COMMA ELLIPSIS COMMA ElementSetSpecs'
4546     t[0] = t[1]
4547     t[0].ext = True
4548
4549 # skip compound constraints, only simple ones are supported
4550
4551 def p_RootElementSetSpec_1 (t):
4552     'RootElementSetSpec : SubtypeElements'
4553     t[0] = t[1]
4554
4555 def p_RootElementSetSpec_2 (t):
4556     'RootElementSetSpec : SubtypeElements IntersectionMark SubtypeElements'
4557     t[0] = Constraint(type = 'Intersection', subtype = [t[1], t[3]])
4558
4559 def p_IntersectionMark (t):
4560     '''IntersectionMark : CIRCUMFLEX
4561                         | INTERSECTION'''
4562
4563 # 47 Subtype elements ---------------------------------------------------------
4564
4565 # 47.1 General
4566 def p_SubtypeElements (t):
4567     '''SubtypeElements : SingleValue
4568                        | ContainedSubtype
4569                        | ValueRange
4570                        | PermittedAlphabet
4571                        | SizeConstraint
4572                        | TypeConstraint
4573                        | InnerTypeConstraints
4574                        | PatternConstraint'''
4575     t[0] = t[1]
4576
4577 # 47.2 Single value
4578 # 47.2.1
4579 def p_SingleValue (t):
4580     'SingleValue : Value'
4581     t[0] = Constraint(type = 'SingleValue', subtype = t[1]) 
4582
4583 # 47.3 Contained subtype
4584 # 47.3.1
4585 def p_ContainedSubtype (t):
4586     'ContainedSubtype : Includes Type'
4587     t[0] = Constraint(type = 'ContainedSubtype', subtype = t[2]) 
4588
4589 def p_Includes (t):
4590     '''Includes : INCLUDES 
4591                 | '''
4592
4593 # 47.4 Value range
4594 # 47.4.1
4595 def p_ValueRange (t):
4596     'ValueRange : lower_end_point RANGE upper_end_point'
4597     t[0] = Constraint(type = 'ValueRange', subtype = [t[1], t[3]])
4598
4599 # 47.4.3
4600 def p_lower_end_point_1 (t):
4601     'lower_end_point : lower_end_value '
4602     t[0] = t[1]
4603
4604 def p_lower_end_point_2 (t):
4605     'lower_end_point : lower_end_value LT' # XXX LT first?
4606     t[0] = t[1] # but not inclusive range
4607     
4608 def p_upper_end_point_1 (t):
4609     'upper_end_point : upper_end_value'
4610     t[0] = t[1]
4611
4612 def p_upper_end_point_2 (t):
4613     'upper_end_point : LT upper_end_value'
4614     t[0] = t[1] # but not inclusive range
4615
4616 def p_lower_end_value (t):
4617     '''lower_end_value : Value
4618                        | MIN'''
4619     t[0] = t[1] # XXX
4620
4621 def p_upper_end_value (t):
4622     '''upper_end_value : Value
4623                        | MAX'''
4624     t[0] = t[1]
4625
4626 # 47.5 Size constraint
4627 # 47.5.1
4628 def p_SizeConstraint (t):
4629     'SizeConstraint : SIZE Constraint'
4630     t[0] = Constraint (type = 'Size', subtype = t[2])
4631
4632 # 47.6 Type constraint
4633 # 47.6.1
4634 def p_TypeConstraint (t):
4635     'TypeConstraint : Type'
4636     t[0] = Constraint (type = 'Type', subtype = t[1])
4637
4638 # 47.7 Permitted alphabet
4639 # 47.7.1
4640 def p_PermittedAlphabet (t):
4641     'PermittedAlphabet : FROM Constraint'
4642     t[0] = Constraint (type = 'From', subtype = t[2])
4643
4644 # 47.8 Inner subtyping
4645 # 47.8.1
4646 def p_InnerTypeConstraints (t):
4647     '''InnerTypeConstraints : WITH COMPONENT SingleTypeConstraint
4648                             | WITH COMPONENTS MultipleTypeConstraints'''
4649     pass # ignore PER invisible constraint
4650
4651 # 47.8.3
4652 def p_SingleTypeConstraint (t):
4653     'SingleTypeConstraint : Constraint'
4654     t[0] = t[1]
4655
4656 # 47.8.4
4657 def p_MultipleTypeConstraints (t):
4658     '''MultipleTypeConstraints : FullSpecification
4659                                | PartialSpecification'''
4660     t[0] = t[1]
4661
4662 def p_FullSpecification (t):
4663     'FullSpecification : LBRACE TypeConstraints RBRACE'
4664     t[0] = t[2]
4665
4666 def p_PartialSpecification (t):
4667     'PartialSpecification : LBRACE ELLIPSIS COMMA TypeConstraints RBRACE'
4668     t[0] = t[4]
4669
4670 def p_TypeConstraints_1 (t):
4671     'TypeConstraints : named_constraint'
4672     t [0] = [t[1]]
4673
4674 def p_TypeConstraints_2 (t):
4675     'TypeConstraints : TypeConstraints COMMA named_constraint'
4676     t[0] = t[1] + [t[3]]
4677
4678 def p_named_constraint_1 (t):
4679     'named_constraint : identifier constraint'
4680     return Node ('named_constraint', ident = t[1], constr = t[2])
4681
4682 def p_named_constraint_2 (t):
4683     'named_constraint : constraint'
4684     return Node ('named_constraint', constr = t[1])
4685
4686 def p_constraint (t):
4687     'constraint : value_constraint presence_constraint'
4688     t[0] = Node ('constraint', value = t[1], presence = t[2])
4689
4690 def p_value_constraint_1 (t):
4691     'value_constraint : Constraint'
4692     t[0] = t[1]
4693
4694 def p_value_constraint_2 (t):
4695     'value_constraint : '
4696     pass
4697
4698 def p_presence_constraint_1 (t):
4699     '''presence_constraint : PRESENT
4700                  | ABSENT
4701                  | OPTIONAL'''
4702     t[0] = t[1]
4703     
4704 def p_presence_constraint_2 (t):
4705     '''presence_constraint : '''
4706     pass
4707
4708 # 47.9 Pattern constraint
4709 # 47.9.1
4710 def p_PatternConstraint (t):
4711     'PatternConstraint : PATTERN Value'
4712     t[0] = Constraint (type = 'Pattern', subtype = t[2])
4713
4714 # 49 The exception identifier
4715
4716 # 49.4
4717 def p_ExceptionSpec (t):
4718     'ExceptionSpec : '
4719     pass
4720
4721 #  /*-----------------------------------------------------------------------*/
4722 #  /* Value Notation Productions */
4723 #  /*-----------------------------------------------------------------------*/
4724
4725
4726
4727
4728 def p_ext_val_ref (t):
4729     'ext_val_ref : type_ref DOT identifier'
4730     # XXX coerce type_ref to module_ref
4731     return Node ('ext_val_ref', module = t[1], ident = t[3])
4732
4733 def p_special_real_val (t):
4734     '''special_real_val : PLUS_INFINITY
4735     | MINUS_INFINITY'''
4736     t[0] = t[1]
4737
4738
4739 # Note that Z39.50 v3 spec has upper-case here for, e.g., SUTRS.
4740 # I've hacked the grammar to be liberal about what it accepts.
4741 # XXX should have -strict command-line flag to only accept lowercase
4742 # here, since that's what X.208 says.
4743 def p_name_form (t):
4744     '''name_form : type_ref
4745     | identifier'''
4746     t[0] = t[1]
4747
4748 def p_name_and_number_form_1 (t):
4749     '''name_and_number_form : identifier LPAREN number_form RPAREN
4750     | type_ref LPAREN number_form RPAREN'''
4751     t[0] = Node ('name_and_number', ident = t[1], number = t[3])
4752
4753 def p_name_and_number_form_2 (t):
4754     'name_and_number_form : identifier LPAREN DefinedValue RPAREN'
4755     t[0] = Node ('name_and_number', ident = t[1], val = t[3])
4756
4757 # see X.208 if you are dubious about lcase only for identifier 
4758 def p_identifier (t):
4759     'identifier : LCASE_IDENT'
4760     t[0] = t[1]
4761
4762
4763 def p_binary_string (t):
4764     'binary_string : BSTRING'
4765     t[0] = t[1]
4766
4767 def p_hex_string (t):
4768     'hex_string : HSTRING'
4769     t[0] = t[1]
4770
4771 def p_char_string (t):
4772     'char_string : QSTRING'
4773     t[0] = t[1]
4774
4775 def p_number (t):
4776   'number : NUMBER'
4777   t[0] = t[1]
4778
4779
4780 #--- ITU-T Recommendation X.681 -----------------------------------------------
4781
4782 # 7 ASN.1 lexical items -------------------------------------------------------
4783
4784 # 7.4 Type field references
4785
4786 def p_typefieldreference (t):
4787   'typefieldreference : AMPERSAND UCASE_IDENT'
4788   t[0] = t[2]
4789
4790 # 7.5 Value field references
4791
4792 def p_valuefieldreference (t):
4793   'valuefieldreference : AMPERSAND LCASE_IDENT'
4794   t[0] = t[2]
4795
4796 # 8 Referencing definitions
4797
4798 # 8.1
4799 def p_DefinedObjectClass (t):
4800   'DefinedObjectClass : UsefulObjectClassReference'
4801   t[0] = t[1]
4802
4803 # 8.4
4804 def p_UsefulObjectClassReference (t):
4805   '''UsefulObjectClassReference : TYPE_IDENTIFIER 
4806                                 | ABSTRACT_SYNTAX'''
4807   t[0] = t[1]
4808
4809 # 9 Information object class definition and assignment
4810
4811 # 9.14
4812 def p_FieldName (t):
4813   '''FieldName : typefieldreference
4814                | valuefieldreference'''
4815   t[0] = t[1]
4816
4817 # 14 Notation for the object class field type ---------------------------------
4818
4819 # 14.1
4820 def p_ObjectClassFieldType (t):
4821   'ObjectClassFieldType : DefinedObjectClass DOT FieldName'''
4822   t[0] = get_type_from_class(t[1], t[3])
4823
4824 object_class_types = {
4825   'TYPE-IDENTIFIER/id'   : lambda : ObjectIdentifierType(),
4826   'TYPE-IDENTIFIER/Type' : lambda : OpenType(),
4827   'ABSTRACT-SYNTAX/id'       : lambda : ObjectIdentifierType(),
4828   'ABSTRACT-SYNTAX/Type'     : lambda : OpenType(),
4829   'ABSTRACT-SYNTAX/property' : lambda : BitStringType(),
4830 }
4831
4832 def get_type_from_class(cls, fld):
4833   return object_class_types.get(cls + '/' + fld, lambda : AnyType())()
4834
4835 #--- ITU-T Recommendation X.682 -----------------------------------------------
4836
4837 # 8 General constraint specification ------------------------------------------
4838
4839 # 8.1
4840 def p_GeneralConstraint (t):
4841   '''GeneralConstraint : UserDefinedConstraint'''
4842 #                         | TableConstraint
4843 #                         | ContentsConstraint''
4844   t[0] = t[1]
4845
4846 # 9 User-defined constraints --------------------------------------------------
4847
4848 # 9.1
4849 def p_UserDefinedConstraint (t):
4850   'UserDefinedConstraint : CONSTRAINED BY LBRACE UserDefinedConstraintParameterList RBRACE'
4851   t[0] = Constraint(type = 'UserDefined', subtype = t[4]) 
4852
4853 def p_UserDefinedConstraintParameterList_1 (t):
4854   'UserDefinedConstraintParameterList : '
4855   t[0] = []
4856
4857 def p_UserDefinedConstraintParameterList_2 (t):
4858   'UserDefinedConstraintParameterList : UserDefinedConstraintParameter'
4859   t[0] = [t[1]]
4860
4861 def p_UserDefinedConstraintParameterList_3 (t):
4862   'UserDefinedConstraintParameterList : UserDefinedConstraintParameterList COMMA UserDefinedConstraintParameter'
4863   t[0] = t[1] + [t[3]]
4864
4865 # 9.3
4866 def p_UserDefinedConstraintParameter (t):
4867   'UserDefinedConstraintParameter : type_ref'
4868   t[0] = t[1]
4869
4870
4871 #--- ITU-T Recommendation X.683 -----------------------------------------------
4872
4873 # 8 Parameterized assignments -------------------------------------------------
4874
4875 # 8.1
4876
4877 # 8.2
4878 def p_ParameterizedTypeAssignment (t):
4879   'ParameterizedTypeAssignment : UCASE_IDENT ParameterList ASSIGNMENT Type'
4880   t[0] = t[4]
4881   t[0].SetName(t[1] + 'xxx')
4882
4883 # 8.3
4884 def p_ParameterList (t):
4885     'ParameterList : LBRACE Parameters RBRACE'
4886     t[0] = t[2]
4887
4888 def p_Parameters_1 (t):
4889   'Parameters : Parameter'
4890   t[0] = [t[1]]
4891
4892 def p_Parameters_2 (t):
4893   'Parameters : Parameters COMMA Parameter'
4894   t[0] = t[1] + [t[3]]
4895
4896 def p_Parameter_1 (t):
4897   'Parameter : Type COLON Reference'
4898   t[0] = [t[1], t[3]]
4899
4900 def p_Parameter_2 (t):
4901   'Parameter : Reference'
4902   t[0] = t[1]
4903
4904
4905 # 9 Referencing parameterized definitions -------------------------------------
4906
4907 # 9.1
4908 def p_ParameterizedReference (t):
4909   'ParameterizedReference : type_ref LBRACE RBRACE'
4910   t[0] = t[1]
4911   t[0].val += 'xxx'
4912
4913 # 9.2
4914 def p_ParameterizedType (t):
4915   'ParameterizedType : type_ref ActualParameterList'
4916   t[0] = t[1]
4917   t[0].val += 'xxx'
4918
4919 # 9.5
4920 def p_ActualParameterList (t):
4921     'ActualParameterList : LBRACE ActualParameters RBRACE'
4922     t[0] = t[2]
4923
4924 def p_ActualParameters_1 (t):
4925   'ActualParameters : ActualParameter'
4926   t[0] = [t[1]]
4927
4928 def p_ActualParameters_2 (t):
4929   'ActualParameters : ActualParameters COMMA ActualParameter'
4930   t[0] = t[1] + [t[3]]
4931
4932 def p_ActualParameter (t):
4933   '''ActualParameter : Type
4934                      | Value'''
4935   t[0] = t[1]
4936
4937
4938 def p_error(t):
4939     raise ParseError(str(t))
4940
4941 def testlex (s):
4942     lexer.input (s)
4943     while 1:
4944         token = lexer.token ()
4945         if not token:
4946             break
4947         print token
4948
4949
4950 def do_module (ast, defined_dict):
4951     assert (ast.type == 'Module')
4952     ctx = Ctx (defined_dict)
4953     print ast.to_python (ctx)
4954     print ctx.output_assignments ()
4955     print ctx.output_pyquotes ()
4956
4957 def eth_do_module (ast, ectx):
4958     assert (ast.type == 'Module')
4959     if ectx.dbg('s'): print ast.str_depth(0)
4960     ast.to_eth(ectx)
4961
4962 def testyacc(s, fn, defined_dict):
4963     ast = yacc.parse(s, debug=0)
4964     time_str = time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime())
4965     print """#!/usr/bin/env python
4966 # Auto-generated from %s at %s
4967 from PyZ3950 import asn1""" % (fn, time_str)
4968     for module in ast:
4969       eth_do_module (module, defined_dict)
4970
4971
4972 # Wireshark compiler
4973 def eth_usage():
4974   print """
4975 asn2wrs [-h|?] [-d dbg] [-b] [-p proto] [-c conform_file] [-e] input_file(s) ...
4976   -h|?          : usage
4977   -b            : BER (default is PER)
4978   -u            : unaligned (default is aligned)
4979   -p proto      : protocol name (implies -S)
4980                   default is module-name from input_file (renamed by #.MODULE if present)
4981   -F            : create 'field functions'
4982   -T            : tagged type support (experimental)
4983   -o name       : output files name core (default is <proto>)
4984   -O dir        : output directory
4985   -c conform_file : conformation file
4986   -e            : create conformation file for exported types
4987   -S            : single output for multiple modules
4988   -s template   : single file output (template is input file without .c/.h extension)
4989   -k            : keep intermediate files though single file output is used
4990   -L            : suppress #line directive from .cnf file
4991   input_file(s) : input ASN.1 file(s)
4992
4993   -d dbg     : debug output, dbg = [l][y][p][s][a][t][c][o]
4994                l - lex 
4995                y - yacc
4996                p - parsing
4997                s - internal ASN.1 structure
4998                a - list of assignments
4999                t - tables
5000                c - conformance values
5001                o - list of output files
5002 """
5003
5004 def eth_main():
5005   print "ASN.1 to Wireshark dissector compiler";
5006   try:
5007     opts, args = getopt.getopt(sys.argv[1:], "h?d:buXp:FTo:O:c:eSs:kL");
5008   except getopt.GetoptError:
5009     eth_usage(); sys.exit(2)
5010   if len(args) < 1:
5011     eth_usage(); sys.exit(2)
5012
5013   conform = EthCnf()
5014   output = EthOut()
5015   ectx = EthCtx(conform, output)
5016   ectx.encoding = 'per'
5017   ectx.proto_opt = None
5018   ectx.fld_opt = False
5019   ectx.tag_opt = False
5020   ectx.outnm_opt = None
5021   ectx.aligned = True
5022   ectx.dbgopt = ''
5023   ectx.new = True
5024   ectx.expcnf = False
5025   ectx.merge_modules = False
5026   ectx.output.suppress_line = False;
5027   ectx.output.outnm = None
5028   ectx.output.single_file = None
5029   for o, a in opts:
5030     if o in ("-h", "-?"):
5031       eth_usage(); sys.exit(2)
5032     if o in ("-b",):
5033       ectx.encoding = 'ber'
5034     if o in ("-p",):
5035       ectx.proto_opt = a
5036       ectx.merge_modules = True
5037     if o in ("-F",):
5038       ectx.fld_opt = True
5039     if o in ("-T",):
5040       ectx.tag_opt = True
5041     if o in ("-c",):
5042       ectx.conform.read(a)
5043     if o in ("-u",):
5044       ectx.aligned = False
5045     if o in ("-d",):
5046       ectx.dbgopt = a
5047     if o in ("-e",):
5048       ectx.expcnf = True
5049     if o in ("-S",):
5050       ectx.merge_modules = True
5051     if o in ("-o",):
5052       ectx.outnm_opt = a
5053     if o in ("-O",):
5054       ectx.output.outdir = a
5055     if o in ("-s",):
5056       ectx.output.single_file = a
5057     if o in ("-k",):
5058       ectx.output.keep = True
5059     if o in ("-L",):
5060       ectx.output.suppress_line = True
5061     if o in ("-X",):
5062         warnings.warn("Command line option -X is obsolete and can be removed")
5063
5064   (ld, yd, pd) = (0, 0, 0); 
5065   if ectx.dbg('l'): ld = 1
5066   if ectx.dbg('y'): yd = 1
5067   if ectx.dbg('p'): pd = 2
5068   lexer = lex.lex(debug=ld)
5069   yacc.yacc(method='LALR', debug=yd)
5070   ast = []
5071   for fn in args:
5072     f = open (fn, "r")
5073     ast.extend(yacc.parse(f.read(), lexer=lexer, debug=pd))
5074     f.close ()
5075   ectx.eth_clean()
5076   for module in ast:
5077     eth_do_module(module, ectx)
5078     if (not ectx.merge_modules):  # output for each module
5079       ectx.eth_prepare()
5080       ectx.eth_do_output()
5081       ectx.eth_clean()
5082   if (ectx.merge_modules):  # common output for all module
5083     ectx.eth_prepare()
5084     ectx.eth_do_output()
5085
5086   if ectx.dbg('c'):
5087     ectx.conform.dbg_print()
5088   ectx.conform.unused_report()
5089
5090   if ectx.dbg('o'):
5091     ectx.output.dbg_print()
5092   ectx.output.make_single_file()
5093     
5094
5095 # Python compiler
5096 def main():
5097     testfn = testyacc
5098     if len (sys.argv) == 1:
5099         while 1:
5100             s = raw_input ('Query: ')
5101             if len (s) == 0:
5102                 break
5103             testfn (s, 'console', {})
5104     else:
5105         defined_dict = {}
5106         for fn in sys.argv [1:]:
5107             f = open (fn, "r")
5108             testfn (f.read (), fn, defined_dict)
5109             f.close ()
5110             lexer.lineno = 1
5111   
5112
5113 #--- BODY ---------------------------------------------------------------------
5114
5115 if __name__ == '__main__':
5116   if (os.path.splitext(os.path.basename(sys.argv[0]))[0].lower() in ('asn2wrs', 'asn2eth')):
5117     eth_main()
5118   else:
5119     main()
5120
5121 #------------------------------------------------------------------------------