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