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