Syntax suport for Embedded pdv.
[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 # ITU-T Recommendation X.880 (07/1994), 
37 #   Information technology - Remote Operations: Concepts, model and notation
38 #
39
40 from __future__ import nested_scopes
41
42 import warnings
43
44 import re
45 import sys
46 import os
47 import os.path
48 import time
49 import getopt
50 import traceback
51
52 import __main__ # XXX blech!
53 import lex
54 import yacc
55
56 # OID name -> number conversion table
57 oid_names = {
58   '/itu-t' : 0,
59   '/itu'   : 0,
60   '/ccitt' : 0,
61   '/itu-r' : 0,
62   '0/recommendation' : 0,
63   '0.0/a' : 1,
64   '0.0/b' : 2,
65   '0.0/c' : 3,
66   '0.0/d' : 4,
67   '0.0/e' : 5,
68   '0.0/f' : 6,
69   '0.0/g' : 7,
70   '0.0/h' : 8,
71   '0.0/i' : 9,
72   '0.0/j' : 10,
73   '0.0/k' : 11,
74   '0.0/l' : 12,
75   '0.0/m' : 13,
76   '0.0/n' : 14,
77   '0.0/o' : 15,
78   '0.0/p' : 16,
79   '0.0/q' : 17,
80   '0.0/r' : 18,
81   '0.0/s' : 19,
82   '0.0/t' : 20,
83   '0.0/tseries' : 20,
84   '0.0/u' : 21,
85   '0.0/v' : 22,
86   '0.0/w' : 23,
87   '0.0/x' : 24,
88   '0.0/y' : 25,
89   '0.0/z' : 26,
90   '0/question' : 1,
91   '0/administration' : 2,
92   '0/network-operator' : 3,
93   '0/identified-organization' : 4,
94   '0/r-recommendation' : 5,
95   '0/data' : 9,
96   '/iso' : 1,
97   '1/standard' : 0,
98   '1/registration-authority' : 1,
99   '1/member-body' : 2,
100   '1/identified-organization' : 3,
101   '/joint-iso-itu-t' : 2,
102   '/joint-iso-ccitt' : 2,
103   '2/presentation' : 0,
104   '2/asn1' : 1,
105   '2/association-control' : 2,
106   '2/reliable-transfer' : 3,
107   '2/remote-operations' : 4,
108   '2/ds' : 5,
109   '2/directory' : 5,
110   '2/mhs' : 6,
111   '2/mhs-motis' : 6,
112   '2/ccr' : 7,
113   '2/oda' : 8,
114   '2/ms' : 9,
115   '2/osi-management' : 9,
116   '2/transaction-processing' : 10,
117   '2/dor' : 11,
118   '2/distinguished-object-reference' : 11,
119   '2/reference-data-transfe' : 12,
120   '2/network-layer' : 13,
121   '2/network-layer-management' : 13,
122   '2/transport-layer' : 14,
123   '2/transport-layer-management' : 14,
124   '2/datalink-layer' : 15,
125   '2/datalink-layer-managemen' : 15,
126   '2/datalink-layer-management-information' : 15,
127   '2/country' : 16,
128   '2/registration-procedures' : 17,
129   '2/registration-procedure' : 17,
130   '2/physical-layer' : 18,
131   '2/physical-layer-management' : 18,
132   '2/mheg' : 19,
133   '2/genericULS' : 20,
134   '2/generic-upper-layers-security' : 20,
135   '2/guls' : 20,
136   '2/transport-layer-security-protocol' : 21,
137   '2/network-layer-security-protocol' : 22,
138   '2/international-organizations' : 23,
139   '2/internationalRA' : 23,
140   '2/sios' : 24,
141   '2/uuid' : 25,
142   '2/odp' : 26,
143   '2/upu' : 40,
144 }
145
146 def asn2c(id):
147   return id.replace('-', '_').replace('.', '_')
148
149 input_file = None
150 lexer = None
151 in_oid = False
152
153 class LexError(Exception):
154   def __init__(self, tok, filename=None):
155     self.tok = tok
156     self.filename = filename
157     self.msg =  "Unexpected character %r" % (self.tok.value[0])
158     Exception.__init__(self, self.msg)
159   def __repr__(self):
160     return "%s:%d: %s" % (self.filename, self.tok.lineno, self.msg)
161   __str__ = __repr__
162
163
164 class ParseError(Exception):
165   def __init__(self, tok, filename=None):
166     self.tok = tok
167     self.filename = filename
168     self.msg =  "Unexpected token %s(%r)" % (self.tok.type, self.tok.value)
169     Exception.__init__(self, self.msg)
170   def __repr__(self):
171     return "%s:%d: %s" % (self.filename, self.tok.lineno, self.msg)
172   __str__ = __repr__
173
174
175 states = (
176   ('braceignore','exclusive'),
177 )
178
179 precedence = (
180   ('left', 'UNION', 'BAR'),
181   ('left', 'INTERSECTION', 'CIRCUMFLEX'),
182 )
183 # 11 ASN.1 lexical items
184
185 static_tokens = {
186   r'::='    : 'ASSIGNMENT',  # 11.16 Assignment lexical item
187   r'\.\.'   : 'RANGE',       # 11.17 Range separator
188   r'\.\.\.' : 'ELLIPSIS',    # 11.18 Ellipsis
189   #r'\[\['   : 'LVERBRACK',   # 11.19 Left version brackets
190   #r'\]\]'   : 'RVERBRACK',   # 11.20 Right version brackets
191   # 11.26 Single character lexical items
192   r'\{' : 'LBRACE',
193   r'\}' : 'RBRACE',
194   r'<'  : 'LT',
195   #r'>'  : 'GT',
196   r','  : 'COMMA',
197   r'\.' : 'DOT',
198   r'\(' : 'LPAREN',
199   r'\)' : 'RPAREN',
200   r'\[' : 'LBRACK',
201   r'\]' : 'RBRACK',
202   r'-'  : 'MINUS',
203 #  r':'  : 'COLON',
204   #r'='  : 'EQ',
205   #r'"'  : 'QUOTATION',
206   #r"'"  : 'APOSTROPHE',
207   r';'  : 'SEMICOLON',
208   r'@'  : 'AT',
209   #r'\!' : 'EXCLAMATION',
210   r'\^' : 'CIRCUMFLEX',
211   r'\&' : 'AMPERSAND',
212   r'\|' : 'BAR'
213 }
214
215 # 11.27 Reserved words
216
217 # all keys in reserved_words must start w/ upper case
218 reserved_words = {
219   'ABSENT'      : 'ABSENT',
220   'ABSTRACT-SYNTAX' : 'ABSTRACT_SYNTAX',
221   'ALL'         : 'ALL',
222   'APPLICATION' : 'APPLICATION',
223   'AUTOMATIC'   : 'AUTOMATIC',
224   'BEGIN'       : 'BEGIN',
225   'BIT'         : 'BIT',
226   'BOOLEAN'     : 'BOOLEAN',
227   'BY'          : 'BY',
228   'CHARACTER'   : 'CHARACTER',
229   'CHOICE'      : 'CHOICE',
230   'CLASS'       : 'CLASS',
231   'COMPONENT'   : 'COMPONENT',
232   'COMPONENTS'  : 'COMPONENTS',
233   'CONSTRAINED' : 'CONSTRAINED',
234   'CONTAINING'  : 'CONTAINING',
235   'DEFAULT'     : 'DEFAULT',
236   'DEFINITIONS' : 'DEFINITIONS',
237   'EMBEDDED'    : 'EMBEDDED',
238 #  'ENCODED'     : 'ENCODED',
239   'END'         : 'END',
240   'ENUMERATED'  : 'ENUMERATED',
241 #  'EXCEPT'      : 'EXCEPT',
242   'EXPLICIT'    : 'EXPLICIT',
243   'EXPORTS'     : 'EXPORTS',
244 #  'EXTENSIBILITY' : 'EXTENSIBILITY',
245   'EXTERNAL'    : 'EXTERNAL',
246   'FALSE'       : 'FALSE',
247   'FROM'        : 'FROM',
248   'GeneralizedTime' : 'GeneralizedTime',
249   'IDENTIFIER'  : 'IDENTIFIER',
250   'IMPLICIT'    : 'IMPLICIT',
251 #  'IMPLIED'     : 'IMPLIED',
252   'IMPORTS'     : 'IMPORTS',
253   'INCLUDES'    : 'INCLUDES',
254 #  'INSTANCE'    : 'INSTANCE',
255   'INTEGER'     : 'INTEGER',
256   'INTERSECTION' : 'INTERSECTION',
257   'MAX'         : 'MAX',
258   'MIN'         : 'MIN',
259   'MINUS-INFINITY' : 'MINUS_INFINITY',
260   'NULL'        : 'NULL',
261   'OBJECT'      : 'OBJECT',
262   'ObjectDescriptor' : 'ObjectDescriptor',
263   'OCTET'       : 'OCTET',
264   'OF'          : 'OF',
265   'OPTIONAL'    : 'OPTIONAL',
266   'PATTERN'     : 'PATTERN',
267   'PDV'         : 'PDV',
268   'PLUS-INFINITY' : 'PLUS_INFINITY',
269   'PRESENT'     : 'PRESENT',
270   'PRIVATE'     : 'PRIVATE',
271   'REAL'        : 'REAL',
272 #  'RELATIVE-OID' : 'RELATIVE-OID',
273   'SEQUENCE'    : 'SEQUENCE',
274   'SET'         : 'SET',
275   'SIZE'        : 'SIZE',
276   'STRING'      : 'STRING',
277   'SYNTAX'      : 'SYNTAX',
278   'TAGS'        : 'TAGS',
279   'TRUE'        : 'TRUE',
280   'TYPE-IDENTIFIER' : 'TYPE_IDENTIFIER',
281   'UNION'       : 'UNION',
282 #  'UNIQUE'      : 'UNIQUE',
283   'UNIVERSAL'   : 'UNIVERSAL',
284   'UTCTime'     : 'UTCTime',
285   'WITH'        : 'WITH',
286 # obsolete but still used
287   'ANY'         : 'ANY',
288 }
289
290 for k in static_tokens.keys ():
291     if static_tokens [k] == None:
292         static_tokens [k] = k
293
294 StringTypes = ['Numeric', 'Printable', 'IA5', 'BMP', 'Universal', 'UTF8',
295                'Teletex', 'T61', 'Videotex', 'Graphic', 'ISO646', 'Visible',
296                'General']
297
298 for s in StringTypes:
299   reserved_words[s + 'String'] = s + 'String'
300
301 tokens = static_tokens.values() \
302          + reserved_words.values() \
303          + ['BSTRING', 'HSTRING', 'QSTRING',
304             'UCASE_IDENT', 'LCASE_IDENT', 'LCASE_IDENT_ASSIGNED', 'CLASS_IDENT',
305             'REAL_NUMBER', 'NUMBER', 'PYQUOTE']
306
307
308 for (k, v) in static_tokens.items ():
309   __main__.__dict__['t_' + v] = k
310
311 # 11.10 Binary strings
312 def t_BSTRING (t):
313     r"'[01]*'B"
314     return t
315
316 # 11.12 Hexadecimal strings
317 def t_HSTRING (t):
318     r"'[0-9A-Fa-f]*'H"
319     return t
320
321 def t_QSTRING (t):
322     r'"([^"]|"")*"'
323     return t 
324
325 def t_UCASE_IDENT (t):
326     r"[A-Z](-[a-zA-Z0-9]|[a-zA-Z0-9])*" # can't end w/ '-'
327     if (is_class_ident(t.value)): t.type = 'CLASS_IDENT'
328     if (is_x880_syntax(t.value)): t.type = t.value
329     t.type = reserved_words.get(t.value, t.type)
330     return t
331
332 lcase_ident_assigned = {}
333 def t_LCASE_IDENT (t):
334     r"[a-z](-[a-zA-Z0-9]|[a-zA-Z0-9])*" # can't end w/ '-'
335     if (not in_oid and lcase_ident_assigned.has_key(t.value)): t.type = 'LCASE_IDENT_ASSIGNED'
336     return t
337
338 # 11.9 Real numbers
339 def t_REAL_NUMBER (t):
340     r"[0-9]+\.[0-9]*(?!\.)"
341     return t
342
343 # 11.8 Numbers
344 def t_NUMBER (t):
345     r"0|([1-9][0-9]*)"
346     return t
347
348 # 11.6 Comments
349 pyquote_str = 'PYQUOTE'
350 def t_COMMENT(t):
351     r"--(-[^\-\n]|[^\-\n])*(--|\n|-\n|$|-$)"
352     if (t.value.find("\n") >= 0) : t.lexer.lineno += 1
353     if t.value[2:2+len (pyquote_str)] == pyquote_str:
354         t.value = t.value[2+len(pyquote_str):]
355         t.value = t.value.lstrip ()
356         t.type = pyquote_str
357         return t
358     return None
359
360 t_ignore = " \t\r"
361
362 def t_NEWLINE(t):
363     r'\n+'
364     t.lexer.lineno += t.value.count("\n")
365
366 def t_error(t):
367   global input_file
368   raise LexError(t, input_file)
369
370 # state 'braceignore'
371
372 def t_braceignore_lbrace(t):     
373   r'\{'
374   t.lexer.level +=1                
375
376 def t_braceignore_rbrace(t):
377   r'\}'
378   t.lexer.level -=1
379   # If closing brace, return token
380   if t.lexer.level == 0:
381     t.type = 'RBRACE'
382     return t
383
384 def t_braceignore_QSTRING (t):
385   r'"([^"]|"")*"'
386
387 def t_braceignore_COMMENT(t):
388   r"--(-[^\-\n]|[^\-\n])*(--|\n|-\n|$|-$)"
389   if (t.value.find("\n") >= 0) : t.lexer.lineno += 1
390
391 def t_braceignore_nonspace(t):
392    r'[^\s\{\}\"-]+|-(?!-)'
393
394 t_braceignore_ignore = " \t\r"
395
396 def t_braceignore_NEWLINE(t):
397   r'\n+'
398   t.lexer.lineno += t.value.count("\n")
399
400 def t_braceignore_error(t):
401   t.lexer.skip(1)
402
403 class Ctx:
404     def __init__ (self, defined_dict, indent = 0):
405         self.tags_def = 'EXPLICIT' # default = explicit
406         self.indent_lev = 0
407         self.assignments = {}
408         self.dependencies = {}
409         self.pyquotes = []
410         self.defined_dict = defined_dict
411         self.name_ctr = 0
412     def spaces (self):
413         return " " * (4 * self.indent_lev)
414     def indent (self):
415         self.indent_lev += 1
416     def outdent (self):
417         self.indent_lev -= 1
418         assert (self.indent_lev >= 0)
419     def register_assignment (self, ident, val, dependencies):
420         if self.assignments.has_key (ident):
421             raise "Duplicate assignment for " + ident
422         if self.defined_dict.has_key (ident):
423             raise "cross-module duplicates for " + ident
424         self.defined_dict [ident] = 1
425         self.assignments[ident] = val
426         self.dependencies [ident] = dependencies
427         return ""
428     #        return "#%s depends on %s" % (ident, str (dependencies))
429     def register_pyquote (self, val):
430         self.pyquotes.append (val)
431         return ""
432     def output_assignments (self):
433         already_output = {}
434         text_list = []
435         assign_keys = self.assignments.keys()
436         to_output_count = len (assign_keys)
437         while 1:
438             any_output = 0
439             for (ident, val) in self.assignments.iteritems ():
440                 if already_output.has_key (ident):
441                     continue
442                 ok = 1
443                 for d in self.dependencies [ident]:
444                     if (not already_output.has_key (d) and
445                         d in assign_keys):
446                         ok = 0
447                 if ok:
448                     text_list.append ("%s=%s" % (ident,
449                                                 self.assignments [ident]))
450                     already_output [ident] = 1
451                     any_output = 1
452                     to_output_count -= 1
453                     assert (to_output_count >= 0)
454             if not any_output:
455                 if to_output_count == 0:
456                     break
457                 # OK, we detected a cycle
458                 cycle_list = []
459                 for ident in self.assignments.iterkeys ():
460                     if not already_output.has_key (ident):
461                         depend_list = [d for d in self.dependencies[ident] if d in assign_keys]
462                         cycle_list.append ("%s(%s)" % (ident, ",".join (depend_list)))
463                         
464                 text_list.append ("# Cycle XXX " + ",".join (cycle_list))
465                 for (ident, val) in self.assignments.iteritems ():
466                     if not already_output.has_key (ident):
467                         text_list.append ("%s=%s" % (ident, self.assignments [ident]))
468                 break
469
470         return "\n".join (text_list)
471     def output_pyquotes (self):
472         return "\n".join (self.pyquotes)
473     def make_new_name (self):
474         self.name_ctr += 1
475         return "_compiler_generated_name_%d" % (self.name_ctr,)
476
477 #--- Flags for EXPORT, USER_DEFINED, NO_EMIT, MAKE_ENUM -------------------------------
478 EF_TYPE    = 0x0001
479 EF_VALS    = 0x0002
480 EF_ENUM    = 0x0004
481 EF_WS_VAR  = 0x0010
482 EF_EXTERN  = 0x0020
483 EF_NO_PROT = 0x0040
484 EF_NO_TYPE = 0x0080
485 EF_UCASE   = 0x0100
486 EF_TABLE   = 0x0400
487 EF_DEFINE  = 0x0800
488
489 #--- common dependency computation ---
490 # Input  : list of items
491 #          dictionary with lists of dependency
492 #
493 #           
494 # Output : list of two outputs:
495 #          [0] list of items in dependency
496 #          [1] list of cycle dependency cycles
497 def dependency_compute(items, dependency, map_fn = lambda t: t, ignore_fn = lambda t: False):
498   item_ord = []
499   item_cyc = []
500   x = {}  # already emitted
501   #print '# Dependency computation'
502   for t in items:
503     if x.has_key(map_fn(t)):
504       #print 'Continue: %s : %s' % (t, (map_fn(t))
505       continue
506     stack = [t]
507     stackx = {t : dependency.get(t, [])[:]}
508     #print 'Push: %s : %s' % (t, str(stackx[t]))
509     while stack:
510       if stackx[stack[-1]]:  # has dependencies
511         d = stackx[stack[-1]].pop(0)
512         if x.has_key(map_fn(d)) or ignore_fn(d):
513           continue
514         if stackx.has_key(d):  # cyclic dependency
515           c = stack[:]
516           c.reverse()
517           c = [d] + c[0:c.index(d)+1]
518           c.reverse()
519           item_cyc.append(c)
520           #print 'Cyclic: %s ' % (' -> '.join(c))
521           continue
522         stack.append(d)
523         stackx[d] = dependency.get(d, [])[:]
524         #print 'Push: %s : %s' % (d, str(stackx[d]))
525       else:
526         #print 'Pop: %s' % (stack[-1])
527         del stackx[stack[-1]]
528         e = map_fn(stack.pop())
529         if x.has_key(e):
530           continue
531         #print 'Add: %s' % (e)
532         item_ord.append(e)
533         x[e] = True
534   return (item_ord, item_cyc)
535
536 #--- EthCtx -------------------------------------------------------------------
537 class EthCtx:
538   def __init__(self, conform, output, indent = 0):
539     self.conform = conform
540     self.output = output
541     self.conform.ectx = self
542     self.output.ectx = self
543     self.encoding = 'per'
544     self.aligned = False
545     self.new_ber = False
546     self.default_oid_variant = ''
547     self.default_opentype_variant = ''
548     self.default_containing_variant = '_pdu_new'
549     self.default_external_type_cb = None
550     self.module = {}
551     self.module_ord = []
552     self.all_tags = {}
553     self.all_vals = {}
554
555   def encp(self):  # encoding protocol
556     encp = self.encoding
557     return encp
558
559   # Encoding
560   def Per(self): return self.encoding == 'per'
561   def Ber(self): return self.encoding == 'ber'
562   def NewBer(self): return self.new_ber
563   def Aligned(self): return self.aligned
564   def Unaligned(self): return not self.aligned
565   def Fld(self, tnm='*'): return self.fld_opt.get('*', False) or self.fld_opt.get(tnm, False) or (self.Ber() and not self.NewBer())
566   def Tag(self): return self.tag_opt # or self.Ber() - temporary comment out (experimental feature)
567   def NAPI(self): return False  # disable planned features
568
569   def Module(self):  # current module name
570     return self.modules[-1][0]
571
572   def dbg(self, d):
573     if (self.dbgopt.find(d) >= 0):
574       return True
575     else:
576       return False
577
578   def value_max(self, a, b):
579     if (a == 'MAX') or (b == 'MAX'): return 'MAX';
580     if a == 'MIN': return b;
581     if b == 'MIN': return a;
582     try:
583       if (int(a) > int(b)):
584         return a
585       else:
586         return b
587     except (ValueError, TypeError):
588       pass
589     return "MAX((%s),(%s))" % (a, b) 
590
591   def value_min(self, a, b):
592     if (a == 'MIN') or (b == 'MIN'): return 'MIN';
593     if a == 'MAX': return b;
594     if b == 'MAX': return a;
595     try:
596       if (int(a) < int(b)):
597         return a
598       else:
599         return b
600     except (ValueError, TypeError):
601       pass
602     return "MIN((%s),(%s))" % (a, b) 
603
604   def value_get_eth(self, nm):
605     ethname = nm
606     if self.value.has_key(nm):
607       ethname = self.value[nm]['ethname']
608     return ethname
609
610   def value_get_val(self, nm):
611     val = asn2c(nm)
612     if self.value.has_key(nm):
613       if self.value[nm]['import']:
614         v = self.get_val_from_all(nm, self.value[nm]['import'])
615         if v is None:
616           msg = 'Need value of imported value identifier %s from %s (%s)' % (nm, self.value[nm]['import'], self.value[nm]['proto'])
617           warnings.warn_explicit(msg, UserWarning, '', '')
618         else:
619           val = v
620       else:
621         val = self.value[nm]['value']
622         if isinstance (val, Value):
623           val = val.to_str(self)
624     else:
625       msg = 'Need value of unknown value identifier %s' % (nm)
626       warnings.warn_explicit(msg, UserWarning, '', '')
627     return val
628
629   def eth_get_type_attr(self, type):
630     types = [type]
631     while (not self.type[type]['import'] 
632            and self.type[type]['val'].type == 'Type_Ref'):
633       type = self.type[type]['val'].val
634       types.append(type)
635     attr = {}
636     while len(types):
637       t = types.pop()
638       attr.update(self.type[t]['attr'])
639       attr.update(self.eth_type[self.type[t]['ethname']]['attr'])
640     return attr
641
642   def get_ttag_from_all(self, type, module):
643     ttag = None
644     if self.all_tags.has_key(module) and self.all_tags[module].has_key(type):
645       ttag = self.all_tags[module][type]
646     return ttag
647
648   def get_val_from_all(self, nm, module):
649     val = None
650     if self.all_vals.has_key(module) and self.all_vals[module].has_key(nm):
651       val = self.all_vals[module][nm]
652     return val
653
654   #--- eth_reg_module -----------------------------------------------------------
655   def eth_reg_module(self, module):
656     #print "eth_reg_module(module='%s')" % (module)
657     self.modules.append((module, self.proto))
658     if self.module.has_key(module):
659       raise "Duplicate module for " + module
660     self.module[module] = []
661     self.module_ord.append(module)
662
663   #--- eth_module_dep_add ------------------------------------------------------------
664   def eth_module_dep_add(self, module, dep):
665     self.module[module].append(dep)
666
667   #--- eth_exports ------------------------------------------------------------
668   def eth_exports(self, exports):
669     self.exports_all = False
670     if ((len(exports) == 1) and (exports[0] == 'ALL')):
671       self.exports_all = True
672       return
673     for e in (exports):
674       if isinstance(e, Type_Ref):
675         self.exports.append(e.val)
676       elif isinstance(e, Class_Ref):
677         self.cexports.append(e.val)
678       else:
679         self.vexports.append(e)
680
681   #--- eth_reg_assign ---------------------------------------------------------
682   def eth_reg_assign(self, ident, val, virt=False):
683     #print "eth_reg_assign(ident='%s')" % (ident)
684     if self.assign.has_key(ident):
685       raise "Duplicate assignment for " + ident
686     self.assign[ident] = { 'val' : val , 'virt' : virt }
687     self.assign_ord.append(ident)
688     if  (self.exports_all):
689       self.exports.append(ident)
690
691   #--- eth_reg_vassign --------------------------------------------------------
692   def eth_reg_vassign(self, vassign):
693     ident = vassign.ident
694     #print "eth_reg_vassign(ident='%s')" % (ident)
695     if self.vassign.has_key(ident):
696       raise "Duplicate value assignment for " + ident
697     self.vassign[ident] = vassign
698     self.vassign_ord.append(ident)
699     if  (self.exports_all):
700       self.vexports.append(ident)
701
702   #--- eth_import_type --------------------------------------------------------
703   def eth_import_type(self, ident, mod, proto):
704     #print "eth_import_type(ident='%s', mod='%s', prot='%s')" % (ident, mod, proto)
705     if self.type.has_key(ident):
706       #print "already defined import=%s, module=%s" % (str(self.type[ident]['import']), self.type[ident]['module'])
707       if not self.type[ident]['import'] and (self.type[ident]['module'] == mod) :
708         return  # OK - already defined
709       elif self.type[ident]['import'] and (self.type[ident]['import'] == mod) :
710         return  # OK - already imported
711       else:
712         raise "Duplicate type for " + ident
713     self.type[ident] = {'import'  : mod, 'proto' : proto,
714                         'ethname' : '' }
715     self.type[ident]['attr'] = { 'TYPE' : 'FT_NONE', 'DISPLAY' : 'BASE_NONE',
716                                  'STRINGS' : 'NULL', 'BITMASK' : '0' }
717     self.type[ident]['attr'].update(self.conform.use_item('TYPE_ATTR', ident))
718     self.type_imp.append(ident)
719
720   #--- dummy_import_type --------------------------------------------------------
721   def dummy_import_type(self, ident):
722     # dummy imported
723     if self.type.has_key(ident):
724         raise "Try to dummy import for existing type :" + ident
725     ethtype = asn2c(ident)
726     self.type[ident] = {'import'  : 'xxx', 'proto' : 'xxx',
727                         'ethname' : ethtype }
728     self.type[ident]['attr'] = { 'TYPE' : 'FT_NONE', 'DISPLAY' : 'BASE_NONE',
729                                  'STRINGS' : 'NULL', 'BITMASK' : '0' }
730     self.eth_type[ethtype] = { 'import' : 'xxx', 'proto' : 'xxx' , 'attr' : {}, 'create_field' : False, 'ref' : []}
731     print "Dummy imported: %s (%s)" % (ident, ethtype)
732     return ethtype
733
734   #--- eth_import_class --------------------------------------------------------
735   def eth_import_class(self, ident, mod, proto):
736     #print "eth_import_class(ident='%s', mod='%s', prot='%s')" % (ident, mod, proto)
737     if self.objectclass.has_key(ident):
738       #print "already defined import=%s, module=%s" % (str(self.objectclass[ident]['import']), self.objectclass[ident]['module'])
739       if not self.objectclass[ident]['import'] and (self.objectclass[ident]['module'] == mod) :
740         return  # OK - already defined
741       elif self.objectclass[ident]['import'] and (self.objectclass[ident]['import'] == mod) :
742         return  # OK - already imported
743       else:
744         raise "Duplicate object class for " + ident
745     self.objectclass[ident] = {'import'  : mod, 'proto' : proto,
746                         'ethname' : '' }
747     self.objectclass_imp.append(ident)
748
749   #--- eth_import_value -------------------------------------------------------
750   def eth_import_value(self, ident, mod, proto):
751     #print "eth_import_value(ident='%s', mod='%s', prot='%s')" % (ident, mod, prot)
752     if self.value.has_key(ident):
753       #print "already defined import=%s, module=%s" % (str(self.value[ident]['import']), self.value[ident]['module'])
754       if not self.value[ident]['import'] and (self.value[ident]['module'] == mod) :
755         return  # OK - already defined
756       elif self.value[ident]['import'] and (self.value[ident]['import'] == mod) :
757         return  # OK - already imported
758       else:
759         raise "Duplicate value for " + ident
760     self.value[ident] = {'import'  : mod, 'proto' : proto,
761                          'ethname' : ''}
762     self.value_imp.append(ident)
763
764   #--- eth_sel_req ------------------------------------------------------------
765   def eth_sel_req(self, typ, sel):
766     key = typ + '.' + sel
767     if not self.sel_req.has_key(key):
768       self.sel_req[key] = { 'typ' : typ , 'sel' : sel}
769       self.sel_req_ord.append(key)
770     return key
771
772   #--- eth_comp_req ------------------------------------------------------------
773   def eth_comp_req(self, type):
774     self.comp_req_ord.append(type)
775
776   #--- eth_dep_add ------------------------------------------------------------
777   def eth_dep_add(self, type, dep):
778     if not self.type_dep.has_key(type): 
779       self.type_dep[type] = []
780     self.type_dep[type].append(dep)
781
782   #--- eth_reg_type -----------------------------------------------------------
783   def eth_reg_type(self, ident, val):
784     #print "eth_reg_type(ident='%s', type='%s')" % (ident, val.type)
785     if self.type.has_key(ident):
786       if self.type[ident]['import'] and (self.type[ident]['import'] == self.Module()) :
787         # replace imported type
788         del self.type[ident]
789         self.type_imp.remove(ident)
790       else:
791         raise "Duplicate type for " + ident
792     self.type[ident] = { 'val' : val, 'import' : None }
793     self.type[ident]['module'] = self.Module()
794     self.type[ident]['proto'] = self.proto
795     if len(ident.split('/')) > 1:
796       self.type[ident]['tname'] = val.eth_tname()
797     else:
798       self.type[ident]['tname'] = asn2c(ident)
799     self.type[ident]['export'] = self.conform.use_item('EXPORTS', ident)
800     self.type[ident]['enum'] = self.conform.use_item('MAKE_ENUM', ident)
801     self.type[ident]['user_def'] = self.conform.use_item('USER_DEFINED', ident)
802     self.type[ident]['no_emit'] = self.conform.use_item('NO_EMIT', ident)
803     self.type[ident]['tname'] = self.conform.use_item('TYPE_RENAME', ident, val_dflt=self.type[ident]['tname'])
804     self.type[ident]['ethname'] = ''
805     if val.type == 'Type_Ref':
806       self.type[ident]['attr'] = {}
807     else:
808       (ftype, display) = val.eth_ftype(self)
809       self.type[ident]['attr'] = { 'TYPE' : ftype, 'DISPLAY' : display,
810                                    'STRINGS' : val.eth_strings(), 'BITMASK' : '0' }
811     self.type[ident]['attr'].update(self.conform.use_item('TYPE_ATTR', ident))
812     self.type_ord.append(ident)
813
814   #--- eth_reg_objectclass ----------------------------------------------------------
815   def eth_reg_objectclass(self, ident):
816     #print "eth_reg_objectclass(ident='%s')" % (ident)
817     if self.objectclass.has_key(ident):
818       if self.objectclass[ident]['import'] and (self.objectclass[ident]['import'] == self.Module()) :
819         # replace imported object class
820         del self.objectclass[ident]
821         self.objectclass_imp.remove(ident)
822       else:
823         raise "Duplicate object class for " + ident
824     self.objectclass[ident] = { 'import' : None, 'module' : self.Module(), 'proto' : self.proto }
825     self.objectclass[ident]['export'] = self.conform.use_item('EXPORTS', ident)
826     self.objectclass_ord.append(ident)
827
828   #--- eth_reg_value ----------------------------------------------------------
829   def eth_reg_value(self, ident, type, value, ethname=None):
830     #print "eth_reg_value(ident='%s')" % (ident)
831     if self.value.has_key(ident):
832       if self.value[ident]['import'] and (self.value[ident]['import'] == self.Module()) :
833         # replace imported value
834         del self.value[ident]
835         self.value_imp.remove(ident)
836       elif ethname:
837         self.value[ident]['ethname'] = ethname
838         return
839       else:
840         raise "Duplicate value for " + ident
841     self.value[ident] = { 'import' : None, 'module' : self.Module(), 'proto' : self.proto,
842                           'type' : type, 'value' : value,
843                           'no_emit' : False }
844     self.value[ident]['export'] = self.conform.use_item('EXPORTS', ident)
845     self.value[ident]['ethname'] = ''
846     if (ethname): self.value[ident]['ethname'] = ethname
847     self.value_ord.append(ident)
848
849   #--- eth_reg_field ----------------------------------------------------------
850   def eth_reg_field(self, ident, type, idx='', parent=None, impl=False, pdu=None):
851     #print "eth_reg_field(ident='%s', type='%s')" % (ident, type)
852     if self.field.has_key(ident):
853       raise "Duplicate field for " + ident
854     self.field[ident] = {'type' : type, 'idx' : idx, 'impl' : impl, 'pdu' : pdu,
855                          'modified' : '', 'attr' : {} , 'create_field' : False }
856     name = ident.split('/')[-1]
857     if len(ident.split('/')) > 1 and name == '_item':  # Sequnce/Set of type
858       self.field[ident]['attr']['NAME'] = '"Item"'
859       self.field[ident]['attr']['ABBREV'] = asn2c(ident.split('/')[-2] + name)
860     else:
861       self.field[ident]['attr']['NAME'] = '"%s"' % name
862       self.field[ident]['attr']['ABBREV'] = asn2c(name)
863     if self.conform.check_item('FIELD_ATTR', ident):
864       self.field[ident]['modified'] = '#' + str(id(self))
865       self.field[ident]['attr'].update(self.conform.use_item('FIELD_ATTR', ident))
866     if (pdu):
867       self.pdu_ord.append(ident)
868     else:
869       self.field_ord.append(ident)
870     if parent:
871       self.field[ident]['create_field'] = self.Fld(parent)
872       self.eth_dep_add(parent, type)
873
874   #--- eth_clean --------------------------------------------------------------
875   def eth_clean(self):
876     self.proto = self.proto_opt;
877     #--- ASN.1 tables ----------------
878     self.assign = {}
879     self.assign_ord = []
880     self.field = {}
881     self.pdu_ord = []
882     self.field_ord = []
883     self.type = {}
884     self.type_ord = []
885     self.type_imp = []
886     self.type_dep = {}
887     self.sel_req = {}
888     self.sel_req_ord = []
889     self.comp_req_ord = []
890     self.vassign = {}
891     self.vassign_ord = []
892     self.value = {}
893     self.value_ord = []
894     self.value_imp = []
895     self.objectclass = {}
896     self.objectclass_ord = []
897     self.objectclass_imp = []
898     #--- Modules ------------
899     self.modules = []
900     self.exports_all = False
901     self.exports = []
902     self.cexports = []
903     self.vexports = []
904     #--- types -------------------
905     self.eth_type = {}
906     self.eth_type_ord = []
907     self.eth_export_ord = []
908     self.eth_type_dupl = {}
909     self.named_bit = []
910     #--- value dependencies -------------------
911     self.value_dep = {}
912     #--- values -------------------
913     self.eth_value = {}
914     self.eth_value_ord = []
915     #--- fields -------------------------
916     self.eth_hf = {}
917     self.eth_hf_ord = []
918     self.eth_hfpdu_ord = []
919     self.eth_hf_dupl = {}
920     #--- type dependencies -------------------
921     self.eth_type_ord1 = []
922     self.eth_dep_cycle = []
923     self.dep_cycle_eth_type = {}
924     #--- value dependencies and export -------------------
925     self.eth_value_ord1 = []
926     self.eth_vexport_ord = []
927
928   #--- eth_prepare ------------------------------------------------------------
929   def eth_prepare(self):
930     self.eproto = asn2c(self.proto)
931
932     #--- dummy types/fields for PDU registration ---
933     nm = 'NULL'
934     if (self.conform.check_item('PDU', nm)):
935       self.eth_reg_type('_dummy/'+nm, NullType())
936       self.eth_reg_field(nm, '_dummy/'+nm, pdu=self.conform.use_item('PDU', nm))
937
938     #--- required PDUs ----------------------------
939     for t in self.type_ord:
940       pdu = self.type[t]['val'].eth_need_pdu(self)
941       if not pdu: continue
942       f = pdu['type']
943       pdu['reg'] = None
944       pdu['hidden'] = False
945       pdu['need_decl'] = True
946       if not self.field.has_key(f):
947         self.eth_reg_field(f, f, pdu=pdu)
948
949     #--- values -> named values -------------------
950     t_for_update = {}
951     for v in self.value_ord:
952       if (self.value[v]['type'].type == 'Type_Ref'):
953         tnm = self.value[v]['type'].val
954         if self.type.has_key(tnm) \
955            and not self.type[tnm]['import'] \
956            and (self.type[tnm]['val'].type == 'IntegerType'):
957           self.type[tnm]['val'].add_named_value(v, self.value[v]['value'])
958           self.value[v]['no_emit'] = True
959           t_for_update[tnm] = True
960     for t in t_for_update.keys():
961       self.type[t]['attr']['STRINGS'] = self.type[t]['val'].eth_strings()
962       self.type[t]['attr'].update(self.conform.use_item('TYPE_ATTR', t))
963
964     #--- required components of ---------------------------
965     #print "self.comp_req_ord = ", self.comp_req_ord
966     for t in self.comp_req_ord:
967       self.type[t]['val'].eth_reg_sub(t, self, components_available=True)
968
969     #--- required selection types ---------------------------
970     #print "self.sel_req_ord = ", self.sel_req_ord
971     for t in self.sel_req_ord:
972       tt = self.sel_req[t]['typ']
973       if not self.type.has_key(tt):
974         self.dummy_import_type(t)
975       elif self.type[tt]['import']:
976         self.eth_import_type(t, self.type[tt]['import'], self.type[tt]['proto'])
977       else:
978         self.type[tt]['val'].sel_req(t, self.sel_req[t]['sel'], self)
979
980     #--- types -------------------
981     for t in self.type_imp:
982       nm = asn2c(t)
983       self.eth_type[nm] = { 'import' : self.type[t]['import'], 
984                             'proto' : asn2c(self.type[t]['proto']),
985                             'attr' : {}, 'create_field' : False, 'ref' : []}
986       self.eth_type[nm]['attr'].update(self.conform.use_item('ETYPE_ATTR', nm))
987       self.type[t]['ethname'] = nm
988     for t in self.type_ord:
989       nm = self.type[t]['tname']
990       if ((nm.find('#') >= 0) or 
991           ((len(t.split('/'))>1) and 
992            (self.conform.get_fn_presence(t) or self.conform.check_item('FN_PARS', t)) and 
993            not self.conform.check_item('TYPE_RENAME', t))):
994         if len(t.split('/')) == 2 and t.split('/')[1] == '_item':  # Sequnce of type at the 1st level
995           nm = t.split('/')[0] + t.split('/')[1]
996         elif t.split('/')[-1] == '_item':  # Sequnce/Set of type at next levels
997           nm = 'T_' + self.conform.use_item('FIELD_RENAME', '/'.join(t.split('/')[0:-1]), val_dflt=t.split('/')[-2]) + t.split('/')[-1]
998         elif t.split('/')[-1] == '_untag':  # Untagged type
999           nm = self.type['/'.join(t.split('/')[0:-1])]['ethname'] + '_U'
1000         else:
1001           nm = 'T_' + self.conform.use_item('FIELD_RENAME', t, val_dflt=t.split('/')[-1])
1002         nm = asn2c(nm)
1003         if self.eth_type.has_key(nm):
1004           if self.eth_type_dupl.has_key(nm):
1005             self.eth_type_dupl[nm].append(t)
1006           else:
1007             self.eth_type_dupl[nm] = [self.eth_type[nm]['ref'][0], t]
1008           nm += '_%02d' % (len(self.eth_type_dupl[nm])-1)
1009       if self.eth_type.has_key(nm):
1010         self.eth_type[nm]['ref'].append(t)
1011       else:
1012         self.eth_type_ord.append(nm)
1013         self.eth_type[nm] = { 'import' : None, 'proto' : self.eproto, 'export' : 0, 'enum' : 0,
1014                               'user_def' : EF_TYPE|EF_VALS, 'no_emit' : EF_TYPE|EF_VALS, 
1015                               'val' : self.type[t]['val'], 
1016                               'attr' : {}, 
1017                               'create_field' : False, 'ref' : [t]}
1018       self.type[t]['ethname'] = nm
1019       if (not self.eth_type[nm]['export'] and self.type[t]['export']):  # new export
1020         self.eth_export_ord.append(nm)
1021       self.eth_type[nm]['export'] |= self.type[t]['export']
1022       self.eth_type[nm]['enum'] |= self.type[t]['enum']
1023       self.eth_type[nm]['user_def'] &= self.type[t]['user_def']
1024       self.eth_type[nm]['no_emit'] &= self.type[t]['no_emit']
1025       if self.type[t]['attr'].get('STRINGS') == '$$':
1026         self.eth_type[nm]['attr']['STRINGS'] = 'VALS(%s)' % (self.eth_vals_nm(nm))
1027       self.eth_type[nm]['attr'].update(self.conform.use_item('ETYPE_ATTR', nm))
1028     for t in self.eth_type_ord:
1029       bits = self.eth_type[t]['val'].eth_named_bits()
1030       if (bits):
1031         for (val, id) in bits:
1032           self.named_bit.append({'name' : id, 'val' : val,
1033                                  'ethname' : 'hf_%s_%s_%s' % (self.eproto, t, asn2c(id)),
1034                                  'ftype'   : 'FT_BOOLEAN', 'display' : '8',
1035                                  'strings' : 'NULL',
1036                                  'bitmask' : '0x'+('80','40','20','10','08','04','02','01')[val%8]})
1037       if self.eth_type[t]['val'].eth_need_tree():
1038         self.eth_type[t]['tree'] = "ett_%s_%s" % (self.eth_type[t]['proto'], t)
1039       else:
1040         self.eth_type[t]['tree'] = None
1041
1042     #--- register values from enums ------------
1043     for t in self.eth_type_ord:
1044       if (self.eth_type[t]['val'].eth_has_enum(t, self)):
1045         self.eth_type[t]['val'].reg_enum_vals(t, self)
1046
1047     #--- value dependencies -------------------
1048     for v in self.value_ord:
1049       if isinstance (self.value[v]['value'], Value):
1050         dep = self.value[v]['value'].get_dep()
1051       else:
1052         dep = self.value[v]['value']
1053       if dep and self.value.has_key(dep):
1054         self.value_dep.setdefault(v, []).append(dep)
1055     
1056     #--- exports all necessary values
1057     for v in self.value_ord:
1058       if not self.value[v]['export']: continue
1059       deparr = self.value_dep.get(v, [])
1060       while deparr:
1061         d = deparr.pop()
1062         if not self.value[d]['import']:
1063           if not self.value[d]['export']:
1064             self.value[d]['export'] = EF_TYPE
1065             deparr.extend(self.value_dep.get(d, []))
1066
1067     #--- values -------------------
1068     for v in self.value_imp:
1069       nm = asn2c(v)
1070       self.eth_value[nm] = { 'import' : self.value[v]['import'], 
1071                              'proto' : asn2c(self.value[v]['proto']), 
1072                              'ref' : []}
1073       self.value[v]['ethname'] = nm
1074     for v in self.value_ord:
1075       if (self.value[v]['ethname']):
1076         continue
1077       if (self.value[v]['no_emit']):
1078         continue
1079       nm = asn2c(v)
1080       self.eth_value[nm] = { 'import' : None, 
1081                              'proto' : asn2c(self.value[v]['proto']),
1082                              'export' : self.value[v]['export'], 'ref' : [v] }
1083       self.eth_value[nm]['value'] = self.value[v]['value']
1084       self.eth_value_ord.append(nm)
1085       self.value[v]['ethname'] = nm
1086
1087     #--- fields -------------------------
1088     for f in (self.pdu_ord + self.field_ord):
1089       if len(f.split('/')) > 1 and f.split('/')[-1] == '_item':  # Sequnce/Set of type
1090         nm = self.conform.use_item('FIELD_RENAME', '/'.join(f.split('/')[0:-1]), val_dflt=f.split('/')[-2]) + f.split('/')[-1]
1091       else:
1092         nm = f.split('/')[-1]
1093       nm = self.conform.use_item('FIELD_RENAME', f, val_dflt=nm)
1094       nm = asn2c(nm)
1095       if (self.field[f]['pdu']): 
1096         nm += '_PDU'
1097       t = self.field[f]['type']
1098       if self.type.has_key(t):
1099         ethtype = self.type[t]['ethname']
1100       else:  # undefined type
1101         ethtype = self.dummy_import_type(t)
1102       ethtypemod = ethtype + self.field[f]['modified']
1103       if self.eth_hf.has_key(nm):
1104         if self.eth_hf_dupl.has_key(nm):
1105           if self.eth_hf_dupl[nm].has_key(ethtypemod):
1106             nm = self.eth_hf_dupl[nm][ethtypemod]
1107             self.eth_hf[nm]['create_field'] = self.eth_hf[nm]['create_field'] or self.field[f]['create_field']
1108             self.eth_hf[nm]['ref'].append(f)
1109             self.field[f]['ethname'] = nm
1110             self.eth_type[ethtype]['create_field'] = self.eth_type[ethtype]['create_field'] or self.eth_hf[nm]['create_field']
1111             continue
1112           else:
1113             nmx = nm + ('_%02d' % (len(self.eth_hf_dupl[nm])))
1114             self.eth_hf_dupl[nm][ethtype] = nmx
1115             nm = nmx
1116         else:
1117           if (self.eth_hf[nm]['ethtype']+self.eth_hf[nm]['modified']) == ethtypemod:
1118             self.eth_hf[nm]['create_field'] = self.eth_hf[nm]['create_field'] or self.field[f]['create_field']
1119             self.eth_hf[nm]['ref'].append(f)
1120             self.field[f]['ethname'] = nm
1121             self.eth_type[ethtype]['create_field'] = self.eth_type[ethtype]['create_field'] or self.eth_hf[nm]['create_field']
1122             continue
1123           else:
1124             nmx = nm + '_01'
1125             self.eth_hf_dupl[nm] = {self.eth_hf[nm]['ethtype']+self.eth_hf[nm]['modified'] : nm, \
1126                                     ethtypemod : nmx}
1127             nm = nmx
1128       if (self.field[f]['pdu']):
1129         self.eth_hfpdu_ord.append(nm)
1130       else:
1131         self.eth_hf_ord.append(nm)
1132       fullname = "hf_%s_%s" % (self.eproto, nm)
1133       attr = self.eth_get_type_attr(self.field[f]['type']).copy()
1134       attr.update(self.field[f]['attr'])
1135       if (self.NAPI() and attr.has_key('NAME')):
1136         attr['NAME'] += self.field[f]['idx']
1137       attr.update(self.conform.use_item('EFIELD_ATTR', nm))
1138       self.eth_hf[nm] = {'fullname' : fullname, 'pdu' : self.field[f]['pdu'],
1139                          'ethtype' : ethtype, 'modified' : self.field[f]['modified'],
1140                          'attr' : attr.copy(), 
1141                          'create_field' : self.field[f]['create_field'],
1142                          'ref' : [f]}
1143       self.field[f]['ethname'] = nm
1144       self.eth_type[ethtype]['create_field'] = self.eth_type[ethtype]['create_field'] or self.eth_hf[nm]['create_field']
1145     #--- type dependencies -------------------
1146     (self.eth_type_ord1, self.eth_dep_cycle) = dependency_compute(self.type_ord, self.type_dep, map_fn = lambda t: self.type[t]['ethname'], ignore_fn = lambda t: self.type[t]['import'])
1147     i = 0
1148     while i < len(self.eth_dep_cycle):
1149       t = self.type[self.eth_dep_cycle[i][0]]['ethname']
1150       self.dep_cycle_eth_type.setdefault(t, []).append(i)
1151       i += 1
1152
1153     #--- value dependencies and export -------------------
1154     for v in self.eth_value_ord:
1155       if self.eth_value[v]['export']:
1156         self.eth_vexport_ord.append(v)
1157       else:
1158         self.eth_value_ord1.append(v)
1159
1160     #--- export tags, values, ... ---
1161     for t in self.exports:
1162       if not self.type.has_key(t):
1163         continue
1164       if self.type[t]['import']:
1165         continue
1166       m = self.type[t]['module']
1167       if not self.all_tags.has_key(m):
1168         self.all_tags[m] = {}
1169       self.all_tags[m][t] = self.type[t]['val'].GetTTag(self)
1170     for v in self.vexports:
1171       if not self.value.has_key(v):
1172         continue
1173       if self.value[v]['import']:
1174         continue
1175       m = self.value[v]['module']
1176       if not self.all_vals.has_key(m):
1177         self.all_vals[m] = {}
1178       vv = self.value[v]['value']
1179       if isinstance (vv, Value):
1180         vv = vv.to_str(self)
1181       self.all_vals[m][v] = vv
1182
1183   #--- eth_vals_nm ------------------------------------------------------------
1184   def eth_vals_nm(self, tname):
1185     out = ""
1186     if (not self.eth_type[tname]['export'] & EF_NO_PROT):
1187       out += "%s_" % (self.eproto)
1188     out += "%s_vals" % (tname)
1189     return out
1190
1191   #--- eth_vals ---------------------------------------------------------------
1192   def eth_vals(self, tname, vals):
1193     out = ""
1194     has_enum = self.eth_type[tname]['enum'] & EF_ENUM
1195     if (not self.eth_type[tname]['export'] & EF_VALS):
1196       out += "static "
1197     if (self.eth_type[tname]['export'] & EF_VALS) and (self.eth_type[tname]['export'] & EF_TABLE):
1198       out += "static "
1199     out += "const value_string %s[] = {\n" % (self.eth_vals_nm(tname))
1200     for (val, id) in vals:
1201       if (has_enum):
1202         vval = self.eth_enum_item(tname, id)
1203       else:
1204         vval = val
1205       out += '  { %3s, "%s" },\n' % (vval, id)
1206     out += "  { 0, NULL }\n};\n"
1207     return out
1208
1209   #--- eth_enum_prefix ------------------------------------------------------------
1210   def eth_enum_prefix(self, tname, type=False):
1211     out = ""
1212     if (self.eth_type[tname]['export'] & EF_ENUM):
1213       no_prot = self.eth_type[tname]['export'] & EF_NO_PROT
1214     else:
1215       no_prot = self.eth_type[tname]['enum'] & EF_NO_PROT
1216     if (not no_prot):
1217       out += self.eproto
1218     if ((not self.eth_type[tname]['enum'] & EF_NO_TYPE) or type):
1219       if (out): out += '_'
1220       out += tname
1221     if (self.eth_type[tname]['enum'] & EF_UCASE):
1222       out = out.upper()
1223     if (out): out += '_'
1224     return out
1225
1226   #--- eth_enum_nm ------------------------------------------------------------
1227   def eth_enum_nm(self, tname):
1228     out = self.eth_enum_prefix(tname, type=True)
1229     out += "enum"
1230     return out
1231
1232   #--- eth_enum_item ---------------------------------------------------------------
1233   def eth_enum_item(self, tname, ident):
1234     out = self.eth_enum_prefix(tname)
1235     out += asn2c(ident)
1236     if (self.eth_type[tname]['enum'] & EF_UCASE):
1237       out = out.upper()
1238     return out
1239
1240   #--- eth_enum ---------------------------------------------------------------
1241   def eth_enum(self, tname, vals):
1242     out = ""
1243     if (self.eth_type[tname]['enum'] & EF_DEFINE):
1244       out += "/* enumerated values for %s */\n" % (tname)
1245       for (val, id) in vals:
1246         out += '#define %-12s %3s\n' % (self.eth_enum_item(tname, id), val)
1247     else:
1248       out += "typedef enum _%s {\n" % (self.eth_enum_nm(tname))
1249       first_line = 1
1250       for (val, id) in vals:
1251         if (first_line == 1):
1252           first_line = 0
1253         else:
1254           out += ",\n"  
1255         out += '  %-12s = %3s' % (self.eth_enum_item(tname, id), val)
1256       out += "\n} %s;\n" % (self.eth_enum_nm(tname))
1257     return out
1258
1259   #--- eth_bits ---------------------------------------------------------------
1260   def eth_bits(self, tname, bits):
1261     out = ""
1262     out += "static const "
1263     out += "asn_namedbit %(TABLE)s[] = {\n"
1264     for (val, id) in bits:
1265       out += '  { %2d, &hf_%s_%s_%s, -1, -1, "%s", NULL },\n' % (val, self.eproto, tname, asn2c(id), id)
1266     out += "  { 0, NULL, 0, 0, NULL, NULL }\n};\n"
1267     return out
1268
1269   #--- eth_type_fn_h ----------------------------------------------------------
1270   def eth_type_fn_h(self, tname):
1271     out = ""
1272     if (not self.eth_type[tname]['export'] & EF_TYPE):
1273       out += "static "
1274     out += "int "
1275     if (self.Ber()):
1276       out += "dissect_%s_%s(gboolean implicit_tag _U_, 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)
1277     elif (self.Per()):
1278       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)
1279     out += ";\n"
1280     return out
1281
1282   #--- eth_fn_call ------------------------------------------------------------
1283   def eth_fn_call(self, fname, ret=None, indent=2, par=None):
1284     out = indent * ' '
1285     if (ret):
1286       if (ret == 'return'):
1287         out += 'return '
1288       else:
1289         out += ret + ' = '
1290     out += fname + '('
1291     ind = len(out)
1292     for i in range(len(par)):
1293       if (i>0): out += ind * ' '
1294       out += ', '.join(par[i])
1295       if (i<(len(par)-1)): out += ',\n'
1296     out += ');\n'
1297     return out
1298
1299   #--- eth_type_fn_hdr --------------------------------------------------------
1300   def eth_type_fn_hdr(self, tname):
1301     out = '\n'
1302     if (not self.eth_type[tname]['export'] & EF_TYPE):
1303       out += "static "
1304     out += "int\n"
1305     if (self.Ber()):
1306       out += "dissect_%s_%s(gboolean implicit_tag _U_, 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)
1307     elif (self.Per()):
1308       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)
1309     if self.conform.get_fn_presence(tname):
1310       out += self.conform.get_fn_text(tname, 'FN_HDR')
1311     elif self.conform.get_fn_presence(self.eth_type[tname]['ref'][0]):
1312       out += self.conform.get_fn_text(self.eth_type[tname]['ref'][0], 'FN_HDR')
1313     return out
1314
1315   #--- eth_type_fn_ftr --------------------------------------------------------
1316   def eth_type_fn_ftr(self, tname):
1317     out = '\n'
1318     if self.conform.get_fn_presence(tname):
1319       out += self.conform.get_fn_text(tname, 'FN_FTR')
1320     elif self.conform.get_fn_presence(self.eth_type[tname]['ref'][0]):
1321       out += self.conform.get_fn_text(self.eth_type[tname]['ref'][0], 'FN_FTR')
1322     out += "  return offset;\n"
1323     out += "}\n"
1324     return out
1325
1326   #--- eth_type_fn_body -------------------------------------------------------
1327   def eth_type_fn_body(self, tname, body, pars=None):
1328     out = body
1329     if self.conform.get_fn_body_presence(tname):
1330       out = self.conform.get_fn_text(tname, 'FN_BODY')
1331     elif self.conform.get_fn_body_presence(self.eth_type[tname]['ref'][0]):
1332       out = self.conform.get_fn_text(self.eth_type[tname]['ref'][0], 'FN_BODY')
1333     if pars:
1334       try:
1335         out = out % pars
1336       except (TypeError):
1337         pass
1338     return out
1339
1340   #--- eth_output_hf ----------------------------------------------------------
1341   def eth_output_hf (self):
1342     if not len(self.eth_hf_ord) and not len(self.eth_hfpdu_ord) and not len(self.named_bit): return
1343     fx = self.output.file_open('hf')
1344     for f in (self.eth_hfpdu_ord + self.eth_hf_ord):
1345       fx.write("%-50s/* %s */\n" % ("static int %s = -1;  " % (self.eth_hf[f]['fullname']), self.eth_hf[f]['ethtype']))
1346     if (self.named_bit):
1347       fx.write('/* named bits */\n')
1348     for nb in self.named_bit:
1349       fx.write("static int %s = -1;\n" % (nb['ethname']))
1350     self.output.file_close(fx)
1351     
1352   #--- eth_output_hf_arr ------------------------------------------------------
1353   def eth_output_hf_arr (self):
1354     if not len(self.eth_hf_ord) and not len(self.eth_hfpdu_ord) and not len(self.named_bit): return
1355     fx = self.output.file_open('hfarr')
1356     for f in (self.eth_hfpdu_ord + self.eth_hf_ord):
1357       t = self.eth_hf[f]['ethtype']
1358       blurb = '"%s.%s"' % (self.eth_type[t]['proto'], t)
1359       attr = self.eth_hf[f]['attr'].copy()
1360       attr['ABBREV'] = '"%s.%s"' % (self.proto, attr['ABBREV'])
1361       if not attr.has_key('BLURB'):
1362         attr['BLURB'] = blurb
1363       fx.write('    { &%s,\n' % (self.eth_hf[f]['fullname']))
1364       fx.write('      { %(NAME)s, %(ABBREV)s,\n' % attr)
1365       fx.write('        %(TYPE)s, %(DISPLAY)s, %(STRINGS)s, %(BITMASK)s,\n' % attr)
1366       fx.write('        %(BLURB)s, HFILL }},\n' % attr)
1367     for nb in self.named_bit:
1368       blurb = ''
1369       fx.write('    { &%s,\n' % (nb['ethname']))
1370       fx.write('      { "%s", "%s.%s",\n' % (nb['name'], self.proto, nb['name']))
1371       fx.write('        %s, %s, %s, %s,\n' % (nb['ftype'], nb['display'], nb['strings'], nb['bitmask']))
1372       fx.write('        "%s", HFILL }},\n' % (blurb))
1373     self.output.file_close(fx)
1374
1375   #--- eth_output_ett ---------------------------------------------------------
1376   def eth_output_ett (self):
1377     fx = self.output.file_open('ett')
1378     fempty = True
1379     #fx.write("static gint ett_%s = -1;\n" % (self.eproto))
1380     for t in self.eth_type_ord:
1381       if self.eth_type[t]['tree']:
1382         fx.write("static gint %s = -1;\n" % (self.eth_type[t]['tree']))
1383         fempty = False
1384     self.output.file_close(fx, discard=fempty)
1385
1386   #--- eth_output_ett_arr -----------------------------------------------------
1387   def eth_output_ett_arr(self):
1388     fx = self.output.file_open('ettarr')
1389     fempty = True
1390     #fx.write("    &ett_%s,\n" % (self.eproto))
1391     for t in self.eth_type_ord:
1392       if self.eth_type[t]['tree']:
1393         fx.write("    &%s,\n" % (self.eth_type[t]['tree']))
1394         fempty = False
1395     self.output.file_close(fx, discard=fempty)
1396
1397   #--- eth_output_export ------------------------------------------------------
1398   def eth_output_export(self):
1399     if (not len(self.eth_export_ord)): return
1400     fx = self.output.file_open('exp', ext='h')
1401     for t in self.eth_export_ord:  # vals
1402       if (self.eth_type[t]['export'] & EF_ENUM) and self.eth_type[t]['val'].eth_has_enum(t, self):
1403         fx.write(self.eth_type[t]['val'].eth_type_enum(t, self))
1404       if (self.eth_type[t]['export'] & EF_VALS) and self.eth_type[t]['val'].eth_has_vals():
1405         if not self.eth_type[t]['export'] & EF_TABLE:
1406           if self.eth_type[t]['export'] & EF_WS_VAR:
1407             fx.write("WS_VAR_IMPORT ")
1408           else:
1409             fx.write("extern ")
1410           fx.write("const value_string %s[];\n" % (self.eth_vals_nm(t)))
1411         else:
1412           fx.write(self.eth_type[t]['val'].eth_type_vals(t, self))
1413     for t in self.eth_export_ord:  # functions
1414       if (self.eth_type[t]['export'] & EF_TYPE):
1415         if self.eth_type[t]['export'] & EF_EXTERN:
1416           fx.write("extern ")
1417         fx.write(self.eth_type_fn_h(t))
1418     self.output.file_close(fx)
1419
1420   #--- eth_output_expcnf ------------------------------------------------------
1421   def eth_output_expcnf(self):
1422     fx = self.output.file_open('exp', ext='cnf')
1423     fx.write('#.MODULE\n')
1424     maxw = 0
1425     for (m, p) in self.modules:
1426       if (len(m) > maxw): maxw = len(m)
1427     for (m, p) in self.modules:
1428       fx.write("%-*s  %s\n" % (maxw, m, p))
1429     fx.write('#.END\n\n')
1430     if self.Ber():
1431       fx.write('#.IMPORT_TAG\n')
1432       for t in self.eth_export_ord:  # tags
1433         if (self.eth_type[t]['export'] & EF_TYPE):
1434           fx.write('%-24s ' % self.eth_type[t]['ref'][0])
1435           fx.write('%s %s\n' % self.eth_type[t]['val'].GetTag(self))
1436       fx.write('#.END\n\n')
1437     fx.write('#.TYPE_ATTR\n')
1438     for t in self.eth_export_ord:  # attributes
1439       if (self.eth_type[t]['export'] & EF_TYPE):
1440         fx.write('%-24s ' % self.eth_type[t]['ref'][0])
1441         attr = self.eth_get_type_attr(self.eth_type[t]['ref'][0]).copy()
1442         fx.write('TYPE = %(TYPE)-9s  DISPLAY = %(DISPLAY)-9s  STRINGS = %(STRINGS)s  BITMASK = %(BITMASK)s\n' % attr)
1443     fx.write('#.END\n\n')
1444     self.output.file_close(fx, keep_anyway=True)
1445
1446   #--- eth_output_val ------------------------------------------------------
1447   def eth_output_val(self):
1448     if (not len(self.eth_value_ord1)): return
1449     fx = self.output.file_open('val', ext='h')
1450     for v in self.eth_value_ord1:
1451       vv = self.eth_value[v]['value']
1452       if isinstance (vv, Value):
1453         vv = vv.to_str(self)
1454       fx.write("#define %-30s %s\n" % (v, vv))
1455     for t in self.eth_type_ord1:
1456       if self.eth_type[t]['import']:
1457         continue
1458       if self.eth_type[t]['val'].eth_has_enum(t, self) and not (self.eth_type[t]['export'] & EF_ENUM):
1459         fx.write(self.eth_type[t]['val'].eth_type_enum(t, self))
1460     self.output.file_close(fx)
1461
1462   #--- eth_output_valexp ------------------------------------------------------
1463   def eth_output_valexp(self):
1464     if (not len(self.eth_vexport_ord)): return
1465     fx = self.output.file_open('valexp', ext='h')
1466     for v in self.eth_vexport_ord:
1467       vv = self.eth_value[v]['value']
1468       if isinstance (vv, Value):
1469         vv = vv.to_str(self)
1470       fx.write("#define %-30s %s\n" % (v, vv))
1471     self.output.file_close(fx)
1472
1473   #--- eth_output_types -------------------------------------------------------
1474   def eth_output_types(self):
1475     def out_field(f):
1476       t = self.eth_hf[f]['ethtype']
1477       if (self.Ber()):
1478         x = {}
1479         for r in self.eth_hf[f]['ref']:
1480           x[self.field[r]['impl']] = self.field[r]['impl']
1481       else:
1482         x = {False : False}
1483       x = x.values()
1484       x.sort()
1485       out = ''
1486       for i in x:
1487         if (i):
1488           postfix = '_impl'
1489           impl = 'TRUE'
1490         else:
1491           postfix = ''
1492           impl = 'FALSE'
1493         if (self.Ber()):
1494           if (i): postfix = '_impl'; impl = 'TRUE'
1495           else:   postfix = '';      impl = 'FALSE'
1496           out += 'static int dissect_'+f+postfix+'(proto_tree *tree _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_) {\n'
1497           par=((impl, 'tvb', 'offset', 'actx', 'tree', self.eth_hf[f]['fullname']),)
1498         else:
1499           out += 'static int dissect_'+f+'(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_) {\n'
1500           par=(('tvb', 'offset', 'actx', 'tree', self.eth_hf[f]['fullname']),)
1501         out += self.eth_fn_call('dissect_%s_%s' % (self.eth_type[t]['proto'], t), ret='return',
1502                                 par=par)
1503         out += '}\n'
1504       return out
1505     #end out_field()
1506     def out_pdu_decl(f):
1507       t = self.eth_hf[f]['ethtype']
1508       is_new = self.eth_hf[f]['pdu']['new']
1509       out = 'static '
1510       if (is_new):
1511         out += 'int'
1512       else:
1513         out += 'void'
1514       out += ' dissect_'+f+'(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_);\n'
1515       return out
1516     #end out_pdu_decl()
1517     def out_pdu(f):
1518       t = self.eth_hf[f]['ethtype']
1519       is_new = self.eth_hf[f]['pdu']['new']
1520       impl = 'FALSE'
1521       out = 'static '
1522       if (is_new):
1523         out += 'int'
1524       else:
1525         out += 'void'
1526       out += ' dissect_'+f+'(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_) {\n'
1527       if (is_new):
1528         out += '  int offset = 0;\n'
1529         off_par = 'offset'
1530         ret_par = 'offset'
1531       else:
1532         off_par = '0'
1533         ret_par = None
1534       if (self.Per()):
1535         if (self.Aligned()):
1536           aligned = 'TRUE'
1537         else:
1538           aligned = 'FALSE'
1539         out += "  asn1_ctx_t asn1_ctx;\n"
1540         out += self.eth_fn_call('asn1_ctx_init', par=(('&asn1_ctx', 'ASN1_ENC_PER', aligned, 'pinfo'),))
1541       if (self.Ber()):
1542         out += "  asn1_ctx_t asn1_ctx;\n"
1543         out += self.eth_fn_call('asn1_ctx_init', par=(('&asn1_ctx', 'ASN1_ENC_BER', 'TRUE', 'pinfo'),))
1544         par=((impl, 'tvb', off_par,'&asn1_ctx', 'tree', self.eth_hf[f]['fullname']),)
1545       elif (self.Per()):
1546         par=(('tvb', off_par, '&asn1_ctx', 'tree', self.eth_hf[f]['fullname']),)
1547       else:
1548         par=((),)
1549       out += self.eth_fn_call('dissect_%s_%s' % (self.eth_type[t]['proto'], t), ret=ret_par, par=par)
1550       if (self.Per() and is_new):
1551         out += '  offset += 7; offset >>= 3;\n'
1552       if (is_new):
1553         out += '  return offset;\n'
1554       out += '}\n'
1555       return out
1556     #end out_pdu()
1557     fx = self.output.file_open('fn')
1558     pos = fx.tell()
1559     if (len(self.eth_hfpdu_ord)):
1560       first_decl = True
1561       for f in self.eth_hfpdu_ord:
1562         if (self.eth_hf[f]['pdu'] and self.eth_hf[f]['pdu']['need_decl']):
1563           if first_decl:
1564             fx.write('/*--- PDUs declarations ---*/\n')
1565             first_decl = False
1566           fx.write(out_pdu_decl(f))
1567       if not first_decl:
1568         fx.write('\n')
1569     if self.eth_dep_cycle:
1570       fx.write('/*--- Cyclic dependencies ---*/\n\n')
1571       i = 0
1572       while i < len(self.eth_dep_cycle):
1573         t = self.type[self.eth_dep_cycle[i][0]]['ethname']
1574         if self.dep_cycle_eth_type[t][0] != i: i += 1; continue
1575         fx.write(''.join(map(lambda i: '/* %s */\n' % ' -> '.join(self.eth_dep_cycle[i]), self.dep_cycle_eth_type[t])))
1576         fx.write(self.eth_type_fn_h(t))
1577         if (self.Fld() or self.eth_type[t]['create_field']):
1578           fx.write('\n')
1579           for f in self.eth_hf_ord:
1580             if ((self.eth_hf[f]['ethtype'] == t) and (self.Fld() or self.eth_hf[f]['create_field'])):
1581               fx.write(out_field(f))
1582         fx.write('\n')
1583         i += 1
1584       fx.write('\n')
1585     if (self.Fld()):  # fields for imported types
1586       fx.write('/*--- Fields for imported types ---*/\n\n')
1587       for f in self.eth_hf_ord:
1588         if (self.eth_type[self.eth_hf[f]['ethtype']]['import']):
1589           fx.write(out_field(f))
1590       fx.write('\n')
1591     for t in self.eth_type_ord1:
1592       if self.eth_type[t]['import']:
1593         continue
1594       if self.eth_type[t]['val'].eth_has_vals():
1595         if self.eth_type[t]['no_emit'] & EF_VALS:
1596           pass
1597         elif self.eth_type[t]['user_def'] & EF_VALS:
1598           fx.write("extern const value_string %s[];\n" % (self.eth_vals_nm(t)))
1599         elif (self.eth_type[t]['export'] & EF_VALS) and (self.eth_type[t]['export'] & EF_TABLE):
1600           pass
1601         else:
1602           fx.write(self.eth_type[t]['val'].eth_type_vals(t, self))
1603       if self.eth_type[t]['no_emit'] & EF_TYPE:
1604         pass
1605       elif self.eth_type[t]['user_def'] & EF_TYPE:
1606         fx.write(self.eth_type_fn_h(t))
1607       else:
1608         fx.write(self.eth_type[t]['val'].eth_type_fn(self.eth_type[t]['proto'], t, self))
1609       if ((self.Fld() or self.eth_type[t]['create_field']) and not self.dep_cycle_eth_type.has_key(t)):
1610         for f in self.eth_hf_ord:
1611           if ((self.eth_hf[f]['ethtype'] == t) and (self.Fld() or self.eth_hf[f]['create_field'])):
1612             fx.write(out_field(f))
1613       fx.write('\n')
1614     if (len(self.eth_hfpdu_ord)):
1615       fx.write('/*--- PDUs ---*/\n\n')
1616       for f in self.eth_hfpdu_ord:
1617         if (self.eth_hf[f]['pdu']):
1618           fx.write(out_pdu(f))
1619       fx.write('\n')
1620     fempty = pos == fx.tell()
1621     self.output.file_close(fx, discard=fempty)
1622
1623   #--- eth_output_dis_hnd -----------------------------------------------------
1624   def eth_output_dis_hnd(self):
1625     fx = self.output.file_open('dis-hnd')
1626     fempty = True
1627     for f in self.eth_hfpdu_ord:
1628       pdu = self.eth_hf[f]['pdu']
1629       if (pdu and pdu['reg'] and not pdu['hidden']):
1630         dis = self.proto
1631         if (pdu['reg'] != '.'):
1632           dis += '.' + pdu['reg']
1633         fx.write('static dissector_handle_t %s_handle;\n' % (asn2c(dis)))
1634         fempty = False
1635     fx.write('\n')
1636     self.output.file_close(fx, discard=fempty)
1637
1638   #--- eth_output_dis_reg -----------------------------------------------------
1639   def eth_output_dis_reg(self):
1640     fx = self.output.file_open('dis-reg')
1641     fempty = True
1642     for f in self.eth_hfpdu_ord:
1643       pdu = self.eth_hf[f]['pdu']
1644       if (pdu and pdu['reg']):
1645         new_prefix = ''
1646         if (pdu['new']): new_prefix = 'new_'
1647         dis = self.proto
1648         if (pdu['reg'] != '.'): dis += '.' + pdu['reg']
1649         fx.write('  %sregister_dissector("%s", dissect_%s, proto_%s);\n' % (new_prefix, dis, f, self.eproto))
1650         if (not pdu['hidden']):
1651           fx.write('  %s_handle = find_dissector("%s");\n' % (asn2c(dis), dis))
1652         fempty = False
1653     fx.write('\n')
1654     self.output.file_close(fx, discard=fempty)
1655
1656   #--- eth_output_dis_tab -----------------------------------------------------
1657   def eth_output_dis_tab(self):
1658     fx = self.output.file_open('dis-tab')
1659     fempty = True
1660     for k in self.conform.get_order('REGISTER'):
1661       reg = self.conform.use_item('REGISTER', k)
1662       if not self.field.has_key(reg['pdu']): continue
1663       f = self.field[reg['pdu']]['ethname']
1664       pdu = self.eth_hf[f]['pdu'] 
1665       new_prefix = ''
1666       if (pdu['new']): new_prefix = 'new_'
1667       if (reg['rtype'] in ('NUM', 'STR')):
1668         rstr = ''
1669         if (reg['rtype'] == 'STR'): rstr = '_string'
1670         if (pdu['reg']):
1671           dis = self.proto
1672           if (pdu['reg'] != '.'): dis += '.' + pdu['reg']
1673           if  (not pdu['hidden']):
1674             hnd = '%s_handle' % (asn2c(dis))
1675           else:
1676             hnd = 'find_dissector("%s")' % (dis)
1677         else:
1678           hnd = '%screate_dissector_handle(dissect_%s, proto_%s)' % (new_prefix, f, self.eproto)
1679         rport = self.value_get_eth(reg['rport'])
1680         fx.write('  dissector_add%s("%s", %s, %s);\n' % (rstr, reg['rtable'], rport, hnd))
1681       elif (reg['rtype'] in ('BER', 'PER')):
1682         roid = self.value_get_eth(reg['roid'])
1683         fx.write('  %sregister_%s_oid_dissector(%s, dissect_%s, proto_%s, %s);\n' % (new_prefix, reg['rtype'].lower(), roid, f, self.eproto, reg['roidname']))
1684       fempty = False
1685     fx.write('\n')
1686     self.output.file_close(fx, discard=fempty)
1687
1688   #--- dupl_report -----------------------------------------------------
1689   def dupl_report(self):
1690     # types
1691     tmplist = self.eth_type_dupl.keys()
1692     tmplist.sort()
1693     for t in tmplist:
1694       msg = "The same type names for different types. Explicit type renaming is recommended.\n"
1695       msg += t + "\n"
1696       for tt in self.eth_type_dupl[t]:
1697         msg += " %-20s %s\n" % (self.type[tt]['ethname'], tt)
1698       warnings.warn_explicit(msg, UserWarning, '', '')
1699     # fields
1700     tmplist = self.eth_hf_dupl.keys()
1701     tmplist.sort()
1702     for f in tmplist:
1703       msg = "The same field names for different types. Explicit field renaming is recommended.\n"
1704       msg += f + "\n"
1705       for tt in self.eth_hf_dupl[f].keys():
1706         msg += " %-20s %-20s " % (self.eth_hf_dupl[f][tt], tt)
1707         msg += ", ".join(self.eth_hf[self.eth_hf_dupl[f][tt]]['ref'])
1708         msg += "\n"
1709       warnings.warn_explicit(msg, UserWarning, '', '')
1710
1711   #--- eth_do_output ------------------------------------------------------------
1712   def eth_do_output(self):
1713     if self.dbg('a'):
1714       print "\n# Assignments"
1715       for a in self.assign_ord:
1716         v = ' '
1717         if (self.assign[a]['virt']): v = '*'
1718         print v, a
1719       print "\n# Value assignments"
1720       for a in self.vassign_ord:
1721         print ' ', a
1722     if self.dbg('t'):
1723       print "\n# Imported Types"
1724       print "%-40s %-24s %-24s" % ("ASN.1 name", "Module", "Protocol")
1725       print "-" * 100
1726       for t in self.type_imp:
1727         print "%-40s %-24s %-24s" % (t, self.type[t]['import'], self.type[t]['proto'])
1728       print "\n# Imported Values"
1729       print "%-40s %-24s %-24s" % ("ASN.1 name", "Module", "Protocol")
1730       print "-" * 100
1731       for t in self.value_imp:
1732         print "%-40s %-24s %-24s" % (t, self.value[t]['import'], self.value[t]['proto'])
1733       print "\n# Imported Object Classes"
1734       print "%-40s %-24s %-24s" % ("ASN.1 name", "Module", "Protocol")
1735       print "-" * 100
1736       for t in self.objectclass_imp:
1737         print "%-40s %-24s %-24s" % (t, self.objectclass[t]['import'], self.objectclass[t]['proto'])
1738       print "\n# Exported Types"
1739       print "%-31s %s" % ("Wireshark type", "Export Flag")
1740       print "-" * 100
1741       for t in self.eth_export_ord:
1742         print "%-31s 0x%02X" % (t, self.eth_type[t]['export'])
1743       print "\n# Exported Values"
1744       print "%-40s %s" % ("Wireshark name", "Value")
1745       print "-" * 100
1746       for v in self.eth_vexport_ord:
1747         vv = self.eth_value[v]['value']
1748         if isinstance (vv, Value):
1749           vv = vv.to_str(self)
1750         print "%-40s %s" % (v, vv)
1751       print "\n# ASN.1 Object Classes"
1752       print "%-40s %-24s %-24s" % ("ASN.1 name", "Module", "Protocol")
1753       print "-" * 100
1754       for t in self.objectclass_ord:
1755         print "%-40s " % (t)
1756       print "\n# ASN.1 Types"
1757       print "%-49s %-24s %-24s" % ("ASN.1 unique name", "'tname'", "Wireshark type")
1758       print "-" * 100
1759       for t in self.type_ord:
1760         print "%-49s %-24s %-24s" % (t, self.type[t]['tname'], self.type[t]['ethname'])
1761       print "\n# Wireshark Types"
1762       print "Wireshark type                   References (ASN.1 types)"
1763       print "-" * 100
1764       for t in self.eth_type_ord:
1765         print "%-31s %d" % (t, len(self.eth_type[t]['ref'])),
1766         print ', '.join(self.eth_type[t]['ref'])
1767       print "\n# ASN.1 Values"
1768       print "%-40s %-18s %-20s %s" % ("ASN.1 unique name", "Type", "Value", "Wireshark value")
1769       print "-" * 100
1770       for v in self.value_ord:
1771         vv = self.value[v]['value']
1772         if isinstance (vv, Value):
1773           vv = vv.to_str(self)
1774         print "%-40s %-18s %-20s %s" % (v, self.value[v]['type'].eth_tname(), vv, self.value[v]['ethname'])
1775       #print "\n# Wireshark Values"
1776       #print "%-40s %s" % ("Wireshark name", "Value")
1777       #print "-" * 100
1778       #for v in self.eth_value_ord:
1779       #  vv = self.eth_value[v]['value']
1780       #  if isinstance (vv, Value):
1781       #    vv = vv.to_str(self)
1782       #  print "%-40s %s" % (v, vv)
1783       print "\n# ASN.1 Fields"
1784       print "ASN.1 unique name                        Wireshark name        ASN.1 type"
1785       print "-" * 100
1786       for f in (self.pdu_ord + self.field_ord):
1787         print "%-40s %-20s %s" % (f, self.field[f]['ethname'], self.field[f]['type'])
1788       print "\n# Wireshark Fields"
1789       print "Wireshark name                  Wireshark type        References (ASN.1 fields)"
1790       print "-" * 100
1791       for f in (self.eth_hfpdu_ord + self.eth_hf_ord):
1792         print "%-30s %-20s %s" % (f, self.eth_hf[f]['ethtype'], len(self.eth_hf[f]['ref'])),
1793         print ', '.join(self.eth_hf[f]['ref'])
1794       #print "\n# Order after dependencies"
1795       #print '\n'.join(self.eth_type_ord1)
1796       print "\n# Cyclic dependencies"
1797       for c in self.eth_dep_cycle:
1798         print ' -> '.join(c)
1799     self.dupl_report()
1800     self.output.outnm = self.outnm_opt
1801     if (not self.output.outnm):
1802       self.output.outnm = self.proto
1803       self.output.outnm = self.output.outnm.replace('.', '-')
1804     self.eth_output_hf()
1805     self.eth_output_ett()
1806     self.eth_output_types()
1807     self.eth_output_hf_arr()
1808     self.eth_output_ett_arr()
1809     self.eth_output_export()
1810     if self.expcnf:
1811       self.eth_output_expcnf()
1812     self.eth_output_val()
1813     self.eth_output_valexp()
1814     self.eth_output_dis_hnd()
1815     self.eth_output_dis_reg()
1816     self.eth_output_dis_tab()
1817
1818   def dbg_modules(self):
1819     def print_mod(m):
1820       print "%-30s " % (m),
1821       dep = self.module[m][:]
1822       for i in range(len(dep)):
1823         if not self.module.has_key(dep[i]): 
1824           dep[i] = '*' + dep[i]
1825       print ', '.join(dep)
1826     # end of print_mod()
1827     (mod_ord, mod_cyc) = dependency_compute(self.module_ord, self.module, ignore_fn = lambda t: not self.module.has_key(t))
1828     print "\n# ASN.1 Moudules"
1829     print "Module name                     Dependency"
1830     print "-" * 100
1831     new_ord = False
1832     for m in (self.module_ord):
1833       print_mod(m)
1834       new_ord = new_ord or (self.module_ord.index(m) != mod_ord.index(m))
1835     if new_ord:
1836       print "\n# ASN.1 Moudules - in dependency order"
1837       print "Module name                     Dependency"
1838       print "-" * 100
1839       for m in (mod_ord):
1840         print_mod(m)
1841     if mod_cyc:
1842       print "\nCyclic dependencies:"
1843       print "mod_cyc = ", mod_cyc
1844
1845
1846 #--- EthCnf -------------------------------------------------------------------
1847 class EthCnf:
1848   def __init__(self):
1849     self.ectx = None
1850     self.tblcfg = {}
1851     self.table = {}
1852     self.order = {}
1853     self.fn = {}
1854     self.suppress_line = False
1855     self.include_path = []
1856     #                                   Value name             Default value       Duplicity check   Usage check
1857     self.tblcfg['EXPORTS']         = { 'val_nm' : 'flag',     'val_dflt' : 0,     'chk_dup' : True, 'chk_use' : True }
1858     self.tblcfg['MAKE_ENUM']       = { 'val_nm' : 'flag',     'val_dflt' : 0,     'chk_dup' : True, 'chk_use' : True }
1859     self.tblcfg['PDU']             = { 'val_nm' : 'attr',     'val_dflt' : None,  'chk_dup' : True, 'chk_use' : True }
1860     self.tblcfg['REGISTER']        = { 'val_nm' : 'attr',     'val_dflt' : None,  'chk_dup' : True, 'chk_use' : True }
1861     self.tblcfg['USER_DEFINED']    = { 'val_nm' : 'flag',     'val_dflt' : 0,     'chk_dup' : True, 'chk_use' : True }
1862     self.tblcfg['NO_EMIT']         = { 'val_nm' : 'flag',     'val_dflt' : 0,     'chk_dup' : True, 'chk_use' : True }
1863     self.tblcfg['MODULE']          = { 'val_nm' : 'proto',    'val_dflt' : None,  'chk_dup' : True, 'chk_use' : False }
1864     self.tblcfg['OMIT_ASSIGNMENT'] = { 'val_nm' : 'omit',     'val_dflt' : False, 'chk_dup' : True, 'chk_use' : True }
1865     self.tblcfg['NO_OMIT_ASSGN']   = { 'val_nm' : 'omit',     'val_dflt' : True,  'chk_dup' : True, 'chk_use' : True }
1866     self.tblcfg['VIRTUAL_ASSGN']   = { 'val_nm' : 'name',     'val_dflt' : None,  'chk_dup' : True, 'chk_use' : True }
1867     self.tblcfg['SET_TYPE']        = { 'val_nm' : 'type',     'val_dflt' : None,  'chk_dup' : True, 'chk_use' : True }
1868     self.tblcfg['TYPE_RENAME']     = { 'val_nm' : 'eth_name', 'val_dflt' : None,  'chk_dup' : True, 'chk_use' : True }
1869     self.tblcfg['FIELD_RENAME']    = { 'val_nm' : 'eth_name', 'val_dflt' : None,  'chk_dup' : True, 'chk_use' : True }
1870     self.tblcfg['IMPORT_TAG']      = { 'val_nm' : 'ttag',     'val_dflt' : (),    'chk_dup' : True, 'chk_use' : False }
1871     self.tblcfg['FN_PARS']         = { 'val_nm' : 'pars',     'val_dflt' : {},    'chk_dup' : True, 'chk_use' : True }
1872     self.tblcfg['TYPE_ATTR']       = { 'val_nm' : 'attr',     'val_dflt' : {},    'chk_dup' : True, 'chk_use' : False }
1873     self.tblcfg['ETYPE_ATTR']      = { 'val_nm' : 'attr',     'val_dflt' : {},    'chk_dup' : True, 'chk_use' : False }
1874     self.tblcfg['FIELD_ATTR']      = { 'val_nm' : 'attr',     'val_dflt' : {},    'chk_dup' : True, 'chk_use' : True }
1875     self.tblcfg['EFIELD_ATTR']     = { 'val_nm' : 'attr',     'val_dflt' : {},    'chk_dup' : True, 'chk_use' : True }
1876
1877
1878     for k in self.tblcfg.keys() :
1879       self.table[k] = {}
1880       self.order[k] = []
1881
1882   def add_item(self, table, key, fn, lineno, **kw):
1883     if self.tblcfg[table]['chk_dup'] and self.table[table].has_key(key):
1884       warnings.warn_explicit("Duplicated %s for %s. Previous one is at %s:%d" % 
1885                              (table, key, self.table[table][key]['fn'], self.table[table][key]['lineno']), 
1886                              UserWarning, fn, lineno)
1887       return
1888     self.table[table][key] = {'fn' : fn, 'lineno' : lineno, 'used' : False}
1889     self.table[table][key].update(kw)
1890     self.order[table].append(key)
1891
1892   def update_item(self, table, key, fn, lineno, **kw):
1893     if not self.table[table].has_key(key):
1894       self.table[table][key] = {'fn' : fn, 'lineno' : lineno, 'used' : False}
1895       self.order[table].append(key)
1896     self.table[table][key][self.tblcfg[table]['val_nm']].update(kw[self.tblcfg[table]['val_nm']])
1897
1898   def get_order(self, table):
1899     return self.order[table]
1900
1901   def check_item(self, table, key):
1902     return self.table[table].has_key(key)
1903
1904   def check_item_value(self, table, key, **kw):
1905     return self.table[table].has_key(key) and self.table[table][key].has_key(kw.get('val_nm', self.tblcfg[table]['val_nm']))
1906
1907   def use_item(self, table, key, **kw):
1908     vdflt = kw.get('val_dflt', self.tblcfg[table]['val_dflt'])
1909     if not self.table[table].has_key(key): return vdflt
1910     vname = kw.get('val_nm', self.tblcfg[table]['val_nm'])
1911     #print "use_item() - set used for %s %s" % (table, key)
1912     self.table[table][key]['used'] = True
1913     return self.table[table][key].get(vname, vdflt)
1914
1915   def omit_assignment(self, type, ident, module):
1916     if self.ectx.conform.use_item('OMIT_ASSIGNMENT', ident): 
1917       return True
1918     if self.ectx.conform.use_item('OMIT_ASSIGNMENT', '*') or \
1919        self.ectx.conform.use_item('OMIT_ASSIGNMENT', '*'+type) or \
1920        self.ectx.conform.use_item('OMIT_ASSIGNMENT', '*/'+module) or \
1921        self.ectx.conform.use_item('OMIT_ASSIGNMENT', '*'+type+'/'+module):
1922       return self.ectx.conform.use_item('NO_OMIT_ASSGN', ident)
1923     return False
1924
1925   def add_fn_line(self, name, ctx, line, fn, lineno):
1926     if not self.fn.has_key(name):
1927       self.fn[name] = {'FN_HDR' : None, 'FN_FTR' : None, 'FN_BODY' : None}
1928     if (self.fn[name][ctx]):
1929       self.fn[name][ctx]['text'] += line
1930     else:
1931       self.fn[name][ctx] = {'text' : line, 'used' : False,
1932                              'fn' : fn, 'lineno' : lineno}
1933   def get_fn_presence(self, name):
1934     #print "get_fn_presence('%s'):%s" % (name, str(self.fn.has_key(name)))
1935     #if self.fn.has_key(name): print self.fn[name]
1936     return self.fn.has_key(name)
1937   def get_fn_body_presence(self, name):
1938     return self.fn.has_key(name) and self.fn[name]['FN_BODY']
1939   def get_fn_text(self, name, ctx):
1940     if (not self.fn.has_key(name)):
1941       return '';
1942     if (not self.fn[name][ctx]):
1943       return '';
1944     self.fn[name][ctx]['used'] = True
1945     out = self.fn[name][ctx]['text']
1946     if (not self.suppress_line): 
1947       out = '#line %u "%s"\n%s\n' % (self.fn[name][ctx]['lineno'], self.fn[name][ctx]['fn'], out);
1948     return out
1949
1950   def add_pdu(self, par, is_new, fn, lineno):
1951     #print "add_pdu(par=%s, %s, %d)" % (str(par), fn, lineno)
1952     (reg, hidden) = (None, False)
1953     if (len(par) > 1): reg = par[1]
1954     if (reg and reg[0]=='@'): (reg, hidden) = (reg[1:], True)
1955     attr = {'new' : is_new, 'reg' : reg, 'hidden' : hidden, 'need_decl' : False}
1956     self.add_item('PDU', par[0], attr=attr, fn=fn, lineno=lineno)
1957     return
1958
1959   def add_register(self, pdu, par, fn, lineno):
1960     #print "add_register(pdu=%s, par=%s, %s, %d)" % (pdu, str(par), fn, lineno)
1961     if (par[0] in ('N', 'NUM')):   rtype = 'NUM'; (pmin, pmax) = (2, 2)
1962     elif (par[0] in ('S', 'STR')): rtype = 'STR'; (pmin, pmax) = (2, 2)
1963     elif (par[0] in ('B', 'BER')): rtype = 'BER'; (pmin, pmax) = (1, 2)
1964     elif (par[0] in ('P', 'PER')): rtype = 'PER'; (pmin, pmax) = (1, 2)
1965     else: warnings.warn_explicit("Unknown registration type '%s'" % (par[2]), UserWarning, fn, lineno); return
1966     if ((len(par)-1) < pmin):
1967       warnings.warn_explicit("Too few parameters for %s registration type. At least %d parameters are required" % (rtype, pmin), UserWarning, fn, lineno)
1968       return
1969     if ((len(par)-1) > pmax):
1970       warnings.warn_explicit("Too many parameters for %s registration type. Only %d parameters are allowed" % (rtype, pmax), UserWarning, fn, lineno)
1971     attr = {'pdu' : pdu, 'rtype' : rtype}
1972     if (rtype in ('NUM', 'STR')): 
1973       attr['rtable'] = par[1]
1974       attr['rport'] = par[2]
1975       rkey = '/'.join([rtype, attr['rtable'], attr['rport']])
1976     elif (rtype in ('BER', 'PER')): 
1977       attr['roid'] = par[1]
1978       attr['roidname'] = '""'
1979       if (len(par)>=3): 
1980         attr['roidname'] = par[2]
1981       elif attr['roid'][0] != '"':
1982         attr['roidname'] = '"' + attr['roid'] + '"'
1983       rkey = '/'.join([rtype, attr['roid']])
1984     self.add_item('REGISTER', rkey, attr=attr, fn=fn, lineno=lineno)
1985
1986   def check_par(self, par, pmin, pmax, fn, lineno):
1987     for i in range(len(par)):
1988       if par[i] == '-':
1989         par[i] = None
1990         continue
1991       if par[i][0] == '#':
1992         par[i:] = []
1993         break
1994     if len(par) < pmin:
1995       warnings.warn_explicit("Too few parameters. At least %d parameters are required" % (pmin), UserWarning, fn, lineno)
1996       return None
1997     if (pmax >= 0) and (len(par) > pmax):
1998       warnings.warn_explicit("Too many parameters. Only %d parameters are allowed" % (pmax), UserWarning, fn, lineno)
1999       return par[0:pmax]
2000     return par
2001
2002   def read(self, fn):
2003     def get_par(line, pmin, pmax, fn, lineno):
2004       par = line.split(None, pmax)
2005       par = self.check_par(par, pmin, pmax, fn, lineno)
2006       return par
2007
2008     def get_par_nm(line, pmin, pmax, fn, lineno):
2009       if pmax:
2010         par = line.split(None, pmax)
2011       else:
2012         par = [line,]
2013       for i in range(len(par)):
2014         if par[i][0] == '#':
2015           par[i:] = []
2016           break
2017       if len(par) < pmin:
2018         warnings.warn_explicit("Too few parameters. At least %d parameters are required" % (pmin), UserWarning, fn, lineno)
2019         return None
2020       if len(par) > pmax:
2021         nmpar = par[pmax]
2022       else:
2023         nmpar = ''
2024       nmpars = {}
2025       nmpar_first = re.compile(r'^\s*(?P<attr>[_A-Z][_A-Z0-9]*)\s*=\s*')
2026       nmpar_next = re.compile(r'\s+(?P<attr>[_A-Z][_A-Z0-9]*)\s*=\s*')
2027       nmpar_end = re.compile(r'\s*$')
2028       result = nmpar_first.search(nmpar)
2029       pos = 0
2030       while result:
2031         k = result.group('attr')
2032         pos = result.end()
2033         result = nmpar_next.search(nmpar, pos)
2034         p1 = pos
2035         if result:
2036           p2 = result.start()
2037         else:
2038           p2 = nmpar_end.search(nmpar, pos).start()
2039         v = nmpar[p1:p2]
2040         nmpars[k] = v
2041       if len(par) > pmax:
2042         par[pmax] = nmpars
2043       return par
2044
2045     f = open(fn, "r")
2046     directive = re.compile(r'^\s*#\.(?P<name>[A-Z_]+)\s+')
2047     comment = re.compile(r'^\s*#[^.]')
2048     empty = re.compile(r'^\s*$')
2049     lineno = 0
2050     ctx = None
2051     name = ''
2052     default_flags = 0x00
2053     stack = []
2054     while 1:
2055       if not f.closed:
2056         line = f.readline()
2057         lineno += 1
2058       else:
2059         line = None
2060       if not line:
2061         if not f.closed:
2062           f.close()
2063         if stack:
2064           frec = stack.pop()
2065           fn, f, lineno = frec['fn'], frec['f'], frec['lineno']
2066           continue
2067         else: 
2068           break
2069       if comment.search(line): continue
2070       result = directive.search(line)
2071       if result:  # directive
2072         if result.group('name') == 'END_OF_CNF':
2073           f.close()
2074         elif result.group('name') == 'OPT':
2075           ctx = result.group('name')
2076           par = get_par(line[result.end():], 0, -1, fn=fn, lineno=lineno)
2077           if not par: continue
2078           self.set_opt(par[0], par[1:], fn, lineno)
2079           ctx = None
2080         elif result.group('name') in ('PDU', 'PDU_NEW', 'REGISTER', 'REGISTER_NEW', 
2081                                     'MODULE', 'MODULE_IMPORT', 
2082                                     'OMIT_ASSIGNMENT', 'NO_OMIT_ASSGN', 
2083                                     'VIRTUAL_ASSGN', 'SET_TYPE',
2084                                     'TYPE_RENAME', 'FIELD_RENAME', 'TF_RENAME', 'IMPORT_TAG',
2085                                     'TYPE_ATTR', 'ETYPE_ATTR', 'FIELD_ATTR', 'EFIELD_ATTR'):
2086           ctx = result.group('name')
2087         elif result.group('name') in ('OMIT_ALL_ASSIGNMENTS', 'OMIT_ASSIGNMENTS_EXCEPT',
2088                                       'OMIT_ALL_TYPE_ASSIGNMENTS', 'OMIT_TYPE_ASSIGNMENTS_EXCEPT',
2089                                       'OMIT_ALL_VALUE_ASSIGNMENTS', 'OMIT_VALUE_ASSIGNMENTS_EXCEPT'):
2090           ctx = result.group('name')
2091           key = '*'
2092           if ctx in ('OMIT_ALL_TYPE_ASSIGNMENTS', 'OMIT_TYPE_ASSIGNMENTS_EXCEPT'):
2093             key += 'T'
2094           if ctx in ('OMIT_ALL_VALUE_ASSIGNMENTS', 'OMIT_VALUE_ASSIGNMENTS_EXCEPT'):
2095             key += 'V'
2096           par = get_par(line[result.end():], 0, 1, fn=fn, lineno=lineno)
2097           if par: 
2098             key += '/' + par[0]
2099           self.add_item('OMIT_ASSIGNMENT', key, omit=True, fn=fn, lineno=lineno)
2100           if ctx in ('OMIT_ASSIGNMENTS_EXCEPT', 'OMIT_TYPE_ASSIGNMENTS_EXCEPT', 'OMIT_VALUE_ASSIGNMENTS_EXCEPT'):
2101             ctx = 'NO_OMIT_ASSGN'
2102           else:
2103             ctx = None
2104         elif result.group('name') in ('EXPORTS', 'USER_DEFINED', 'NO_EMIT'):
2105           ctx = result.group('name')
2106           default_flags = EF_TYPE|EF_VALS
2107           if ctx == 'EXPORTS':
2108             par = get_par(line[result.end():], 0, 5, fn=fn, lineno=lineno)
2109           else:
2110             par = get_par(line[result.end():], 0, 1, fn=fn, lineno=lineno)
2111           if not par: continue
2112           p = 1
2113           if (par[0] == 'WITH_VALS'):      default_flags |= EF_TYPE|EF_VALS
2114           elif (par[0] == 'WITHOUT_VALS'): default_flags |= EF_TYPE; default_flags &= ~EF_TYPE
2115           elif (par[0] == 'ONLY_VALS'):    default_flags &= ~EF_TYPE; default_flags |= EF_VALS
2116           elif (ctx == 'EXPORTS'): p = 0
2117           else: warnings.warn_explicit("Unknown parameter value '%s'" % (par[0]), UserWarning, fn, lineno)
2118           for i in range(p, len(par)):
2119             if (par[i] == 'ONLY_ENUM'):   default_flags &= ~(EF_TYPE|EF_VALS); default_flags |= EF_ENUM
2120             elif (par[i] == 'WITH_ENUM'): default_flags |= EF_ENUM
2121             elif (par[i] == 'VALS_WITH_TABLE'):  default_flags |= EF_TABLE
2122             elif (par[i] == 'WS_VAR'):    default_flags |= EF_WS_VAR
2123             elif (par[i] == 'EXTERN'):    default_flags |= EF_EXTERN
2124             elif (par[i] == 'NO_PROT_PREFIX'): default_flags |= EF_NO_PROT
2125             else: warnings.warn_explicit("Unknown parameter value '%s'" % (par[i]), UserWarning, fn, lineno)
2126         elif result.group('name') in ('MAKE_ENUM', 'MAKE_DEFINES'):
2127           ctx = result.group('name')
2128           default_flags = EF_ENUM
2129           if ctx == 'MAKE_ENUM': default_flags |= EF_NO_PROT|EF_NO_TYPE
2130           if ctx == 'MAKE_DEFINES': default_flags |= EF_DEFINE|EF_UCASE|EF_NO_TYPE
2131           par = get_par(line[result.end():], 0, 3, fn=fn, lineno=lineno)
2132           for i in range(0, len(par)):
2133             if (par[i] == 'NO_PROT_PREFIX'):   default_flags |= EF_NO_PROT
2134             elif (par[i] == 'NO_TYPE_PREFIX'): default_flags |= EF_NO_TYPE
2135             elif (par[i] == 'UPPER_CASE'):     default_flags |= EF_UCASE
2136             elif (par[i] == 'NO_UPPER_CASE'):  default_flags &= ~EF_UCASE
2137             else: warnings.warn_explicit("Unknown parameter value '%s'" % (par[i]), UserWarning, fn, lineno)
2138         elif result.group('name') in ('FN_HDR', 'FN_FTR'):
2139           par = get_par(line[result.end():], 1, 1, fn=fn, lineno=lineno)
2140           if not par: continue
2141           ctx = result.group('name')
2142           name = par[0]
2143         elif result.group('name') == 'FN_BODY':
2144           par = get_par_nm(line[result.end():], 1, 1, fn=fn, lineno=lineno)
2145           if not par: continue
2146           ctx = result.group('name')
2147           name = par[0]
2148           if len(par) > 1:
2149             self.add_item('FN_PARS', name, pars=par[1], fn=fn, lineno=lineno)
2150         elif result.group('name') == 'FN_PARS':
2151           par = get_par_nm(line[result.end():], 0, 1, fn=fn, lineno=lineno)
2152           ctx = result.group('name')
2153           if not par:
2154             name = None
2155           elif len(par) == 1:
2156             name = par[0]
2157             self.add_item(ctx, name, pars={}, fn=fn, lineno=lineno)
2158           elif len(par) > 1:
2159             self.add_item(ctx, par[0], pars=par[1], fn=fn, lineno=lineno)
2160             ctx = None
2161         elif result.group('name') == 'CLASS':
2162           par = get_par(line[result.end():], 1, 1, fn=fn, lineno=lineno)
2163           if not par: continue
2164           ctx = result.group('name')
2165           name = par[0]
2166           add_class_ident(name)
2167           if not name.isupper():
2168             warnings.warn_explicit("No lower-case letters shall be included in information object class name (%s)" % (name),
2169                                     UserWarning, fn, lineno)
2170         elif result.group('name') == 'INCLUDE':
2171           par = get_par(line[result.end():], 1, 1, fn=fn, lineno=lineno)
2172           if not par: 
2173             warnings.warn_explicit("INCLUDE requires parameter", UserWarning, fn, lineno)
2174             continue
2175           fname = par[0]
2176           #print "Try include: %s" % (fname)
2177           if (not os.path.exists(fname)):
2178             fname = os.path.join(os.path.split(fn)[0], par[0])
2179           #print "Try include: %s" % (fname)
2180           i = 0
2181           while not os.path.exists(fname) and (i < len(self.include_path)):
2182             fname = os.path.join(self.include_path[i], par[0])
2183             #print "Try include: %s" % (fname)
2184             i += 1
2185           if (not os.path.exists(fname)):
2186             fname = par[0]
2187           fnew = open(fname, "r")
2188           stack.append({'fn' : fn, 'f' : f, 'lineno' : lineno})
2189           fn, f, lineno = par[0], fnew, 0
2190         elif result.group('name') == 'END':
2191           ctx = None
2192         else:
2193           warnings.warn_explicit("Unknown directive '%s'" % (result.group('name')), UserWarning, fn, lineno)
2194         continue
2195       if not ctx:
2196         if not empty.match(line):
2197           warnings.warn_explicit("Non-empty line in empty context", UserWarning, fn, lineno)
2198       elif ctx == 'OPT':
2199         if empty.match(line): continue
2200         par = get_par(line, 1, -1, fn=fn, lineno=lineno)
2201         if not par: continue
2202         self.set_opt(par[0], par[1:], fn, lineno)
2203       elif ctx in ('EXPORTS', 'USER_DEFINED', 'NO_EMIT'):
2204         if empty.match(line): continue
2205         if ctx == 'EXPORTS':
2206           par = get_par(line, 1, 6, fn=fn, lineno=lineno)
2207         else:
2208           par = get_par(line, 1, 2, fn=fn, lineno=lineno)
2209         if not par: continue
2210         flags = default_flags
2211         p = 2
2212         if (len(par)>=2):
2213           if (par[1] == 'WITH_VALS'):      flags |= EF_TYPE|EF_VALS
2214           elif (par[1] == 'WITHOUT_VALS'): flags |= EF_TYPE; flags &= ~EF_TYPE
2215           elif (par[1] == 'ONLY_VALS'):    flags &= ~EF_TYPE; flags |= EF_VALS
2216           elif (ctx == 'EXPORTS'): p = 1
2217           else: warnings.warn_explicit("Unknown parameter value '%s'" % (par[1]), UserWarning, fn, lineno)
2218         for i in range(p, len(par)):
2219           if (par[i] == 'ONLY_ENUM'):        flags &= ~(EF_TYPE|EF_VALS); flags |= EF_ENUM
2220           elif (par[i] == 'WITH_ENUM'):      flags |= EF_ENUM
2221           elif (par[i] == 'VALS_WITH_TABLE'):  flags |= EF_TABLE
2222           elif (par[i] == 'WS_VAR'):         flags |= EF_WS_VAR
2223           elif (par[i] == 'EXTERN'):         flags |= EF_EXTERN
2224           elif (par[i] == 'NO_PROT_PREFIX'): flags |= EF_NO_PROT
2225           else: warnings.warn_explicit("Unknown parameter value '%s'" % (par[i]), UserWarning, fn, lineno)
2226         self.add_item(ctx, par[0], flag=flags, fn=fn, lineno=lineno)
2227       elif ctx in ('MAKE_ENUM', 'MAKE_DEFINES'):
2228         if empty.match(line): continue
2229         par = get_par(line, 1, 4, fn=fn, lineno=lineno)
2230         if not par: continue
2231         flags = default_flags
2232         for i in range(1, len(par)):
2233           if (par[i] == 'NO_PROT_PREFIX'):   flags |= EF_NO_PROT
2234           elif (par[i] == 'NO_TYPE_PREFIX'): flags |= EF_NO_TYPE
2235           elif (par[i] == 'UPPER_CASE'):     flags |= EF_UCASE
2236           elif (par[i] == 'NO_UPPER_CASE'):  flags &= ~EF_UCASE
2237           else: warnings.warn_explicit("Unknown parameter value '%s'" % (par[i]), UserWarning, fn, lineno)
2238         self.add_item('MAKE_ENUM', par[0], flag=flags, fn=fn, lineno=lineno)
2239       elif ctx in ('PDU', 'PDU_NEW'):
2240         if empty.match(line): continue
2241         par = get_par(line, 1, 5, fn=fn, lineno=lineno)
2242         if not par: continue
2243         is_new = False
2244         if (ctx == 'PDU_NEW'): is_new = True
2245         self.add_pdu(par[0:2], is_new, fn, lineno)
2246         if (len(par)>=3):
2247           self.add_register(par[0], par[2:5], fn, lineno)
2248       elif ctx in ('REGISTER', 'REGISTER_NEW'):
2249         if empty.match(line): continue
2250         par = get_par(line, 3, 4, fn=fn, lineno=lineno)
2251         if not par: continue
2252         if not self.check_item('PDU', par[0]):
2253           is_new = False
2254           if (ctx == 'REGISTER_NEW'): is_new = True
2255           self.add_pdu(par[0:1], is_new, fn, lineno)
2256         self.add_register(par[0], par[1:4], fn, lineno)
2257       elif ctx in ('MODULE', 'MODULE_IMPORT'):
2258         if empty.match(line): continue
2259         par = get_par(line, 2, 2, fn=fn, lineno=lineno)
2260         if not par: continue
2261         self.add_item('MODULE', par[0], proto=par[1], fn=fn, lineno=lineno)
2262       elif ctx == 'IMPORT_TAG':
2263         if empty.match(line): continue
2264         par = get_par(line, 3, 3, fn=fn, lineno=lineno)
2265         if not par: continue
2266         self.add_item(ctx, par[0], ttag=(par[1], par[2]), fn=fn, lineno=lineno)
2267       elif ctx == 'OMIT_ASSIGNMENT':
2268         if empty.match(line): continue
2269         par = get_par(line, 1, 1, fn=fn, lineno=lineno)
2270         if not par: continue
2271         self.add_item(ctx, par[0], omit=True, fn=fn, lineno=lineno)
2272       elif ctx == 'NO_OMIT_ASSGN':
2273         if empty.match(line): continue
2274         par = get_par(line, 1, 1, fn=fn, lineno=lineno)
2275         if not par: continue
2276         self.add_item(ctx, par[0], omit=False, fn=fn, lineno=lineno)
2277       elif ctx == 'VIRTUAL_ASSGN':
2278         if empty.match(line): continue
2279         par = get_par(line, 2, -1, fn=fn, lineno=lineno)
2280         if not par: continue
2281         if (len(par[1].split('/')) > 1) and not self.check_item('SET_TYPE', par[1]):
2282           self.add_item('SET_TYPE', par[1], type=par[0], fn=fn, lineno=lineno)
2283         self.add_item('VIRTUAL_ASSGN', par[1], name=par[0], fn=fn, lineno=lineno)
2284         for nm in par[2:]:
2285           self.add_item('SET_TYPE', nm, type=par[0], fn=fn, lineno=lineno)
2286         if not par[0][0].isupper():
2287           warnings.warn_explicit("Virtual assignment should have uppercase name (%s)" % (par[0]),
2288                                   UserWarning, fn, lineno)
2289       elif ctx == 'SET_TYPE':
2290         if empty.match(line): continue
2291         par = get_par(line, 2, 2, fn=fn, lineno=lineno)
2292         if not par: continue
2293         if not self.check_item('VIRTUAL_ASSGN', par[0]):
2294           self.add_item('SET_TYPE', par[0], type=par[1], fn=fn, lineno=lineno)
2295         if not par[1][0].isupper():
2296           warnings.warn_explicit("Set type should have uppercase name (%s)" % (par[1]),
2297                                   UserWarning, fn, lineno)
2298       elif ctx == 'TYPE_RENAME':
2299         if empty.match(line): continue
2300         par = get_par(line, 2, 2, fn=fn, lineno=lineno)
2301         if not par: continue
2302         self.add_item('TYPE_RENAME', par[0], eth_name=par[1], fn=fn, lineno=lineno)
2303         if not par[1][0].isupper():
2304           warnings.warn_explicit("Type should be renamed to uppercase name (%s)" % (par[1]),
2305                                   UserWarning, fn, lineno)
2306       elif ctx == 'FIELD_RENAME':
2307         if empty.match(line): continue
2308         par = get_par(line, 2, 2, fn=fn, lineno=lineno)
2309         if not par: continue
2310         self.add_item('FIELD_RENAME', par[0], eth_name=par[1], fn=fn, lineno=lineno)
2311         if not par[1][0].islower():
2312           warnings.warn_explicit("Field should be renamed to lowercase name (%s)" % (par[1]),
2313                                   UserWarning, fn, lineno)
2314       elif ctx == 'TF_RENAME':
2315         if empty.match(line): continue
2316         par = get_par(line, 2, 2, fn=fn, lineno=lineno)
2317         if not par: continue
2318         tmpu = par[1][0].upper() + par[1][1:]
2319         tmpl = par[1][0].lower() + par[1][1:]
2320         self.add_item('TYPE_RENAME', par[0], eth_name=tmpu, fn=fn, lineno=lineno)
2321         if not tmpu[0].isupper():
2322           warnings.warn_explicit("Type should be renamed to uppercase name (%s)" % (par[1]),
2323                                   UserWarning, fn, lineno)
2324         self.add_item('FIELD_RENAME', par[0], eth_name=tmpl, fn=fn, lineno=lineno)
2325         if not tmpl[0].islower():
2326           warnings.warn_explicit("Field should be renamed to lowercase name (%s)" % (par[1]),
2327                                   UserWarning, fn, lineno)
2328       elif ctx in ('TYPE_ATTR', 'ETYPE_ATTR', 'FIELD_ATTR', 'EFIELD_ATTR'):
2329         if empty.match(line): continue
2330         par = get_par_nm(line, 1, 1, fn=fn, lineno=lineno)
2331         if not par: continue
2332         self.add_item(ctx, par[0], attr=par[1], fn=fn, lineno=lineno)
2333       elif ctx == 'FN_PARS':
2334         if empty.match(line): continue
2335         if name:
2336           par = get_par_nm(line, 0, 0, fn=fn, lineno=lineno)
2337         else:
2338           par = get_par_nm(line, 1, 1, fn=fn, lineno=lineno)
2339         if not par: continue
2340         if name:
2341           self.update_item(ctx, name, pars=par[0], fn=fn, lineno=lineno)
2342         else:
2343           self.add_item(ctx, par[0], pars=par[1], fn=fn, lineno=lineno)
2344       elif ctx in ('FN_HDR', 'FN_FTR', 'FN_BODY'):
2345         self.add_fn_line(name, ctx, line, fn=fn, lineno=lineno)
2346       elif ctx == 'CLASS':
2347         if empty.match(line): continue
2348         par = get_par(line, 1, 3, fn=fn, lineno=lineno)
2349         if not par: continue
2350         if (len(par) < 2): par.append('OpenType')
2351         if (len(par) < 3): par.append(None)
2352         if not set_type_to_class(name, par[0], par[1], par[2]):
2353           warnings.warn_explicit("Could not set type of class member %s.&%s to %s" % (name, par[0], par[1]),
2354                                   UserWarning, fn, lineno)
2355
2356   def set_opt(self, opt, par, fn, lineno):
2357     #print "set_opt: %s, %s" % (opt, par)
2358     if opt in ("-I",):
2359       par = self.check_par(par, 1, 1, fn, lineno)
2360       if not par: return
2361       self.include_path.append(par[0])
2362     elif opt in ("-b", "BER", "CER", "DER"):
2363       par = self.check_par(par, 0, 0, fn, lineno)
2364       self.ectx.encoding = 'ber'
2365     elif opt in ("-X", "NEW_BER"):
2366       par = self.check_par(par, 0, 0, fn, lineno)
2367       self.ectx.new_ber = True
2368     elif opt in ("PER",):
2369       par = self.check_par(par, 0, 0, fn, lineno)
2370       self.ectx.encoding = 'per'
2371     elif opt in ("-p", "PROTO"):
2372       par = self.check_par(par, 1, 1, fn, lineno)
2373       if not par: return
2374       self.ectx.proto_opt = par[0]
2375       self.ectx.merge_modules = True
2376     elif opt in ("-F", "CREATE_FIELDS"):
2377       par = self.check_par(par, 0, 1, fn, lineno)
2378       tnm = '*'
2379       if (len(par) > 0): tnm = par[0]
2380       self.ectx.fld_opt[tnm] = True
2381     elif opt in ("-T",):
2382       par = self.check_par(par, 0, 0, fn, lineno)
2383       self.ectx.tag_opt = True
2384     elif opt in ("ALIGNED",):
2385       par = self.check_par(par, 0, 0, fn, lineno)
2386       self.ectx.aligned = True
2387     elif opt in ("-u", "UNALIGNED"):
2388       par = self.check_par(par, 0, 0, fn, lineno)
2389       self.ectx.aligned = False
2390     elif opt in ("-d",):
2391       par = self.check_par(par, 1, 1, fn, lineno)
2392       if not par: return
2393       self.ectx.dbgopt = par[0]
2394     elif opt in ("-e",):
2395       par = self.check_par(par, 0, 0, fn, lineno)
2396       self.ectx.expcnf = True
2397     elif opt in ("-S",):
2398       par = self.check_par(par, 0, 0, fn, lineno)
2399       self.ectx.merge_modules = True
2400     elif opt in ("-o",):
2401       par = self.check_par(par, 1, 1, fn, lineno)
2402       if not par: return
2403       self.ectx.outnm_opt = par[0]
2404     elif opt in ("-O",):
2405       par = self.check_par(par, 1, 1, fn, lineno)
2406       if not par: return
2407       self.ectx.output.outdir = par[0]
2408     elif opt in ("-s",):
2409       par = self.check_par(par, 1, 1, fn, lineno)
2410       if not par: return
2411       self.ectx.output.single_file = par[0]
2412     elif opt in ("-k",):
2413       par = self.check_par(par, 0, 0, fn, lineno)
2414       self.ectx.output.keep = True
2415     elif opt in ("-L",):
2416       par = self.check_par(par, 0, 0, fn, lineno)
2417       self.suppress_line = True
2418     elif opt in ("EXTERNAL_TYPE_CB",):
2419       par = self.check_par(par, 1, 1, fn, lineno)
2420       if not par: return
2421       self.ectx.default_external_type_cb = par[0]
2422     else:
2423       warnings.warn_explicit("Unknown option %s" % (opt),
2424                              UserWarning, fn, lineno)
2425
2426   def dbg_print(self):
2427     print "\n# Conformance values"
2428     print "%-15s %-4s %-15s %-20s %s" % ("File", "Line", "Table", "Key", "Value")
2429     print "-" * 100
2430     tbls = self.table.keys()
2431     tbls.sort()
2432     for t in tbls:
2433       keys = self.table[t].keys()
2434       keys.sort()
2435       for k in keys:
2436         print "%-15s %4s %-15s %-20s %s" % (
2437               self.table[t][k]['fn'], self.table[t][k]['lineno'], t, k, str(self.table[t][k][self.tblcfg[t]['val_nm']]))
2438
2439   def unused_report(self):
2440     tbls = self.table.keys()
2441     tbls.sort()
2442     for t in tbls:
2443       if not self.tblcfg[t]['chk_use']: continue
2444       keys = self.table[t].keys()
2445       keys.sort()
2446       for k in keys:
2447         if not self.table[t][k]['used']:
2448           warnings.warn_explicit("Unused %s for %s" % (t, k),
2449                                   UserWarning, self.table[t][k]['fn'], self.table[t][k]['lineno'])
2450     fnms = self.fn.keys()
2451     fnms.sort()
2452     for f in fnms:
2453       keys = self.fn[f].keys()
2454       keys.sort()
2455       for k in keys:
2456         if not self.fn[f][k]: continue
2457         if not self.fn[f][k]['used']:
2458           warnings.warn_explicit("Unused %s for %s" % (k, f),
2459                                   UserWarning, self.fn[f][k]['fn'], self.fn[f][k]['lineno'])
2460
2461 #--- EthOut -------------------------------------------------------------------
2462 class EthOut:
2463   def __init__(self):
2464     self.ectx = None
2465     self.outnm = None
2466     self.outdir = '.'
2467     self.single_file = None
2468     self.created_files = {}
2469     self.created_files_ord = []
2470     self.keep = False
2471
2472   def outcomment(self, ln, comment=None):
2473     if comment:
2474       return '%s %s\n' % (comment, ln)
2475     else:
2476       return '/* %-74s */\n' % (ln)
2477
2478   def created_file_add(self, name, keep_anyway):
2479     name = os.path.normcase(os.path.abspath(name))
2480     if not self.created_files.has_key(name):
2481       self.created_files_ord.append(name)
2482       self.created_files[name] = keep_anyway
2483     else:
2484       self.created_files[name] = self.created_files[name] or keep_anyway
2485
2486   def created_file_exists(self, name):
2487     name = os.path.normcase(os.path.abspath(name))
2488     return self.created_files.has_key(name)
2489
2490   #--- output_fname -------------------------------------------------------
2491   def output_fname(self, ftype, ext='c'):
2492     fn = ''
2493     if not ext in ('cnf',):
2494       fn += 'packet-' 
2495     fn += self.outnm
2496     if (ftype):
2497       fn += '-' + ftype
2498     fn += '.' + ext
2499     return fn
2500   #--- output_fullname -------------------------------------------------------
2501   def output_fullname(self, ftype, ext='c'):
2502     return os.path.join(self.outdir, self.output_fname(ftype, ext=ext))
2503   #--- file_open -------------------------------------------------------
2504   def file_open(self, ftype, ext='c'):
2505     fn = self.output_fullname(ftype, ext=ext)
2506     if self.created_file_exists(fn):
2507       fx = file(fn, 'a')
2508     else:
2509       fx = file(fn, 'w')
2510     comment = None
2511     if ext in ('cnf',):
2512       comment = '#'
2513       fx.write(self.fhdr(fn, comment = comment))
2514     else:
2515       if (not self.single_file and not self.created_file_exists(fn)):
2516         fx.write(self.fhdr(fn))
2517     if not self.ectx.merge_modules:
2518       fx.write('\n')
2519       fx.write(self.outcomment("--- Module %s --- --- ---" % (self.ectx.Module()), comment))
2520       fx.write('\n')
2521     return fx
2522   #--- file_close -------------------------------------------------------
2523   def file_close(self, fx, discard=False, keep_anyway=False):
2524     fx.close()
2525     if discard and not self.created_file_exists(fx.name): 
2526       os.unlink(fx.name)
2527     else:
2528       self.created_file_add(fx.name, keep_anyway)
2529   #--- fhdr -------------------------------------------------------
2530   def fhdr(self, fn, comment=None):
2531     out = ''
2532     out += self.outcomment('Do not modify this file.', comment)
2533     out += self.outcomment('It is created automatically by the ASN.1 to Wireshark dissector compiler', comment)
2534     out += self.outcomment(fn, comment)
2535     out += self.outcomment(' '.join(sys.argv), comment)
2536     out += '\n'
2537     return out
2538
2539   #--- dbg_print -------------------------------------------------------
2540   def dbg_print(self):
2541     print "\n# Output files"
2542     print "\n".join(self.created_files_ord)
2543     print "\n"
2544
2545   #--- make_single_file -------------------------------------------------------
2546   def make_single_file(self):
2547     if (not self.single_file): return
2548     in_nm = self.single_file + '.c'
2549     out_nm = self.output_fullname('')
2550     self.do_include(out_nm, in_nm)
2551     in_nm = self.single_file + '.h'
2552     if (os.path.exists(in_nm)):
2553       out_nm = self.output_fullname('', ext='h')
2554       self.do_include(out_nm, in_nm)
2555     if (not self.keep):
2556       for fn in self.created_files_ord:
2557         if not self.created_files[fn]:
2558           os.unlink(fn)
2559
2560   #--- do_include -------------------------------------------------------
2561   def do_include(self, out_nm, in_nm):
2562     def check_file(fn, fnlist):
2563       fnfull = os.path.normcase(os.path.abspath(fn))
2564       if (fnlist.has_key(fnfull) and os.path.exists(fnfull)):
2565         return os.path.normpath(fn)
2566       return None
2567     fin = file(in_nm, "r")
2568     fout = file(out_nm, "w")
2569     fout.write(self.fhdr(out_nm))
2570     fout.write('/* Input file: ' + in_nm +' */\n')
2571     fout.write('\n')
2572     fout.write('#line 1 "%s"\n' % (in_nm))
2573
2574     include = re.compile(r'^\s*#\s*include\s+[<"](?P<fname>[^>"]+)[>"]', re.IGNORECASE)
2575
2576     cont_linenum = 0;
2577
2578     while (True):
2579       cont_linenum = cont_linenum + 1;
2580       line = fin.readline()
2581       if (line == ''): break
2582       ifile = None
2583       result = include.search(line)
2584       #if (result): print os.path.normcase(os.path.abspath(result.group('fname')))
2585       if (result):
2586         ifile = check_file(os.path.join(os.path.split(in_nm)[0], result.group('fname')), self.created_files)
2587         if (not ifile):
2588           ifile = check_file(os.path.join(self.outdir, result.group('fname')), self.created_files)
2589         if (not ifile):
2590           ifile = check_file(result.group('fname'), self.created_files)
2591       if (ifile):
2592         fout.write('\n')
2593         fout.write('/*--- Included file: ' + ifile + ' ---*/\n')
2594         fout.write('#line 1 "' + ifile + '"\n')
2595         finc = file(ifile, "r")
2596         fout.write(finc.read())
2597         fout.write('\n')
2598         fout.write('/*--- End of included file: ' + ifile + ' ---*/\n')
2599         fout.write('#line %i "%s"\n' % (cont_linenum+1,in_nm) )
2600         finc.close()
2601       else:
2602         fout.write(line)
2603
2604     fout.close()
2605     fin.close()
2606
2607
2608 #--- Node ---------------------------------------------------------------------
2609 class Node:
2610     def __init__(self,*args, **kw):
2611         if len (args) == 0:
2612             self.type = self.__class__.__name__
2613         else:
2614             assert (len(args) == 1)
2615             self.type = args[0]
2616         self.__dict__.update (kw)
2617     def str_child (self, key, child, depth):
2618         indent = " " * (2 * depth)
2619         keystr = indent + key + ": "
2620         if key == 'type': # already processed in str_depth
2621             return ""
2622         if isinstance (child, Node): # ugh
2623             return keystr + "\n" + child.str_depth (depth+1)
2624         if type (child) == type ([]):
2625             l = []
2626             for x in child:
2627               if isinstance (x, Node):
2628                 l.append (x.str_depth (depth+1))
2629               else:
2630                 l.append (indent + "  " + str(x) + "\n")
2631             return keystr + "[\n" + ''.join(l) + indent + "]\n"
2632         else:
2633             return keystr + str (child) + "\n"
2634     def str_depth (self, depth): # ugh
2635         indent = " " * (2 * depth)
2636         l = ["%s%s" % (indent, self.type)]
2637         l.append ("".join (map (lambda (k,v): self.str_child (k, v, depth + 1),
2638                                 self.__dict__.items ())))
2639         return "\n".join (l)
2640     def __str__(self):
2641         return "\n" + self.str_depth (0)
2642     def to_python (self, ctx):
2643         return self.str_depth (ctx.indent_lev)
2644
2645     def eth_reg(self, ident, ectx):
2646         pass
2647
2648 #--- value_assign -------------------------------------------------------------
2649 class value_assign (Node):
2650   def __init__(self,*args, **kw) :
2651     Node.__init__ (self,*args, **kw)
2652
2653   def eth_reg(self, ident, ectx):
2654     if ectx.conform.omit_assignment('V', self.ident, ectx.Module()): return # Assignment to omit
2655     ectx.eth_reg_vassign(self)
2656     ectx.eth_reg_value(self.ident, self.typ, self.val)
2657
2658
2659 #--- Type ---------------------------------------------------------------------
2660 class Type (Node):
2661   def __init__(self,*args, **kw) :
2662     self.name = None
2663     self.constr = None
2664     self.tags = []
2665     Node.__init__ (self,*args, **kw)
2666
2667   def IsNamed(self):
2668     if self.name is None :
2669       return False
2670     else:
2671       return True
2672
2673   def HasConstraint(self):
2674     if self.constr is None :
2675       return False
2676     else :
2677       return True
2678
2679   def HasSizeConstraint(self):
2680     return self.HasConstraint() and self.constr.IsSize()
2681
2682   def HasValueConstraint(self):
2683     return self.HasConstraint() and self.constr.IsValue()
2684
2685   def HasPermAlph(self):
2686     return self.HasConstraint() and self.constr.IsPermAlph()
2687
2688   def HasContentsConstraint(self):
2689     return self.HasConstraint() and self.constr.IsContents()
2690
2691   def HasOwnTag(self):
2692     return len(self.tags) > 0
2693
2694   def HasImplicitTag(self, ectx):
2695     return (self.HasOwnTag() and self.tags[0].IsImplicit(ectx))
2696
2697   def IndetermTag(self, ectx):
2698     return False
2699
2700   def AddTag(self, tag):
2701     self.tags[0:0] = [tag]
2702
2703   def GetTag(self, ectx):
2704     #print "GetTag(%s)\n" % self.name;
2705     if (self.HasOwnTag()):
2706       return self.tags[0].GetTag(ectx)
2707     else:
2708       return self.GetTTag(ectx)
2709
2710   def GetTTag(self, ectx):
2711     print "#Unhandled  GetTTag() in %s" % (self.type)
2712     print self.str_depth(1)
2713     return ('BER_CLASS_unknown', 'TAG_unknown')
2714
2715   def SetName(self, name):
2716     self.name = name
2717
2718   def AddConstraint(self, constr):
2719     if not self.HasConstraint():
2720       self.constr = constr
2721     else:
2722       self.constr = Constraint(type = 'Intersection', subtype = [self.constr, constr])
2723
2724   def eth_tname(self):
2725     return '#' + self.type + '_' + str(id(self))
2726
2727   def eth_ftype(self, ectx):
2728     return ('FT_NONE', 'BASE_NONE')
2729
2730   def eth_strings(self):
2731     return 'NULL'
2732
2733   def eth_need_tree(self):
2734     return False
2735
2736   def eth_has_vals(self):
2737     return False
2738
2739   def eth_has_enum(self, tname, ectx):
2740     return self.eth_has_vals() and (ectx.eth_type[tname]['enum'] & EF_ENUM)
2741
2742   def eth_need_pdu(self, ectx):
2743     return None
2744
2745   def eth_named_bits(self):
2746     return None
2747
2748   def eth_reg_sub(self, ident, ectx):
2749     pass
2750
2751   def get_components(self, ectx):
2752     print "#Unhandled  get_components() in %s" % (self.type)
2753     print self.str_depth(1)
2754     return []
2755
2756   def sel_req(self, sel, ectx):
2757     print "#Selection '%s' required for non-CHOICE type %s" % (sel, self.type)
2758     print self.str_depth(1)
2759     
2760   def eth_reg(self, ident, ectx, tstrip=0, tagflag=False, selflag=False, idx='', parent=None):
2761     #print "eth_reg(): %s, ident=%s, tstrip=%d, tagflag=%s, selflag=%s, parent=%s" %(self.type, ident, tstrip, str(tagflag), str(selflag), str(parent))
2762     if (ectx.Tag() and (len(self.tags) > tstrip)):
2763       tagged_type = TaggedType(val=self, tstrip=tstrip)
2764       tagged_type.AddTag(self.tags[tstrip])
2765       if not tagflag:  # 1st tagged level
2766         if self.IsNamed() and not selflag:
2767           tagged_type.SetName(self.name)
2768       tagged_type.eth_reg(ident, ectx, tstrip=1, tagflag=tagflag, idx=idx, parent=parent)
2769       return
2770     nm = ''
2771     if ident and self.IsNamed() and not tagflag and not selflag:
2772       nm = ident + '/' + self.name
2773     elif ident:
2774       nm = ident
2775     elif self.IsNamed():
2776       nm = self.name
2777     if not ident and ectx.conform.omit_assignment('T', nm, ectx.Module()): return # Assignment to omit
2778     if not ident:  # Assignment
2779       ectx.eth_reg_assign(nm, self)
2780       if self.type == 'Type_Ref':
2781         ectx.eth_reg_type(nm, self)
2782       if (ectx.conform.check_item('PDU', nm)):
2783         ectx.eth_reg_field(nm, nm, impl=self.HasImplicitTag(ectx), pdu=ectx.conform.use_item('PDU', nm))
2784     virtual_tr = Type_Ref(val=ectx.conform.use_item('SET_TYPE', nm))
2785     if (self.type == 'Type_Ref') or ectx.conform.check_item('SET_TYPE', nm):
2786       if ident and (ectx.conform.check_item('TYPE_RENAME', nm) or ectx.conform.get_fn_presence(nm)):
2787         if ectx.conform.check_item('SET_TYPE', nm):
2788           ectx.eth_reg_type(nm, virtual_tr)  # dummy Type Reference
2789         else:
2790           ectx.eth_reg_type(nm, self)  # new type
2791         trnm = nm
2792       elif ectx.conform.check_item('SET_TYPE', nm):
2793         trnm = ectx.conform.use_item('SET_TYPE', nm)
2794       else:
2795         trnm = self.val
2796     else:
2797       ectx.eth_reg_type(nm, self)
2798       trnm = nm
2799     if ectx.conform.check_item('VIRTUAL_ASSGN', nm):
2800       vnm = ectx.conform.use_item('VIRTUAL_ASSGN', nm)
2801       ectx.eth_reg_assign(vnm, self, virt=True)
2802       ectx.eth_reg_type(vnm, self)
2803       self.eth_reg_sub(vnm, ectx)
2804     if parent and (ectx.type[parent]['val'].type == 'TaggedType'):
2805       ectx.type[parent]['val'].eth_set_val_name(parent, trnm, ectx)
2806     if ident and not tagflag:
2807       ectx.eth_reg_field(nm, trnm, idx=idx, parent=parent, impl=self.HasImplicitTag(ectx))
2808     if ectx.conform.check_item('SET_TYPE', nm):
2809       virtual_tr.eth_reg_sub(nm, ectx)
2810     else:
2811       self.eth_reg_sub(nm, ectx)
2812
2813   def eth_get_size_constr(self, ectx):
2814     (minv, maxv, ext) = ('MIN', 'MAX', False)
2815     if self.HasSizeConstraint():
2816       if self.constr.IsSize():
2817         (minv, maxv, ext) = self.constr.GetSize(ectx)
2818       if (self.constr.type == 'Intersection'):
2819         if self.constr.subtype[0].IsSize():
2820           (minv, maxv, ext) = self.constr.subtype[0].GetSize(ectx)
2821         elif self.constr.subtype[1].IsSize():
2822           (minv, maxv, ext) = self.constr.subtype[1].GetSize(ectx)
2823     if minv == 'MIN': minv = 'NO_BOUND'
2824     if maxv == 'MAX': maxv = 'NO_BOUND'
2825     if (ext): ext = 'TRUE'
2826     else: ext = 'FALSE'
2827     return (minv, maxv, ext)
2828
2829   def eth_get_value_constr(self, ectx):
2830     (minv, maxv, ext) = ('MIN', 'MAX', False)
2831     if self.HasValueConstraint():
2832       (minv, maxv, ext) = self.constr.GetValue(ectx)
2833     if minv == 'MIN': minv = 'NO_BOUND'
2834     if maxv == 'MAX': maxv = 'NO_BOUND'
2835     if str(minv).isdigit(): minv += 'U'
2836     if str(maxv).isdigit(): maxv += 'U'
2837     if (ext): ext = 'TRUE'
2838     else: ext = 'FALSE'
2839     return (minv, maxv, ext)
2840
2841   def eth_get_alphabet_constr(self, ectx):
2842     (alph, alphlen) = ('NULL', '0')
2843     if self.HasPermAlph():
2844       alph = self.constr.GetPermAlph(ectx)
2845       if not alph:
2846         alph = 'NULL'
2847       if (alph != 'NULL'):
2848         if (((alph[0] + alph[-1]) == '""') and (not alph.count('"', 1, -1))):
2849           alphlen = str(len(alph) - 2)
2850         else:
2851           alphlen = 'strlen(%s)' % (alph)
2852     return (alph, alphlen)
2853
2854   def eth_type_vals(self, tname, ectx):
2855     if self.eth_has_vals():
2856       print "#Unhandled  eth_type_vals('%s') in %s" % (tname, self.type)
2857       print self.str_depth(1)
2858     return ''
2859
2860   def eth_type_enum(self, tname, ectx):
2861     if self.eth_has_enum(tname, ectx):
2862       print "#Unhandled  eth_type_enum('%s') in %s" % (tname, self.type)
2863       print self.str_depth(1)
2864     return ''
2865
2866   def eth_type_default_table(self, ectx, tname):
2867     return ''
2868
2869   def eth_type_default_body(self, ectx):
2870     print "#Unhandled  eth_type_default_body() in %s" % (self.type)
2871     print self.str_depth(1)
2872     return ''
2873
2874   def eth_type_default_pars(self, ectx, tname):
2875     pars = {
2876       'TNAME' : tname,
2877       'ER' : ectx.encp(),
2878       'FN_VARIANT' : '',
2879       'TREE' : 'tree', 
2880       'TVB' : 'tvb', 
2881       'OFFSET' : 'offset',
2882       'ACTX' : 'actx',
2883       'HF_INDEX' : 'hf_index',
2884       'VAL_PTR' : 'NULL',
2885       'IMPLICIT_TAG' : 'implicit_tag',
2886     }
2887     if (ectx.eth_type[tname]['tree']):
2888       pars['ETT_INDEX'] = ectx.eth_type[tname]['tree']
2889     if (not ectx.Per()):
2890       pars['PINFO'] = 'pinfo'
2891     return pars
2892
2893   def eth_type_fn(self, proto, tname, ectx):
2894     body = self.eth_type_default_body(ectx, tname)
2895     pars = self.eth_type_default_pars(ectx, tname)
2896     if ectx.conform.check_item('FN_PARS', tname):
2897       pars.update(ectx.conform.use_item('FN_PARS', tname))
2898     elif ectx.conform.check_item('FN_PARS', ectx.eth_type[tname]['ref'][0]):
2899       pars.update(ectx.conform.use_item('FN_PARS', ectx.eth_type[tname]['ref'][0]))
2900     pars['DEFAULT_BODY'] = body
2901     for i in range(4):
2902       for k in pars.keys(): pars[k] = pars[k] % pars
2903     out = '\n'
2904     out += self.eth_type_default_table(ectx, tname) % pars
2905     out += ectx.eth_type_fn_hdr(tname)
2906     out += ectx.eth_type_fn_body(tname, body, pars=pars)
2907     out += ectx.eth_type_fn_ftr(tname)
2908     return out
2909
2910 #--- Value --------------------------------------------------------------------
2911 class Value (Node):
2912   def __init__(self,*args, **kw) :
2913     self.name = None
2914     Node.__init__ (self,*args, **kw)
2915
2916   def SetName(self, name) :
2917     self.name = name
2918
2919   def to_str(self, ectx):
2920     return str(self)
2921
2922   def get_dep(self):
2923     return None
2924
2925 #--- ObjectClass ---------------------------------------------------------------------
2926 class ObjectClass (Node):
2927   def __init__(self,*args, **kw) :
2928     self.name = None
2929     Node.__init__ (self,*args, **kw)
2930
2931   def SetName(self, name):
2932     self.name = name
2933     add_class_ident(self.name)
2934
2935   def eth_reg(self, ident, ectx):
2936     if ectx.conform.omit_assignment('C', self.name, ectx.Module()): return # Assignment to omit
2937     ectx.eth_reg_objectclass(self.name)
2938
2939 #--- Tag ---------------------------------------------------------------
2940 class Tag (Node):
2941   def to_python (self, ctx):
2942     return 'asn1.TYPE(%s,%s)' % (mk_tag_str (ctx, self.tag.cls,
2943                                                 self.tag_typ,
2944                                                 self.tag.num),
2945                                     self.typ.to_python (ctx))
2946   def IsImplicit(self, ectx):
2947     return ((self.mode == 'IMPLICIT') or ((self.mode == 'default') and (ectx.tag_def == 'IMPLICIT')))
2948
2949   def GetTag(self, ectx):
2950     tc = ''
2951     if (self.cls == 'UNIVERSAL'): tc = 'BER_CLASS_UNI'
2952     elif (self.cls == 'APPLICATION'): tc = 'BER_CLASS_APP'
2953     elif (self.cls == 'CONTEXT'): tc = 'BER_CLASS_CON'
2954     elif (self.cls == 'PRIVATE'): tc = 'BER_CLASS_PRI'
2955     return (tc, self.num)
2956
2957   def eth_tname(self):
2958     n = ''
2959     if (self.cls == 'UNIVERSAL'): n = 'U'
2960     elif (self.cls == 'APPLICATION'): n = 'A'
2961     elif (self.cls == 'CONTEXT'): n = 'C'
2962     elif (self.cls == 'PRIVATE'): n = 'P'
2963     return n + str(self.num)
2964  
2965 #--- Constraint ---------------------------------------------------------------
2966 class Constraint (Node):
2967   def to_python (self, ctx):
2968     print "Ignoring constraint:", self.type
2969     return self.subtype.typ.to_python (ctx)
2970   def __str__ (self):
2971     return "Constraint: type=%s, subtype=%s" % (self.type, self.subtype)
2972
2973   def IsSize(self):
2974     return (self.type == 'Size' and self.subtype.IsValue()) \
2975            or (self.type == 'Intersection' and (self.subtype[0].IsSize() or self.subtype[1].IsSize())) \
2976
2977   def GetSize(self, ectx):
2978     (minv, maxv, ext) = ('MIN', 'MAX', False)
2979     if self.IsSize():
2980       if self.type == 'Size':
2981         (minv, maxv, ext) = self.subtype.GetValue(ectx)
2982       elif self.type == 'Intersection':
2983         if self.subtype[0].IsSize() and not self.subtype[1].IsSize():
2984           (minv, maxv, ext) = self.subtype[0].GetSize(ectx)
2985         elif not self.subtype[0].IsSize() and self.subtype[1].IsSize():
2986           (minv, maxv, ext) = self.subtype[1].GetSize(ectx)
2987     return (minv, maxv, ext)
2988
2989   def IsValue(self):
2990     return self.type == 'SingleValue' \
2991            or self.type == 'ValueRange' \
2992            or (self.type == 'Intersection' and (self.subtype[0].IsValue() or self.subtype[1].IsValue())) \
2993            or (self.type == 'Union' and (self.subtype[0].IsValue() and self.subtype[1].IsValue()))
2994
2995   def GetValue(self, ectx):
2996     (minv, maxv, ext) = ('MIN', 'MAX', False)
2997     if self.IsValue():
2998       if self.type == 'SingleValue':
2999         minv = ectx.value_get_eth(self.subtype)
3000         maxv = ectx.value_get_eth(self.subtype)
3001         ext = hasattr(self, 'ext') and self.ext
3002       elif self.type == 'ValueRange':
3003         minv = ectx.value_get_eth(self.subtype[0])
3004         maxv = ectx.value_get_eth(self.subtype[1])
3005         ext = hasattr(self, 'ext') and self.ext
3006       elif self.type == 'Intersection':
3007         if self.subtype[0].IsValue() and not self.subtype[1].IsValue():
3008           (minv, maxv, ext) = self.subtype[0].GetValue(ectx)
3009         elif not self.subtype[0].IsValue() and self.subtype[1].IsValue():
3010           (minv, maxv, ext) = self.subtype[1].GetValue(ectx)
3011         elif self.subtype[0].IsValue() and self.subtype[1].IsValue():
3012           v0 = self.subtype[0].GetValue(ectx)
3013           v1 = self.subtype[1].GetValue(ectx)
3014           (minv, maxv, ext) = (ectx.value_max(v0[0],v1[0]), ectx.value_min(v0[1],v1[1]), v0[2] and v1[2])
3015       elif self.type == 'Union':
3016         if self.subtype[0].IsValue() and self.subtype[1].IsValue():
3017           v0 = self.subtype[0].GetValue(ectx)
3018           v1 = self.subtype[1].GetValue(ectx)
3019           (minv, maxv, ext) = (ectx.value_min(v0[0],v1[0]), ectx.value_max(v0[1],v1[1]), v0[2] or v1[2])
3020     return (minv, maxv, ext)
3021
3022   def IsAlphabet(self):
3023     return self.type == 'SingleValue' \
3024            or self.type == 'ValueRange' \
3025            or (self.type == 'Intersection' and (self.subtype[0].IsAlphabet() or self.subtype[1].IsAlphabet())) \
3026            or (self.type == 'Union' and (self.subtype[0].IsAlphabet() and self.subtype[1].IsAlphabet()))
3027
3028   def GetAlphabet(self, ectx):
3029     alph = None
3030     if self.IsAlphabet():
3031       if self.type == 'SingleValue':
3032         alph = ectx.value_get_eth(self.subtype)
3033       elif self.type == 'ValueRange':
3034         if ((len(self.subtype[0]) == 3) and ((self.subtype[0][0] + self.subtype[0][-1]) == '""') \
3035             and (len(self.subtype[1]) == 3) and ((self.subtype[1][0] + self.subtype[1][-1]) == '""')):
3036           alph = '"'
3037           for c in range(ord(self.subtype[0][1]), ord(self.subtype[1][1]) + 1):
3038             alph += chr(c)
3039           alph += '"'
3040       elif self.type == 'Union':
3041         if self.subtype[0].IsAlphabet() and self.subtype[1].IsAlphabet():
3042           a0 = self.subtype[0].GetAlphabet(ectx)
3043           a1 = self.subtype[1].GetAlphabet(ectx)
3044           if (((a0[0] + a0[-1]) == '""') and not a0.count('"', 1, -1) \
3045               and ((a1[0] + a1[-1]) == '""') and not a1.count('"', 1, -1)):
3046             alph = '"' + a0[1:-1] + a1[1:-1] + '"'
3047           else:
3048             alph = a0 + ' ' + a1
3049     return alph
3050
3051   def IsPermAlph(self):
3052     return self.type == 'From' and self.subtype.IsAlphabet() \
3053            or (self.type == 'Intersection' and (self.subtype[0].IsPermAlph() or self.subtype[1].IsPermAlph())) \
3054
3055   def GetPermAlph(self, ectx):
3056     alph = None
3057     if self.IsPermAlph():
3058       if self.type == 'From':
3059         alph = self.subtype.GetAlphabet(ectx)
3060       elif self.type == 'Intersection':
3061         if self.subtype[0].IsPermAlph() and not self.subtype[1].IsPermAlph():
3062           alph = self.subtype[0].GetPermAlph(ectx)
3063         elif not self.subtype[0].IsPermAlph() and self.subtype[1].IsPermAlph():
3064           alph = self.subtype[1].GetPermAlph(ectx)
3065     return alph
3066
3067   def IsContents(self):
3068     return self.type == 'Contents' \
3069            or (self.type == 'Intersection' and (self.subtype[0].IsContents() or self.subtype[1].IsContents())) \
3070
3071   def GetContents(self, ectx):
3072     contents = None
3073     if self.IsContents():
3074       if self.type == 'Contents':
3075         if self.subtype.type == 'Type_Ref':
3076           contents = self.subtype.val
3077       elif self.type == 'Intersection':
3078         if self.subtype[0].IsContents() and not self.subtype[1].IsContents():
3079           contents = self.subtype[0].GetContents(ectx)
3080         elif not self.subtype[0].IsContents() and self.subtype[1].IsContents():
3081           contents = self.subtype[1].GetContents(ectx)
3082     return contents
3083
3084   def IsNegativ(self):
3085     def is_neg(sval):
3086       return sval[0] == '-'
3087     if self.type == 'SingleValue':
3088       return is_neg(self.subtype)
3089     elif self.type == 'ValueRange':
3090       if self.subtype[0] == 'MIN': return True
3091       return is_neg(self.subtype[0])
3092     return False
3093
3094   def eth_constrname(self):
3095     def int2str(val):
3096       try:
3097         if (int(val) < 0):
3098           return 'M' + str(-int(val))
3099         else:
3100           return str(val)
3101       except (ValueError, TypeError):
3102         return asn2c(str(val))
3103
3104     ext = ''
3105     if hasattr(self, 'ext') and self.ext:
3106       ext = '_'
3107     if self.type == 'SingleValue':
3108       return int2str(self.subtype) + ext
3109     elif self.type == 'ValueRange':
3110       return int2str(self.subtype[0]) + '_' + int2str(self.subtype[1]) + ext
3111     elif self.type == 'Size':
3112       return 'SIZE_' + self.subtype.eth_constrname() + ext
3113     else:
3114       return 'CONSTR' + str(id(self)) + ext
3115
3116
3117 class Module (Node):
3118   def to_python (self, ctx):
3119     ctx.tag_def = self.tag_def.dfl_tag
3120     return """#%s
3121 %s""" % (self.ident, self.body.to_python (ctx))
3122
3123   def to_eth (self, ectx):
3124     ectx.tags_def = 'EXPLICIT' # default = explicit
3125     if (not ectx.proto):
3126       ectx.proto = ectx.conform.use_item('MODULE', self.ident.val, val_dflt=self.ident.val)
3127     ectx.tag_def = self.tag_def.dfl_tag
3128     ectx.eth_reg_module(self.ident.val)
3129     self.body.to_eth(ectx)
3130
3131 class Module_Body (Node):
3132   def to_python (self, ctx):
3133     # XXX handle exports, imports.
3134     l = map (lambda x: x.to_python (ctx), self.assign_list)
3135     l = [a for a in l if a <> '']
3136     return "\n".join (l)
3137
3138   def to_eth(self, ectx):
3139     # Exports
3140     ectx.eth_exports(self.exports)
3141     # Imports
3142     for i in self.imports:
3143       mod = i.module.val
3144       proto = ectx.conform.use_item('MODULE', mod, val_dflt=mod)
3145       ectx.eth_module_dep_add(ectx.Module(), mod)
3146       for s in i.symbol_list:
3147         if isinstance(s, Type_Ref):
3148           ectx.eth_import_type(s.val, mod, proto)
3149         elif isinstance(s, Class_Ref):
3150           ectx.eth_import_class(s.val, mod, proto)
3151         else:
3152           ectx.eth_import_value(s, mod, proto)
3153     # AssignmentList
3154     for a in self.assign_list:
3155       a.eth_reg('', ectx)
3156
3157 class Default_Tags (Node):
3158     def to_python (self, ctx): # not to be used directly
3159         assert (0)
3160
3161 # XXX should just calculate dependencies as we go along.
3162 def calc_dependencies (node, dict, trace = 0):
3163     if not hasattr (node, '__dict__'):
3164         if trace: print "#returning, node=", node
3165         return
3166     if isinstance (node, Type_Ref):
3167         dict [node.val] = 1
3168         if trace: print "#Setting", node.val
3169         return
3170     for (a, val) in node.__dict__.items ():
3171         if trace: print "# Testing node ", node, "attr", a, " val", val
3172         if a[0] == '_':
3173             continue
3174         elif isinstance (val, Node):
3175             calc_dependencies (val, dict, trace)
3176         elif isinstance (val, type ([])):
3177             for v in val:
3178                 calc_dependencies (v, dict, trace)
3179     
3180                           
3181 class Type_Assign (Node):
3182     def __init__ (self, *args, **kw):
3183         Node.__init__ (self, *args, **kw)
3184         if isinstance (self.val, Tag): # XXX replace with generalized get_typ_ignoring_tag (no-op for Node, override in Tag)
3185             to_test = self.val.typ
3186         else:
3187             to_test = self.val
3188         if isinstance (to_test, SequenceType):
3189             to_test.sequence_name = self.name.name
3190             
3191     def to_python (self, ctx):
3192         dep_dict = {}
3193         calc_dependencies (self.val, dep_dict, 0)
3194         depend_list = dep_dict.keys ()
3195         return ctx.register_assignment (self.name.name,
3196                                         self.val.to_python (ctx),
3197                                         depend_list)
3198
3199 class PyQuote (Node):
3200     def to_python (self, ctx):
3201         return ctx.register_pyquote (self.val)
3202
3203 #--- Class_Ref -----------------------------------------------------------------
3204 class Class_Ref (Type):
3205   def to_python (self, ctx):
3206     return self.val
3207
3208   def eth_tname(self):
3209     return asn2c(self.val)
3210
3211 #--- Type_Ref -----------------------------------------------------------------
3212 class Type_Ref (Type):
3213   def to_python (self, ctx):
3214     return self.val
3215
3216   def eth_reg_sub(self, ident, ectx):
3217     ectx.eth_dep_add(ident, self.val)
3218
3219   def eth_tname(self):
3220     return asn2c(self.val)
3221
3222   def get_components(self, ectx):
3223     if not ectx.type.has_key(self.val) or ectx.type[self.val]['import']:
3224       msg = "Can not get COMPONENTS OF %s which is imported type" % (self.val)
3225       warnings.warn_explicit(msg, UserWarning, '', '')
3226       return []
3227     else:
3228       return ectx.type[self.val]['val'].get_components(ectx)
3229
3230   def GetTTag(self, ectx):
3231     #print "GetTTag(%s)\n" % self.val;
3232     if (ectx.type[self.val]['import']):
3233       if not ectx.type[self.val].has_key('ttag'):
3234         ttag = ectx.get_ttag_from_all(self.val, ectx.type[self.val]['import'])
3235         if not ttag and not ectx.conform.check_item('IMPORT_TAG', self.val):
3236           msg = 'Missing tag information for imported type %s from %s (%s)' % (self.val, ectx.type[self.val]['import'], ectx.type[self.val]['proto'])
3237           warnings.warn_explicit(msg, UserWarning, '', '')
3238           ttag = ('-1 /*imported*/', '-1 /*imported*/')
3239         ectx.type[self.val]['ttag'] = ectx.conform.use_item('IMPORT_TAG', self.val, val_dflt=ttag)
3240       return ectx.type[self.val]['ttag']
3241     else:
3242       return ectx.type[self.val]['val'].GetTag(ectx)
3243
3244   def IndetermTag(self, ectx):
3245     if (ectx.type[self.val]['import']):
3246       return False
3247     else:
3248       return ectx.type[self.val]['val'].IndetermTag(ectx)
3249
3250   def eth_type_default_pars(self, ectx, tname):
3251     pars = Type.eth_type_default_pars(self, ectx, tname)
3252     t = ectx.type[self.val]['ethname']
3253     pars['TYPE_REF_PROTO'] = ectx.eth_type[t]['proto']
3254     pars['TYPE_REF_TNAME'] = t
3255     pars['TYPE_REF_FN'] = 'dissect_%(TYPE_REF_PROTO)s_%(TYPE_REF_TNAME)s'
3256     return pars
3257
3258   def eth_type_default_body(self, ectx, tname):
3259     if (ectx.Ber()):
3260       body = ectx.eth_fn_call('%(TYPE_REF_FN)s', ret='offset',
3261                               par=(('%(IMPLICIT_TAG)s', '%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),))
3262     elif (ectx.Per()):
3263       body = ectx.eth_fn_call('%(TYPE_REF_FN)s', ret='offset',
3264                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),))
3265     else:
3266       body = '#error Can not decode %s' % (tname)
3267     return body
3268
3269 #--- SelectionType ------------------------------------------------------------
3270 class SelectionType (Type):
3271   def to_python (self, ctx):
3272     return self.val
3273
3274   def sel_of_typeref(self):
3275     return self.typ.type == 'Type_Ref'
3276
3277   def eth_reg_sub(self, ident, ectx):
3278     if not self.sel_of_typeref():
3279       self.seltype = ''
3280       return
3281     self.seltype = ectx.eth_sel_req(self.typ.val, self.sel)
3282     ectx.eth_dep_add(ident, self.seltype)
3283
3284   def GetTTag(self, ectx):
3285     #print "GetTTag(%s)\n" % self.seltype;
3286     if (ectx.type[self.seltype]['import']):
3287       if not ectx.type[self.seltype].has_key('ttag'):
3288         if not ectx.conform.check_item('IMPORT_TAG', self.seltype):
3289           msg = 'Missing tag information for imported type %s from %s (%s)' % (self.seltype, ectx.type[self.seltype]['import'], ectx.type[self.seltype]['proto'])
3290           warnings.warn_explicit(msg, UserWarning, '', '')
3291         ectx.type[self.seltype]['ttag'] = ectx.conform.use_item('IMPORT_TAG', self.seltype, val_dflt=('-1 /*imported*/', '-1 /*imported*/'))
3292       return ectx.type[self.seltype]['ttag']
3293     else:
3294       return ectx.type[self.typ.val]['val'].GetTTagSel(self.sel, ectx)
3295
3296   def eth_type_default_pars(self, ectx, tname):
3297     pars = Type.eth_type_default_pars(self, ectx, tname)
3298     if self.sel_of_typeref():
3299       t = ectx.type[self.seltype]['ethname']
3300       pars['TYPE_REF_PROTO'] = ectx.eth_type[t]['proto']
3301       pars['TYPE_REF_TNAME'] = t
3302       pars['TYPE_REF_FN'] = 'dissect_%(TYPE_REF_PROTO)s_%(TYPE_REF_TNAME)s'
3303     return pars
3304
3305   def eth_type_default_body(self, ectx, tname):
3306     if not self.sel_of_typeref():
3307       body = '#error Can not decode %s' % (tname)
3308     elif (ectx.Ber()):
3309       body = ectx.eth_fn_call('%(TYPE_REF_FN)s', ret='offset',
3310                               par=(('%(IMPLICIT_TAG)s', '%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),))
3311     elif (ectx.Per()):
3312       body = ectx.eth_fn_call('%(TYPE_REF_FN)s', ret='offset',
3313                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),))
3314     else:
3315       body = '#error Can not decode %s' % (tname)
3316     return body
3317
3318 #--- TaggedType -----------------------------------------------------------------
3319 class TaggedType (Type):
3320   def eth_tname(self):
3321     tn = ''
3322     for i in range(self.tstrip, len(self.val.tags)):
3323       tn += self.val.tags[i].eth_tname()
3324       tn += '_'
3325     tn += self.val.eth_tname()
3326     return tn
3327
3328   def eth_set_val_name(self, ident, val_name, ectx):
3329     #print "TaggedType::eth_set_val_name(): ident=%s, val_name=%s" % (ident, val_name)
3330     self.val_name = val_name
3331     ectx.eth_dep_add(ident, self.val_name)
3332
3333   def eth_reg_sub(self, ident, ectx):
3334     self.val_name = ident + '/' + '_untag'
3335     self.val.eth_reg(self.val_name, ectx, tstrip=self.tstrip+1, tagflag=True, parent=ident)
3336
3337   def GetTTag(self, ectx):
3338     #print "GetTTag(%s)\n" % self.seltype;
3339     return self.GetTag(ectx)
3340
3341   def eth_ftype(self, ectx):
3342     return self.val.eth_ftype(ectx)
3343
3344   def eth_type_default_pars(self, ectx, tname):
3345     pars = Type.eth_type_default_pars(self, ectx, tname)
3346     t = ectx.type[self.val_name]['ethname']
3347     pars['TYPE_REF_PROTO'] = ectx.eth_type[t]['proto']
3348     pars['TYPE_REF_TNAME'] = t
3349     pars['TYPE_REF_FN'] = 'dissect_%(TYPE_REF_PROTO)s_%(TYPE_REF_TNAME)s'
3350     (pars['TAG_CLS'], pars['TAG_TAG']) = self.GetTag(ectx)
3351     if self.HasImplicitTag(ectx):
3352       pars['TAG_IMPL'] = 'TRUE'
3353     else:
3354       pars['TAG_IMPL'] = 'FALSE'
3355     return pars
3356
3357   def eth_type_default_body(self, ectx, tname):
3358     if (ectx.Ber()):
3359       body = ectx.eth_fn_call('dissect_%(ER)s_tagged_type', ret='offset',
3360                               par=(('%(IMPLICIT_TAG)s', '%(ACTX)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s'),
3361                                    ('%(HF_INDEX)s', '%(TAG_CLS)s', '%(TAG_TAG)s', '%(TAG_IMPL)s', '%(TYPE_REF_FN)s',),))
3362     else:
3363       body = '#error Can not decode %s' % (tname)
3364     return body
3365
3366 #--- SqType -----------------------------------------------------------
3367 class SqType (Type):
3368   def out_item(self, f, val, optional, ext, ectx):
3369     ef = ectx.field[f]['ethname']
3370     t = ectx.eth_hf[ef]['ethtype']
3371     efd = ef
3372     if (ectx.Ber() and ectx.field[f]['impl']):
3373       efd += '_impl'
3374     if (ectx.Ber()):
3375       #print "optional=%s, e.val.HasOwnTag()=%s, e.val.IndetermTag()=%s" % (str(e.optional), str(e.val.HasOwnTag()), str(e.val.IndetermTag(ectx)))
3376       #print val.str_depth(1)
3377       opt = ''
3378       if (optional):
3379         opt = 'BER_FLAGS_OPTIONAL'
3380       if (not val.HasOwnTag()):
3381         if (opt): opt += '|'
3382         opt += 'BER_FLAGS_NOOWNTAG'
3383       elif (val.HasImplicitTag(ectx)):
3384         if (opt): opt += '|'
3385         opt += 'BER_FLAGS_IMPLTAG'
3386       if (val.IndetermTag(ectx)):
3387         if (opt): opt += '|'
3388         opt += 'BER_FLAGS_NOTCHKTAG'
3389       if (not opt): opt = '0'
3390     else:
3391       if optional:
3392         opt = 'ASN1_OPTIONAL'
3393       else:
3394         opt = 'ASN1_NOT_OPTIONAL'
3395     if (ectx.Ber()):
3396       (tc, tn) = val.GetTag(ectx)
3397       if (ectx.NewBer()):
3398         out = '  { %-24s, %-13s, %s, %s, dissect_%s_%s },\n' \
3399               % ('&'+ectx.eth_hf[ef]['fullname'], tc, tn, opt, ectx.eth_type[t]['proto'], t)
3400       else:
3401         out = '  { %-13s, %s, %s, dissect_%s },\n' \
3402               % (tc, tn, opt, efd)
3403     elif (ectx.Per()):
3404       out = '  { %-24s, %-23s, %-17s, dissect_%s_%s },\n' \
3405             % ('&'+ectx.eth_hf[ef]['fullname'], ext, opt, ectx.eth_type[t]['proto'], t)
3406     else:
3407       out = ''
3408     return out   
3409
3410 #--- SeqType -----------------------------------------------------------
3411 class SeqType (SqType):
3412
3413   def need_components(self):
3414     lst = self.elt_list[:]
3415     if hasattr(self, 'ext_list'):
3416       lst.extend(self.ext_list)
3417     for e in (self.elt_list):
3418       if e.type == 'components_of':
3419         return True
3420     return False
3421
3422   def expand_components(self, ectx):
3423     while self.need_components():
3424       for i in range(len(self.elt_list)):
3425         if self.elt_list[i].type == 'components_of':
3426           comp = self.elt_list[i].typ.get_components(ectx)
3427           self.elt_list[i:i+1] = comp
3428           break
3429       if hasattr(self, 'ext_list'):
3430         for i in range(len(self.ext_list)):
3431           if self.ext_list[i].type == 'components_of':
3432             comp = self.ext_list[i].typ.get_components(ectx)
3433             self.ext_list[i:i+1] = comp
3434             break
3435
3436   def get_components(self, ectx):
3437     return self.elt_list[:]
3438
3439   def eth_type_default_table(self, ectx, tname):
3440     #print "eth_type_default_table(tname='%s')" % (tname)
3441     fname = ectx.eth_type[tname]['ref'][0]
3442     if (ectx.Ber()):
3443         if (ectx.NewBer()):
3444             table = "static const %(ER)s_sequence_t %(TABLE)s[] = {\n"
3445         else:
3446             table = "static const %(ER)s_old_sequence_t %(TABLE)s[] = {\n"
3447     else:
3448         table = "static const %(ER)s_sequence_t %(TABLE)s[] = {\n"
3449     if hasattr(self, 'ext_list'):
3450       ext = 'ASN1_EXTENSION_ROOT'
3451     else:
3452       ext = 'ASN1_NO_EXTENSIONS'
3453     for e in (self.elt_list):
3454       f = fname + '/' + e.val.name
3455       table += self.out_item(f, e.val, e.optional, ext, ectx)
3456     if hasattr(self, 'ext_list'):
3457       for e in (self.ext_list):
3458         f = fname + '/' + e.val.name
3459         table += self.out_item(f, e.val, e.optional, 'ASN1_NOT_EXTENSION_ROOT', ectx)
3460     if (ectx.Ber()):
3461       if (ectx.NewBer()):
3462         table += "  { NULL, 0, 0, 0, NULL }\n};\n"
3463       else:
3464         table += "  { 0, 0, 0, NULL }\n};\n"
3465     else:
3466       table += "  { NULL, 0, 0, NULL }\n};\n"
3467     return table
3468
3469 #--- SeqOfType -----------------------------------------------------------
3470 class SeqOfType (SqType):
3471   def eth_type_default_table(self, ectx, tname):
3472     #print "eth_type_default_table(tname='%s')" % (tname)
3473     fname = ectx.eth_type[tname]['ref'][0]
3474     if self.val.IsNamed ():
3475       f = fname + '/' + self.val.name
3476     else:
3477       f = fname + '/' + '_item'
3478     if (ectx.Ber()):
3479         if (ectx.NewBer()):
3480             table = "static const %(ER)s_sequence_t %(TABLE)s[1] = {\n"
3481         else:
3482             table = "static const %(ER)s_old_sequence_t %(TABLE)s[1] = {\n"
3483     else:
3484         table = "static const %(ER)s_sequence_t %(TABLE)s[1] = {\n"
3485     table += self.out_item(f, self.val, False, 'ASN1_NO_EXTENSIONS', ectx)
3486     table += "};\n"
3487     return table
3488
3489 #--- SequenceOfType -----------------------------------------------------------
3490 class SequenceOfType (SeqOfType):
3491   def to_python (self, ctx):
3492     # name, tag (None for no tag, EXPLICIT() for explicit), typ)
3493     # or '' + (1,) for optional
3494     sizestr = ''
3495     if self.size_constr <> None:
3496         print "#Ignoring size constraint:", self.size_constr.subtype
3497     return "%sasn1.SEQUENCE_OF (%s%s)" % (ctx.spaces (),
3498                                           self.val.to_python (ctx),
3499                                           sizestr)
3500
3501   def eth_reg_sub(self, ident, ectx):
3502     itmnm = ident
3503     if not self.val.IsNamed ():
3504       itmnm += '/' + '_item'
3505     self.val.eth_reg(itmnm, ectx, tstrip=1, idx='[##]', parent=ident)
3506
3507   def eth_tname(self):
3508     if self.val.type != 'Type_Ref':
3509       return '#' + self.type + '_' + str(id(self))
3510     if not self.HasConstraint():
3511       return "SEQUENCE_OF_" + self.val.eth_tname()
3512     elif self.constr.IsSize():
3513       return 'SEQUENCE_' + self.constr.eth_constrname() + '_OF_' + self.val.eth_tname()
3514     else:
3515       return '#' + self.type + '_' + str(id(self))
3516
3517   def eth_ftype(self, ectx):
3518     return ('FT_UINT32', 'BASE_DEC')
3519
3520   def eth_need_tree(self):
3521     return True
3522
3523   def GetTTag(self, ectx):
3524     return ('BER_CLASS_UNI', 'BER_UNI_TAG_SEQUENCE')
3525
3526   def eth_type_default_pars(self, ectx, tname):
3527     pars = Type.eth_type_default_pars(self, ectx, tname)
3528     (pars['MIN_VAL'], pars['MAX_VAL'], pars['EXT']) = self.eth_get_size_constr(ectx)
3529     pars['TABLE'] = '%(TNAME)s_sequence_of'
3530     return pars
3531
3532   def eth_type_default_body(self, ectx, tname):
3533     if (ectx.Ber()):
3534         if (ectx.NewBer()):
3535             body = ectx.eth_fn_call('dissect_%(ER)s_sequence_of', ret='offset',
3536                               par=(('%(IMPLICIT_TAG)s', '%(ACTX)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s'),
3537                                    ('%(TABLE)s', '%(HF_INDEX)s', '%(ETT_INDEX)s',),))
3538         else:            
3539             body = ectx.eth_fn_call('dissect_%(ER)s_old_sequence_of', ret='offset',
3540                               par=(('%(IMPLICIT_TAG)s', '%(ACTX)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s'),
3541                                    ('%(TABLE)s', '%(HF_INDEX)s', '%(ETT_INDEX)s',),))
3542     elif (ectx.Per() and not self.HasConstraint()):
3543       body = ectx.eth_fn_call('dissect_%(ER)s_sequence_of', ret='offset',
3544                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
3545                                    ('%(ETT_INDEX)s', '%(TABLE)s',),))
3546     elif (ectx.Per() and self.constr.type == 'Size'):
3547       body = ectx.eth_fn_call('dissect_%(ER)s_constrained_sequence_of', ret='offset',
3548                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
3549                                    ('%(ETT_INDEX)s', '%(TABLE)s',),
3550                                    ('%(MIN_VAL)s', '%(MAX_VAL)s',),))
3551     else:
3552       body = '#error Can not decode %s' % (tname)
3553     return body
3554
3555
3556 #--- SetOfType ----------------------------------------------------------------
3557 class SetOfType (SeqOfType):
3558   def eth_reg_sub(self, ident, ectx):
3559     itmnm = ident
3560     if not self.val.IsNamed ():
3561       itmnm += '/' + '_item'
3562     self.val.eth_reg(itmnm, ectx, tstrip=1, idx='(##)', parent=ident)
3563
3564   def eth_tname(self):
3565     if self.val.type != 'Type_Ref':
3566       return '#' + self.type + '_' + str(id(self))
3567     if not self.HasConstraint():
3568       return "SET_OF_" + self.val.eth_tname()
3569     elif self.constr.IsSize():
3570       return 'SET_' + self.constr.eth_constrname() + '_OF_' + self.val.eth_tname()
3571     else:
3572       return '#' + self.type + '_' + str(id(self))
3573
3574   def eth_ftype(self, ectx):
3575     return ('FT_UINT32', 'BASE_DEC')
3576
3577   def eth_need_tree(self):
3578     return True
3579
3580   def GetTTag(self, ectx):
3581     return ('BER_CLASS_UNI', 'BER_UNI_TAG_SET')
3582
3583   def eth_type_default_pars(self, ectx, tname):
3584     pars = Type.eth_type_default_pars(self, ectx, tname)
3585     (pars['MIN_VAL'], pars['MAX_VAL'], pars['EXT']) = self.eth_get_size_constr(ectx)
3586     pars['TABLE'] = '%(TNAME)s_set_of'
3587     return pars
3588
3589   def eth_type_default_body(self, ectx, tname):
3590     if (ectx.Ber()):
3591         if (ectx.NewBer()):
3592             body = ectx.eth_fn_call('dissect_%(ER)s_set_of', ret='offset',
3593                               par=(('%(IMPLICIT_TAG)s', '%(ACTX)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s'),
3594                                    ('%(TABLE)s', '%(HF_INDEX)s', '%(ETT_INDEX)s',),))
3595         else:    
3596             body = ectx.eth_fn_call('dissect_%(ER)s_old_set_of', ret='offset',
3597                               par=(('%(IMPLICIT_TAG)s', '%(ACTX)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s'),
3598                                    ('%(TABLE)s', '%(HF_INDEX)s', '%(ETT_INDEX)s',),))
3599     elif (ectx.Per() and not self.HasConstraint()):
3600       body = ectx.eth_fn_call('dissect_%(ER)s_set_of', ret='offset',
3601                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
3602                                    ('%(ETT_INDEX)s', '%(TABLE)s',),))
3603     elif (ectx.Per() and self.constr.type == 'Size'):
3604       body = ectx.eth_fn_call('dissect_%(ER)s_constrained_set_of', ret='offset',
3605                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
3606                                    ('%(ETT_INDEX)s', '%(TABLE)s',),
3607                                    ('%(MIN_VAL)s', '%(MAX_VAL)s',),))
3608     else:
3609       body = '#error Can not decode %s' % (tname)
3610     return body
3611
3612 def mk_tag_str (ctx, cls, typ, num):
3613
3614     # XXX should do conversion to int earlier!
3615     val = int (num)
3616     typ = typ.upper()
3617     if typ == 'DEFAULT':
3618         typ = ctx.tags_def
3619     return 'asn1.%s(%d,cls=asn1.%s_FLAG)' % (typ, val, cls) # XXX still ned
3620
3621 #--- SequenceType -------------------------------------------------------------
3622 class SequenceType (SeqType):
3623   def to_python (self, ctx):
3624       # name, tag (None for no tag, EXPLICIT() for explicit), typ)
3625       # or '' + (1,) for optional
3626       # XXX should also collect names for SEQUENCE inside SEQUENCE or
3627       # CHOICE or SEQUENCE_OF (where should the SEQUENCE_OF name come
3628       # from?  for others, element or arm name would be fine)
3629       seq_name = getattr (self, 'sequence_name', None)
3630       if seq_name == None:
3631           seq_name = 'None'
3632       else:
3633           seq_name = "'" + seq_name + "'"
3634       if self.__dict__.has_key('ext_list'):
3635         return "%sasn1.SEQUENCE ([%s], ext=[%s], seq_name = %s)" % (ctx.spaces (), 
3636                                  self.elts_to_py (self.elt_list, ctx),
3637                                  self.elts_to_py (self.ext_list, ctx), seq_name)
3638       else:
3639         return "%sasn1.SEQUENCE ([%s]), seq_name = %s" % (ctx.spaces (), 
3640                                  self.elts_to_py (self.elt_list, ctx), seq_name)
3641   def elts_to_py (self, list, ctx):
3642       # we have elt_type, val= named_type, maybe default=, optional=
3643       # named_type node: either ident = or typ =
3644       # need to dismember these in order to generate Python output syntax.
3645       ctx.indent ()
3646       def elt_to_py (e):
3647           assert (e.type == 'elt_type')
3648           nt = e.val
3649           optflag = e.optional
3650           #assert (not hasattr (e, 'default')) # XXX add support for DEFAULT!
3651           assert (nt.type == 'named_type')
3652           tagstr = 'None'
3653           identstr = nt.ident
3654           if hasattr (nt.typ, 'type') and nt.typ.type == 'tag': # ugh
3655               tagstr = mk_tag_str (ctx,nt.typ.tag.cls,
3656                                    nt.typ.tag.tag_typ,nt.typ.tag.num)
3657       
3658
3659               nt = nt.typ
3660           return "('%s',%s,%s,%d)" % (identstr, tagstr,
3661                                     nt.typ.to_python (ctx), optflag)
3662       indentstr = ",\n" + ctx.spaces ()
3663       rv = indentstr.join ([elt_to_py (e) for e in list])
3664       ctx.outdent ()
3665       return rv
3666
3667   def eth_reg_sub(self, ident, ectx, components_available=False):
3668     if self.need_components():
3669       if components_available:
3670         self.expand_components(ectx)
3671       else:
3672         ectx.eth_comp_req(ident)
3673         return
3674     for e in (self.elt_list):
3675         e.val.eth_reg(ident, ectx, tstrip=1, parent=ident)
3676     if hasattr(self, 'ext_list'):
3677         for e in (self.ext_list):
3678             e.val.eth_reg(ident, ectx, tstrip=1, parent=ident)
3679
3680   def eth_need_tree(self):
3681     return True
3682
3683   def GetTTag(self, ectx):
3684     return ('BER_CLASS_UNI', 'BER_UNI_TAG_SEQUENCE')
3685
3686   def eth_type_default_pars(self, ectx, tname):
3687     pars = Type.eth_type_default_pars(self, ectx, tname)
3688     pars['TABLE'] = '%(TNAME)s_sequence'
3689     return pars
3690
3691   def eth_type_default_body(self, ectx, tname):
3692     if (ectx.Ber()):
3693         if(ectx.NewBer()):
3694             body = ectx.eth_fn_call('dissect_%(ER)s_sequence', ret='offset',
3695                               par=(('%(IMPLICIT_TAG)s', '%(ACTX)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s'),
3696                                    ('%(TABLE)s', '%(HF_INDEX)s', '%(ETT_INDEX)s',),))
3697         else:
3698             body = ectx.eth_fn_call('dissect_%(ER)s_old_sequence', ret='offset',
3699                               par=(('%(IMPLICIT_TAG)s', '%(ACTX)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s'),
3700                                    ('%(TABLE)s', '%(HF_INDEX)s', '%(ETT_INDEX)s',),))
3701     elif (ectx.Per()):
3702       body = ectx.eth_fn_call('dissect_%(ER)s_sequence', ret='offset',
3703                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
3704                                    ('%(ETT_INDEX)s', '%(TABLE)s',),))
3705     else:
3706       body = '#error Can not decode %s' % (tname)
3707     return body
3708
3709 #--- SetType ------------------------------------------------------------------
3710 class SetType(SeqType):
3711
3712   def eth_reg_sub(self, ident, ectx, components_available=False):
3713     if self.need_components():
3714       if components_available:
3715         self.expand_components(ectx)
3716       else:
3717         ectx.eth_comp_req(ident)
3718         return
3719     for e in (self.elt_list):
3720       e.val.eth_reg(ident, ectx, tstrip=1, parent=ident)
3721     if hasattr(self, 'ext_list'):
3722       for e in (self.ext_list):
3723         e.val.eth_reg(ident, ectx, tstrip=1, parent=ident)
3724
3725   def eth_need_tree(self):
3726     return True
3727
3728   def GetTTag(self, ectx):
3729     return ('BER_CLASS_UNI', 'BER_UNI_TAG_SET')
3730
3731   def eth_type_default_pars(self, ectx, tname):
3732     pars = Type.eth_type_default_pars(self, ectx, tname)
3733     pars['TABLE'] = '%(TNAME)s_set'
3734     return pars
3735
3736   def eth_type_default_body(self, ectx, tname):
3737     if (ectx.Ber()):
3738         if(ectx.NewBer()):
3739             body = ectx.eth_fn_call('dissect_%(ER)s_set', ret='offset',
3740                               par=(('%(IMPLICIT_TAG)s', '%(ACTX)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s'),
3741                                    ('%(TABLE)s', '%(HF_INDEX)s', '%(ETT_INDEX)s',),))
3742         else:
3743             body = ectx.eth_fn_call('dissect_%(ER)s_old_set', ret='offset',
3744                               par=(('%(IMPLICIT_TAG)s', '%(ACTX)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s'),
3745                                    ('%(TABLE)s', '%(HF_INDEX)s', '%(ETT_INDEX)s',),))
3746     elif (ectx.Per()):
3747       body = ectx.eth_fn_call('dissect_%(ER)s_set', ret='offset',
3748                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
3749                                    ('%(ETT_INDEX)s', '%(TABLE)s',),))
3750     else:
3751       body = '#error Can not decode %s' % (tname)
3752     return body
3753
3754 #--- ChoiceType ---------------------------------------------------------------
3755 class ChoiceType (Type):
3756   def to_python (self, ctx):
3757       # name, tag (None for no tag, EXPLICIT() for explicit), typ)
3758       # or '' + (1,) for optional
3759       if self.__dict__.has_key('ext_list'):
3760         return "%sasn1.CHOICE ([%s], ext=[%s])" % (ctx.spaces (), 
3761                                self.elts_to_py (self.elt_list, ctx),
3762                                self.elts_to_py (self.ext_list, ctx))
3763       else:
3764         return "%sasn1.CHOICE ([%s])" % (ctx.spaces (), self.elts_to_py (self.elt_list, ctx))
3765   def elts_to_py (self, list, ctx):
3766       ctx.indent ()
3767       def elt_to_py (nt):
3768           assert (nt.type == 'named_type')
3769           tagstr = 'None'
3770           if hasattr (nt, 'ident'):
3771               identstr = nt.ident
3772           else:
3773               if hasattr (nt.typ, 'val'):
3774                   identstr = nt.typ.val # XXX, making up name
3775               elif hasattr (nt.typ, 'name'):
3776                   identstr = nt.typ.name
3777               else:
3778                   identstr = ctx.make_new_name ()
3779
3780           if hasattr (nt.typ, 'type') and nt.typ.type == 'tag': # ugh
3781               tagstr = mk_tag_str (ctx,nt.typ.tag.cls,
3782                                    nt.typ.tag.tag_typ,nt.typ.tag.num)
3783       
3784
3785               nt = nt.typ
3786           return "('%s',%s,%s)" % (identstr, tagstr,
3787                                     nt.typ.to_python (ctx))
3788       indentstr = ",\n" + ctx.spaces ()
3789       rv =  indentstr.join ([elt_to_py (e) for e in list])
3790       ctx.outdent ()
3791       return rv
3792
3793   def eth_reg_sub(self, ident, ectx):
3794     #print "eth_reg_sub(ident='%s')" % (ident)
3795     for e in (self.elt_list):
3796         e.eth_reg(ident, ectx, tstrip=1, parent=ident)
3797         if ectx.conform.check_item('EXPORTS', ident + '.' + e.name):
3798           ectx.eth_sel_req(ident, e.name)
3799     if hasattr(self, 'ext_list'):
3800         for e in (self.ext_list):
3801             e.eth_reg(ident, ectx, tstrip=1, parent=ident)
3802             if ectx.conform.check_item('EXPORTS', ident + '.' + e.name):
3803               ectx.eth_sel_req(ident, e.name)
3804
3805   def sel_item(self, ident, sel, ectx):
3806     lst = self.elt_list[:]
3807     if hasattr(self, 'ext_list'):
3808       lst.extend(self.ext_list)
3809     ee = None
3810     for e in (self.elt_list):
3811       if e.IsNamed() and (e.name == sel):
3812         ee = e
3813         break
3814     if not ee:
3815       print "#CHOICE %s does not contain item %s" % (ident, sel)
3816     return ee
3817
3818   def sel_req(self, ident, sel, ectx):
3819     #print "sel_req(ident='%s', sel=%s)" % (ident, sel)
3820     ee = self.sel_item(ident, sel, ectx)
3821     if ee:
3822       ee.eth_reg(ident, ectx, tstrip=0, selflag=True)
3823
3824   def eth_ftype(self, ectx):
3825     return ('FT_UINT32', 'BASE_DEC')
3826
3827   def eth_strings(self):
3828     return '$$'
3829
3830   def eth_need_tree(self):
3831     return True
3832
3833   def eth_has_vals(self):
3834     return True
3835
3836   def GetTTag(self, ectx):
3837     lst = self.elt_list
3838     cls = 'BER_CLASS_ANY/*choice*/'
3839     #if hasattr(self, 'ext_list'):
3840     #  lst.extend(self.ext_list)
3841     #if (len(lst) > 0):
3842     #  cls = lst[0].GetTag(ectx)[0]
3843     #for e in (lst):
3844     #  if (e.GetTag(ectx)[0] != cls):
3845     #    cls = '-1/*choice*/'
3846     return (cls, '-1/*choice*/')
3847
3848   def GetTTagSel(self, sel, ectx):
3849     ee = self.sel_item('', sel, ectx)
3850     if ee:
3851       return ee.GetTag(ectx)
3852     else:
3853       return ('BER_CLASS_ANY/*unknown selection*/', '-1/*unknown selection*/')
3854
3855   def IndetermTag(self, ectx):
3856     #print "Choice IndetermTag()=%s" % (str(not self.HasOwnTag()))
3857     return not self.HasOwnTag()
3858
3859   def get_vals(self, ectx):
3860     tagval = False
3861     if (ectx.Ber()):
3862       lst = self.elt_list[:]
3863       if hasattr(self, 'ext_list'):
3864         lst.extend(self.ext_list)
3865       if (len(lst) > 0):
3866         t = lst[0].GetTag(ectx)[0]
3867         tagval = True
3868       if (t == 'BER_CLASS_UNI'):
3869         tagval = False
3870       for e in (lst):
3871         if (e.GetTag(ectx)[0] != t):
3872           tagval = False
3873     vals = []
3874     cnt = 0
3875     for e in (self.elt_list):
3876       if (tagval): val = e.GetTag(ectx)[1]
3877       else: val = str(cnt)
3878       vals.append((val, e.name))
3879       cnt += 1
3880     if hasattr(self, 'ext_list'):
3881       for e in (self.ext_list):
3882         if (tagval): val = e.GetTag(ectx)[1]
3883         else: val = str(cnt)
3884         vals.append((val, e.name))
3885         cnt += 1
3886     return vals
3887
3888   def eth_type_vals(self, tname, ectx):
3889     out = '\n'
3890     vals = self.get_vals(ectx)
3891     out += ectx.eth_vals(tname, vals)
3892     return out
3893
3894   def eth_type_enum(self, tname, ectx):
3895     out = '\n'
3896     vals = self.get_vals(ectx)
3897     out += ectx.eth_enum(tname, vals)
3898     return out
3899
3900   def eth_type_default_pars(self, ectx, tname):
3901     pars = Type.eth_type_default_pars(self, ectx, tname)
3902     pars['TABLE'] = '%(TNAME)s_choice'
3903     return pars
3904
3905   def eth_type_default_table(self, ectx, tname):
3906     def out_item(val, e, ext, ectx):
3907       has_enum = ectx.eth_type[tname]['enum'] & EF_ENUM
3908       if (has_enum):
3909         vval = ectx.eth_enum_item(tname, e.name)
3910       else:
3911         vval = val
3912       f = fname + '/' + e.name
3913       ef = ectx.field[f]['ethname']
3914       t = ectx.eth_hf[ef]['ethtype']
3915       efd = ef
3916       if (ectx.field[f]['impl']):
3917         efd += '_impl'
3918       if (ectx.Ber()):
3919         opt = ''
3920         if (not e.HasOwnTag()):
3921           opt = 'BER_FLAGS_NOOWNTAG'
3922         elif (e.HasImplicitTag(ectx)):
3923           if (opt): opt += '|'
3924           opt += 'BER_FLAGS_IMPLTAG'
3925         if (not opt): opt = '0'
3926       if (ectx.Ber()):
3927         (tc, tn) = e.GetTag(ectx)
3928         if (ectx.NewBer()):
3929           out = '  { %3s, %-24s, %-13s, %s, %s, dissect_%s_%s },\n' \
3930                 % (vval, '&'+ectx.eth_hf[ef]['fullname'], tc, tn, opt, ectx.eth_type[t]['proto'], t)
3931         else:
3932           out = '  { %3s, %-13s, %s, %s, dissect_%s },\n' \
3933                 % (vval, tc, tn, opt, efd)
3934       elif (ectx.Per()):
3935         out = '  { %3s, %-24s, %-23s, dissect_%s_%s },\n' \
3936               % (vval, '&'+ectx.eth_hf[ef]['fullname'], ext, ectx.eth_type[t]['proto'], t)
3937       else:
3938         out = ''
3939       return out   
3940     # end out_item()
3941     #print "eth_type_default_table(tname='%s')" % (tname)
3942     fname = ectx.eth_type[tname]['ref'][0]
3943     tagval = False
3944     if (ectx.Ber()):
3945       lst = self.elt_list[:]
3946       if hasattr(self, 'ext_list'):
3947         lst.extend(self.ext_list)
3948       if (len(lst) > 0):
3949         t = lst[0].GetTag(ectx)[0]
3950         tagval = True
3951       if (t == 'BER_CLASS_UNI'):
3952         tagval = False
3953       for e in (lst):
3954         if (e.GetTag(ectx)[0] != t):
3955           tagval = False
3956     if (ectx.Ber()):
3957         if (ectx.NewBer()):
3958             table = "static const %(ER)s_choice_t %(TABLE)s[] = {\n"
3959         else:
3960             table = "static const %(ER)s_old_choice_t %(TABLE)s[] = {\n"
3961     else:
3962         table = "static const %(ER)s_choice_t %(TABLE)s[] = {\n"
3963     cnt = 0
3964     if hasattr(self, 'ext_list'):
3965       ext = 'ASN1_EXTENSION_ROOT'
3966     else:
3967       ext = 'ASN1_NO_EXTENSIONS'
3968     for e in (self.elt_list):
3969       if (tagval): val = e.GetTag(ectx)[1]
3970       else: val = str(cnt)
3971       table += out_item(val, e, ext, ectx)
3972       cnt += 1
3973     if hasattr(self, 'ext_list'):
3974       for e in (self.ext_list):
3975         if (tagval): val = e.GetTag(ectx)[1]
3976         else: val = str(cnt)
3977         table += out_item(val, e, 'ASN1_NOT_EXTENSION_ROOT', ectx)
3978         cnt += 1
3979     if (ectx.Ber()):
3980       if (ectx.NewBer()):
3981         table += "  { 0, NULL, 0, 0, 0, NULL }\n};\n"
3982       else:
3983         table += "  { 0, 0, 0, 0, NULL }\n};\n"
3984     else:
3985       table += "  { 0, NULL, 0, NULL }\n};\n"
3986     return table
3987
3988   def eth_type_default_body(self, ectx, tname):
3989     if (ectx.Ber()):
3990         if (ectx.NewBer()):
3991             body = ectx.eth_fn_call('dissect_%(ER)s_choice', ret='offset',
3992                               par=(('%(ACTX)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s'),
3993                                    ('%(TABLE)s', '%(HF_INDEX)s', '%(ETT_INDEX)s'),
3994                                    ('%(VAL_PTR)s',),))
3995         else:
3996             body = ectx.eth_fn_call('dissect_%(ER)s_old_choice', ret='offset',
3997                               par=(('%(ACTX)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s'),
3998                                    ('%(TABLE)s', '%(HF_INDEX)s', '%(ETT_INDEX)s'),
3999                                    ('%(VAL_PTR)s',),))
4000     elif (ectx.Per()):
4001       body = ectx.eth_fn_call('dissect_%(ER)s_choice', ret='offset',
4002                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
4003                                    ('%(ETT_INDEX)s', '%(TABLE)s',),
4004                                    ('%(VAL_PTR)s',),))
4005     else:
4006       body = '#error Can not decode %s' % (tname)
4007     return body
4008    
4009 #--- EnumeratedType -----------------------------------------------------------
4010 class EnumeratedType (Type):
4011   def to_python (self, ctx):
4012     def strify_one (named_num):
4013       return "%s=%s" % (named_num.ident, named_num.val)
4014     return "asn1.ENUM(%s)" % ",".join (map (strify_one, self.val))
4015
4016   def eth_ftype(self, ectx):
4017     return ('FT_UINT32', 'BASE_DEC')
4018
4019   def eth_strings(self):
4020     return '$$'
4021
4022   def eth_has_vals(self):
4023     return True
4024
4025   def GetTTag(self, ectx):
4026     return ('BER_CLASS_UNI', 'BER_UNI_TAG_ENUMERATED')
4027
4028   def get_vals_etc(self, ectx):
4029     vals = []
4030     lastv = 0
4031     used = {}
4032     maxv = 0
4033     root_num = 0
4034     ext_num = 0
4035     map_table = []
4036     for e in (self.val):
4037       if e.type == 'NamedNumber':
4038         used[int(e.val)] = True
4039     for e in (self.val):
4040       if e.type == 'NamedNumber':
4041         val = int(e.val)
4042       else:
4043         while used.has_key(lastv):
4044           lastv += 1
4045         val = lastv
4046         used[val] = True
4047       vals.append((val, e.ident))
4048       map_table.append(val)
4049       root_num += 1
4050       if val > maxv:
4051         maxv = val
4052     if self.ext is not None:
4053       for e in (self.ext):
4054         if e.type == 'NamedNumber':
4055           used[int(e.val)] = True
4056       for e in (self.ext):
4057         if e.type == 'NamedNumber':
4058           val = int(e.val)
4059         else:
4060           while used.has_key(lastv):
4061             lastv += 1
4062           val = lastv
4063           used[val] = True
4064         vals.append((val, e.ident))
4065         map_table.append(val)
4066         ext_num += 1
4067         if val > maxv:
4068           maxv = val
4069     need_map = False
4070     for i in range(len(map_table)):
4071       need_map = need_map or (map_table[i] != i)
4072     if (not need_map):
4073       map_table = None
4074     return (vals, root_num, ext_num, map_table)
4075
4076   def eth_type_vals(self, tname, ectx):
4077     out = '\n'
4078     vals = self.get_vals_etc(ectx)[0]
4079     out += ectx.eth_vals(tname, vals)
4080     return out
4081
4082   def reg_enum_vals(self, tname, ectx):
4083     vals = self.get_vals_etc(ectx)[0]
4084     for (val, id) in vals:
4085       ectx.eth_reg_value(id, self, val, ethname=ectx.eth_enum_item(tname, id))
4086
4087   def eth_type_enum(self, tname, ectx):
4088     out = '\n'
4089     vals = self.get_vals_etc(ectx)[0]
4090     out += ectx.eth_enum(tname, vals)
4091     return out
4092
4093   def eth_type_default_pars(self, ectx, tname):
4094     pars = Type.eth_type_default_pars(self, ectx, tname)
4095     (root_num, ext_num, map_table) = self.get_vals_etc(ectx)[1:]
4096     if (self.ext != None):
4097       ext = 'TRUE'
4098     else:
4099       ext = 'FALSE'
4100     pars['ROOT_NUM'] = str(root_num)
4101     pars['EXT'] = ext
4102     pars['EXT_NUM'] = str(ext_num)
4103     if (map_table):
4104       pars['TABLE'] = '%(TNAME)s_value_map'
4105     else:
4106       pars['TABLE'] = 'NULL'
4107     return pars
4108
4109   def eth_type_default_table(self, ectx, tname):
4110     if (not ectx.Per()): return ''
4111     map_table = self.get_vals_etc(ectx)[3]
4112     if (map_table == None): return ''
4113     table = "static guint32 %(TABLE)s[%(ROOT_NUM)s+%(EXT_NUM)s] = {"
4114     table += ", ".join([str(v) for v in map_table])
4115     table += "};\n"
4116     return table
4117
4118   def eth_type_default_body(self, ectx, tname):
4119     if (ectx.Ber()):
4120       body = ectx.eth_fn_call('dissect_%(ER)s_integer', ret='offset',
4121                               par=(('%(IMPLICIT_TAG)s', '%(ACTX)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s', '%(HF_INDEX)s'),
4122                                    ('%(VAL_PTR)s',),))
4123     elif (ectx.Per()):
4124       body = ectx.eth_fn_call('dissect_%(ER)s_enumerated', ret='offset',
4125                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
4126                                    ('%(ROOT_NUM)s', '%(VAL_PTR)s', '%(EXT)s', '%(EXT_NUM)s', '%(TABLE)s',),))
4127     else:
4128       body = '#error Can not decode %s' % (tname)
4129     return body
4130 #--- EmbeddedPDVType -----------------------------------------------------------
4131 class EmbeddedPDVType (Type):
4132   def eth_tname(self):
4133     return 'EMBEDDED_PDV'
4134
4135   def eth_ftype(self, ectx):
4136     return ('FT_NONE', 'BASE_NONE')
4137
4138   def GetTTag(self, ectx):
4139     return ('BER_CLASS_UNI', 'BER_UNI_TAG_EMBEDDED_PDV')
4140
4141
4142   def eth_type_default_body(self, ectx, tname):
4143     body = '#error Can not decode %s' % (tname)
4144     return body
4145
4146 #--- ExternalType -----------------------------------------------------------
4147 class ExternalType (Type):
4148   def eth_tname(self):
4149     return 'EXTERNAL'
4150
4151   def eth_ftype(self, ectx):
4152     return ('FT_NONE', 'BASE_NONE')
4153
4154   def GetTTag(self, ectx):
4155     return ('BER_CLASS_UNI', 'BER_UNI_TAG_EXTERNAL')
4156
4157   def eth_type_default_pars(self, ectx, tname):
4158     pars = Type.eth_type_default_pars(self, ectx, tname)
4159     if ectx.default_external_type_cb:
4160       pars['TYPE_REF_FN'] = ectx.default_external_type_cb
4161     else:
4162       pars['TYPE_REF_FN'] = 'NULL'
4163     return pars
4164
4165   def eth_type_default_body(self, ectx, tname):
4166     if (ectx.Ber()):  
4167       body = ectx.eth_fn_call('dissect_%(ER)s_external_type', ret='offset',
4168                               par=(('%(IMPLICIT_TAG)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(HF_INDEX)s', '%(TYPE_REF_FN)s',),))
4169     elif (ectx.Per()):
4170       body = ectx.eth_fn_call('dissect_%(ER)s_external_type', ret='offset',
4171                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s', '%(TYPE_REF_FN)s',),))
4172     else:
4173       body = '#error Can not decode %s' % (tname)
4174     return body
4175
4176 #--- OpenType -----------------------------------------------------------
4177 class OpenType (Type):
4178   def to_python (self, ctx):
4179     return "asn1.ANY"
4180
4181   def single_type(self):
4182     if (self.HasConstraint() and 
4183         self.constr.type == 'Type' and 
4184         self.constr.subtype.type == 'Type_Ref'):
4185       return self.constr.subtype.val
4186     return None
4187
4188   def eth_reg_sub(self, ident, ectx):
4189     t = self.single_type()
4190     if t:
4191       ectx.eth_dep_add(ident, t)
4192
4193   def eth_tname(self):
4194     t = self.single_type()
4195     if t:
4196       return 'OpenType_' + t
4197     else:
4198       return Type.eth_tname(self)
4199
4200   def eth_ftype(self, ectx):
4201     return ('FT_NONE', 'BASE_NONE')
4202
4203   def GetTTag(self, ectx):
4204     return ('BER_CLASS_ANY', '0')
4205
4206   def eth_type_default_pars(self, ectx, tname):
4207     pars = Type.eth_type_default_pars(self, ectx, tname)
4208     pars['FN_VARIANT'] = ectx.default_opentype_variant
4209     t = self.single_type()
4210     if t:
4211       t = ectx.type[t]['ethname']
4212       pars['TYPE_REF_PROTO'] = ectx.eth_type[t]['proto']
4213       pars['TYPE_REF_TNAME'] = t
4214       pars['TYPE_REF_FN'] = 'dissect_%(TYPE_REF_PROTO)s_%(TYPE_REF_TNAME)s'
4215     else:
4216       pars['TYPE_REF_FN'] = 'NULL'
4217     return pars
4218
4219   def eth_type_default_body(self, ectx, tname):
4220     if (ectx.Per()):
4221       body = ectx.eth_fn_call('dissect_%(ER)s_open_type%(FN_VARIANT)s', ret='offset',
4222                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s', '%(TYPE_REF_FN)s',),))
4223     else:
4224       body = '#error Can not decode %s' % (tname)
4225     return body
4226
4227 #--- AnyType -----------------------------------------------------------
4228 class AnyType (Type):
4229   def to_python (self, ctx):
4230     return "asn1.ANY"
4231
4232   def eth_ftype(self, ectx):
4233     return ('FT_NONE', 'BASE_NONE')
4234
4235   def GetTTag(self, ectx):
4236     return ('BER_CLASS_ANY', '0')
4237
4238   def eth_type_default_body(self, ectx, tname):
4239     body = '#error Can not decode %s' % (tname)
4240     return body
4241
4242 class Literal (Node):
4243     def to_python (self, ctx):
4244         return self.val
4245
4246 #--- NullType -----------------------------------------------------------------
4247 class NullType (Type):
4248   def to_python (self, ctx):
4249     return 'asn1.NULL'
4250
4251   def eth_tname(self):
4252     return 'NULL'
4253
4254   def GetTTag(self, ectx):
4255     return ('BER_CLASS_UNI', 'BER_UNI_TAG_NULL')
4256
4257   def eth_type_default_body(self, ectx, tname):
4258     if (ectx.Ber()):
4259       body = ectx.eth_fn_call('dissect_%(ER)s_null', ret='offset',
4260                               par=(('%(IMPLICIT_TAG)s', '%(ACTX)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s', '%(HF_INDEX)s'),))
4261     elif (ectx.Per()):
4262       body = ectx.eth_fn_call('dissect_%(ER)s_null', ret='offset',
4263                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),))
4264     else:
4265       body = '#error Can not decode %s' % (tname)
4266     return body
4267
4268 #--- RealType -----------------------------------------------------------------
4269 class RealType (Type):
4270   def to_python (self, ctx):
4271     return 'asn1.REAL'
4272
4273   def eth_tname(self):
4274     return 'REAL'
4275
4276   def GetTTag(self, ectx):
4277     return ('BER_CLASS_UNI', 'BER_UNI_TAG_REAL')
4278
4279   def eth_ftype(self, ectx):
4280     return ('FT_DOUBLE', 'BASE_NONE')
4281
4282   def eth_type_default_body(self, ectx, tname):
4283     if (ectx.Ber()):
4284       body = ectx.eth_fn_call('dissect_%(ER)s_real', ret='offset',
4285                               par=(('%(IMPLICIT_TAG)s', '%(ACTX)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s', '%(HF_INDEX)s'),
4286                                    ('%(VAL_PTR)s',),))
4287     elif (ectx.Per()):
4288       body = ectx.eth_fn_call('dissect_%(ER)s_real', ret='offset',
4289                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s', '%(VAL_PTR)s',),))
4290     else:
4291       body = '#error Can not decode %s' % (tname)
4292     return body
4293
4294 #--- BooleanType --------------------------------------------------------------
4295 class BooleanType (Type):
4296   def to_python (self, ctx):
4297     return 'asn1.BOOLEAN'
4298
4299   def eth_tname(self):
4300     return 'BOOLEAN'
4301
4302   def GetTTag(self, ectx):
4303     return ('BER_CLASS_UNI', 'BER_UNI_TAG_BOOLEAN')
4304
4305   def eth_ftype(self, ectx):
4306     return ('FT_BOOLEAN', '8')
4307
4308   def eth_type_default_body(self, ectx, tname):
4309     if (ectx.Ber()):
4310       body = ectx.eth_fn_call('dissect_%(ER)s_boolean', ret='offset',
4311                               par=(('%(IMPLICIT_TAG)s', '%(ACTX)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s', '%(HF_INDEX)s'),))
4312     elif (ectx.Per()):
4313       body = ectx.eth_fn_call('dissect_%(ER)s_boolean', ret='offset',
4314                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s', '%(VAL_PTR)s',),))
4315     else:
4316       body = '#error Can not decode %s' % (tname)
4317     return body
4318
4319 #--- OctetStringType ----------------------------------------------------------
4320 class OctetStringType (Type):
4321   def to_python (self, ctx):
4322     return 'asn1.OCTSTRING'
4323
4324   def eth_tname(self):
4325     if not self.HasConstraint():
4326       return 'OCTET_STRING'
4327     elif self.constr.type == 'Size':
4328       return 'OCTET_STRING' + '_' + self.constr.eth_constrname()
4329     else:
4330       return '#' + self.type + '_' + str(id(self))
4331
4332   def eth_ftype(self, ectx):
4333     return ('FT_BYTES', 'BASE_HEX')
4334
4335   def GetTTag(self, ectx):
4336     return ('BER_CLASS_UNI', 'BER_UNI_TAG_OCTETSTRING')
4337
4338   def eth_need_pdu(self, ectx):
4339     pdu = None
4340     if self.HasContentsConstraint():
4341       t = self.constr.GetContents(ectx)
4342       if t and (ectx.default_containing_variant in ('_pdu', '_pdu_new')):
4343         pdu = { 'type' : t,
4344                 'new' : ectx.default_containing_variant == '_pdu_new' }
4345     return pdu
4346
4347   def eth_type_default_pars(self, ectx, tname):
4348     pars = Type.eth_type_default_pars(self, ectx, tname)
4349     (pars['MIN_VAL'], pars['MAX_VAL'], pars['EXT']) = self.eth_get_size_constr(ectx)
4350     if self.HasContentsConstraint():
4351       pars['FN_VARIANT'] = ectx.default_containing_variant
4352       t = self.constr.GetContents(ectx)
4353       if t:
4354         if pars['FN_VARIANT'] in ('_pdu', '_pdu_new'):
4355           t = ectx.field[t]['ethname']
4356           pars['TYPE_REF_PROTO'] = ''
4357           pars['TYPE_REF_TNAME'] = t
4358           pars['TYPE_REF_FN'] = 'dissect_%(TYPE_REF_TNAME)s'
4359         else:
4360           t = ectx.type[t]['ethname']
4361           pars['TYPE_REF_PROTO'] = ectx.eth_type[t]['proto']
4362           pars['TYPE_REF_TNAME'] = t
4363           pars['TYPE_REF_FN'] = 'dissect_%(TYPE_REF_PROTO)s_%(TYPE_REF_TNAME)s'
4364       else:
4365         pars['TYPE_REF_FN'] = 'NULL'
4366     return pars
4367
4368   def eth_type_default_body(self, ectx, tname):
4369     if (ectx.Ber()):
4370       body = ectx.eth_fn_call('dissect_%(ER)s_octet_string', ret='offset',
4371                               par=(('%(IMPLICIT_TAG)s', '%(ACTX)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s', '%(HF_INDEX)s'),
4372                                    ('%(VAL_PTR)s',),))
4373     elif (ectx.Per()):
4374       if self.HasContentsConstraint():
4375         body = ectx.eth_fn_call('dissect_%(ER)s_octet_string_containing%(FN_VARIANT)s', ret='offset',
4376                                 par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
4377                                      ('%(MIN_VAL)s', '%(MAX_VAL)s', '%(TYPE_REF_FN)s',),))
4378       else:
4379         body = ectx.eth_fn_call('dissect_%(ER)s_octet_string', ret='offset',
4380                                 par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
4381                                      ('%(MIN_VAL)s', '%(MAX_VAL)s', '%(VAL_PTR)s',),))
4382     else:
4383       body = '#error Can not decode %s' % (tname)
4384     return body
4385
4386 #--- CharacterStringType ------------------------------------------------------
4387 class CharacterStringType (Type):
4388   def eth_tname(self):
4389     if not self.HasConstraint():
4390       return self.eth_tsname()
4391     elif self.constr.type == 'Size':
4392       return self.eth_tsname() + '_' + self.constr.eth_constrname()
4393     else:
4394       return '#' + self.type + '_' + str(id(self))
4395
4396   def eth_ftype(self, ectx):
4397     return ('FT_STRING', 'BASE_NONE')
4398
4399 class RestrictedCharacterStringType (CharacterStringType):
4400   def to_python (self, ctx):
4401     return 'asn1.' + self.eth_tsname()
4402
4403   def GetTTag(self, ectx):
4404     return ('BER_CLASS_UNI', 'BER_UNI_TAG_' + self.eth_tsname())
4405
4406   def eth_type_default_pars(self, ectx, tname):
4407     pars = Type.eth_type_default_pars(self, ectx, tname)
4408     (pars['MIN_VAL'], pars['MAX_VAL'], pars['EXT']) = self.eth_get_size_constr(ectx)
4409     (pars['STRING_TYPE'], pars['STRING_TAG']) = (self.eth_tsname(), self.GetTTag(ectx)[1])
4410     (pars['ALPHABET'], pars['ALPHABET_LEN']) = self.eth_get_alphabet_constr(ectx)
4411     return pars
4412
4413   def eth_type_default_body(self, ectx, tname):
4414     if (ectx.Ber()):
4415       body = ectx.eth_fn_call('dissect_%(ER)s_restricted_string', ret='offset',
4416                               par=(('%(IMPLICIT_TAG)s', '%(STRING_TAG)s'),
4417                                    ('%(ACTX)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s', '%(HF_INDEX)s'),
4418                                    ('%(VAL_PTR)s',),))
4419     elif (ectx.Per() and self.HasPermAlph()):
4420       body = ectx.eth_fn_call('dissect_%(ER)s_restricted_character_string', ret='offset',
4421                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
4422                                    ('%(MIN_VAL)s', '%(MAX_VAL)s', '%(ALPHABET)s', '%(ALPHABET_LEN)s'),
4423                                    ('%(VAL_PTR)s',),))
4424     elif (ectx.Per()):
4425       if (self.eth_tsname() == 'GeneralString'):
4426         body = ectx.eth_fn_call('dissect_%(ER)s_%(STRING_TYPE)s', ret='offset',
4427                                 par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),))
4428       elif (self.eth_tsname() == 'GeneralizedTime'):
4429         body = ectx.eth_fn_call('dissect_%(ER)s_VisibleString', ret='offset',
4430                                 par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
4431                                      ('%(MIN_VAL)s', '%(MAX_VAL)s',),))
4432       elif (self.eth_tsname() == 'UTCTime'):
4433         body = ectx.eth_fn_call('dissect_%(ER)s_VisibleString', ret='offset',
4434                                 par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
4435                                      ('%(MIN_VAL)s', '%(MAX_VAL)s',),))
4436       else:
4437         body = ectx.eth_fn_call('dissect_%(ER)s_%(STRING_TYPE)s', ret='offset',
4438                                 par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
4439                                      ('%(MIN_VAL)s', '%(MAX_VAL)s',),))
4440     else:
4441       body = '#error Can not decode %s' % (tname)
4442     return body
4443
4444 class BMPStringType (RestrictedCharacterStringType):
4445   def eth_tsname(self):
4446     return 'BMPString'
4447
4448 class GeneralStringType (RestrictedCharacterStringType):
4449   def eth_tsname(self):
4450     return 'GeneralString'
4451
4452 class GraphicStringType (RestrictedCharacterStringType):
4453   def eth_tsname(self):
4454     return 'GraphicString'
4455
4456 class IA5StringType (RestrictedCharacterStringType):
4457   def eth_tsname(self):
4458     return 'IA5String'
4459
4460 class NumericStringType (RestrictedCharacterStringType):
4461   def eth_tsname(self):
4462     return 'NumericString'
4463
4464 class PrintableStringType (RestrictedCharacterStringType):
4465   def eth_tsname(self):
4466     return 'PrintableString'
4467
4468 class TeletexStringType (RestrictedCharacterStringType):
4469   def eth_tsname(self):
4470     return 'TeletexString'
4471
4472 class T61StringType (RestrictedCharacterStringType):
4473   def eth_tsname(self):
4474     return 'T61String'
4475   def GetTTag(self, ectx):
4476     return ('BER_CLASS_UNI', 'BER_UNI_TAG_TeletexString')
4477
4478 class UniversalStringType (RestrictedCharacterStringType):
4479   def eth_tsname(self):
4480     return 'UniversalString'
4481
4482 class UTF8StringType (RestrictedCharacterStringType):
4483   def eth_tsname(self):
4484     return 'UTF8String'
4485
4486 class VideotexStringType (RestrictedCharacterStringType):
4487   def eth_tsname(self):
4488     return 'VideotexString'
4489
4490 class VisibleStringType (RestrictedCharacterStringType):
4491   def eth_tsname(self):
4492     return 'VisibleString'
4493
4494 class ISO646StringType (RestrictedCharacterStringType):
4495   def eth_tsname(self):
4496     return 'ISO646String'
4497   def GetTTag(self, ectx):
4498     return ('BER_CLASS_UNI', 'BER_UNI_TAG_VisibleString')
4499
4500 class UnrestrictedCharacterStringType (CharacterStringType):
4501   def to_python (self, ctx):
4502     return 'asn1.UnrestrictedCharacterString'
4503   def eth_tsname(self):
4504     return 'CHARACTER_STRING'
4505
4506 #--- UsefulType ---------------------------------------------------------------
4507 class GeneralizedTime (RestrictedCharacterStringType):
4508   def eth_tsname(self):
4509     return 'GeneralizedTime'
4510
4511   def eth_type_default_body(self, ectx, tname):
4512     if (ectx.Ber()):
4513       body = ectx.eth_fn_call('dissect_%(ER)s_%(STRING_TYPE)s', ret='offset',
4514                               par=(('%(IMPLICIT_TAG)s', '%(ACTX)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s', '%(HF_INDEX)s'),))
4515       return body
4516     else:
4517       return RestrictedCharacterStringType.eth_type_default_body(self, ectx, tname)
4518
4519 class UTCTime (RestrictedCharacterStringType):
4520   def eth_tsname(self):
4521     return 'UTCTime'
4522
4523 class ObjectDescriptor (RestrictedCharacterStringType):
4524   def eth_tsname(self):
4525     return 'ObjectDescriptor'
4526
4527   def eth_type_default_body(self, ectx, tname):
4528     if (ectx.Ber()):
4529       body = RestrictedCharacterStringType.eth_type_default_body(self, ectx, tname)
4530     elif (ectx.Per()):
4531       body = ectx.eth_fn_call('dissect_%(ER)s_object_descriptor', ret='offset',
4532                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s', '%(VAL_PTR)s',),))
4533     else:
4534       body = '#error Can not decode %s' % (tname)
4535     return body
4536
4537 #--- ObjectIdentifierType -----------------------------------------------------
4538 class ObjectIdentifierType (Type):
4539   def to_python (self, ctx):
4540     return 'asn1.OBJECT_IDENTIFIER'
4541
4542   def eth_tname(self):
4543     return 'OBJECT_IDENTIFIER'
4544
4545   def eth_ftype(self, ectx):
4546     return ('FT_OID', 'BASE_NONE')
4547
4548   def GetTTag(self, ectx):
4549     return ('BER_CLASS_UNI', 'BER_UNI_TAG_OID')
4550
4551   def eth_type_default_pars(self, ectx, tname):
4552     pars = Type.eth_type_default_pars(self, ectx, tname)
4553     pars['FN_VARIANT'] = ectx.default_oid_variant
4554     return pars
4555
4556   def eth_type_default_body(self, ectx, tname):
4557     if (ectx.Ber()):
4558       body = ectx.eth_fn_call('dissect_%(ER)s_object_identifier%(FN_VARIANT)s', ret='offset',
4559                               par=(('%(IMPLICIT_TAG)s', '%(ACTX)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s', '%(HF_INDEX)s', '%(VAL_PTR)s',),))
4560     elif (ectx.Per()):
4561       body = ectx.eth_fn_call('dissect_%(ER)s_object_identifier%(FN_VARIANT)s', ret='offset',
4562                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s', '%(VAL_PTR)s',),))
4563     else:
4564       body = '#error Can not decode %s' % (tname)
4565     return body
4566
4567 #--- ObjectIdentifierValue ----------------------------------------------------
4568 class ObjectIdentifierValue (Value):
4569   def get_num(self, path, val):
4570     return str(oid_names.get(path + '/' + val, val))
4571
4572   def to_str(self, ectx):
4573     out = ''
4574     path = ''
4575     first = True
4576     sep = ''
4577     for v in self.comp_list:
4578       if isinstance(v, Node) and (v.type == 'name_and_number'):
4579         vstr = v.number
4580       elif v.isdigit():
4581         vstr = v
4582       else:
4583         vstr = self.get_num(path, v)
4584       if not first and not vstr.isdigit():
4585         vstr = ectx.value_get_val(vstr)
4586       if first:
4587         if vstr.isdigit():
4588           out += '"' + vstr
4589         else:
4590           out += ectx.value_get_eth(vstr) + '"'
4591       else:
4592        out += sep + vstr
4593       path += sep + vstr
4594       first = False
4595       sep = '.'
4596     out += '"'
4597     return out
4598
4599   def get_dep(self):
4600     v = self.comp_list[0]
4601     if isinstance(v, Node) and (v.type == 'name_and_number'):
4602       return None
4603     elif v.isdigit():
4604       return None
4605     else:
4606       vstr = self.get_num('', v)
4607     if vstr.isdigit():
4608       return None
4609     else:
4610       return vstr
4611
4612 class NamedNumber(Node):
4613     def to_python (self, ctx):
4614         return "('%s',%s)" % (self.ident, self.val)
4615
4616 class NamedNumListBase(Node):
4617     def to_python (self, ctx):
4618         return "asn1.%s_class ([%s])" % (self.asn1_typ,",".join (
4619             map (lambda x: x.to_python (ctx), self.named_list)))
4620
4621 #--- IntegerType --------------------------------------------------------------
4622 class IntegerType (Type):
4623   def to_python (self, ctx):
4624         return "asn1.INTEGER_class ([%s])" % (",".join (
4625             map (lambda x: x.to_python (ctx), self.named_list)))
4626
4627   def add_named_value(self, ident, val):
4628     e = NamedNumber(ident = ident, val = val)
4629     if not self.named_list: 
4630       self.named_list = []
4631     self.named_list.append(e)
4632
4633   def eth_tname(self):
4634     if self.named_list:
4635       return Type.eth_tname(self)
4636     if not self.HasConstraint():
4637       return 'INTEGER'
4638     elif self.constr.type == 'SingleValue' or self.constr.type == 'ValueRange':
4639       return 'INTEGER' + '_' + self.constr.eth_constrname()
4640     else:
4641       return 'INTEGER' + '_' + self.constr.eth_tname()
4642
4643   def GetTTag(self, ectx):
4644     return ('BER_CLASS_UNI', 'BER_UNI_TAG_INTEGER')
4645
4646
4647   def eth_ftype(self, ectx):
4648     if self.HasConstraint():
4649       if not self.constr.IsNegativ():
4650         return ('FT_UINT32', 'BASE_DEC')
4651     return ('FT_INT32', 'BASE_DEC')
4652
4653   def eth_strings(self):
4654     if (self.named_list):
4655       return '$$'
4656     else:
4657       return 'NULL'
4658
4659   def eth_has_vals(self):
4660     if (self.named_list):
4661       return True
4662     else:
4663       return False
4664
4665   def get_vals(self, ectx):
4666     vals = []
4667     for e in (self.named_list):
4668       vals.append((int(e.val), e.ident))
4669     return vals
4670
4671   def eth_type_vals(self, tname, ectx):
4672     if not self.eth_has_vals(): return ''
4673     out = '\n'
4674     vals = self.get_vals(ectx)
4675     out += ectx.eth_vals(tname, vals)
4676     return out
4677
4678   def reg_enum_vals(self, tname, ectx):
4679     vals = self.get_vals(ectx)
4680     for (val, id) in vals:
4681       ectx.eth_reg_value(id, self, val, ethname=ectx.eth_enum_item(tname, id))
4682
4683   def eth_type_enum(self, tname, ectx):
4684     if not self.eth_has_enum(tname, ectx): return ''
4685     out = '\n'
4686     vals = self.get_vals(ectx)
4687     out += ectx.eth_enum(tname, vals)
4688     return out
4689
4690   def eth_type_default_pars(self, ectx, tname):
4691     pars = Type.eth_type_default_pars(self, ectx, tname)
4692     if self.HasValueConstraint():
4693       (pars['MIN_VAL'], pars['MAX_VAL'], pars['EXT']) = self.eth_get_value_constr(ectx)
4694     return pars
4695
4696   def eth_type_default_body(self, ectx, tname):
4697     if (ectx.Ber()):
4698       body = ectx.eth_fn_call('dissect_%(ER)s_integer', ret='offset',
4699                               par=(('%(IMPLICIT_TAG)s', '%(ACTX)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s', '%(HF_INDEX)s'),
4700                                    ('%(VAL_PTR)s',),))
4701     elif (ectx.Per() and not self.HasValueConstraint()):
4702       body = ectx.eth_fn_call('dissect_%(ER)s_integer', ret='offset',
4703                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s', '%(VAL_PTR)s'),))
4704     elif (ectx.Per() and self.HasValueConstraint()):
4705       body = ectx.eth_fn_call('dissect_%(ER)s_constrained_integer', ret='offset',
4706                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
4707                                    ('%(MIN_VAL)s', '%(MAX_VAL)s', '%(VAL_PTR)s', '%(EXT)s'),))
4708     else:
4709       body = '#error Can not decode %s' % (tname)
4710     return body
4711
4712 #--- BitStringType ------------------------------------------------------------
4713 class BitStringType (Type):
4714   def to_python (self, ctx):
4715         return "asn1.BITSTRING_class ([%s])" % (",".join (
4716             map (lambda x: x.to_python (ctx), self.named_list)))
4717
4718   def eth_tname(self):
4719     if self.named_list:
4720       return Type.eth_tname(self)
4721     elif not self.HasConstraint():
4722       return 'BIT_STRING'
4723     elif self.constr.IsSize():
4724       return 'BIT_STRING' + '_' + self.constr.eth_constrname()
4725     else:
4726       return '#' + self.type + '_' + str(id(self))
4727
4728   def GetTTag(self, ectx):
4729     return ('BER_CLASS_UNI', 'BER_UNI_TAG_BITSTRING')
4730
4731   def eth_ftype(self, ectx):
4732     return ('FT_BYTES', 'BASE_HEX')
4733
4734   def eth_need_tree(self):
4735     return self.named_list
4736
4737   def eth_need_pdu(self, ectx):
4738     pdu = None
4739     if self.HasContentsConstraint():
4740       t = self.constr.GetContents(ectx)
4741       if t and (ectx.default_containing_variant in ('_pdu', '_pdu_new')):
4742         pdu = { 'type' : t,
4743                 'new' : ectx.default_containing_variant == '_pdu_new' }
4744     return pdu
4745
4746   def eth_named_bits(self):
4747     bits = []
4748     if (self.named_list):
4749       for e in (self.named_list):
4750         bits.append((int(e.val), e.ident))
4751     return bits
4752
4753   def eth_type_default_pars(self, ectx, tname):
4754     pars = Type.eth_type_default_pars(self, ectx, tname)
4755     (pars['MIN_VAL'], pars['MAX_VAL'], pars['EXT']) = self.eth_get_size_constr(ectx)
4756     if not pars.has_key('ETT_INDEX'):
4757       pars['ETT_INDEX'] = '-1'
4758     pars['TABLE'] = 'NULL'
4759     if self.eth_named_bits():
4760       pars['TABLE'] = '%(TNAME)s_bits'
4761     if self.HasContentsConstraint():
4762       pars['FN_VARIANT'] = ectx.default_containing_variant
4763       t = self.constr.GetContents(ectx)
4764       if t:
4765         if pars['FN_VARIANT'] in ('_pdu', '_pdu_new'):
4766           t = ectx.field[t]['ethname']
4767           pars['TYPE_REF_PROTO'] = ''
4768           pars['TYPE_REF_TNAME'] = t
4769           pars['TYPE_REF_FN'] = 'dissect_%(TYPE_REF_TNAME)s'
4770         else:
4771           t = ectx.type[t]['ethname']
4772           pars['TYPE_REF_PROTO'] = ectx.eth_type[t]['proto']
4773           pars['TYPE_REF_TNAME'] = t
4774           pars['TYPE_REF_FN'] = 'dissect_%(TYPE_REF_PROTO)s_%(TYPE_REF_TNAME)s'
4775       else:
4776         pars['TYPE_REF_FN'] = 'NULL'
4777     return pars
4778
4779   def eth_type_default_table(self, ectx, tname):
4780     #print "eth_type_default_table(tname='%s')" % (tname)
4781     table = ''
4782     bits = self.eth_named_bits()
4783     if (bits):
4784       table = ectx.eth_bits(tname, bits)
4785     return table
4786
4787   def eth_type_default_body(self, ectx, tname):
4788     if (ectx.Ber()):
4789       body = ectx.eth_fn_call('dissect_%(ER)s_bitstring', ret='offset',
4790                               par=(('%(IMPLICIT_TAG)s', '%(ACTX)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s'),
4791                                    ('%(TABLE)s', '%(HF_INDEX)s', '%(ETT_INDEX)s',),
4792                                    ('%(VAL_PTR)s',),))
4793     elif (ectx.Per()):
4794       if self.HasContentsConstraint():
4795         body = ectx.eth_fn_call('dissect_%(ER)s_bit_string_containing%(FN_VARIANT)s', ret='offset',
4796                                 par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
4797                                      ('%(MIN_VAL)s', '%(MAX_VAL)s', '%(EXT)s', '%(TYPE_REF_FN)s'),))
4798       else:
4799         body = ectx.eth_fn_call('dissect_%(ER)s_bit_string', ret='offset',
4800                                 par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
4801                                      ('%(MIN_VAL)s', '%(MAX_VAL)s', '%(EXT)s', '%(VAL_PTR)s'),))
4802     else:
4803       body = '#error Can not decode %s' % (tname)
4804     return body
4805
4806 #--- BStringValue ------------------------------------------------------------
4807 bstring_tab = {
4808   '0000' : '0',
4809   '0001' : '1',
4810   '0010' : '2',
4811   '0011' : '3',
4812   '0100' : '4',
4813   '0101' : '5',
4814   '0110' : '6',
4815   '0111' : '7',
4816   '1000' : '8',
4817   '1001' : '9',
4818   '1010' : 'A',
4819   '1011' : 'B',
4820   '1100' : 'C',
4821   '1101' : 'D',
4822   '1110' : 'E',
4823   '1111' : 'F',
4824 }
4825 class BStringValue (Value):
4826   def to_str(self, ectx):
4827     v = self.val[1:-2]
4828     if len(v) % 8:
4829       v += '0' * (8 - len(v) % 8)
4830     vv = '0x'
4831     for i in (range(0, len(v), 4)):
4832       vv += bstring_tab[v[i:i+4]]
4833     return vv
4834
4835 #==============================================================================
4836     
4837 def p_module_list_1 (t):
4838     'module_list : module_list ModuleDefinition'
4839     t[0] = t[1] + [t[2]]
4840
4841 def p_module_list_2 (t):
4842     'module_list : ModuleDefinition'
4843     t[0] = [t[1]]
4844
4845
4846 #--- ITU-T Recommendation X.680 -----------------------------------------------
4847
4848
4849 # 11 ASN.1 lexical items --------------------------------------------------------
4850
4851 # 11.2 Type references
4852 def p_type_ref (t):
4853   'type_ref : UCASE_IDENT'
4854   t[0] = Type_Ref(val=t[1])
4855
4856 # 11.3 Identifiers
4857 def p_identifier (t):
4858   'identifier : LCASE_IDENT'
4859   t[0] = t[1]
4860
4861 # 11.4 Value references
4862 def p_valuereference (t):
4863   'valuereference : LCASE_IDENT'
4864   t[0] = t[1]
4865
4866 # 11.5 Module references
4867 def p_modulereference (t):
4868   'modulereference : UCASE_IDENT'
4869   t[0] = t[1]
4870
4871
4872 # 12 Module definition --------------------------------------------------------
4873
4874 # 12.1
4875 def p_ModuleDefinition (t):
4876   'ModuleDefinition : ModuleIdentifier DEFINITIONS TagDefault ASSIGNMENT BEGIN ModuleBody END'
4877   t[0] = Module (ident = t[1], tag_def = t[3], body = t[6])
4878
4879 def p_TagDefault_1 (t):
4880   '''TagDefault : EXPLICIT TAGS
4881   | IMPLICIT TAGS
4882   | AUTOMATIC TAGS'''
4883   t[0] = Default_Tags (dfl_tag = t[1])
4884
4885 def p_TagDefault_2 (t):
4886   'TagDefault : '
4887   # 12.2 The "TagDefault" is taken as EXPLICIT TAGS if it is "empty".
4888   t[0] = Default_Tags (dfl_tag = 'EXPLICIT') 
4889
4890 def p_ModuleIdentifier_1 (t):
4891   'ModuleIdentifier : modulereference DefinitiveIdentifier' # name, oid
4892   t [0] = Node('module_ident', val = t[1], ident = t[2])
4893
4894 def p_ModuleIdentifier_2 (t):
4895   'ModuleIdentifier : modulereference' # name, oid
4896   t [0] = Node('module_ident', val = t[1], ident = None)
4897
4898 def p_DefinitiveIdentifier (t):
4899   'DefinitiveIdentifier : ObjectIdentifierValue'
4900   t[0] = t[1]
4901
4902 #def p_module_ref (t):
4903 #    'module_ref : UCASE_IDENT'
4904 #    t[0] = t[1]
4905
4906 def p_ModuleBody_1 (t):
4907   'ModuleBody : Exports Imports AssignmentList'
4908   t[0] = Module_Body (exports = t[1], imports = t[2], assign_list = t[3])
4909
4910 def p_ModuleBody_2 (t):
4911   'ModuleBody : '
4912   t[0] = Node ('module_body', exports = [], imports = [], assign_list = [])
4913
4914 def p_Exports_1 (t):
4915     'Exports : EXPORTS syms_exported SEMICOLON'
4916     t[0] = t[2]
4917
4918 def p_Exports_2 (t):
4919     'Exports : EXPORTS ALL SEMICOLON'
4920     t[0] = [ 'ALL' ]
4921
4922 def p_Exports_3 (t):
4923     'Exports : '
4924     t[0] = [ 'ALL' ]
4925
4926 def p_syms_exported_1 (t):
4927     'syms_exported : exp_sym_list'
4928     t[0] = t[1]
4929
4930 def p_syms_exported_2 (t):
4931     'syms_exported : '
4932     t[0] = []
4933
4934 def p_exp_sym_list_1 (t):
4935     'exp_sym_list : Symbol'
4936     t[0] = [t[1]]
4937
4938 def p_exp_sym_list_2 (t):
4939     'exp_sym_list : exp_sym_list COMMA Symbol'
4940     t[0] = t[1] + [t[3]]
4941     
4942
4943 def p_Imports_1 (t):
4944   'Imports : IMPORTS SymbolsImported SEMICOLON'
4945   t[0] = t[2]
4946   global lcase_ident_assigned
4947   lcase_ident_assigned = {}
4948
4949 def p_Imports_2 (t):
4950   'Imports : '
4951   t[0] = []
4952
4953 def p_SymbolsImported_1(t):
4954   'SymbolsImported : '
4955   t[0] = []
4956
4957 def p_SymbolsImported_2 (t):
4958   'SymbolsImported : SymbolsFromModuleList'
4959   t[0] = t[1]
4960
4961 def p_SymbolsFromModuleList_1 (t):
4962    'SymbolsFromModuleList : SymbolsFromModuleList SymbolsFromModule'
4963    t[0] = t[1] + [t[2]]
4964
4965 def p_SymbolsFromModuleList_2 (t):
4966    'SymbolsFromModuleList : SymbolsFromModule'
4967    t[0] = [t[1]]
4968
4969 def p_SymbolsFromModule (t):
4970   'SymbolsFromModule : SymbolList FROM GlobalModuleReference'
4971   t[0] = Node ('SymbolList', symbol_list = t[1], module = t[3])
4972   for s in (t[0].symbol_list): 
4973     if (isinstance(s, str) and s[0].islower()): lcase_ident_assigned[s] = t[3]
4974   if t[0].module.val == 'Remote-Operations-Information-Objects':
4975     for i in range(len(t[0].symbol_list)):
4976       s = t[0].symbol_list[i]
4977       if isinstance(s, Type_Ref) or isinstance(s, Class_Ref):
4978         x880_import(s.val)
4979         if isinstance(s, Type_Ref) and is_class_ident(s.val):
4980           t[0].symbol_list[i] = Class_Ref (val = s.val)
4981
4982 def p_GlobalModuleReference (t):
4983   'GlobalModuleReference : modulereference AssignedIdentifier'
4984   t [0] = Node('module_ident', val = t[1], ident = t[2])
4985
4986 def p_AssignedIdentifier_1 (t):
4987   'AssignedIdentifier : ObjectIdentifierValue'
4988   t[0] = t[1]
4989
4990 def p_AssignedIdentifier_2 (t):
4991   'AssignedIdentifier : LCASE_IDENT_ASSIGNED'
4992   t[0] = t[1]
4993
4994 def p_AssignedIdentifier_3 (t):
4995   'AssignedIdentifier : '
4996   pass
4997
4998 def p_SymbolList_1 (t):
4999   'SymbolList : Symbol'
5000   t[0] = [t[1]]
5001
5002 def p_SymbolList_2 (t):
5003   'SymbolList : SymbolList COMMA Symbol'
5004   t[0] = t[1] + [t[3]]
5005
5006 def p_Symbol (t):
5007   '''Symbol : Reference
5008             | ParameterizedReference'''
5009   t[0] = t[1]
5010
5011 def p_Reference (t):
5012   '''Reference : type_ref
5013                | valuereference
5014                | objectclassreference'''
5015   t[0] = t[1]
5016
5017 def p_AssignmentList_1 (t):
5018   'AssignmentList : AssignmentList Assignment'
5019   t[0] = t[1] + [t[2]]
5020
5021 def p_AssignmentList_2 (t):
5022   'AssignmentList : Assignment SEMICOLON'
5023   t[0] = [t[1]]
5024
5025 def p_AssignmentList_3 (t):
5026   'AssignmentList : Assignment'
5027   t[0] = [t[1]]
5028
5029 def p_Assignment (t):
5030   '''Assignment : TypeAssignment
5031                 | ValueAssignment
5032                 | ObjectClassAssignment
5033                 | ObjectAssignment
5034                 | ObjectSetAssignment
5035                 | ParameterizedTypeAssignment
5036                 | pyquote'''
5037   t[0] = t[1]
5038
5039
5040 # 13 Referencing type and value definitions -----------------------------------
5041
5042 # 13.1
5043 def p_DefinedType (t): 
5044   '''DefinedType : ExternalTypeReference
5045                  | type_ref
5046                  | ParameterizedType'''
5047   t[0] = t[1]
5048
5049 def p_DefinedValue(t):
5050   '''DefinedValue : ExternalValueReference
5051                   | identifier'''
5052   t[0] = t[1]
5053
5054 # 13.6
5055 def p_ExternalTypeReference (t):
5056   'ExternalTypeReference : modulereference DOT type_ref'
5057   t[0] = Node ('ExternalTypeReference', module = t[1], typ = t[3])
5058
5059 def p_ExternalValueReference (t):
5060   'ExternalValueReference : modulereference DOT identifier'
5061   t[0] = Node ('ExternalValueReference', module = t[1], ident = t[3])
5062
5063
5064 # 15 Assigning types and values -----------------------------------------------
5065
5066 # 15.1
5067 def p_TypeAssignment (t):
5068   'TypeAssignment : UCASE_IDENT ASSIGNMENT Type'
5069   t[0] = t[3]
5070   t[0].SetName(t[1])
5071
5072 # 15.2
5073 def p_ValueAssignment (t):
5074   'ValueAssignment : valuereference ValueType ASSIGNMENT Value'
5075   t[0] = value_assign (ident = t[1], typ = t[2], val = t[4])
5076
5077 # only "simple" types are supported to simplify grammer
5078 def p_ValueType (t):
5079   '''ValueType : type_ref
5080                | BooleanType
5081                | IntegerType
5082                | ObjectIdentifierType
5083                | OctetStringType
5084                | RealType'''
5085
5086   t[0] = t[1]
5087
5088
5089 # 16 Definition of types and values -------------------------------------------
5090
5091 # 16.1
5092 def p_Type (t):
5093   '''Type : BuiltinType
5094           | ReferencedType
5095           | ConstrainedType'''
5096   t[0] = t[1]
5097
5098 # 16.2
5099 def p_BuiltinType (t):
5100   '''BuiltinType : AnyType
5101                  | BitStringType
5102                  | BooleanType
5103                  | CharacterStringType
5104                  | ChoiceType
5105                  | EmbeddedPDVType
5106                  | EnumeratedType
5107                  | ExternalType
5108                  | IntegerType
5109                  | NullType
5110                  | ObjectClassFieldType
5111                  | ObjectIdentifierType
5112                  | OctetStringType
5113                  | RealType
5114                  | SequenceType
5115                  | SequenceOfType
5116                  | SetType
5117                  | SetOfType
5118                  | TaggedType'''
5119   t[0] = t[1]
5120
5121 # 16.3
5122 def p_ReferencedType (t):
5123   '''ReferencedType : DefinedType
5124                     | UsefulType
5125                     | SelectionType'''
5126   t[0] = t[1]
5127
5128 # 16.5
5129 def p_NamedType (t):
5130   'NamedType : identifier Type'
5131   t[0] = t[2]
5132   t[0].SetName (t[1]) 
5133
5134 # 16.7
5135 def p_Value (t):
5136   '''Value : BuiltinValue
5137            | ReferencedValue'''
5138   t[0] = t[1]
5139
5140 # 16.9
5141 def p_BuiltinValue (t):
5142   '''BuiltinValue : BooleanValue
5143                   | IntegerValue
5144                   | ObjectIdentifierValue
5145                   | RealValue
5146                   | SequenceValue
5147                   | hex_string
5148                   | binary_string
5149                   | char_string''' # XXX we don't support {data} here
5150   t[0] = t[1]
5151
5152 # 16.11
5153 def p_ReferencedValue (t):
5154   '''ReferencedValue : DefinedValue'''
5155   t[0] = t[1]
5156
5157 # 16.13
5158 #def p_NamedValue (t):
5159 #  'NamedValue : identifier Value'
5160 #  t[0] = Node ('NamedValue', ident = t[1], value = t[2])
5161
5162
5163 # 17 Notation for the boolean type --------------------------------------------
5164
5165 # 17.1
5166 def p_BooleanType (t):
5167   'BooleanType : BOOLEAN'
5168   t[0] = BooleanType ()
5169
5170 # 17.2
5171 def p_BooleanValue (t):
5172   '''BooleanValue : TRUE
5173                   | FALSE'''
5174   t[0] = t[1]
5175
5176
5177 # 18 Notation for the integer type --------------------------------------------
5178
5179 # 18.1
5180 def p_IntegerType_1 (t):
5181   'IntegerType : INTEGER'
5182   t[0] = IntegerType (named_list = None)
5183
5184 def p_IntegerType_2 (t):
5185   'IntegerType : INTEGER LBRACE NamedNumberList RBRACE'
5186   t[0] = IntegerType(named_list = t[3])
5187
5188 def p_NamedNumberList_1 (t):
5189   'NamedNumberList : NamedNumber'
5190   t[0] = [t[1]]
5191
5192 def p_NamedNumberList_2 (t):
5193   'NamedNumberList : NamedNumberList COMMA NamedNumber'
5194   t[0] = t[1] + [t[3]]
5195
5196 def p_NamedNumber (t):
5197   '''NamedNumber : identifier LPAREN SignedNumber RPAREN
5198                  | identifier LPAREN DefinedValue RPAREN'''
5199   t[0] = NamedNumber(ident = t[1], val = t[3])
5200
5201 def p_SignedNumber_1 (t):
5202   'SignedNumber : NUMBER'
5203   t[0] = t [1]
5204
5205 def p_SignedNumber_2 (t):
5206   'SignedNumber : MINUS NUMBER'
5207   t[0] = '-' + t[2]
5208
5209 # 18.9
5210 def p_IntegerValue (t):
5211   'IntegerValue : SignedNumber'
5212   t[0] = t [1]
5213
5214 # 19 Notation for the enumerated type -----------------------------------------
5215
5216 # 19.1
5217 def p_EnumeratedType (t):
5218     'EnumeratedType : ENUMERATED LBRACE Enumerations RBRACE'
5219     t[0] = EnumeratedType (val = t[3]['val'], ext = t[3]['ext'])
5220
5221 def p_Enumerations_1 (t):
5222     'Enumerations : Enumeration'
5223     t[0] = { 'val' : t[1], 'ext' : None }
5224
5225 def p_Enumerations_2 (t):
5226     'Enumerations : Enumeration COMMA ELLIPSIS ExceptionSpec'
5227     t[0] = { 'val' : t[1], 'ext' : [] }
5228
5229 def p_Enumerations_3 (t):
5230     'Enumerations : Enumeration COMMA ELLIPSIS ExceptionSpec COMMA Enumeration'
5231     t[0] = { 'val' : t[1], 'ext' : t[6] }
5232
5233 def p_Enumeration_1 (t):
5234     'Enumeration : EnumerationItem'
5235     t[0] = [t[1]]
5236
5237 def p_Enumeration_2 (t):
5238     'Enumeration : Enumeration COMMA EnumerationItem'
5239     t[0] = t[1] + [t[3]]
5240
5241 def p_EnumerationItem (t):
5242     '''EnumerationItem : Identifier
5243                        | NamedNumber'''
5244     t[0] = t[1]
5245
5246 def p_Identifier (t):
5247     'Identifier : identifier'
5248     t[0] = Node ('Identifier', ident = t[1])
5249
5250
5251 # 20 Notation for the real type -----------------------------------------------
5252
5253 # 20.1
5254 def p_RealType (t):
5255   'RealType : REAL'
5256   t[0] = RealType ()
5257
5258 # 20.6
5259 def p_RealValue (t):
5260   '''RealValue : REAL_NUMBER
5261                | SpecialRealValue'''
5262   t[0] = t [1]
5263
5264 def p_SpecialRealValue (t):
5265   '''SpecialRealValue : PLUS_INFINITY
5266                       | MINUS_INFINITY'''
5267   t[0] = t[1]
5268
5269
5270 # 21 Notation for the bitstring type ------------------------------------------
5271
5272 # 21.1
5273 def p_BitStringType_1 (t):
5274     'BitStringType : BIT STRING'
5275     t[0] = BitStringType (named_list = None)
5276
5277 def p_BitStringType_2 (t):
5278     'BitStringType : BIT STRING LBRACE NamedBitList RBRACE'
5279     t[0] = BitStringType (named_list = t[4])
5280
5281 def p_NamedBitList_1 (t):
5282     'NamedBitList : NamedBit'
5283     t[0] = [t[1]]
5284
5285 def p_NamedBitList_2 (t):
5286     'NamedBitList : NamedBitList COMMA NamedBit'
5287     t[0] = t[1] + [t[3]]
5288
5289 def p_NamedBit (t):
5290     '''NamedBit : identifier LPAREN NUMBER RPAREN
5291                 | identifier LPAREN DefinedValue RPAREN'''
5292     t[0] = NamedNumber (ident = t[1], val = t[3])
5293
5294
5295 # 22 Notation for the octetstring type ----------------------------------------
5296
5297 # 22.1
5298 def p_OctetStringType (t):
5299     'OctetStringType : OCTET STRING'
5300     t[0] = OctetStringType ()
5301
5302
5303 # 23 Notation for the null type -----------------------------------------------
5304
5305 # 23.1
5306 def p_NullType (t):
5307     'NullType : NULL'
5308     t[0] = NullType ()
5309
5310 # 23.3
5311 #def p_NullValue (t):
5312 #    'NullValue : NULL'
5313 #    t[0] = t[1]
5314
5315
5316 # 24 Notation for sequence types ----------------------------------------------
5317
5318 # 24.1
5319 def p_SequenceType_1 (t):
5320   'SequenceType : SEQUENCE LBRACE RBRACE'
5321   t[0] = SequenceType (elt_list = [])
5322
5323 def p_SequenceType_2 (t):
5324   'SequenceType : SEQUENCE LBRACE ComponentTypeLists RBRACE'
5325   if t[3].has_key('ext_list'):
5326       t[0] = SequenceType (elt_list = t[3]['elt_list'], ext_list = t[3]['ext_list'])
5327   else:
5328       t[0] = SequenceType (elt_list = t[3]['elt_list'])
5329
5330 def p_ExtensionAndException_1 (t):
5331   'ExtensionAndException : ELLIPSIS'
5332   t[0] = []
5333
5334 def p_OptionalExtensionMarker_1 (t):
5335   'OptionalExtensionMarker : COMMA ELLIPSIS'
5336   t[0] = True
5337
5338 def p_OptionalExtensionMarker_2 (t):
5339   'OptionalExtensionMarker : '
5340   t[0] = False
5341
5342 def p_ComponentTypeLists_1 (t):
5343   'ComponentTypeLists : ComponentTypeList'
5344   t[0] = {'elt_list' : t[1]}
5345
5346 def p_ComponentTypeLists_2 (t):
5347     'ComponentTypeLists : ComponentTypeList COMMA ExtensionAndException extension_additions OptionalExtensionMarker'
5348     t[0] = {'elt_list' : t[1], 'ext_list' : t[4]}
5349
5350 def p_ComponentTypeLists_3 (t):
5351     'ComponentTypeLists : ExtensionAndException extension_additions OptionalExtensionMarker'
5352     t[0] = {'elt_list' : [], 'ext_list' : t[2]}
5353
5354 #def p_RootComponentTypeList (t):
5355 #    'RootComponentTypeList : ComponentTypeList'
5356 #    t[0] = t[1]
5357
5358 def p_extension_additions_1 (t):
5359     'extension_additions : extension_addition_list'
5360     t[0] = t[1]
5361
5362 def p_extension_additions_2 (t):
5363     'extension_additions : '
5364     t[0] = []
5365
5366 def p_extension_addition_list_1 (t):
5367     'extension_addition_list : COMMA extension_addition'
5368     t[0] = [t[2]]
5369
5370 def p_extension_addition_list_2 (t):
5371     'extension_addition_list : extension_addition_list COMMA extension_addition'
5372     t[0] = t[1] + [t[3]]
5373
5374 def p_extension_addition_1 (t):
5375     'extension_addition : ComponentType'
5376     t[0] = t[1]
5377
5378 def p_ComponentTypeList_1 (t):
5379   'ComponentTypeList : ComponentType'
5380   t[0] = [t[1]]
5381
5382 def p_ComponentTypeList_2 (t):
5383   'ComponentTypeList : ComponentTypeList COMMA ComponentType'
5384   t[0] = t[1] + [t[3]]
5385
5386 def p_ComponentType_1 (t):
5387   'ComponentType : NamedType'
5388   t[0] = Node ('elt_type', val = t[1], optional = 0)
5389
5390 def p_ComponentType_2 (t):
5391   'ComponentType : NamedType OPTIONAL'
5392   t[0] = Node ('elt_type', val = t[1], optional = 1)
5393
5394 def p_ComponentType_3 (t):
5395   'ComponentType : NamedType DEFAULT DefaultValue'
5396   t[0] = Node ('elt_type', val = t[1], optional = 1, default = t[3])
5397
5398 def p_ComponentType_4 (t):
5399   'ComponentType : COMPONENTS OF Type'
5400   t[0] = Node ('components_of', typ = t[3])
5401
5402 def p_DefaultValue_1 (t):
5403   '''DefaultValue : ReferencedValue 
5404                   | BooleanValue
5405                   | IntegerValue
5406                   | RealValue
5407                   | hex_string
5408                   | binary_string
5409                   | char_string'''
5410   t[0] = t[1]
5411
5412 def p_DefaultValue_2 (t):
5413   'DefaultValue : lbraceignore rbraceignore'
5414   t[0] = ''
5415
5416 # 24.17
5417 def p_SequenceValue_1 (t):
5418   'SequenceValue : LBRACE RBRACE'
5419   t[0] = []
5420
5421
5422 #def p_SequenceValue_2 (t):
5423 #  'SequenceValue : LBRACE ComponentValueList RBRACE'
5424 #  t[0] = t[2]
5425     
5426 #def p_ComponentValueList_1 (t):
5427 #    'ComponentValueList : NamedValue'
5428 #    t[0] = [t[1]]
5429
5430 #def p_ComponentValueList_2 (t):
5431 #    'ComponentValueList : ComponentValueList COMMA NamedValue'
5432 #    t[0] = t[1] + [t[3]]
5433
5434
5435 # 25 Notation for sequence-of types -------------------------------------------
5436
5437 # 25.1
5438 def p_SequenceOfType (t):
5439     '''SequenceOfType : SEQUENCE OF Type
5440                       | SEQUENCE OF NamedType'''
5441     t[0] = SequenceOfType (val = t[3], size_constr = None)
5442
5443
5444 # 26 Notation for set types ---------------------------------------------------
5445
5446 # 26.1
5447 def p_SetType_1 (t):
5448     'SetType : SET LBRACE RBRACE'
5449     if t[3].has_key('ext_list'):
5450         t[0] = SetType (elt_list = [])
5451
5452 def p_SetType_2 (t):
5453     'SetType : SET LBRACE ComponentTypeLists RBRACE'
5454     if t[3].has_key('ext_list'):
5455         t[0] = SetType (elt_list = t[3]['elt_list'], ext_list = t[3]['ext_list'])
5456     else:
5457         t[0] = SetType (elt_list = t[3]['elt_list'])
5458
5459
5460 # 27 Notation for set-of types ------------------------------------------------
5461
5462 # 27.1
5463 def p_SetOfType (t):
5464     '''SetOfType : SET OF Type
5465                  | SET OF NamedType'''
5466     t[0] = SetOfType (val = t[3])
5467
5468 # 28 Notation for choice types ------------------------------------------------
5469
5470 # 28.1
5471 def p_ChoiceType (t):
5472     'ChoiceType : CHOICE LBRACE alternative_type_lists RBRACE'
5473     if t[3].has_key('ext_list'):
5474         t[0] = ChoiceType (elt_list = t[3]['elt_list'], ext_list = t[3]['ext_list'])
5475     else:
5476         t[0] = ChoiceType (elt_list = t[3]['elt_list'])
5477
5478 def p_alternative_type_lists_1 (t):
5479     'alternative_type_lists : alternative_type_list'
5480     t[0] = {'elt_list' : t[1]}
5481
5482 def p_alternative_type_lists_2 (t):
5483     '''alternative_type_lists : alternative_type_list COMMA ExtensionAndException extension_addition_alternatives OptionalExtensionMarker'''
5484     t[0] = {'elt_list' : t[1], 'ext_list' : t[4]}
5485
5486 def p_extension_addition_alternatives_1 (t):
5487     'extension_addition_alternatives : extension_addition_alternatives_list'
5488     t[0] = t[1]
5489
5490 def p_extension_addition_alternatives_2 (t):
5491     'extension_addition_alternatives : '
5492     t[0] = []
5493
5494 def p_extension_addition_alternatives_list_1 (t):
5495     'extension_addition_alternatives_list : COMMA extension_addition_alternative'
5496     t[0] = [t[2]]
5497
5498 def p_extension_addition_alternatives_list_2 (t):
5499     'extension_addition_alternatives_list : extension_addition_alternatives_list COMMA extension_addition_alternative'
5500     t[0] = t[1] + [t[3]]
5501
5502 def p_extension_addition_alternative_1 (t):
5503     'extension_addition_alternative : NamedType'
5504     t[0] = t[1]
5505
5506 def p_alternative_type_list_1 (t):
5507     'alternative_type_list : NamedType'
5508     t[0] = [t[1]]
5509
5510 def p_alternative_type_list_2 (t):
5511     'alternative_type_list : alternative_type_list COMMA NamedType'
5512     t[0] = t[1] + [t[3]]
5513
5514 # 29 Notation for selection types
5515
5516 # 29.1
5517 def p_SelectionType (t): #
5518   'SelectionType : identifier LT Type'
5519   t[0] = SelectionType (typ = t[3], sel = t[1])
5520
5521 # 30 Notation for tagged types ------------------------------------------------
5522
5523 # 30.1
5524 def p_TaggedType_1 (t):
5525     'TaggedType : Tag Type'
5526     t[1].mode = 'default'
5527     t[0] = t[2]
5528     t[0].AddTag(t[1])
5529
5530 def p_TaggedType_2 (t):
5531     '''TaggedType : Tag IMPLICIT Type
5532                   | Tag EXPLICIT Type'''
5533     t[1].mode = t[2]
5534     t[0] = t[3]
5535     t[0].AddTag(t[1])
5536
5537 def p_Tag (t):
5538     'Tag : LBRACK Class ClassNumber RBRACK'
5539     t[0] = Tag(cls = t[2], num = t[3])
5540
5541 def p_ClassNumber_1 (t):
5542     'ClassNumber : number'
5543     t[0] = t[1]
5544
5545 def p_ClassNumber_2 (t):
5546     'ClassNumber : DefinedValue'
5547     t[0] = t[1]
5548
5549 def p_Class_1 (t):
5550     '''Class : UNIVERSAL
5551              | APPLICATION
5552              | PRIVATE'''
5553     t[0] = t[1]
5554
5555 def p_Class_2 (t):
5556     'Class :'
5557     t[0] = 'CONTEXT'
5558
5559
5560 def p_AnyType (t):
5561     'AnyType : ANY'
5562     t[0] = AnyType ()
5563
5564
5565 # 31 Notation for the object identifier type ----------------------------------
5566
5567 # 31.1
5568 def p_ObjectIdentifierType (t):
5569   'ObjectIdentifierType : OBJECT IDENTIFIER'
5570   t[0] = ObjectIdentifierType()
5571
5572 # 31.3
5573 def p_ObjectIdentifierValue (t):
5574     'ObjectIdentifierValue : LBRACE oid_comp_list RBRACE'
5575     t[0] = ObjectIdentifierValue (comp_list=t[2])
5576
5577 def p_oid_comp_list_1 (t):
5578     'oid_comp_list : oid_comp_list ObjIdComponents'
5579     t[0] = t[1] + [t[2]]
5580
5581 def p_oid_comp_list_2 (t):
5582     'oid_comp_list : ObjIdComponents'
5583     t[0] = [t[1]]
5584
5585 def p_ObjIdComponents (t):
5586   '''ObjIdComponents : NameForm
5587                      | NumberForm
5588                      | NameAndNumberForm'''
5589   t[0] = t[1]
5590
5591 def p_NameForm (t):
5592   '''NameForm : LCASE_IDENT
5593               | LCASE_IDENT_ASSIGNED'''
5594   t [0] = t[1]
5595
5596 def p_NumberForm (t):
5597   '''NumberForm : NUMBER'''
5598 #                | DefinedValue'''
5599   t [0] = t[1]
5600
5601 def p_NameAndNumberForm (t):
5602   '''NameAndNumberForm : LCASE_IDENT_ASSIGNED LPAREN NumberForm RPAREN
5603                        | LCASE_IDENT LPAREN NumberForm RPAREN'''
5604   t[0] = Node('name_and_number', ident = t[1], number = t[3])
5605   
5606 # 33 Notation for the embedded-pdv type -------------------------------------------
5607 # 33.1
5608 def p_EmbeddedPDVType (t):
5609   'EmbeddedPDVType : EMBEDDED PDV'
5610   t[0] = EmbeddedPDVType()
5611
5612 # 34 Notation for the external type -------------------------------------------
5613
5614 # 34.1
5615 def p_ExternalType (t):
5616   'ExternalType : EXTERNAL'
5617   t[0] = ExternalType()
5618
5619 # 36 Notation for character string types --------------------------------------
5620
5621 # 36.1
5622 def p_CharacterStringType (t):
5623     '''CharacterStringType : RestrictedCharacterStringType
5624     | UnrestrictedCharacterStringType'''
5625     t[0] = t[1]
5626
5627
5628 # 37 Definition of restricted character string types --------------------------
5629
5630 def p_RestrictedCharacterStringType_1 (t):
5631     'RestrictedCharacterStringType : BMPString'
5632     t[0] = BMPStringType ()
5633 def p_RestrictedCharacterStringType_2 (t):
5634     'RestrictedCharacterStringType : GeneralString'
5635     t[0] = GeneralStringType ()
5636 def p_RestrictedCharacterStringType_3 (t):
5637     'RestrictedCharacterStringType : GraphicString'
5638     t[0] = GraphicStringType ()
5639 def p_RestrictedCharacterStringType_4 (t):
5640     'RestrictedCharacterStringType : IA5String'
5641     t[0] = IA5StringType ()
5642 def p_RestrictedCharacterStringType_5 (t):
5643     'RestrictedCharacterStringType : ISO646String'
5644     t[0] = ISO646StringType ()
5645 def p_RestrictedCharacterStringType_6 (t):
5646     'RestrictedCharacterStringType : NumericString'
5647     t[0] = NumericStringType ()
5648 def p_RestrictedCharacterStringType_7 (t):
5649     'RestrictedCharacterStringType : PrintableString'
5650     t[0] = PrintableStringType ()
5651 def p_RestrictedCharacterStringType_8 (t):
5652     'RestrictedCharacterStringType : TeletexString'
5653     t[0] = TeletexStringType ()
5654 def p_RestrictedCharacterStringType_9 (t):
5655     'RestrictedCharacterStringType : T61String'
5656     t[0] = T61StringType ()
5657 def p_RestrictedCharacterStringType_10 (t):
5658     'RestrictedCharacterStringType : UniversalString'
5659     t[0] = UniversalStringType ()
5660 def p_RestrictedCharacterStringType_11 (t):
5661     'RestrictedCharacterStringType : UTF8String'
5662     t[0] = UTF8StringType ()
5663 def p_RestrictedCharacterStringType_12 (t):
5664     'RestrictedCharacterStringType : VideotexString'
5665     t[0] = VideotexStringType ()
5666 def p_RestrictedCharacterStringType_13 (t):
5667     'RestrictedCharacterStringType : VisibleString'
5668     t[0] = VisibleStringType ()
5669
5670
5671 # 40 Definition of unrestricted character string types ------------------------
5672
5673 # 40.1
5674 def p_UnrestrictedCharacterStringType (t):
5675     'UnrestrictedCharacterStringType : CHARACTER STRING'
5676     t[0] = UnrestrictedCharacterStringType ()
5677
5678
5679 # 41 Notation for types defined in clauses 42 to 44 ---------------------------
5680
5681 # 42 Generalized time ---------------------------------------------------------
5682
5683 def p_UsefulType_1 (t):
5684   'UsefulType : GeneralizedTime'
5685   t[0] = GeneralizedTime()
5686
5687 # 43 Universal time -----------------------------------------------------------
5688
5689 def p_UsefulType_2 (t):
5690   'UsefulType : UTCTime'
5691   t[0] = UTCTime()
5692
5693 # 44 The object descriptor type -----------------------------------------------
5694
5695 def p_UsefulType_3 (t):
5696   'UsefulType : ObjectDescriptor'
5697   t[0] = ObjectDescriptor()
5698
5699
5700 # 45 Constrained types --------------------------------------------------------
5701
5702 # 45.1
5703 def p_ConstrainedType_1 (t):
5704     'ConstrainedType : Type Constraint'
5705     t[0] = t[1]
5706     t[0].AddConstraint(t[2])
5707
5708 def p_ConstrainedType_2 (t):
5709     'ConstrainedType : TypeWithConstraint'
5710     t[0] = t[1]
5711
5712 # 45.5
5713 def p_TypeWithConstraint_1 (t):
5714     '''TypeWithConstraint : SET Constraint OF Type
5715                           | SET SizeConstraint OF Type'''
5716     t[0] = SetOfType (val = t[4], constr = t[2])
5717
5718 def p_TypeWithConstraint_2 (t):
5719     '''TypeWithConstraint : SEQUENCE Constraint OF Type
5720                           | SEQUENCE SizeConstraint OF Type'''
5721     t[0] = SequenceOfType (val = t[4], constr = t[2])
5722
5723 def p_TypeWithConstraint_3 (t):
5724     '''TypeWithConstraint : SET Constraint OF NamedType
5725                           | SET SizeConstraint OF NamedType'''
5726     t[0] = SetOfType (val = t[4], constr = t[2])
5727
5728 def p_TypeWithConstraint_4 (t):
5729     '''TypeWithConstraint : SEQUENCE Constraint OF NamedType
5730                           | SEQUENCE SizeConstraint OF NamedType'''
5731     t[0] = SequenceOfType (val = t[4], constr = t[2])
5732
5733 # 45.6
5734 # 45.7
5735 def p_Constraint (t):
5736     'Constraint : LPAREN ConstraintSpec ExceptionSpec RPAREN'
5737     t[0] = t[2]
5738
5739 def p_ConstraintSpec (t):
5740     '''ConstraintSpec : ElementSetSpecs
5741                       | GeneralConstraint'''
5742     t[0] = t[1]
5743
5744 # 46 Element set specification ------------------------------------------------
5745
5746 # 46.1
5747 def p_ElementSetSpecs_1 (t):
5748   'ElementSetSpecs : RootElementSetSpec'
5749   t[0] = t[1]
5750
5751 def p_ElementSetSpecs_2 (t):
5752   'ElementSetSpecs : RootElementSetSpec COMMA ELLIPSIS'
5753   t[0] = t[1]
5754   t[0].ext = True
5755
5756 def p_ElementSetSpecs_3 (t):
5757   'ElementSetSpecs : RootElementSetSpec COMMA ELLIPSIS COMMA AdditionalElementSetSpec'
5758   t[0] = t[1]
5759   t[0].ext = True
5760
5761 def p_RootElementSetSpec (t):
5762   'RootElementSetSpec : ElementSetSpec'
5763   t[0] = t[1]
5764
5765 def p_AdditionalElementSetSpec (t):
5766   'AdditionalElementSetSpec : ElementSetSpec'
5767   t[0] = t[1]
5768
5769 def p_ElementSetSpec (t):
5770   'ElementSetSpec : Unions'
5771   t[0] = t[1]
5772
5773 def p_Unions_1 (t):
5774   'Unions : Intersections'
5775   t[0] = t[1]
5776
5777 def p_Unions_2 (t):
5778   'Unions : UElems UnionMark Intersections'
5779   t[0] = Constraint(type = 'Union', subtype = [t[1], t[3]])
5780
5781 def p_UElems (t):
5782   'UElems : Unions'
5783   t[0] = t[1]
5784
5785 def p_Intersections_1 (t):
5786   'Intersections : IntersectionElements'
5787   t[0] = t[1]
5788
5789 def p_Intersections_2 (t):
5790   'Intersections : IElems IntersectionMark IntersectionElements'
5791   t[0] = Constraint(type = 'Intersection', subtype = [t[1], t[3]])
5792
5793 def p_IElems (t):
5794   'IElems : Intersections'
5795   t[0] = t[1]
5796
5797 def p_IntersectionElements (t):
5798   'IntersectionElements : SubtypeElements'
5799   t[0] = t[1]
5800
5801 def p_UnionMark (t):
5802   '''UnionMark : BAR
5803                | UNION'''
5804
5805 def p_IntersectionMark (t):
5806   '''IntersectionMark : CIRCUMFLEX
5807                       | INTERSECTION'''
5808
5809 # 47 Subtype elements ---------------------------------------------------------
5810
5811 # 47.1 General
5812 def p_SubtypeElements (t):
5813     '''SubtypeElements : SingleValue
5814                        | ContainedSubtype
5815                        | ValueRange
5816                        | PermittedAlphabet
5817                        | SizeConstraint
5818                        | TypeConstraint
5819                        | InnerTypeConstraints
5820                        | PatternConstraint'''
5821     t[0] = t[1]
5822
5823 # 47.2 Single value
5824 # 47.2.1
5825 def p_SingleValue (t):
5826     'SingleValue : Value'
5827     t[0] = Constraint(type = 'SingleValue', subtype = t[1]) 
5828
5829 # 47.3 Contained subtype
5830 # 47.3.1
5831 def p_ContainedSubtype (t):
5832   'ContainedSubtype : Includes Type'
5833   t[0] = Constraint(type = 'ContainedSubtype', subtype = t[2]) 
5834
5835 def p_Includes (t):
5836   '''Includes : INCLUDES 
5837               | '''
5838
5839 # 47.4 Value range
5840 # 47.4.1
5841 def p_ValueRange (t):
5842   'ValueRange : LowerEndpoint RANGE UpperEndpoint'
5843   t[0] = Constraint(type = 'ValueRange', subtype = [t[1], t[3]])
5844
5845 # 47.4.3
5846 def p_LowerEndpoint_1 (t):
5847   'LowerEndpoint : LowerEndValue'
5848   t[0] = t[1]
5849
5850 def p_LowerEndpoint_2 (t):
5851   'LowerEndpoint : LowerEndValue LT'
5852   t[0] = t[1] # but not inclusive range
5853     
5854 def p_UpperEndpoint_1 (t):
5855   'UpperEndpoint : UpperEndValue'
5856   t[0] = t[1]
5857
5858 def p_UpperEndpoint_2 (t):
5859   'UpperEndpoint : LT UpperEndValue'
5860   t[0] = t[1] # but not inclusive range
5861
5862 # 47.4.4
5863 def p_LowerEndValue (t):
5864   '''LowerEndValue : Value
5865                    | MIN'''
5866   t[0] = t[1] # XXX
5867
5868 def p_UpperEndValue (t):
5869   '''UpperEndValue : Value
5870                     | MAX'''
5871   t[0] = t[1]
5872
5873 # 47.5 Size constraint
5874 # 47.5.1
5875 def p_SizeConstraint (t):
5876     'SizeConstraint : SIZE Constraint'
5877     t[0] = Constraint (type = 'Size', subtype = t[2])
5878
5879 # 47.6 Type constraint
5880 # 47.6.1
5881 def p_TypeConstraint (t):
5882     'TypeConstraint : Type'
5883     t[0] = Constraint (type = 'Type', subtype = t[1])
5884
5885 # 47.7 Permitted alphabet
5886 # 47.7.1
5887 def p_PermittedAlphabet (t):
5888     'PermittedAlphabet : FROM Constraint'
5889     t[0] = Constraint (type = 'From', subtype = t[2])
5890
5891 # 47.8 Inner subtyping
5892 # 47.8.1
5893 def p_InnerTypeConstraints (t):
5894     '''InnerTypeConstraints : WITH COMPONENT SingleTypeConstraint
5895                             | WITH COMPONENTS MultipleTypeConstraints'''
5896     pass # ignore PER invisible constraint
5897
5898 # 47.8.3
5899 def p_SingleTypeConstraint (t):
5900     'SingleTypeConstraint : Constraint'
5901     t[0] = t[1]
5902
5903 # 47.8.4
5904 def p_MultipleTypeConstraints (t):
5905     '''MultipleTypeConstraints : FullSpecification
5906                                | PartialSpecification'''
5907     t[0] = t[1]
5908
5909 def p_FullSpecification (t):
5910     'FullSpecification : LBRACE TypeConstraints RBRACE'
5911     t[0] = t[2]
5912
5913 def p_PartialSpecification (t):
5914     'PartialSpecification : LBRACE ELLIPSIS COMMA TypeConstraints RBRACE'
5915     t[0] = t[4]
5916
5917 def p_TypeConstraints_1 (t):
5918     'TypeConstraints : named_constraint'
5919     t [0] = [t[1]]
5920
5921 def p_TypeConstraints_2 (t):
5922     'TypeConstraints : TypeConstraints COMMA named_constraint'
5923     t[0] = t[1] + [t[3]]
5924
5925 def p_named_constraint_1 (t):
5926     'named_constraint : identifier constraint'
5927     return Node ('named_constraint', ident = t[1], constr = t[2])
5928
5929 def p_named_constraint_2 (t):
5930     'named_constraint : constraint'
5931     return Node ('named_constraint', constr = t[1])
5932
5933 def p_constraint (t):
5934     'constraint : value_constraint presence_constraint'
5935     t[0] = Node ('constraint', value = t[1], presence = t[2])
5936
5937 def p_value_constraint_1 (t):
5938     'value_constraint : Constraint'
5939     t[0] = t[1]
5940
5941 def p_value_constraint_2 (t):
5942     'value_constraint : '
5943     pass
5944
5945 def p_presence_constraint_1 (t):
5946     '''presence_constraint : PRESENT
5947                  | ABSENT
5948                  | OPTIONAL'''
5949     t[0] = t[1]
5950     
5951 def p_presence_constraint_2 (t):
5952     '''presence_constraint : '''
5953     pass
5954
5955 # 47.9 Pattern constraint
5956 # 47.9.1
5957 def p_PatternConstraint (t):
5958     'PatternConstraint : PATTERN Value'
5959     t[0] = Constraint (type = 'Pattern', subtype = t[2])
5960
5961 # 49 The exception identifier
5962
5963 # 49.4
5964 def p_ExceptionSpec (t):
5965     'ExceptionSpec : '
5966     pass
5967
5968 #  /*-----------------------------------------------------------------------*/
5969 #  /* Value Notation Productions */
5970 #  /*-----------------------------------------------------------------------*/
5971
5972
5973
5974 def p_binary_string (t):
5975     'binary_string : BSTRING'
5976     t[0] = BStringValue(val = t[1])
5977
5978 def p_hex_string (t):
5979     'hex_string : HSTRING'
5980     t[0] = t[1]
5981
5982 def p_char_string (t):
5983     'char_string : QSTRING'
5984     t[0] = t[1]
5985
5986 def p_number (t):
5987   'number : NUMBER'
5988   t[0] = t[1]
5989
5990
5991 #--- ITU-T Recommendation X.681 -----------------------------------------------
5992
5993 # 7 ASN.1 lexical items -------------------------------------------------------
5994
5995 # 7.1 Information object class references
5996
5997 def p_objectclassreference (t):
5998   'objectclassreference : CLASS_IDENT'
5999   t[0] = Class_Ref(val=t[1])
6000
6001 # 7.2 Information object references
6002
6003 def p_objectreference (t):
6004   'objectreference : LCASE_IDENT'
6005   t[0] = t[1]
6006
6007 # 7.3 Information object set references
6008
6009 def p_objectsetreference (t):
6010   'objectsetreference : UCASE_IDENT'
6011   t[0] = t[1]
6012
6013 # 7.4 Type field references
6014
6015 def p_typefieldreference (t):
6016   'typefieldreference : AMPERSAND UCASE_IDENT'
6017   t[0] = t[2]
6018
6019 # 7.5 Value field references
6020
6021 def p_valuefieldreference (t):
6022   'valuefieldreference : AMPERSAND LCASE_IDENT'
6023   t[0] = t[2]
6024
6025 # 8 Referencing definitions
6026
6027 # 8.1
6028 def p_DefinedObjectClass (t):
6029   '''DefinedObjectClass : objectclassreference
6030                         | UsefulObjectClassReference'''
6031   t[0] = t[1]
6032
6033 def p_DefinedObject (t):
6034   '''DefinedObject : objectreference'''
6035   t[0] = t[1]
6036
6037 # 8.4
6038 def p_UsefulObjectClassReference (t):
6039   '''UsefulObjectClassReference : TYPE_IDENTIFIER 
6040                                 | ABSTRACT_SYNTAX'''
6041   t[0] = t[1]
6042
6043 # 9 Information object class definition and assignment
6044
6045 # 9.1
6046 def p_ObjectClassAssignment (t):
6047   '''ObjectClassAssignment : CLASS_IDENT ASSIGNMENT ObjectClass
6048                            | UCASE_IDENT ASSIGNMENT ObjectClass'''
6049   t[0] = t[3]
6050   t[0].SetName(t[1])
6051
6052 # 9.2
6053 def p_ObjectClass (t):
6054   '''ObjectClass : ObjectClassDefn'''
6055   t[0] = t[1]
6056
6057 # 9.3
6058 def p_ObjectClassDefn (t):
6059   '''ObjectClassDefn : CLASS lbraceignore rbraceignore
6060                      | CLASS lbraceignore rbraceignore WithSyntaxSpec'''
6061   t[0] = ObjectClass()
6062
6063 def p_WithSyntaxSpec (t):
6064   'WithSyntaxSpec : WITH SYNTAX lbraceignore rbraceignore'
6065   t[0] = None
6066
6067 # 9.14
6068 def p_FieldName (t):
6069   '''FieldName : typefieldreference
6070                | valuefieldreference'''
6071   t[0] = t[1]
6072
6073 # 11 Information object definition and assignment
6074
6075 # 11.1
6076 def p_ObjectAssignment (t):
6077   'ObjectAssignment : objectreference CLASS_IDENT ASSIGNMENT Object'
6078   t[0] = Node('ObjectAssignment', name=t[1], cls=t[2], val=t[4])
6079
6080 # 11.3
6081 def p_Object (t):
6082   '''Object : DefinedObject
6083             | ObjectDefn'''
6084   t[0] = t[1]
6085
6086 # 11.4
6087 def p_ObjectDefn (t):
6088   'ObjectDefn : lbraceignore rbraceignore'
6089   t[0] = None
6090
6091 # 12 Information object set definition and assignment
6092
6093 # 12.1
6094 def p_ObjectSetAssignment (t):
6095   'ObjectSetAssignment : objectsetreference CLASS_IDENT ASSIGNMENT ObjectSet'
6096   t[0] = Node('ObjectSetAssignment', name=t[1], cls=t[2], val=t[4])
6097
6098 # 12.3
6099 def p_ObjectSet (t):
6100   'ObjectSet : lbraceignore rbraceignore'
6101   t[0] = None
6102
6103 # 14 Notation for the object class field type ---------------------------------
6104
6105 # 14.1
6106 def p_ObjectClassFieldType (t):
6107   'ObjectClassFieldType : DefinedObjectClass DOT FieldName'
6108   t[0] = get_type_from_class(t[1], t[3])
6109
6110 useful_object_class_types = {
6111   # Annex A
6112   'TYPE-IDENTIFIER/id'   : lambda : ObjectIdentifierType(),
6113   'TYPE-IDENTIFIER/Type' : lambda : OpenType(),
6114   # Annex B
6115   'ABSTRACT-SYNTAX/id'       : lambda : ObjectIdentifierType(),
6116   'ABSTRACT-SYNTAX/Type'     : lambda : OpenType(),
6117   'ABSTRACT-SYNTAX/property' : lambda : BitStringType(),
6118 }
6119
6120 object_class_types = { }
6121
6122 object_class_typerefs = { }
6123
6124 class_types_creator = {
6125   'IntegerType'          : lambda : IntegerType(),
6126   'ObjectIdentifierType' : lambda : ObjectIdentifierType(),
6127   'OpenType'             : lambda : OpenType(),
6128 }
6129
6130 class_names = { }
6131
6132 def is_class_ident(name):
6133   return class_names.has_key(name)
6134
6135 def add_class_ident(name):
6136   class_names[name] = name
6137
6138 def get_type_from_class(cls, fld):
6139   if (isinstance(cls, Class_Ref)):
6140     key = cls.val + '/' + fld
6141   else:
6142     key = cls + '/' + fld
6143
6144   if object_class_typerefs.has_key(key):
6145     return Type_Ref(val=object_class_typerefs[key])
6146
6147   creator = lambda : AnyType()
6148   creator = useful_object_class_types.get(key, creator)
6149   creator = object_class_types.get(key, creator)
6150   return creator()
6151
6152 def set_type_to_class(cls, fld, typename, typeref = None):
6153   key = cls + '/' + fld
6154   if object_class_types.has_key(key): return False
6155   if object_class_typerefs.has_key(key): return False
6156
6157   if (typename == 'TypeReference'):
6158     if not typeref: return False
6159     object_class_typerefs[key] = typeref
6160     return True
6161
6162   creator = class_types_creator.get(typename)
6163   if creator:
6164     object_class_types[key] = creator
6165     return True
6166   else:
6167     return False
6168
6169 #--- ITU-T Recommendation X.682 -----------------------------------------------
6170
6171 # 8 General constraint specification ------------------------------------------
6172
6173 # 8.1
6174 def p_GeneralConstraint (t):
6175   '''GeneralConstraint : UserDefinedConstraint
6176                        | TableConstraint
6177                        | ContentsConstraint'''
6178   t[0] = t[1]
6179
6180 # 9 User-defined constraints --------------------------------------------------
6181
6182 # 9.1
6183 def p_UserDefinedConstraint (t):
6184   'UserDefinedConstraint : CONSTRAINED BY LBRACE UserDefinedConstraintParameterList RBRACE'
6185   t[0] = Constraint(type = 'UserDefined', subtype = t[4]) 
6186
6187 def p_UserDefinedConstraintParameterList_1 (t):
6188   'UserDefinedConstraintParameterList : '
6189   t[0] = []
6190
6191 def p_UserDefinedConstraintParameterList_2 (t):
6192   'UserDefinedConstraintParameterList : UserDefinedConstraintParameter'
6193   t[0] = [t[1]]
6194
6195 def p_UserDefinedConstraintParameterList_3 (t):
6196   'UserDefinedConstraintParameterList : UserDefinedConstraintParameterList COMMA UserDefinedConstraintParameter'
6197   t[0] = t[1] + [t[3]]
6198
6199 # 9.3
6200 def p_UserDefinedConstraintParameter (t):
6201   'UserDefinedConstraintParameter : type_ref'
6202   t[0] = t[1]
6203
6204 # 10 Table constraints, including component relation constraints --------------
6205
6206 # 10.3
6207 def p_TableConstraint (t):
6208   '''TableConstraint : SimpleTableConstraint
6209                      | ComponentRelationConstraint'''
6210   t[0] = Constraint(type = 'Table', subtype = t[1]) 
6211
6212 def p_SimpleTableConstraint (t):
6213   'SimpleTableConstraint : LBRACE UCASE_IDENT RBRACE'
6214   t[0] = t[2]
6215
6216 # 10.7
6217 def p_ComponentRelationConstraint (t):
6218   'ComponentRelationConstraint : LBRACE UCASE_IDENT RBRACE LBRACE AT LCASE_IDENT RBRACE'
6219   t[0] = t[2] + '@' + t[6]
6220
6221 # 11 Contents constraints -----------------------------------------------------
6222
6223 # 11.1
6224 def p_ContentsConstraint (t):
6225   'ContentsConstraint : CONTAINING type_ref'
6226   t[0] = Constraint(type = 'Contents', subtype = t[2]) 
6227
6228
6229 #--- ITU-T Recommendation X.683 -----------------------------------------------
6230
6231 # 8 Parameterized assignments -------------------------------------------------
6232
6233 # 8.1
6234
6235 # 8.2
6236 def p_ParameterizedTypeAssignment (t):
6237   'ParameterizedTypeAssignment : UCASE_IDENT ParameterList ASSIGNMENT Type'
6238   t[0] = t[4]
6239   t[0].SetName(t[1])  # t[0].SetName(t[1] + 'xxx')
6240
6241 # 8.3
6242 def p_ParameterList (t):
6243   'ParameterList : lbraceignore rbraceignore'
6244
6245 #def p_ParameterList (t):
6246 #  'ParameterList : LBRACE Parameters RBRACE'
6247 #  t[0] = t[2]
6248
6249 #def p_Parameters_1 (t):
6250 #  'Parameters : Parameter'
6251 #  t[0] = [t[1]]
6252
6253 #def p_Parameters_2 (t):
6254 #  'Parameters : Parameters COMMA Parameter'
6255 #  t[0] = t[1] + [t[3]]
6256
6257 #def p_Parameter_1 (t):
6258 #  'Parameter : Type COLON Reference'
6259 #  t[0] = [t[1], t[3]]
6260
6261 #def p_Parameter_2 (t):
6262 #  'Parameter : Reference'
6263 #  t[0] = t[1]
6264
6265
6266 # 9 Referencing parameterized definitions -------------------------------------
6267
6268 # 9.1
6269 def p_ParameterizedReference (t):
6270   'ParameterizedReference : type_ref LBRACE RBRACE'
6271   t[0] = t[1]
6272   #t[0].val += 'xxx'
6273
6274 # 9.2
6275 def p_ParameterizedType (t):
6276   'ParameterizedType : type_ref ActualParameterList'
6277   t[0] = t[1]
6278   #t[0].val += 'xxx'
6279
6280 # 9.5
6281 def p_ActualParameterList (t):
6282   'ActualParameterList : lbraceignore rbraceignore'
6283
6284 #def p_ActualParameterList (t):
6285 #  'ActualParameterList : LBRACE ActualParameters RBRACE'
6286 #  t[0] = t[2]
6287
6288 #def p_ActualParameters_1 (t):
6289 #  'ActualParameters : ActualParameter'
6290 #  t[0] = [t[1]]
6291
6292 #def p_ActualParameters_2 (t):
6293 #  'ActualParameters : ActualParameters COMMA ActualParameter'
6294 #  t[0] = t[1] + [t[3]]
6295
6296 #def p_ActualParameter (t):
6297 #  '''ActualParameter : Type
6298 #                     | Value'''
6299 #  t[0] = t[1]
6300
6301
6302 #--- ITU-T Recommendation X.880 -----------------------------------------------
6303
6304 x880_syntaxes = {
6305   'OPERATION' : {
6306     'ARGUMENT'       : 'ARGUMENT',
6307     'RESULT'         : 'RESULT',         
6308     'RETURN'         : 'RETURN',         
6309     'ERRORS'         : 'ERRORS',         
6310     'LINKED'         : 'LINKED',         
6311     'SYNCHRONOUS'    : 'SYNCHRONOUS',    
6312     'IDEMPOTENT'     : 'IDEMPOTENT',     
6313     'ALWAYS'         : 'ALWAYS',         
6314     'RESPONDS'       : 'RESPONDS',       
6315     'INVOKE'         : 'INVOKE',         
6316     'PRIORITY'       : 'PRIORITY',       
6317     'RESULT-PRIORITY': 'RESULT-PRIORITY',
6318     'CODE'           : 'CODE',           
6319   },
6320   'ERROR' : {
6321   },
6322   'OPERATION-PACKAGE' : {
6323   },
6324   'CONNECTION-PACKAGE' : {
6325   },
6326   'CONTRACT' : {
6327   },
6328   'ROS-OBJECT-CLASS' : {
6329   },
6330
6331 }
6332
6333 x880_syntaxes_enabled = { }
6334 x880_current_syntaxes = None
6335
6336 def x880_import(name):
6337   if x880_syntaxes.has_key(name):
6338     x880_syntaxes_enabled[name] = True
6339     add_class_ident(name)
6340
6341 def is_x880_syntax(name):
6342   return False
6343
6344 #  {...} OID value
6345 #def p_lbrace_oid(t):
6346 #  'lbrace_oid : brace_oid_begin LBRACE'
6347 #  t[0] = t[1]
6348
6349 #def p_brace_oid_begin(t):
6350 #  'brace_oid_begin : '
6351 #  global in_oid
6352 #  in_oid = True
6353
6354 #def p_rbrace_oid(t):
6355 #  'rbrace_oid : brace_oid_end RBRACE'
6356 #  t[0] = t[2]
6357
6358 #def p_brace_oid_end(t):
6359 #  'brace_oid_end : '
6360 #  global in_oid
6361 #  in_oid = False
6362
6363 #  {...} block to be ignored
6364 def p_lbraceignore(t):
6365   'lbraceignore : braceignorebegin LBRACE'
6366   t[0] = t[1]
6367
6368 def p_braceignorebegin(t):
6369   'braceignorebegin : '
6370   global lexer
6371   lexer.level = 1
6372   lexer.begin('braceignore')
6373
6374 def p_rbraceignore(t):
6375   'rbraceignore : braceignoreend RBRACE'
6376   t[0] = t[2]
6377
6378 def p_braceignoreend(t):
6379   'braceignoreend : '
6380   global lexer
6381   lexer.begin('INITIAL')
6382
6383 def p_error(t):
6384   global input_file
6385   raise ParseError(t, input_file)
6386
6387 def p_pyquote (t):
6388     '''pyquote : PYQUOTE'''
6389     t[0] = PyQuote (val = t[1])
6390
6391
6392 def testlex (s):
6393     lexer.input (s)
6394     while 1:
6395         token = lexer.token ()
6396         if not token:
6397             break
6398         print token
6399
6400
6401 def do_module (ast, defined_dict):
6402     assert (ast.type == 'Module')
6403     ctx = Ctx (defined_dict)
6404     print ast.to_python (ctx)
6405     print ctx.output_assignments ()
6406     print ctx.output_pyquotes ()
6407
6408 def eth_do_module (ast, ectx):
6409     assert (ast.type == 'Module')
6410     if ectx.dbg('s'): print ast.str_depth(0)
6411     ast.to_eth(ectx)
6412
6413 def testyacc(s, fn, defined_dict):
6414     ast = yacc.parse(s, debug=0)
6415     time_str = time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime())
6416     print """#!/usr/bin/env python
6417 # Auto-generated from %s at %s
6418 from PyZ3950 import asn1""" % (fn, time_str)
6419     for module in ast:
6420       eth_do_module (module, defined_dict)
6421
6422
6423 # Wireshark compiler
6424 def eth_usage():
6425   print """
6426 asn2wrs [-h|?] [-d dbg] [-b] [-p proto] [-c conform_file] [-e] input_file(s) ...
6427   -h|?          : usage
6428   -b            : BER (default is PER)
6429   -u            : unaligned (default is aligned)
6430   -p proto      : protocol name (implies -S)
6431                   default is module-name from input_file (renamed by #.MODULE if present)
6432   -F            : create 'field functions'
6433   -T            : tagged type support (experimental)
6434   -o name       : output files name core (default is <proto>)
6435   -O dir        : output directory
6436   -c conform_file : conformation file
6437   -I path       : path for conformance file includes
6438   -e            : create conformation file for exported types
6439   -S            : single output for multiple modules
6440   -s template   : single file output (template is input file without .c/.h extension)
6441   -k            : keep intermediate files though single file output is used
6442   -L            : suppress #line directive from .cnf file
6443   input_file(s) : input ASN.1 file(s)
6444
6445   -d dbg     : debug output, dbg = [l][y][p][s][a][t][c][m][o]
6446                l - lex 
6447                y - yacc
6448                p - parsing
6449                s - internal ASN.1 structure
6450                a - list of assignments
6451                t - tables
6452                c - conformance values
6453                m - list of compiled modules with dependency
6454                o - list of output files
6455 """
6456
6457 def eth_main():
6458   global input_file
6459   global lexer
6460   print "ASN.1 to Wireshark dissector compiler";
6461   try:
6462     opts, args = getopt.getopt(sys.argv[1:], "h?d:buXp:FTo:O:c:I:eSs:kL");
6463   except getopt.GetoptError:
6464     eth_usage(); sys.exit(2)
6465   if len(args) < 1:
6466     eth_usage(); sys.exit(2)
6467
6468   conform = EthCnf()
6469   conf_to_read = None
6470   output = EthOut()
6471   ectx = EthCtx(conform, output)
6472   ectx.encoding = 'per'
6473   ectx.proto_opt = None
6474   ectx.fld_opt = {}
6475   ectx.tag_opt = False
6476   ectx.outnm_opt = None
6477   ectx.aligned = True
6478   ectx.dbgopt = ''
6479   ectx.new = True
6480   ectx.expcnf = False
6481   ectx.merge_modules = False
6482   ectx.conform.suppress_line = False;
6483   ectx.output.outnm = None
6484   ectx.output.single_file = None
6485   for o, a in opts:
6486     if o in ("-h", "-?"):
6487       eth_usage(); sys.exit(2)
6488     if o in ("-c",):
6489       conf_to_read = a
6490     if o in ("-I",):
6491       ectx.conform.include_path.append(a)
6492     #if o in ("-X",):
6493     #    warnings.warn("Command line option -X is obsolete and can be removed")
6494
6495   if conf_to_read:
6496     ectx.conform.read(conf_to_read)
6497
6498   for o, a in opts:
6499     if o in ("-h", "-?", "-c", "-I"):
6500       pass  # already processed
6501     else:
6502       par = []
6503       if a: par.append(a)
6504       ectx.conform.set_opt(o, par, "commandline", 0)
6505
6506   (ld, yd, pd) = (0, 0, 0); 
6507   if ectx.dbg('l'): ld = 1
6508   if ectx.dbg('y'): yd = 1
6509   if ectx.dbg('p'): pd = 2
6510   lexer = lex.lex(debug=ld)
6511   yacc.yacc(method='LALR', debug=yd)
6512   ast = []
6513   for fn in args:
6514     input_file = fn
6515     lexer.lineno = 1
6516     f = open (fn, "r")
6517     ast.extend(yacc.parse(f.read(), lexer=lexer, debug=pd))
6518     f.close ()
6519   ectx.eth_clean()
6520   for module in ast:
6521     eth_do_module(module, ectx)
6522     if (not ectx.merge_modules):  # output for each module
6523       ectx.eth_prepare()
6524       ectx.eth_do_output()
6525       ectx.eth_clean()
6526   if (ectx.merge_modules):  # common output for all module
6527     ectx.eth_prepare()
6528     ectx.eth_do_output()
6529
6530   if ectx.dbg('m'):
6531     ectx.dbg_modules()
6532
6533   if ectx.dbg('c'):
6534     ectx.conform.dbg_print()
6535   ectx.conform.unused_report()
6536
6537   if ectx.dbg('o'):
6538     ectx.output.dbg_print()
6539   ectx.output.make_single_file()
6540     
6541
6542 # Python compiler
6543 def main():
6544     testfn = testyacc
6545     if len (sys.argv) == 1:
6546         while 1:
6547             s = raw_input ('Query: ')
6548             if len (s) == 0:
6549                 break
6550             testfn (s, 'console', {})
6551     else:
6552         defined_dict = {}
6553         for fn in sys.argv [1:]:
6554             f = open (fn, "r")
6555             testfn (f.read (), fn, defined_dict)
6556             f.close ()
6557             lexer.lineno = 1
6558   
6559
6560 #--- BODY ---------------------------------------------------------------------
6561
6562 if __name__ == '__main__':
6563   if (os.path.splitext(os.path.basename(sys.argv[0]))[0].lower() in ('asn2wrs', 'asn2eth')):
6564     eth_main()
6565   else:
6566     main()
6567
6568 #------------------------------------------------------------------------------