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