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