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