QSIG fully implemented
[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_class_syntax(t.value)): t.type = t.value
331     t.type = reserved_words.get(t.value, t.type)
332     return t
333
334 lcase_ident_assigned = {}
335 def t_LCASE_IDENT (t):
336     r"[a-z](-[a-zA-Z0-9]|[a-zA-Z0-9])*" # can't end w/ '-'
337     if (not in_oid and lcase_ident_assigned.has_key(t.value)): t.type = 'LCASE_IDENT_ASSIGNED'
338     return t
339
340 # 11.9 Real numbers
341 def t_REAL_NUMBER (t):
342     r"[0-9]+\.[0-9]*(?!\.)"
343     return t
344
345 # 11.8 Numbers
346 def t_NUMBER (t):
347     r"0|([1-9][0-9]*)"
348     return t
349
350 # 11.6 Comments
351 pyquote_str = 'PYQUOTE'
352 def t_COMMENT(t):
353     r"--(-[^\-\n]|[^\-\n])*(--|\n|-\n|$|-$)"
354     if (t.value.find("\n") >= 0) : t.lexer.lineno += 1
355     if t.value[2:2+len (pyquote_str)] == pyquote_str:
356         t.value = t.value[2+len(pyquote_str):]
357         t.value = t.value.lstrip ()
358         t.type = pyquote_str
359         return t
360     return None
361
362 t_ignore = " \t\r"
363
364 def t_NEWLINE(t):
365     r'\n+'
366     t.lexer.lineno += t.value.count("\n")
367
368 def t_error(t):
369   global input_file
370   raise LexError(t, input_file)
371
372 # state 'braceignore'
373
374 def t_braceignore_lbrace(t):     
375   r'\{'
376   t.lexer.level +=1                
377
378 def t_braceignore_rbrace(t):
379   r'\}'
380   t.lexer.level -=1
381   # If closing brace, return token
382   if t.lexer.level == 0:
383     t.type = 'RBRACE'
384     return t
385
386 def t_braceignore_QSTRING (t):
387   r'"([^"]|"")*"'
388   t.lexer.lineno += t.value.count("\n")
389
390 def t_braceignore_COMMENT(t):
391   r"--(-[^\-\n]|[^\-\n])*(--|\n|-\n|$|-$)"
392   if (t.value.find("\n") >= 0) : t.lexer.lineno += 1
393
394 def t_braceignore_nonspace(t):
395    r'[^\s\{\}\"-]+|-(?!-)'
396
397 t_braceignore_ignore = " \t\r"
398
399 def t_braceignore_NEWLINE(t):
400   r'\n+'
401   t.lexer.lineno += t.value.count("\n")
402
403 def t_braceignore_error(t):
404   t.lexer.skip(1)
405
406 class Ctx:
407     def __init__ (self, defined_dict, indent = 0):
408         self.tags_def = 'EXPLICIT' # default = explicit
409         self.indent_lev = 0
410         self.assignments = {}
411         self.dependencies = {}
412         self.pyquotes = []
413         self.defined_dict = defined_dict
414         self.name_ctr = 0
415     def spaces (self):
416         return " " * (4 * self.indent_lev)
417     def indent (self):
418         self.indent_lev += 1
419     def outdent (self):
420         self.indent_lev -= 1
421         assert (self.indent_lev >= 0)
422     def register_assignment (self, ident, val, dependencies):
423         if self.assignments.has_key (ident):
424             raise "Duplicate assignment for " + ident
425         if self.defined_dict.has_key (ident):
426             raise "cross-module duplicates for " + ident
427         self.defined_dict [ident] = 1
428         self.assignments[ident] = val
429         self.dependencies [ident] = dependencies
430         return ""
431     #        return "#%s depends on %s" % (ident, str (dependencies))
432     def register_pyquote (self, val):
433         self.pyquotes.append (val)
434         return ""
435     def output_assignments (self):
436         already_output = {}
437         text_list = []
438         assign_keys = self.assignments.keys()
439         to_output_count = len (assign_keys)
440         while 1:
441             any_output = 0
442             for (ident, val) in self.assignments.iteritems ():
443                 if already_output.has_key (ident):
444                     continue
445                 ok = 1
446                 for d in self.dependencies [ident]:
447                     if (not already_output.has_key (d) and
448                         d in assign_keys):
449                         ok = 0
450                 if ok:
451                     text_list.append ("%s=%s" % (ident,
452                                                 self.assignments [ident]))
453                     already_output [ident] = 1
454                     any_output = 1
455                     to_output_count -= 1
456                     assert (to_output_count >= 0)
457             if not any_output:
458                 if to_output_count == 0:
459                     break
460                 # OK, we detected a cycle
461                 cycle_list = []
462                 for ident in self.assignments.iterkeys ():
463                     if not already_output.has_key (ident):
464                         depend_list = [d for d in self.dependencies[ident] if d in assign_keys]
465                         cycle_list.append ("%s(%s)" % (ident, ",".join (depend_list)))
466                         
467                 text_list.append ("# Cycle XXX " + ",".join (cycle_list))
468                 for (ident, val) in self.assignments.iteritems ():
469                     if not already_output.has_key (ident):
470                         text_list.append ("%s=%s" % (ident, self.assignments [ident]))
471                 break
472
473         return "\n".join (text_list)
474     def output_pyquotes (self):
475         return "\n".join (self.pyquotes)
476     def make_new_name (self):
477         self.name_ctr += 1
478         return "_compiler_generated_name_%d" % (self.name_ctr,)
479
480 #--- Flags for EXPORT, USER_DEFINED, NO_EMIT, MAKE_ENUM -------------------------------
481 EF_TYPE    = 0x0001
482 EF_VALS    = 0x0002
483 EF_ENUM    = 0x0004
484 EF_WS_VAR  = 0x0010
485 EF_EXTERN  = 0x0020
486 EF_NO_PROT = 0x0040
487 EF_NO_TYPE = 0x0080
488 EF_UCASE   = 0x0100
489 EF_TABLE   = 0x0400
490 EF_DEFINE  = 0x0800
491
492 #--- common dependency computation ---
493 # Input  : list of items
494 #          dictionary with lists of dependency
495 #
496 #           
497 # Output : list of two outputs:
498 #          [0] list of items in dependency
499 #          [1] list of cycle dependency cycles
500 def dependency_compute(items, dependency, map_fn = lambda t: t, ignore_fn = lambda t: False):
501   item_ord = []
502   item_cyc = []
503   x = {}  # already emitted
504   #print '# Dependency computation'
505   for t in items:
506     if x.has_key(map_fn(t)):
507       #print 'Continue: %s : %s' % (t, (map_fn(t))
508       continue
509     stack = [t]
510     stackx = {t : dependency.get(t, [])[:]}
511     #print 'Push: %s : %s' % (t, str(stackx[t]))
512     while stack:
513       if stackx[stack[-1]]:  # has dependencies
514         d = stackx[stack[-1]].pop(0)
515         if x.has_key(map_fn(d)) or ignore_fn(d):
516           continue
517         if stackx.has_key(d):  # cyclic dependency
518           c = stack[:]
519           c.reverse()
520           c = [d] + c[0:c.index(d)+1]
521           c.reverse()
522           item_cyc.append(c)
523           #print 'Cyclic: %s ' % (' -> '.join(c))
524           continue
525         stack.append(d)
526         stackx[d] = dependency.get(d, [])[:]
527         #print 'Push: %s : %s' % (d, str(stackx[d]))
528       else:
529         #print 'Pop: %s' % (stack[-1])
530         del stackx[stack[-1]]
531         e = map_fn(stack.pop())
532         if x.has_key(e):
533           continue
534         #print 'Add: %s' % (e)
535         item_ord.append(e)
536         x[e] = True
537   return (item_ord, item_cyc)
538
539 #--- EthCtx -------------------------------------------------------------------
540 class EthCtx:
541   def __init__(self, conform, output, indent = 0):
542     self.conform = conform
543     self.output = output
544     self.conform.ectx = self
545     self.output.ectx = self
546     self.encoding = 'per'
547     self.aligned = False
548     self.new_ber = False
549     self.default_oid_variant = ''
550     self.default_opentype_variant = ''
551     self.default_containing_variant = '_pdu_new'
552     self.default_embedded_pdv_cb = None
553     self.default_external_type_cb = None
554     self.emitted_pdu = {}
555     self.module = {}
556     self.module_ord = []
557     self.all_type_attr = {}
558     self.all_tags = {}
559     self.all_vals = {}
560
561   def encp(self):  # encoding protocol
562     encp = self.encoding
563     return encp
564
565   # Encoding
566   def Per(self): return self.encoding == 'per'
567   def Ber(self): return self.encoding == 'ber'
568   def NewBer(self): return self.new_ber
569   def Aligned(self): return self.aligned
570   def Unaligned(self): return not self.aligned
571   def Fld(self, tnm='*'): return self.fld_opt.get('*', False) or self.fld_opt.get(tnm, False) or (self.Ber() and not self.NewBer())
572   def Tag(self): return self.tag_opt # or self.Ber() - temporary comment out (experimental feature)
573   def NAPI(self): return False  # disable planned features
574
575   def Module(self):  # current module name
576     return self.modules[-1][0]
577
578   def groups(self):
579     return self.group_by_prot or (self.conform.last_group > 0)
580
581   def dbg(self, d):
582     if (self.dbgopt.find(d) >= 0):
583       return True
584     else:
585       return False
586
587   def value_max(self, a, b):
588     if (a == 'MAX') or (b == 'MAX'): return 'MAX';
589     if a == 'MIN': return b;
590     if b == 'MIN': return a;
591     try:
592       if (int(a) > int(b)):
593         return a
594       else:
595         return b
596     except (ValueError, TypeError):
597       pass
598     return "MAX((%s),(%s))" % (a, b) 
599
600   def value_min(self, a, b):
601     if (a == 'MIN') or (b == 'MIN'): return 'MIN';
602     if a == 'MAX': return b;
603     if b == 'MAX': return a;
604     try:
605       if (int(a) < int(b)):
606         return a
607       else:
608         return b
609     except (ValueError, TypeError):
610       pass
611     return "MIN((%s),(%s))" % (a, b) 
612
613   def value_get_eth(self, val):
614     if isinstance(val, Value):
615       return val.to_str(self)
616     ethname = val
617     if self.value.has_key(val):
618       ethname = self.value[val]['ethname']
619     return ethname
620
621   def value_get_val(self, nm):
622     val = asn2c(nm)
623     if self.value.has_key(nm):
624       if self.value[nm]['import']:
625         v = self.get_val_from_all(nm, self.value[nm]['import'])
626         if v is None:
627           msg = 'Need value of imported value identifier %s from %s (%s)' % (nm, self.value[nm]['import'], self.value[nm]['proto'])
628           warnings.warn_explicit(msg, UserWarning, '', '')
629         else:
630           val = v
631       else:
632         val = self.value[nm]['value']
633         if isinstance (val, Value):
634           val = val.to_str(self)
635     else:
636       msg = 'Need value of unknown value identifier %s' % (nm)
637       warnings.warn_explicit(msg, UserWarning, '', '')
638     return val
639
640   def eth_get_type_attr(self, type):
641     types = [type]
642     while (not self.type[type]['import'] 
643            and self.type[type]['val'].type == 'Type_Ref'):
644       type = self.type[type]['val'].val
645       types.append(type)
646     attr = {}
647     while len(types):
648       t = types.pop()
649       if (self.type[t]['import']):
650         attr.update(self.type[t]['attr'])
651         attr.update(self.eth_get_type_attr_from_all(t, self.type[t]['import']))
652       elif (self.type[t]['val'].type == 'SelectionType'):
653         val = self.type[t]['val']
654         (ftype, display) = val.eth_ftype(self)
655         attr.update({ 'TYPE' : ftype, 'DISPLAY' : display,
656                       'STRINGS' : val.eth_strings(), 'BITMASK' : '0' });
657       else:
658         attr.update(self.type[t]['attr'])
659         attr.update(self.eth_type[self.type[t]['ethname']]['attr'])
660     return attr
661
662   def eth_get_type_attr_from_all(self, type, module):
663     attr = {}
664     if self.all_type_attr.has_key(module) and self.all_type_attr[module].has_key(type):
665       attr = self.all_type_attr[module][type]
666     return attr
667
668   def get_ttag_from_all(self, type, module):
669     ttag = None
670     if self.all_tags.has_key(module) and self.all_tags[module].has_key(type):
671       ttag = self.all_tags[module][type]
672     return ttag
673
674   def get_val_from_all(self, nm, module):
675     val = None
676     if self.all_vals.has_key(module) and self.all_vals[module].has_key(nm):
677       val = self.all_vals[module][nm]
678     return val
679
680   def get_obj_repr(self, ident, restr):
681     def set_type_fn(cls, field, fnfield):
682       obj[fnfield + '_fn'] = 'NULL'
683       obj[fnfield + '_pdu'] = 'NULL'
684       if val.has_key(field) and isinstance(val[field], Type_Ref):
685         p = val[field].eth_type_default_pars(self, '')
686         obj[fnfield + '_fn'] = p['TYPE_REF_FN']
687         obj[fnfield + '_fn'] = obj[fnfield + '_fn'] % p  # one iteration
688         if (self.conform.check_item('PDU', cls + '.' + field)):
689           obj[fnfield + '_pdu'] = 'dissect_' + self.field[val[field].val]['ethname']
690       return
691     # end of get_type_fn()
692     obj = { '_name' : ident, '_ident' : asn2c(ident)}
693     obj['_class'] = self.oassign[ident].cls
694     val = self.oassign[ident].val
695     fld = None
696     fld_neg = False
697     if len(restr) > 0:
698       fld = restr[0]
699       if fld[0] == '!':
700         fld_neg = True
701         fld = fld[1:]
702     if fld:
703       if fld_neg:
704         if val.has_key(fld):
705           return None
706       else:
707         if not val.has_key(fld):
708           return None
709     for f in val.keys():
710       if isinstance(val[f], Node):
711         obj[f] = val[f].fld_obj_repr(self)
712       else:
713         obj[f] = str(val[f])
714     if (obj['_class'] == 'TYPE-IDENTIFIER') or (obj['_class'] == 'ABSTRACT-SYNTAX'):
715       set_type_fn(obj['_class'], '&Type', '_type')
716     if (obj['_class'] == 'OPERATION'):
717       set_type_fn(obj['_class'], '&ArgumentType', '_argument')
718       set_type_fn(obj['_class'], '&ResultType', '_result')
719     if (obj['_class'] == 'ERROR'):
720       set_type_fn(obj['_class'], '&ParameterType', '_parameter')
721     return obj
722
723   #--- eth_reg_module -----------------------------------------------------------
724   def eth_reg_module(self, module):
725     #print "eth_reg_module(module='%s')" % (module)
726     name = module.get_name()
727     self.modules.append([name, module.get_proto(self)])
728     if self.module.has_key(name):
729       raise "Duplicate module for " + name
730     self.module[name] = []
731     self.module_ord.append(name)
732
733   #--- eth_module_dep_add ------------------------------------------------------------
734   def eth_module_dep_add(self, module, dep):
735     self.module[module].append(dep)
736
737   #--- eth_exports ------------------------------------------------------------
738   def eth_exports(self, exports):
739     self.exports_all = False
740     if ((len(exports) == 1) and (exports[0] == 'ALL')):
741       self.exports_all = True
742       return
743     for e in (exports):
744       if isinstance(e, Type_Ref):
745         self.exports.append(e.val)
746       elif isinstance(e, Class_Ref):
747         self.cexports.append(e.val)
748       else:
749         self.vexports.append(e)
750
751   #--- eth_reg_assign ---------------------------------------------------------
752   def eth_reg_assign(self, ident, val, virt=False):
753     #print "eth_reg_assign(ident='%s')" % (ident)
754     if self.assign.has_key(ident):
755       raise "Duplicate assignment for " + ident
756     self.assign[ident] = { 'val' : val , 'virt' : virt }
757     self.assign_ord.append(ident)
758     if  (self.exports_all):
759       self.exports.append(ident)
760
761   #--- eth_reg_vassign --------------------------------------------------------
762   def eth_reg_vassign(self, vassign):
763     ident = vassign.ident
764     #print "eth_reg_vassign(ident='%s')" % (ident)
765     if self.vassign.has_key(ident):
766       raise "Duplicate value assignment for " + ident
767     self.vassign[ident] = vassign
768     self.vassign_ord.append(ident)
769     if  (self.exports_all):
770       self.vexports.append(ident)
771
772   #--- eth_reg_oassign --------------------------------------------------------
773   def eth_reg_oassign(self, oassign):
774     ident = oassign.ident
775     #print "eth_reg_oassign(ident='%s')" % (ident)
776     if self.oassign.has_key(ident):
777       if self.oassign[ident] == oassign:
778         return  # OK - already defined
779       else:
780         raise "Duplicate information object assignment for " + ident
781     self.oassign[ident] = oassign
782     self.oassign_ord.append(ident)
783     self.oassign_cls.setdefault(oassign.cls, []).append(ident)
784
785   #--- eth_import_type --------------------------------------------------------
786   def eth_import_type(self, ident, mod, proto):
787     #print "eth_import_type(ident='%s', mod='%s', prot='%s')" % (ident, mod, proto)
788     if self.type.has_key(ident):
789       #print "already defined import=%s, module=%s" % (str(self.type[ident]['import']), self.type[ident]['module'])
790       if not self.type[ident]['import'] and (self.type[ident]['module'] == mod) :
791         return  # OK - already defined
792       elif self.type[ident]['import'] and (self.type[ident]['import'] == mod) :
793         return  # OK - already imported
794       else:
795         raise "Duplicate type for " + ident
796     self.type[ident] = {'import'  : mod, 'proto' : proto,
797                         'ethname' : '' }
798     self.type[ident]['attr'] = { 'TYPE' : 'FT_NONE', 'DISPLAY' : 'BASE_NONE',
799                                  'STRINGS' : 'NULL', 'BITMASK' : '0' }
800     self.type[ident]['attr'].update(self.conform.use_item('TYPE_ATTR', ident))
801     self.type_imp.append(ident)
802
803   #--- dummy_import_type --------------------------------------------------------
804   def dummy_import_type(self, ident):
805     # dummy imported
806     if self.type.has_key(ident):
807         raise "Try to dummy import for existing type :" + ident
808     ethtype = asn2c(ident)
809     self.type[ident] = {'import'  : 'xxx', 'proto' : 'xxx',
810                         'ethname' : ethtype }
811     self.type[ident]['attr'] = { 'TYPE' : 'FT_NONE', 'DISPLAY' : 'BASE_NONE',
812                                  'STRINGS' : 'NULL', 'BITMASK' : '0' }
813     self.eth_type[ethtype] = { 'import' : 'xxx', 'proto' : 'xxx' , 'attr' : {}, 'create_field' : False, 'ref' : []}
814     print "Dummy imported: %s (%s)" % (ident, ethtype)
815     return ethtype
816
817   #--- eth_import_class --------------------------------------------------------
818   def eth_import_class(self, ident, mod, proto):
819     #print "eth_import_class(ident='%s', mod='%s', prot='%s')" % (ident, mod, proto)
820     if self.objectclass.has_key(ident):
821       #print "already defined import=%s, module=%s" % (str(self.objectclass[ident]['import']), self.objectclass[ident]['module'])
822       if not self.objectclass[ident]['import'] and (self.objectclass[ident]['module'] == mod) :
823         return  # OK - already defined
824       elif self.objectclass[ident]['import'] and (self.objectclass[ident]['import'] == mod) :
825         return  # OK - already imported
826       else:
827         raise "Duplicate object class for " + ident
828     self.objectclass[ident] = {'import'  : mod, 'proto' : proto,
829                         'ethname' : '' }
830     self.objectclass_imp.append(ident)
831
832   #--- eth_import_value -------------------------------------------------------
833   def eth_import_value(self, ident, mod, proto):
834     #print "eth_import_value(ident='%s', mod='%s', prot='%s')" % (ident, mod, prot)
835     if self.value.has_key(ident):
836       #print "already defined import=%s, module=%s" % (str(self.value[ident]['import']), self.value[ident]['module'])
837       if not self.value[ident]['import'] and (self.value[ident]['module'] == mod) :
838         return  # OK - already defined
839       elif self.value[ident]['import'] and (self.value[ident]['import'] == mod) :
840         return  # OK - already imported
841       else:
842         raise "Duplicate value for " + ident
843     self.value[ident] = {'import'  : mod, 'proto' : proto,
844                          'ethname' : ''}
845     self.value_imp.append(ident)
846
847   #--- eth_sel_req ------------------------------------------------------------
848   def eth_sel_req(self, typ, sel):
849     key = typ + '.' + sel
850     if not self.sel_req.has_key(key):
851       self.sel_req[key] = { 'typ' : typ , 'sel' : sel}
852       self.sel_req_ord.append(key)
853     return key
854
855   #--- eth_comp_req ------------------------------------------------------------
856   def eth_comp_req(self, type):
857     self.comp_req_ord.append(type)
858
859   #--- eth_dep_add ------------------------------------------------------------
860   def eth_dep_add(self, type, dep):
861     if not self.type_dep.has_key(type): 
862       self.type_dep[type] = []
863     self.type_dep[type].append(dep)
864
865   #--- eth_reg_type -----------------------------------------------------------
866   def eth_reg_type(self, ident, val):
867     #print "eth_reg_type(ident='%s', type='%s')" % (ident, val.type)
868     if self.type.has_key(ident):
869       if self.type[ident]['import'] and (self.type[ident]['import'] == self.Module()) :
870         # replace imported type
871         del self.type[ident]
872         self.type_imp.remove(ident)
873       else:
874         raise "Duplicate type for " + ident
875     self.type[ident] = { 'val' : val, 'import' : None }
876     self.type[ident]['module'] = self.Module()
877     self.type[ident]['proto'] = self.proto
878     if len(ident.split('/')) > 1:
879       self.type[ident]['tname'] = val.eth_tname()
880     else:
881       self.type[ident]['tname'] = asn2c(ident)
882     self.type[ident]['export'] = self.conform.use_item('EXPORTS', ident)
883     self.type[ident]['enum'] = self.conform.use_item('MAKE_ENUM', ident)
884     self.type[ident]['user_def'] = self.conform.use_item('USER_DEFINED', ident)
885     self.type[ident]['no_emit'] = self.conform.use_item('NO_EMIT', ident)
886     self.type[ident]['tname'] = self.conform.use_item('TYPE_RENAME', ident, val_dflt=self.type[ident]['tname'])
887     self.type[ident]['ethname'] = ''
888     if (val.type == 'Type_Ref') or (val.type == 'SelectionType') :
889       self.type[ident]['attr'] = {}
890     else:
891       (ftype, display) = val.eth_ftype(self)
892       self.type[ident]['attr'] = { 'TYPE' : ftype, 'DISPLAY' : display,
893                                    'STRINGS' : val.eth_strings(), 'BITMASK' : '0' }
894     self.type[ident]['attr'].update(self.conform.use_item('TYPE_ATTR', ident))
895     self.type_ord.append(ident)
896     # PDU
897     if (self.conform.check_item('PDU', ident)):
898       self.eth_reg_field(ident, ident, impl=val.HasImplicitTag(self), pdu=self.conform.use_item('PDU', ident))
899
900   #--- eth_reg_objectclass ----------------------------------------------------------
901   def eth_reg_objectclass(self, ident, val):
902     #print "eth_reg_objectclass(ident='%s')" % (ident)
903     if self.objectclass.has_key(ident):
904       if self.objectclass[ident]['import'] and (self.objectclass[ident]['import'] == self.Module()) :
905         # replace imported object class
906         del self.objectclass[ident]
907         self.objectclass_imp.remove(ident)
908       elif isinstance(self.objectclass[ident]['val'], Class_Ref) and \
909            isinstance(val, Class_Ref) and \
910            (self.objectclass[ident]['val'].val == val.val):
911         pass  # ignore duplicated CLASS1 ::= CLASS2
912       else:
913         raise "Duplicate object class for " + ident
914     self.objectclass[ident] = { 'import' : None, 'module' : self.Module(), 'proto' : self.proto }
915     self.objectclass[ident]['val'] = val
916     self.objectclass[ident]['export'] = self.conform.use_item('EXPORTS', ident)
917     self.objectclass_ord.append(ident)
918
919   #--- eth_reg_value ----------------------------------------------------------
920   def eth_reg_value(self, ident, type, value, ethname=None):
921     #print "eth_reg_value(ident='%s')" % (ident)
922     if self.value.has_key(ident):
923       if self.value[ident]['import'] and (self.value[ident]['import'] == self.Module()) :
924         # replace imported value
925         del self.value[ident]
926         self.value_imp.remove(ident)
927       elif ethname:
928         self.value[ident]['ethname'] = ethname
929         return
930       else:
931         raise "Duplicate value for " + ident
932     self.value[ident] = { 'import' : None, 'module' : self.Module(), 'proto' : self.proto,
933                           'type' : type, 'value' : value,
934                           'no_emit' : False }
935     self.value[ident]['export'] = self.conform.use_item('EXPORTS', ident)
936     self.value[ident]['ethname'] = ''
937     if (ethname): self.value[ident]['ethname'] = ethname
938     self.value_ord.append(ident)
939
940   #--- eth_reg_field ----------------------------------------------------------
941   def eth_reg_field(self, ident, type, idx='', parent=None, impl=False, pdu=None):
942     #print "eth_reg_field(ident='%s', type='%s')" % (ident, type)
943     if self.field.has_key(ident):
944       if pdu and (type == self.field[ident]['type']):
945         pass  # OK already created PDU
946       else:
947         raise "Duplicate field for " + ident
948     self.field[ident] = {'type' : type, 'idx' : idx, 'impl' : impl, 'pdu' : pdu,
949                          'modified' : '', 'attr' : {} , 'create_field' : False }
950     name = ident.split('/')[-1]
951     if len(ident.split('/')) > 1 and name == '_item':  # Sequnce/Set of type
952       self.field[ident]['attr']['NAME'] = '"Item"'
953       self.field[ident]['attr']['ABBREV'] = asn2c(ident.split('/')[-2] + name)
954     else:
955       self.field[ident]['attr']['NAME'] = '"%s"' % name
956       self.field[ident]['attr']['ABBREV'] = asn2c(name)
957     if self.conform.check_item('FIELD_ATTR', ident):
958       self.field[ident]['modified'] = '#' + str(id(self))
959       self.field[ident]['attr'].update(self.conform.use_item('FIELD_ATTR', ident))
960     if (pdu):
961       self.pdu_ord.append(ident)
962     else:
963       self.field_ord.append(ident)
964     if parent:
965       self.field[ident]['create_field'] = self.Fld(parent)
966       self.eth_dep_add(parent, type)
967
968   #--- eth_clean --------------------------------------------------------------
969   def eth_clean(self):
970     self.proto = self.proto_opt;
971     #--- ASN.1 tables ----------------
972     self.assign = {}
973     self.assign_ord = []
974     self.field = {}
975     self.pdu_ord = []
976     self.field_ord = []
977     self.type = {}
978     self.type_ord = []
979     self.type_imp = []
980     self.type_dep = {}
981     self.sel_req = {}
982     self.sel_req_ord = []
983     self.comp_req_ord = []
984     self.vassign = {}
985     self.vassign_ord = []
986     self.value = {}
987     self.value_ord = []
988     self.value_imp = []
989     self.objectclass = {}
990     self.objectclass_ord = []
991     self.objectclass_imp = []
992     self.oassign = {}
993     self.oassign_ord = []
994     self.oassign_cls = {}
995     #--- Modules ------------
996     self.modules = []
997     self.exports_all = False
998     self.exports = []
999     self.cexports = []
1000     self.vexports = []
1001     #--- types -------------------
1002     self.eth_type = {}
1003     self.eth_type_ord = []
1004     self.eth_export_ord = []
1005     self.eth_type_dupl = {}
1006     self.named_bit = []
1007     #--- value dependencies -------------------
1008     self.value_dep = {}
1009     #--- values -------------------
1010     self.eth_value = {}
1011     self.eth_value_ord = []
1012     #--- fields -------------------------
1013     self.eth_hf = {}
1014     self.eth_hf_ord = []
1015     self.eth_hfpdu_ord = []
1016     self.eth_hf_dupl = {}
1017     #--- type dependencies -------------------
1018     self.eth_type_ord1 = []
1019     self.eth_dep_cycle = []
1020     self.dep_cycle_eth_type = {}
1021     #--- value dependencies and export -------------------
1022     self.eth_value_ord1 = []
1023     self.eth_vexport_ord = []
1024
1025   #--- eth_prepare ------------------------------------------------------------
1026   def eth_prepare(self):
1027     self.eproto = asn2c(self.proto)
1028
1029     #--- dummy types/fields for PDU registration ---
1030     nm = 'NULL'
1031     if (self.conform.check_item('PDU', nm)):
1032       self.eth_reg_type('_dummy/'+nm, NullType())
1033       self.eth_reg_field(nm, '_dummy/'+nm, pdu=self.conform.use_item('PDU', nm))
1034
1035     #--- required PDUs ----------------------------
1036     for t in self.type_ord:
1037       pdu = self.type[t]['val'].eth_need_pdu(self)
1038       if not pdu: continue
1039       f = pdu['type']
1040       pdu['reg'] = None
1041       pdu['hidden'] = False
1042       pdu['need_decl'] = True
1043       if not self.field.has_key(f):
1044         self.eth_reg_field(f, f, pdu=pdu)
1045
1046     #--- values -> named values -------------------
1047     t_for_update = {}
1048     for v in self.value_ord:
1049       if (self.value[v]['type'].type == 'Type_Ref'):
1050         tnm = self.value[v]['type'].val
1051         if self.type.has_key(tnm) \
1052            and not self.type[tnm]['import'] \
1053            and (self.type[tnm]['val'].type == 'IntegerType'):
1054           self.type[tnm]['val'].add_named_value(v, self.value[v]['value'])
1055           self.value[v]['no_emit'] = True
1056           t_for_update[tnm] = True
1057     for t in t_for_update.keys():
1058       self.type[t]['attr']['STRINGS'] = self.type[t]['val'].eth_strings()
1059       self.type[t]['attr'].update(self.conform.use_item('TYPE_ATTR', t))
1060
1061     #--- required components of ---------------------------
1062     #print "self.comp_req_ord = ", self.comp_req_ord
1063     for t in self.comp_req_ord:
1064       self.type[t]['val'].eth_reg_sub(t, self, components_available=True)
1065
1066     #--- required selection types ---------------------------
1067     #print "self.sel_req_ord = ", self.sel_req_ord
1068     for t in self.sel_req_ord:
1069       tt = self.sel_req[t]['typ']
1070       if not self.type.has_key(tt):
1071         self.dummy_import_type(t)
1072       elif self.type[tt]['import']:
1073         self.eth_import_type(t, self.type[tt]['import'], self.type[tt]['proto'])
1074       else:
1075         self.type[tt]['val'].sel_req(t, self.sel_req[t]['sel'], self)
1076
1077     #--- types -------------------
1078     for t in self.type_imp:
1079       nm = asn2c(t)
1080       self.eth_type[nm] = { 'import' : self.type[t]['import'], 
1081                             'proto' : asn2c(self.type[t]['proto']),
1082                             'attr' : {}, 'create_field' : False, 'ref' : []}
1083       self.eth_type[nm]['attr'].update(self.conform.use_item('ETYPE_ATTR', nm))
1084       self.type[t]['ethname'] = nm
1085     for t in self.type_ord:
1086       nm = self.type[t]['tname']
1087       if ((nm.find('#') >= 0) or 
1088           ((len(t.split('/'))>1) and 
1089            (self.conform.get_fn_presence(t) or self.conform.check_item('FN_PARS', t)) and 
1090            not self.conform.check_item('TYPE_RENAME', t))):
1091         if len(t.split('/')) == 2 and t.split('/')[1] == '_item':  # Sequnce of type at the 1st level
1092           nm = t.split('/')[0] + t.split('/')[1]
1093         elif t.split('/')[-1] == '_item':  # Sequnce/Set of type at next levels
1094           nm = 'T_' + self.conform.use_item('FIELD_RENAME', '/'.join(t.split('/')[0:-1]), val_dflt=t.split('/')[-2]) + t.split('/')[-1]
1095         elif t.split('/')[-1] == '_untag':  # Untagged type
1096           nm = self.type['/'.join(t.split('/')[0:-1])]['ethname'] + '_U'
1097         else:
1098           nm = 'T_' + self.conform.use_item('FIELD_RENAME', t, val_dflt=t.split('/')[-1])
1099         nm = asn2c(nm)
1100         if self.eth_type.has_key(nm):
1101           if self.eth_type_dupl.has_key(nm):
1102             self.eth_type_dupl[nm].append(t)
1103           else:
1104             self.eth_type_dupl[nm] = [self.eth_type[nm]['ref'][0], t]
1105           nm += '_%02d' % (len(self.eth_type_dupl[nm])-1)
1106       if self.eth_type.has_key(nm):
1107         self.eth_type[nm]['ref'].append(t)
1108       else:
1109         self.eth_type_ord.append(nm)
1110         self.eth_type[nm] = { 'import' : None, 'proto' : self.eproto, 'export' : 0, 'enum' : 0,
1111                               'user_def' : EF_TYPE|EF_VALS, 'no_emit' : EF_TYPE|EF_VALS, 
1112                               'val' : self.type[t]['val'], 
1113                               'attr' : {}, 
1114                               'create_field' : False, 'ref' : [t]}
1115       self.type[t]['ethname'] = nm
1116       if (not self.eth_type[nm]['export'] and self.type[t]['export']):  # new export
1117         self.eth_export_ord.append(nm)
1118       self.eth_type[nm]['export'] |= self.type[t]['export']
1119       self.eth_type[nm]['enum'] |= self.type[t]['enum']
1120       self.eth_type[nm]['user_def'] &= self.type[t]['user_def']
1121       self.eth_type[nm]['no_emit'] &= self.type[t]['no_emit']
1122       if self.type[t]['attr'].get('STRINGS') == '$$':
1123         self.eth_type[nm]['attr']['STRINGS'] = 'VALS(%s)' % (self.eth_vals_nm(nm))
1124       self.eth_type[nm]['attr'].update(self.conform.use_item('ETYPE_ATTR', nm))
1125     for t in self.eth_type_ord:
1126       bits = self.eth_type[t]['val'].eth_named_bits()
1127       if (bits):
1128         for (val, id) in bits:
1129           self.named_bit.append({'name' : id, 'val' : val,
1130                                  'ethname' : 'hf_%s_%s_%s' % (self.eproto, t, asn2c(id)),
1131                                  'ftype'   : 'FT_BOOLEAN', 'display' : '8',
1132                                  'strings' : 'NULL',
1133                                  'bitmask' : '0x'+('80','40','20','10','08','04','02','01')[val%8]})
1134       if self.eth_type[t]['val'].eth_need_tree():
1135         self.eth_type[t]['tree'] = "ett_%s_%s" % (self.eth_type[t]['proto'], t)
1136       else:
1137         self.eth_type[t]['tree'] = None
1138
1139     #--- register values from enums ------------
1140     for t in self.eth_type_ord:
1141       if (self.eth_type[t]['val'].eth_has_enum(t, self)):
1142         self.eth_type[t]['val'].reg_enum_vals(t, self)
1143
1144     #--- value dependencies -------------------
1145     for v in self.value_ord:
1146       if isinstance (self.value[v]['value'], Value):
1147         dep = self.value[v]['value'].get_dep()
1148       else:
1149         dep = self.value[v]['value']
1150       if dep and self.value.has_key(dep):
1151         self.value_dep.setdefault(v, []).append(dep)
1152     
1153     #--- exports all necessary values
1154     for v in self.value_ord:
1155       if not self.value[v]['export']: continue
1156       deparr = self.value_dep.get(v, [])
1157       while deparr:
1158         d = deparr.pop()
1159         if not self.value[d]['import']:
1160           if not self.value[d]['export']:
1161             self.value[d]['export'] = EF_TYPE
1162             deparr.extend(self.value_dep.get(d, []))
1163
1164     #--- values -------------------
1165     for v in self.value_imp:
1166       nm = asn2c(v)
1167       self.eth_value[nm] = { 'import' : self.value[v]['import'], 
1168                              'proto' : asn2c(self.value[v]['proto']), 
1169                              'ref' : []}
1170       self.value[v]['ethname'] = nm
1171     for v in self.value_ord:
1172       if (self.value[v]['ethname']):
1173         continue
1174       if (self.value[v]['no_emit']):
1175         continue
1176       nm = asn2c(v)
1177       self.eth_value[nm] = { 'import' : None, 
1178                              'proto' : asn2c(self.value[v]['proto']),
1179                              'export' : self.value[v]['export'], 'ref' : [v] }
1180       self.eth_value[nm]['value'] = self.value[v]['value']
1181       self.eth_value_ord.append(nm)
1182       self.value[v]['ethname'] = nm
1183
1184     #--- fields -------------------------
1185     for f in (self.pdu_ord + self.field_ord):
1186       if len(f.split('/')) > 1 and f.split('/')[-1] == '_item':  # Sequnce/Set of type
1187         nm = self.conform.use_item('FIELD_RENAME', '/'.join(f.split('/')[0:-1]), val_dflt=f.split('/')[-2]) + f.split('/')[-1]
1188       else:
1189         nm = f.split('/')[-1]
1190       nm = self.conform.use_item('FIELD_RENAME', f, val_dflt=nm)
1191       nm = asn2c(nm)
1192       if (self.field[f]['pdu']): 
1193         nm += '_PDU'
1194         if (not self.merge_modules):
1195           nm = self.eproto + '_' + nm
1196       t = self.field[f]['type']
1197       if self.type.has_key(t):
1198         ethtype = self.type[t]['ethname']
1199       else:  # undefined type
1200         ethtype = self.dummy_import_type(t)
1201       ethtypemod = ethtype + self.field[f]['modified']
1202       if self.eth_hf.has_key(nm):
1203         if self.eth_hf_dupl.has_key(nm):
1204           if self.eth_hf_dupl[nm].has_key(ethtypemod):
1205             nm = self.eth_hf_dupl[nm][ethtypemod]
1206             self.eth_hf[nm]['create_field'] = self.eth_hf[nm]['create_field'] or self.field[f]['create_field']
1207             self.eth_hf[nm]['ref'].append(f)
1208             self.field[f]['ethname'] = nm
1209             self.eth_type[ethtype]['create_field'] = self.eth_type[ethtype]['create_field'] or self.eth_hf[nm]['create_field']
1210             continue
1211           else:
1212             nmx = nm + ('_%02d' % (len(self.eth_hf_dupl[nm])))
1213             self.eth_hf_dupl[nm][ethtype] = nmx
1214             nm = nmx
1215         else:
1216           if (self.eth_hf[nm]['ethtype']+self.eth_hf[nm]['modified']) == ethtypemod:
1217             self.eth_hf[nm]['create_field'] = self.eth_hf[nm]['create_field'] or self.field[f]['create_field']
1218             self.eth_hf[nm]['ref'].append(f)
1219             self.field[f]['ethname'] = nm
1220             self.eth_type[ethtype]['create_field'] = self.eth_type[ethtype]['create_field'] or self.eth_hf[nm]['create_field']
1221             continue
1222           else:
1223             nmx = nm + '_01'
1224             self.eth_hf_dupl[nm] = {self.eth_hf[nm]['ethtype']+self.eth_hf[nm]['modified'] : nm, \
1225                                     ethtypemod : nmx}
1226             nm = nmx
1227       if (self.field[f]['pdu']):
1228         self.eth_hfpdu_ord.append(nm)
1229       else:
1230         self.eth_hf_ord.append(nm)
1231       fullname = 'hf_%s_%s' % (self.eproto, nm)
1232       attr = self.eth_get_type_attr(self.field[f]['type']).copy()
1233       attr.update(self.field[f]['attr'])
1234       if (self.NAPI() and attr.has_key('NAME')):
1235         attr['NAME'] += self.field[f]['idx']
1236       attr.update(self.conform.use_item('EFIELD_ATTR', nm))
1237       self.eth_hf[nm] = {'fullname' : fullname, 'pdu' : self.field[f]['pdu'],
1238                          'ethtype' : ethtype, 'modified' : self.field[f]['modified'],
1239                          'attr' : attr.copy(), 
1240                          'create_field' : self.field[f]['create_field'],
1241                          'ref' : [f]}
1242       self.field[f]['ethname'] = nm
1243       self.eth_type[ethtype]['create_field'] = self.eth_type[ethtype]['create_field'] or self.eth_hf[nm]['create_field']
1244     #--- type dependencies -------------------
1245     (self.eth_type_ord1, self.eth_dep_cycle) = dependency_compute(self.type_ord, self.type_dep, map_fn = lambda t: self.type[t]['ethname'], ignore_fn = lambda t: self.type[t]['import'])
1246     i = 0
1247     while i < len(self.eth_dep_cycle):
1248       t = self.type[self.eth_dep_cycle[i][0]]['ethname']
1249       self.dep_cycle_eth_type.setdefault(t, []).append(i)
1250       i += 1
1251
1252     #--- value dependencies and export -------------------
1253     for v in self.eth_value_ord:
1254       if self.eth_value[v]['export']:
1255         self.eth_vexport_ord.append(v)
1256       else:
1257         self.eth_value_ord1.append(v)
1258
1259     #--- export tags, values, ... ---
1260     for t in self.exports:
1261       if not self.type.has_key(t):
1262         continue
1263       if self.type[t]['import']:
1264         continue
1265       m = self.type[t]['module']
1266       if not self.all_tags.has_key(m):
1267         self.all_tags[m] = {}
1268       self.all_tags[m][t] = self.type[t]['val'].GetTTag(self)
1269       if not self.all_type_attr.has_key(m):
1270         self.all_type_attr[m] = {}
1271       self.all_type_attr[m][t] = self.eth_get_type_attr(t).copy()
1272     for v in self.vexports:
1273       if not self.value.has_key(v):
1274         continue
1275       if self.value[v]['import']:
1276         continue
1277       m = self.value[v]['module']
1278       if not self.all_vals.has_key(m):
1279         self.all_vals[m] = {}
1280       vv = self.value[v]['value']
1281       if isinstance (vv, Value):
1282         vv = vv.to_str(self)
1283       self.all_vals[m][v] = vv
1284
1285   #--- eth_vals_nm ------------------------------------------------------------
1286   def eth_vals_nm(self, tname):
1287     out = ""
1288     if (not self.eth_type[tname]['export'] & EF_NO_PROT):
1289       out += "%s_" % (self.eproto)
1290     out += "%s_vals" % (tname)
1291     return out
1292
1293   #--- eth_vals ---------------------------------------------------------------
1294   def eth_vals(self, tname, vals):
1295     out = ""
1296     has_enum = self.eth_type[tname]['enum'] & EF_ENUM
1297     if (not self.eth_type[tname]['export'] & EF_VALS):
1298       out += "static "
1299     if (self.eth_type[tname]['export'] & EF_VALS) and (self.eth_type[tname]['export'] & EF_TABLE):
1300       out += "static "
1301     out += "const value_string %s[] = {\n" % (self.eth_vals_nm(tname))
1302     for (val, id) in vals:
1303       if (has_enum):
1304         vval = self.eth_enum_item(tname, id)
1305       else:
1306         vval = val
1307       out += '  { %3s, "%s" },\n' % (vval, id)
1308     out += "  { 0, NULL }\n};\n"
1309     return out
1310
1311   #--- eth_enum_prefix ------------------------------------------------------------
1312   def eth_enum_prefix(self, tname, type=False):
1313     out = ""
1314     if (self.eth_type[tname]['export'] & EF_ENUM):
1315       no_prot = self.eth_type[tname]['export'] & EF_NO_PROT
1316     else:
1317       no_prot = self.eth_type[tname]['enum'] & EF_NO_PROT
1318     if (not no_prot):
1319       out += self.eproto
1320     if ((not self.eth_type[tname]['enum'] & EF_NO_TYPE) or type):
1321       if (out): out += '_'
1322       out += tname
1323     if (self.eth_type[tname]['enum'] & EF_UCASE):
1324       out = out.upper()
1325     if (out): out += '_'
1326     return out
1327
1328   #--- eth_enum_nm ------------------------------------------------------------
1329   def eth_enum_nm(self, tname):
1330     out = self.eth_enum_prefix(tname, type=True)
1331     out += "enum"
1332     return out
1333
1334   #--- eth_enum_item ---------------------------------------------------------------
1335   def eth_enum_item(self, tname, ident):
1336     out = self.eth_enum_prefix(tname)
1337     out += asn2c(ident)
1338     if (self.eth_type[tname]['enum'] & EF_UCASE):
1339       out = out.upper()
1340     return out
1341
1342   #--- eth_enum ---------------------------------------------------------------
1343   def eth_enum(self, tname, vals):
1344     out = ""
1345     if (self.eth_type[tname]['enum'] & EF_DEFINE):
1346       out += "/* enumerated values for %s */\n" % (tname)
1347       for (val, id) in vals:
1348         out += '#define %-12s %3s\n' % (self.eth_enum_item(tname, id), val)
1349     else:
1350       out += "typedef enum _%s {\n" % (self.eth_enum_nm(tname))
1351       first_line = 1
1352       for (val, id) in vals:
1353         if (first_line == 1):
1354           first_line = 0
1355         else:
1356           out += ",\n"  
1357         out += '  %-12s = %3s' % (self.eth_enum_item(tname, id), val)
1358       out += "\n} %s;\n" % (self.eth_enum_nm(tname))
1359     return out
1360
1361   #--- eth_bits ---------------------------------------------------------------
1362   def eth_bits(self, tname, bits):
1363     out = ""
1364     out += "static const "
1365     out += "asn_namedbit %(TABLE)s[] = {\n"
1366     for (val, id) in bits:
1367       out += '  { %2d, &hf_%s_%s_%s, -1, -1, "%s", NULL },\n' % (val, self.eproto, tname, asn2c(id), id)
1368     out += "  { 0, NULL, 0, 0, NULL, NULL }\n};\n"
1369     return out
1370
1371   #--- eth_type_fn_h ----------------------------------------------------------
1372   def eth_type_fn_h(self, tname):
1373     out = ""
1374     if (not self.eth_type[tname]['export'] & EF_TYPE):
1375       out += "static "
1376     out += "int "
1377     if (self.Ber()):
1378       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)
1379     elif (self.Per()):
1380       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)
1381     out += ";\n"
1382     return out
1383
1384   #--- eth_fn_call ------------------------------------------------------------
1385   def eth_fn_call(self, fname, ret=None, indent=2, par=None):
1386     out = indent * ' '
1387     if (ret):
1388       if (ret == 'return'):
1389         out += 'return '
1390       else:
1391         out += ret + ' = '
1392     out += fname + '('
1393     ind = len(out)
1394     for i in range(len(par)):
1395       if (i>0): out += ind * ' '
1396       out += ', '.join(par[i])
1397       if (i<(len(par)-1)): out += ',\n'
1398     out += ');\n'
1399     return out
1400
1401   #--- eth_type_fn_hdr --------------------------------------------------------
1402   def eth_type_fn_hdr(self, tname):
1403     out = '\n'
1404     if (not self.eth_type[tname]['export'] & EF_TYPE):
1405       out += "static "
1406     out += "int\n"
1407     if (self.Ber()):
1408       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)
1409     elif (self.Per()):
1410       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)
1411     #if self.conform.get_fn_presence(tname):
1412     #  out += self.conform.get_fn_text(tname, 'FN_HDR')
1413     #el
1414     if self.conform.get_fn_presence(self.eth_type[tname]['ref'][0]):
1415       out += self.conform.get_fn_text(self.eth_type[tname]['ref'][0], 'FN_HDR')
1416     return out
1417
1418   #--- eth_type_fn_ftr --------------------------------------------------------
1419   def eth_type_fn_ftr(self, tname):
1420     out = '\n'
1421     #if self.conform.get_fn_presence(tname):
1422     #  out += self.conform.get_fn_text(tname, 'FN_FTR')
1423     #el
1424     if self.conform.get_fn_presence(self.eth_type[tname]['ref'][0]):
1425       out += self.conform.get_fn_text(self.eth_type[tname]['ref'][0], 'FN_FTR')
1426     out += "  return offset;\n"
1427     out += "}\n"
1428     return out
1429
1430   #--- eth_type_fn_body -------------------------------------------------------
1431   def eth_type_fn_body(self, tname, body, pars=None):
1432     out = body
1433     #if self.conform.get_fn_body_presence(tname):
1434     #  out = self.conform.get_fn_text(tname, 'FN_BODY')
1435     #el
1436     if self.conform.get_fn_body_presence(self.eth_type[tname]['ref'][0]):
1437       out = self.conform.get_fn_text(self.eth_type[tname]['ref'][0], 'FN_BODY')
1438     if pars:
1439       try:
1440         out = out % pars
1441       except (TypeError):
1442         pass
1443     return out
1444
1445   #--- eth_output_hf ----------------------------------------------------------
1446   def eth_output_hf (self):
1447     if not len(self.eth_hf_ord) and not len(self.eth_hfpdu_ord) and not len(self.named_bit): return
1448     fx = self.output.file_open('hf')
1449     for f in (self.eth_hfpdu_ord + self.eth_hf_ord):
1450       fx.write("%-50s/* %s */\n" % ("static int %s = -1;  " % (self.eth_hf[f]['fullname']), self.eth_hf[f]['ethtype']))
1451     if (self.named_bit):
1452       fx.write('/* named bits */\n')
1453     for nb in self.named_bit:
1454       fx.write("static int %s = -1;\n" % (nb['ethname']))
1455     self.output.file_close(fx)
1456     
1457   #--- eth_output_hf_arr ------------------------------------------------------
1458   def eth_output_hf_arr (self):
1459     if not len(self.eth_hf_ord) and not len(self.eth_hfpdu_ord) and not len(self.named_bit): return
1460     fx = self.output.file_open('hfarr')
1461     for f in (self.eth_hfpdu_ord + self.eth_hf_ord):
1462       t = self.eth_hf[f]['ethtype']
1463       blurb = '"%s.%s"' % (self.eth_type[t]['proto'], t)
1464       attr = self.eth_hf[f]['attr'].copy()
1465       attr['ABBREV'] = '"%s.%s"' % (self.proto, attr['ABBREV'])
1466       if not attr.has_key('BLURB'):
1467         attr['BLURB'] = blurb
1468       fx.write('    { &%s,\n' % (self.eth_hf[f]['fullname']))
1469       fx.write('      { %(NAME)s, %(ABBREV)s,\n' % attr)
1470       fx.write('        %(TYPE)s, %(DISPLAY)s, %(STRINGS)s, %(BITMASK)s,\n' % attr)
1471       fx.write('        %(BLURB)s, HFILL }},\n' % attr)
1472     for nb in self.named_bit:
1473       blurb = ''
1474       fx.write('    { &%s,\n' % (nb['ethname']))
1475       fx.write('      { "%s", "%s.%s",\n' % (nb['name'], self.proto, nb['name']))
1476       fx.write('        %s, %s, %s, %s,\n' % (nb['ftype'], nb['display'], nb['strings'], nb['bitmask']))
1477       fx.write('        "%s", HFILL }},\n' % (blurb))
1478     self.output.file_close(fx)
1479
1480   #--- eth_output_ett ---------------------------------------------------------
1481   def eth_output_ett (self):
1482     fx = self.output.file_open('ett')
1483     fempty = True
1484     #fx.write("static gint ett_%s = -1;\n" % (self.eproto))
1485     for t in self.eth_type_ord:
1486       if self.eth_type[t]['tree']:
1487         fx.write("static gint %s = -1;\n" % (self.eth_type[t]['tree']))
1488         fempty = False
1489     self.output.file_close(fx, discard=fempty)
1490
1491   #--- eth_output_ett_arr -----------------------------------------------------
1492   def eth_output_ett_arr(self):
1493     fx = self.output.file_open('ettarr')
1494     fempty = True
1495     #fx.write("    &ett_%s,\n" % (self.eproto))
1496     for t in self.eth_type_ord:
1497       if self.eth_type[t]['tree']:
1498         fx.write("    &%s,\n" % (self.eth_type[t]['tree']))
1499         fempty = False
1500     self.output.file_close(fx, discard=fempty)
1501
1502   #--- eth_output_export ------------------------------------------------------
1503   def eth_output_export(self):
1504     if (not len(self.eth_export_ord)): return
1505     fx = self.output.file_open('exp', ext='h')
1506     for t in self.eth_export_ord:  # vals
1507       if (self.eth_type[t]['export'] & EF_ENUM) and self.eth_type[t]['val'].eth_has_enum(t, self):
1508         fx.write(self.eth_type[t]['val'].eth_type_enum(t, self))
1509       if (self.eth_type[t]['export'] & EF_VALS) and self.eth_type[t]['val'].eth_has_vals():
1510         if not self.eth_type[t]['export'] & EF_TABLE:
1511           if self.eth_type[t]['export'] & EF_WS_VAR:
1512             fx.write("WS_VAR_IMPORT ")
1513           else:
1514             fx.write("extern ")
1515           fx.write("const value_string %s[];\n" % (self.eth_vals_nm(t)))
1516         else:
1517           fx.write(self.eth_type[t]['val'].eth_type_vals(t, self))
1518     for t in self.eth_export_ord:  # functions
1519       if (self.eth_type[t]['export'] & EF_TYPE):
1520         if self.eth_type[t]['export'] & EF_EXTERN:
1521           fx.write("extern ")
1522         fx.write(self.eth_type_fn_h(t))
1523     self.output.file_close(fx)
1524
1525   #--- eth_output_expcnf ------------------------------------------------------
1526   def eth_output_expcnf(self):
1527     fx = self.output.file_open('exp', ext='cnf')
1528     fx.write('#.MODULE\n')
1529     maxw = 0
1530     for (m, p) in self.modules:
1531       if (len(m) > maxw): maxw = len(m)
1532     for (m, p) in self.modules:
1533       fx.write("%-*s  %s\n" % (maxw, m, p))
1534     fx.write('#.END\n\n')
1535     for cls in self.objectclass_ord:
1536       if self.objectclass[cls]['export']:
1537         fx.write('#.CLASS %s\n' % (cls))
1538         maxw = 2
1539         for fld in self.objectclass[cls]['val'].fields:
1540           w = len(fld.fld_repr()[0])  
1541           if (w > maxw): maxw = w
1542         for fld in self.objectclass[cls]['val'].fields:
1543           repr = fld.fld_repr()
1544           fx.write('%-*s  %s\n' % (maxw, repr[0], ' '.join(repr[1:])))
1545         fx.write('#.END\n\n')
1546     if self.Ber():
1547       fx.write('#.IMPORT_TAG\n')
1548       for t in self.eth_export_ord:  # tags
1549         if (self.eth_type[t]['export'] & EF_TYPE):
1550           fx.write('%-24s ' % self.eth_type[t]['ref'][0])
1551           fx.write('%s %s\n' % self.eth_type[t]['val'].GetTag(self))
1552       fx.write('#.END\n\n')
1553     fx.write('#.TYPE_ATTR\n')
1554     for t in self.eth_export_ord:  # attributes
1555       if (self.eth_type[t]['export'] & EF_TYPE):
1556         fx.write('%-24s ' % self.eth_type[t]['ref'][0])
1557         attr = self.eth_get_type_attr(self.eth_type[t]['ref'][0]).copy()
1558         fx.write('TYPE = %(TYPE)-9s  DISPLAY = %(DISPLAY)-9s  STRINGS = %(STRINGS)s  BITMASK = %(BITMASK)s\n' % attr)
1559     fx.write('#.END\n\n')
1560     self.output.file_close(fx, keep_anyway=True)
1561
1562   #--- eth_output_val ------------------------------------------------------
1563   def eth_output_val(self):
1564     if (not len(self.eth_value_ord1)): return
1565     fx = self.output.file_open('val', ext='h')
1566     for v in self.eth_value_ord1:
1567       vv = self.eth_value[v]['value']
1568       if isinstance (vv, Value):
1569         vv = vv.to_str(self)
1570       fx.write("#define %-30s %s\n" % (v, vv))
1571     for t in self.eth_type_ord1:
1572       if self.eth_type[t]['import']:
1573         continue
1574       if self.eth_type[t]['val'].eth_has_enum(t, self) and not (self.eth_type[t]['export'] & EF_ENUM):
1575         fx.write(self.eth_type[t]['val'].eth_type_enum(t, self))
1576     self.output.file_close(fx)
1577
1578   #--- eth_output_valexp ------------------------------------------------------
1579   def eth_output_valexp(self):
1580     if (not len(self.eth_vexport_ord)): return
1581     fx = self.output.file_open('valexp', ext='h')
1582     for v in self.eth_vexport_ord:
1583       vv = self.eth_value[v]['value']
1584       if isinstance (vv, Value):
1585         vv = vv.to_str(self)
1586       fx.write("#define %-30s %s\n" % (v, vv))
1587     self.output.file_close(fx)
1588
1589   #--- eth_output_types -------------------------------------------------------
1590   def eth_output_types(self):
1591     def out_field(f):
1592       t = self.eth_hf[f]['ethtype']
1593       if (self.Ber()):
1594         x = {}
1595         for r in self.eth_hf[f]['ref']:
1596           x[self.field[r]['impl']] = self.field[r]['impl']
1597       else:
1598         x = {False : False}
1599       x = x.values()
1600       x.sort()
1601       out = ''
1602       for i in x:
1603         if (i):
1604           postfix = '_impl'
1605           impl = 'TRUE'
1606         else:
1607           postfix = ''
1608           impl = 'FALSE'
1609         if (self.Ber()):
1610           if (i): postfix = '_impl'; impl = 'TRUE'
1611           else:   postfix = '';      impl = 'FALSE'
1612           out += 'static int dissect_'+f+postfix+'(proto_tree *tree _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_) {\n'
1613           par=((impl, 'tvb', 'offset', 'actx', 'tree', self.eth_hf[f]['fullname']),)
1614         else:
1615           out += 'static int dissect_'+f+'(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_) {\n'
1616           par=(('tvb', 'offset', 'actx', 'tree', self.eth_hf[f]['fullname']),)
1617         out += self.eth_fn_call('dissect_%s_%s' % (self.eth_type[t]['proto'], t), ret='return',
1618                                 par=par)
1619         out += '}\n'
1620       return out
1621     #end out_field()
1622     def out_pdu_decl(f):
1623       t = self.eth_hf[f]['ethtype']
1624       is_new = self.eth_hf[f]['pdu']['new']
1625       out = 'static '
1626       if (is_new):
1627         out += 'int'
1628       else:
1629         out += 'void'
1630       out += ' dissect_'+f+'(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_);\n'
1631       return out
1632     #end out_pdu_decl()
1633     def out_pdu(f):
1634       t = self.eth_hf[f]['ethtype']
1635       is_new = self.eth_hf[f]['pdu']['new']
1636       impl = 'FALSE'
1637       out = 'static '
1638       if (is_new):
1639         out += 'int'
1640       else:
1641         out += 'void'
1642       out += ' dissect_'+f+'(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_) {\n'
1643       if (is_new):
1644         out += '  int offset = 0;\n'
1645         off_par = 'offset'
1646         ret_par = 'offset'
1647       else:
1648         off_par = '0'
1649         ret_par = None
1650       if (self.Per()):
1651         if (self.Aligned()):
1652           aligned = 'TRUE'
1653         else:
1654           aligned = 'FALSE'
1655         out += "  asn1_ctx_t asn1_ctx;\n"
1656         out += self.eth_fn_call('asn1_ctx_init', par=(('&asn1_ctx', 'ASN1_ENC_PER', aligned, 'pinfo'),))
1657       if (self.Ber()):
1658         out += "  asn1_ctx_t asn1_ctx;\n"
1659         out += self.eth_fn_call('asn1_ctx_init', par=(('&asn1_ctx', 'ASN1_ENC_BER', 'TRUE', 'pinfo'),))
1660         par=((impl, 'tvb', off_par,'&asn1_ctx', 'tree', self.eth_hf[f]['fullname']),)
1661       elif (self.Per()):
1662         par=(('tvb', off_par, '&asn1_ctx', 'tree', self.eth_hf[f]['fullname']),)
1663       else:
1664         par=((),)
1665       out += self.eth_fn_call('dissect_%s_%s' % (self.eth_type[t]['proto'], t), ret=ret_par, par=par)
1666       if (self.Per() and is_new):
1667         out += '  offset += 7; offset >>= 3;\n'
1668       if (is_new):
1669         out += '  return offset;\n'
1670       out += '}\n'
1671       return out
1672     #end out_pdu()
1673     fx = self.output.file_open('fn')
1674     pos = fx.tell()
1675     if (len(self.eth_hfpdu_ord)):
1676       first_decl = True
1677       for f in self.eth_hfpdu_ord:
1678         if (self.eth_hf[f]['pdu'] and self.eth_hf[f]['pdu']['need_decl']):
1679           if first_decl:
1680             fx.write('/*--- PDUs declarations ---*/\n')
1681             first_decl = False
1682           fx.write(out_pdu_decl(f))
1683       if not first_decl:
1684         fx.write('\n')
1685     if self.eth_dep_cycle:
1686       fx.write('/*--- Cyclic dependencies ---*/\n\n')
1687       i = 0
1688       while i < len(self.eth_dep_cycle):
1689         t = self.type[self.eth_dep_cycle[i][0]]['ethname']
1690         if self.dep_cycle_eth_type[t][0] != i: i += 1; continue
1691         fx.write(''.join(map(lambda i: '/* %s */\n' % ' -> '.join(self.eth_dep_cycle[i]), self.dep_cycle_eth_type[t])))
1692         fx.write(self.eth_type_fn_h(t))
1693         if (self.Fld() or self.eth_type[t]['create_field']):
1694           fx.write('\n')
1695           for f in self.eth_hf_ord:
1696             if ((self.eth_hf[f]['ethtype'] == t) and (self.Fld() or self.eth_hf[f]['create_field'])):
1697               fx.write(out_field(f))
1698         fx.write('\n')
1699         i += 1
1700       fx.write('\n')
1701     if (self.Fld()):  # fields for imported types
1702       fx.write('/*--- Fields for imported types ---*/\n\n')
1703       for f in self.eth_hf_ord:
1704         if (self.eth_type[self.eth_hf[f]['ethtype']]['import']):
1705           fx.write(out_field(f))
1706       fx.write('\n')
1707     for t in self.eth_type_ord1:
1708       if self.eth_type[t]['import']:
1709         continue
1710       if self.eth_type[t]['val'].eth_has_vals():
1711         if self.eth_type[t]['no_emit'] & EF_VALS:
1712           pass
1713         elif self.eth_type[t]['user_def'] & EF_VALS:
1714           fx.write("extern const value_string %s[];\n" % (self.eth_vals_nm(t)))
1715         elif (self.eth_type[t]['export'] & EF_VALS) and (self.eth_type[t]['export'] & EF_TABLE):
1716           pass
1717         else:
1718           fx.write(self.eth_type[t]['val'].eth_type_vals(t, self))
1719       if self.eth_type[t]['no_emit'] & EF_TYPE:
1720         pass
1721       elif self.eth_type[t]['user_def'] & EF_TYPE:
1722         fx.write(self.eth_type_fn_h(t))
1723       else:
1724         fx.write(self.eth_type[t]['val'].eth_type_fn(self.eth_type[t]['proto'], t, self))
1725       if ((self.Fld() or self.eth_type[t]['create_field']) and not self.dep_cycle_eth_type.has_key(t)):
1726         for f in self.eth_hf_ord:
1727           if ((self.eth_hf[f]['ethtype'] == t) and (self.Fld() or self.eth_hf[f]['create_field'])):
1728             fx.write(out_field(f))
1729       fx.write('\n')
1730     if (len(self.eth_hfpdu_ord)):
1731       fx.write('/*--- PDUs ---*/\n\n')
1732       for f in self.eth_hfpdu_ord:
1733         if (self.eth_hf[f]['pdu']):
1734           if (self.emitted_pdu.has_key(f)):
1735             fx.write("  /* %s already emitted */\n" % (f))
1736           else:
1737             fx.write(out_pdu(f))
1738             self.emitted_pdu[f] = True
1739       fx.write('\n')
1740     fempty = pos == fx.tell()
1741     self.output.file_close(fx, discard=fempty)
1742
1743   #--- eth_output_dis_hnd -----------------------------------------------------
1744   def eth_output_dis_hnd(self):
1745     fx = self.output.file_open('dis-hnd')
1746     fempty = True
1747     for f in self.eth_hfpdu_ord:
1748       pdu = self.eth_hf[f]['pdu']
1749       if (pdu and pdu['reg'] and not pdu['hidden']):
1750         dis = self.proto
1751         if (pdu['reg'] != '.'):
1752           dis += '.' + pdu['reg']
1753         fx.write('static dissector_handle_t %s_handle;\n' % (asn2c(dis)))
1754         fempty = False
1755     fx.write('\n')
1756     self.output.file_close(fx, discard=fempty)
1757
1758   #--- eth_output_dis_reg -----------------------------------------------------
1759   def eth_output_dis_reg(self):
1760     fx = self.output.file_open('dis-reg')
1761     fempty = True
1762     for f in self.eth_hfpdu_ord:
1763       pdu = self.eth_hf[f]['pdu']
1764       if (pdu and pdu['reg']):
1765         new_prefix = ''
1766         if (pdu['new']): new_prefix = 'new_'
1767         dis = self.proto
1768         if (pdu['reg'] != '.'): dis += '.' + pdu['reg']
1769         fx.write('  %sregister_dissector("%s", dissect_%s, proto_%s);\n' % (new_prefix, dis, f, self.eproto))
1770         if (not pdu['hidden']):
1771           fx.write('  %s_handle = find_dissector("%s");\n' % (asn2c(dis), dis))
1772         fempty = False
1773     fx.write('\n')
1774     self.output.file_close(fx, discard=fempty)
1775
1776   #--- eth_output_dis_tab -----------------------------------------------------
1777   def eth_output_dis_tab(self):
1778     fx = self.output.file_open('dis-tab')
1779     fempty = True
1780     for k in self.conform.get_order('REGISTER'):
1781       reg = self.conform.use_item('REGISTER', k)
1782       if not self.field.has_key(reg['pdu']): continue
1783       f = self.field[reg['pdu']]['ethname']
1784       pdu = self.eth_hf[f]['pdu'] 
1785       new_prefix = ''
1786       if (pdu['new']): new_prefix = 'new_'
1787       if (reg['rtype'] in ('NUM', 'STR')):
1788         rstr = ''
1789         if (reg['rtype'] == 'STR'): rstr = '_string'
1790         if (pdu['reg']):
1791           dis = self.proto
1792           if (pdu['reg'] != '.'): dis += '.' + pdu['reg']
1793           if  (not pdu['hidden']):
1794             hnd = '%s_handle' % (asn2c(dis))
1795           else:
1796             hnd = 'find_dissector("%s")' % (dis)
1797         else:
1798           hnd = '%screate_dissector_handle(dissect_%s, proto_%s)' % (new_prefix, f, self.eproto)
1799         rport = self.value_get_eth(reg['rport'])
1800         fx.write('  dissector_add%s("%s", %s, %s);\n' % (rstr, reg['rtable'], rport, hnd))
1801       elif (reg['rtype'] in ('BER', 'PER')):
1802         roid = self.value_get_eth(reg['roid'])
1803         fx.write('  %sregister_%s_oid_dissector(%s, dissect_%s, proto_%s, %s);\n' % (new_prefix, reg['rtype'].lower(), roid, f, self.eproto, reg['roidname']))
1804       fempty = False
1805     fx.write('\n')
1806     self.output.file_close(fx, discard=fempty)
1807
1808   #--- eth_output_table -----------------------------------------------------
1809   def eth_output_table(self):
1810     for num in self.conform.report.keys():
1811       fx = self.output.file_open('table' + num)
1812       for rep in self.conform.report[num]:
1813         if rep['type'] == 'HDR':
1814           fx.write('\n')
1815         if rep['var']:
1816           var = rep['var']
1817           var_list = var.split('.')
1818           cls = var_list[0]
1819           del var_list[0]
1820           if (self.oassign_cls.has_key(cls)):
1821             for ident in self.oassign_cls[cls]:
1822              obj = self.get_obj_repr(ident, var_list)
1823              if not obj:
1824                continue
1825              obj['_LOOP'] = var
1826              obj['_DICT'] = str(obj)
1827              try:
1828                text = rep['text'] % obj
1829              except (KeyError):
1830                raise sys.exc_type, "%s:%s invalid key %s for information object %s of %s" % (rep['fn'], rep['lineno'], sys.exc_value, ident, var)
1831              fx.write(text)
1832           else:
1833             fx.write("/* Unknown or empty loop list %s */\n" % (var))
1834         else:
1835           fx.write(rep['text'])
1836         if rep['type'] == 'FTR':
1837           fx.write('\n')
1838       self.output.file_close(fx)
1839
1840   #--- dupl_report -----------------------------------------------------
1841   def dupl_report(self):
1842     # types
1843     tmplist = self.eth_type_dupl.keys()
1844     tmplist.sort()
1845     for t in tmplist:
1846       msg = "The same type names for different types. Explicit type renaming is recommended.\n"
1847       msg += t + "\n"
1848       for tt in self.eth_type_dupl[t]:
1849         msg += " %-20s %s\n" % (self.type[tt]['ethname'], tt)
1850       warnings.warn_explicit(msg, UserWarning, '', '')
1851     # fields
1852     tmplist = self.eth_hf_dupl.keys()
1853     tmplist.sort()
1854     for f in tmplist:
1855       msg = "The same field names for different types. Explicit field renaming is recommended.\n"
1856       msg += f + "\n"
1857       for tt in self.eth_hf_dupl[f].keys():
1858         msg += " %-20s %-20s " % (self.eth_hf_dupl[f][tt], tt)
1859         msg += ", ".join(self.eth_hf[self.eth_hf_dupl[f][tt]]['ref'])
1860         msg += "\n"
1861       warnings.warn_explicit(msg, UserWarning, '', '')
1862
1863   #--- eth_do_output ------------------------------------------------------------
1864   def eth_do_output(self):
1865     if self.dbg('a'):
1866       print "\n# Assignments"
1867       for a in self.assign_ord:
1868         v = ' '
1869         if (self.assign[a]['virt']): v = '*'
1870         print v, a
1871       print "\n# Value assignments"
1872       for a in self.vassign_ord:
1873         print ' ', a
1874       print "\n# Information object assignments"
1875       for a in self.oassign_ord:
1876         print " %-12s (%s)" % (a, self.oassign[a].cls)
1877     if self.dbg('t'):
1878       print "\n# Imported Types"
1879       print "%-40s %-24s %-24s" % ("ASN.1 name", "Module", "Protocol")
1880       print "-" * 100
1881       for t in self.type_imp:
1882         print "%-40s %-24s %-24s" % (t, self.type[t]['import'], self.type[t]['proto'])
1883       print "\n# Imported Values"
1884       print "%-40s %-24s %-24s" % ("ASN.1 name", "Module", "Protocol")
1885       print "-" * 100
1886       for t in self.value_imp:
1887         print "%-40s %-24s %-24s" % (t, self.value[t]['import'], self.value[t]['proto'])
1888       print "\n# Imported Object Classes"
1889       print "%-40s %-24s %-24s" % ("ASN.1 name", "Module", "Protocol")
1890       print "-" * 100
1891       for t in self.objectclass_imp:
1892         print "%-40s %-24s %-24s" % (t, self.objectclass[t]['import'], self.objectclass[t]['proto'])
1893       print "\n# Exported Types"
1894       print "%-31s %s" % ("Wireshark type", "Export Flag")
1895       print "-" * 100
1896       for t in self.eth_export_ord:
1897         print "%-31s 0x%02X" % (t, self.eth_type[t]['export'])
1898       print "\n# Exported Values"
1899       print "%-40s %s" % ("Wireshark name", "Value")
1900       print "-" * 100
1901       for v in self.eth_vexport_ord:
1902         vv = self.eth_value[v]['value']
1903         if isinstance (vv, Value):
1904           vv = vv.to_str(self)
1905         print "%-40s %s" % (v, vv)
1906       print "\n# ASN.1 Object Classes"
1907       print "%-40s %-24s %-24s" % ("ASN.1 name", "Module", "Protocol")
1908       print "-" * 100
1909       for t in self.objectclass_ord:
1910         print "%-40s " % (t)
1911       print "\n# ASN.1 Types"
1912       print "%-49s %-24s %-24s" % ("ASN.1 unique name", "'tname'", "Wireshark type")
1913       print "-" * 100
1914       for t in self.type_ord:
1915         print "%-49s %-24s %-24s" % (t, self.type[t]['tname'], self.type[t]['ethname'])
1916       print "\n# Wireshark Types"
1917       print "Wireshark type                   References (ASN.1 types)"
1918       print "-" * 100
1919       for t in self.eth_type_ord:
1920         print "%-31s %d" % (t, len(self.eth_type[t]['ref'])),
1921         print ', '.join(self.eth_type[t]['ref'])
1922       print "\n# ASN.1 Values"
1923       print "%-40s %-18s %-20s %s" % ("ASN.1 unique name", "Type", "Value", "Wireshark value")
1924       print "-" * 100
1925       for v in self.value_ord:
1926         vv = self.value[v]['value']
1927         if isinstance (vv, Value):
1928           vv = vv.to_str(self)
1929         print "%-40s %-18s %-20s %s" % (v, self.value[v]['type'].eth_tname(), vv, self.value[v]['ethname'])
1930       #print "\n# Wireshark Values"
1931       #print "%-40s %s" % ("Wireshark name", "Value")
1932       #print "-" * 100
1933       #for v in self.eth_value_ord:
1934       #  vv = self.eth_value[v]['value']
1935       #  if isinstance (vv, Value):
1936       #    vv = vv.to_str(self)
1937       #  print "%-40s %s" % (v, vv)
1938       print "\n# ASN.1 Fields"
1939       print "ASN.1 unique name                        Wireshark name        ASN.1 type"
1940       print "-" * 100
1941       for f in (self.pdu_ord + self.field_ord):
1942         print "%-40s %-20s %s" % (f, self.field[f]['ethname'], self.field[f]['type'])
1943       print "\n# Wireshark Fields"
1944       print "Wireshark name                  Wireshark type        References (ASN.1 fields)"
1945       print "-" * 100
1946       for f in (self.eth_hfpdu_ord + self.eth_hf_ord):
1947         print "%-30s %-20s %s" % (f, self.eth_hf[f]['ethtype'], len(self.eth_hf[f]['ref'])),
1948         print ', '.join(self.eth_hf[f]['ref'])
1949       #print "\n# Order after dependencies"
1950       #print '\n'.join(self.eth_type_ord1)
1951       print "\n# Cyclic dependencies"
1952       for c in self.eth_dep_cycle:
1953         print ' -> '.join(c)
1954     self.dupl_report()
1955     self.output.outnm = self.outnm_opt
1956     if (not self.output.outnm):
1957       self.output.outnm = self.proto
1958       self.output.outnm = self.output.outnm.replace('.', '-')
1959     self.eth_output_hf()
1960     self.eth_output_ett()
1961     self.eth_output_types()
1962     self.eth_output_hf_arr()
1963     self.eth_output_ett_arr()
1964     self.eth_output_export()
1965     if self.expcnf:
1966       self.eth_output_expcnf()
1967     self.eth_output_val()
1968     self.eth_output_valexp()
1969     self.eth_output_dis_hnd()
1970     self.eth_output_dis_reg()
1971     self.eth_output_dis_tab()
1972     self.eth_output_table()
1973
1974   def dbg_modules(self):
1975     def print_mod(m):
1976       print "%-30s " % (m),
1977       dep = self.module[m][:]
1978       for i in range(len(dep)):
1979         if not self.module.has_key(dep[i]): 
1980           dep[i] = '*' + dep[i]
1981       print ', '.join(dep)
1982     # end of print_mod()
1983     (mod_ord, mod_cyc) = dependency_compute(self.module_ord, self.module, ignore_fn = lambda t: not self.module.has_key(t))
1984     print "\n# ASN.1 Moudules"
1985     print "Module name                     Dependency"
1986     print "-" * 100
1987     new_ord = False
1988     for m in (self.module_ord):
1989       print_mod(m)
1990       new_ord = new_ord or (self.module_ord.index(m) != mod_ord.index(m))
1991     if new_ord:
1992       print "\n# ASN.1 Moudules - in dependency order"
1993       print "Module name                     Dependency"
1994       print "-" * 100
1995       for m in (mod_ord):
1996         print_mod(m)
1997     if mod_cyc:
1998       print "\nCyclic dependencies:"
1999       for i in (range(len(mod_cyc))):
2000         print "%02d: %s" % (i + 1, str(mod_cyc[i]))
2001
2002
2003 #--- EthCnf -------------------------------------------------------------------
2004 class EthCnf:
2005   def __init__(self):
2006     self.ectx = None
2007     self.tblcfg = {}
2008     self.table = {}
2009     self.order = {}
2010     self.fn = {}
2011     self.report = {}
2012     self.suppress_line = False
2013     self.include_path = []
2014     #                                   Value name             Default value       Duplicity check   Usage check
2015     self.tblcfg['EXPORTS']         = { 'val_nm' : 'flag',     'val_dflt' : 0,     'chk_dup' : True, 'chk_use' : True }
2016     self.tblcfg['MAKE_ENUM']       = { 'val_nm' : 'flag',     'val_dflt' : 0,     'chk_dup' : True, 'chk_use' : True }
2017     self.tblcfg['PDU']             = { 'val_nm' : 'attr',     'val_dflt' : None,  'chk_dup' : True, 'chk_use' : True }
2018     self.tblcfg['REGISTER']        = { 'val_nm' : 'attr',     'val_dflt' : None,  'chk_dup' : True, 'chk_use' : True }
2019     self.tblcfg['USER_DEFINED']    = { 'val_nm' : 'flag',     'val_dflt' : 0,     'chk_dup' : True, 'chk_use' : True }
2020     self.tblcfg['NO_EMIT']         = { 'val_nm' : 'flag',     'val_dflt' : 0,     'chk_dup' : True, 'chk_use' : True }
2021     self.tblcfg['MODULE']          = { 'val_nm' : 'proto',    'val_dflt' : None,  'chk_dup' : True, 'chk_use' : False }
2022     self.tblcfg['OMIT_ASSIGNMENT'] = { 'val_nm' : 'omit',     'val_dflt' : False, 'chk_dup' : True, 'chk_use' : True }
2023     self.tblcfg['NO_OMIT_ASSGN']   = { 'val_nm' : 'omit',     'val_dflt' : True,  'chk_dup' : True, 'chk_use' : True }
2024     self.tblcfg['VIRTUAL_ASSGN']   = { 'val_nm' : 'name',     'val_dflt' : None,  'chk_dup' : True, 'chk_use' : True }
2025     self.tblcfg['SET_TYPE']        = { 'val_nm' : 'type',     'val_dflt' : None,  'chk_dup' : True, 'chk_use' : True }
2026     self.tblcfg['TYPE_RENAME']     = { 'val_nm' : 'eth_name', 'val_dflt' : None,  'chk_dup' : True, 'chk_use' : True }
2027     self.tblcfg['FIELD_RENAME']    = { 'val_nm' : 'eth_name', 'val_dflt' : None,  'chk_dup' : True, 'chk_use' : True }
2028     self.tblcfg['IMPORT_TAG']      = { 'val_nm' : 'ttag',     'val_dflt' : (),    'chk_dup' : True, 'chk_use' : False }
2029     self.tblcfg['FN_PARS']         = { 'val_nm' : 'pars',     'val_dflt' : {},    'chk_dup' : True, 'chk_use' : True }
2030     self.tblcfg['TYPE_ATTR']       = { 'val_nm' : 'attr',     'val_dflt' : {},    'chk_dup' : True, 'chk_use' : False }
2031     self.tblcfg['ETYPE_ATTR']      = { 'val_nm' : 'attr',     'val_dflt' : {},    'chk_dup' : True, 'chk_use' : False }
2032     self.tblcfg['FIELD_ATTR']      = { 'val_nm' : 'attr',     'val_dflt' : {},    'chk_dup' : True, 'chk_use' : True }
2033     self.tblcfg['EFIELD_ATTR']     = { 'val_nm' : 'attr',     'val_dflt' : {},    'chk_dup' : True, 'chk_use' : True }
2034     self.tblcfg['ASSIGNED_ID']     = { 'val_nm' : 'ids',      'val_dflt' : {},    'chk_dup' : False,'chk_use' : False }
2035
2036
2037     for k in self.tblcfg.keys() :
2038       self.table[k] = {}
2039       self.order[k] = []
2040
2041   def add_item(self, table, key, fn, lineno, **kw):
2042     if self.tblcfg[table]['chk_dup'] and self.table[table].has_key(key):
2043       warnings.warn_explicit("Duplicated %s for %s. Previous one is at %s:%d" % 
2044                              (table, key, self.table[table][key]['fn'], self.table[table][key]['lineno']), 
2045                              UserWarning, fn, lineno)
2046       return
2047     self.table[table][key] = {'fn' : fn, 'lineno' : lineno, 'used' : False}
2048     self.table[table][key].update(kw)
2049     self.order[table].append(key)
2050
2051   def update_item(self, table, key, fn, lineno, **kw):
2052     if not self.table[table].has_key(key):
2053       self.table[table][key] = {'fn' : fn, 'lineno' : lineno, 'used' : False}
2054       self.order[table].append(key)
2055       self.table[table][key][self.tblcfg[table]['val_nm']] = {}
2056     self.table[table][key][self.tblcfg[table]['val_nm']].update(kw[self.tblcfg[table]['val_nm']])
2057
2058   def get_order(self, table):
2059     return self.order[table]
2060
2061   def check_item(self, table, key):
2062     return self.table[table].has_key(key)
2063
2064   def check_item_value(self, table, key, **kw):
2065     return self.table[table].has_key(key) and self.table[table][key].has_key(kw.get('val_nm', self.tblcfg[table]['val_nm']))
2066
2067   def use_item(self, table, key, **kw):
2068     vdflt = kw.get('val_dflt', self.tblcfg[table]['val_dflt'])
2069     if not self.table[table].has_key(key): return vdflt
2070     vname = kw.get('val_nm', self.tblcfg[table]['val_nm'])
2071     #print "use_item() - set used for %s %s" % (table, key)
2072     self.table[table][key]['used'] = True
2073     return self.table[table][key].get(vname, vdflt)
2074
2075   def omit_assignment(self, type, ident, module):
2076     if self.ectx.conform.use_item('OMIT_ASSIGNMENT', ident): 
2077       return True
2078     if self.ectx.conform.use_item('OMIT_ASSIGNMENT', '*') or \
2079        self.ectx.conform.use_item('OMIT_ASSIGNMENT', '*'+type) or \
2080        self.ectx.conform.use_item('OMIT_ASSIGNMENT', '*/'+module) or \
2081        self.ectx.conform.use_item('OMIT_ASSIGNMENT', '*'+type+'/'+module):
2082       return self.ectx.conform.use_item('NO_OMIT_ASSGN', ident)
2083     return False
2084
2085   def add_fn_line(self, name, ctx, line, fn, lineno):
2086     if not self.fn.has_key(name):
2087       self.fn[name] = {'FN_HDR' : None, 'FN_FTR' : None, 'FN_BODY' : None}
2088     if (self.fn[name][ctx]):
2089       self.fn[name][ctx]['text'] += line
2090     else:
2091       self.fn[name][ctx] = {'text' : line, 'used' : False,
2092                              'fn' : fn, 'lineno' : lineno}
2093   def get_fn_presence(self, name):
2094     #print "get_fn_presence('%s'):%s" % (name, str(self.fn.has_key(name)))
2095     #if self.fn.has_key(name): print self.fn[name]
2096     return self.fn.has_key(name)
2097   def get_fn_body_presence(self, name):
2098     return self.fn.has_key(name) and self.fn[name]['FN_BODY']
2099   def get_fn_text(self, name, ctx):
2100     if (not self.fn.has_key(name)):
2101       return '';
2102     if (not self.fn[name][ctx]):
2103       return '';
2104     self.fn[name][ctx]['used'] = True
2105     out = self.fn[name][ctx]['text']
2106     if (not self.suppress_line): 
2107       out = '#line %u "%s"\n%s\n' % (self.fn[name][ctx]['lineno'], self.fn[name][ctx]['fn'], out);
2108     return out
2109
2110   def add_pdu(self, par, is_new, fn, lineno):
2111     #print "add_pdu(par=%s, %s, %d)" % (str(par), fn, lineno)
2112     (reg, hidden) = (None, False)
2113     if (len(par) > 1): reg = par[1]
2114     if (reg and reg[0]=='@'): (reg, hidden) = (reg[1:], True)
2115     attr = {'new' : is_new, 'reg' : reg, 'hidden' : hidden, 'need_decl' : False}
2116     self.add_item('PDU', par[0], attr=attr, fn=fn, lineno=lineno)
2117     return
2118
2119   def add_register(self, pdu, par, fn, lineno):
2120     #print "add_register(pdu=%s, par=%s, %s, %d)" % (pdu, str(par), fn, lineno)
2121     if (par[0] in ('N', 'NUM')):   rtype = 'NUM'; (pmin, pmax) = (2, 2)
2122     elif (par[0] in ('S', 'STR')): rtype = 'STR'; (pmin, pmax) = (2, 2)
2123     elif (par[0] in ('B', 'BER')): rtype = 'BER'; (pmin, pmax) = (1, 2)
2124     elif (par[0] in ('P', 'PER')): rtype = 'PER'; (pmin, pmax) = (1, 2)
2125     else: warnings.warn_explicit("Unknown registration type '%s'" % (par[2]), UserWarning, fn, lineno); return
2126     if ((len(par)-1) < pmin):
2127       warnings.warn_explicit("Too few parameters for %s registration type. At least %d parameters are required" % (rtype, pmin), UserWarning, fn, lineno)
2128       return
2129     if ((len(par)-1) > pmax):
2130       warnings.warn_explicit("Too many parameters for %s registration type. Only %d parameters are allowed" % (rtype, pmax), UserWarning, fn, lineno)
2131     attr = {'pdu' : pdu, 'rtype' : rtype}
2132     if (rtype in ('NUM', 'STR')): 
2133       attr['rtable'] = par[1]
2134       attr['rport'] = par[2]
2135       rkey = '/'.join([rtype, attr['rtable'], attr['rport']])
2136     elif (rtype in ('BER', 'PER')): 
2137       attr['roid'] = par[1]
2138       attr['roidname'] = '""'
2139       if (len(par)>=3): 
2140         attr['roidname'] = par[2]
2141       elif attr['roid'][0] != '"':
2142         attr['roidname'] = '"' + attr['roid'] + '"'
2143       rkey = '/'.join([rtype, attr['roid']])
2144     self.add_item('REGISTER', rkey, attr=attr, fn=fn, lineno=lineno)
2145
2146   def check_par(self, par, pmin, pmax, fn, lineno):
2147     for i in range(len(par)):
2148       if par[i] == '-':
2149         par[i] = None
2150         continue
2151       if par[i][0] == '#':
2152         par[i:] = []
2153         break
2154     if len(par) < pmin:
2155       warnings.warn_explicit("Too few parameters. At least %d parameters are required" % (pmin), UserWarning, fn, lineno)
2156       return None
2157     if (pmax >= 0) and (len(par) > pmax):
2158       warnings.warn_explicit("Too many parameters. Only %d parameters are allowed" % (pmax), UserWarning, fn, lineno)
2159       return par[0:pmax]
2160     return par
2161
2162   def read(self, fn):
2163     def get_par(line, pmin, pmax, fn, lineno):
2164       par = line.split(None, pmax)
2165       par = self.check_par(par, pmin, pmax, fn, lineno)
2166       return par
2167
2168     def get_par_nm(line, pmin, pmax, fn, lineno):
2169       if pmax:
2170         par = line.split(None, pmax)
2171       else:
2172         par = [line,]
2173       for i in range(len(par)):
2174         if par[i][0] == '#':
2175           par[i:] = []
2176           break
2177       if len(par) < pmin:
2178         warnings.warn_explicit("Too few parameters. At least %d parameters are required" % (pmin), UserWarning, fn, lineno)
2179         return None
2180       if len(par) > pmax:
2181         nmpar = par[pmax]
2182       else:
2183         nmpar = ''
2184       nmpars = {}
2185       nmpar_first = re.compile(r'^\s*(?P<attr>[_A-Z][_A-Z0-9]*)\s*=\s*')
2186       nmpar_next = re.compile(r'\s+(?P<attr>[_A-Z][_A-Z0-9]*)\s*=\s*')
2187       nmpar_end = re.compile(r'\s*$')
2188       result = nmpar_first.search(nmpar)
2189       pos = 0
2190       while result:
2191         k = result.group('attr')
2192         pos = result.end()
2193         result = nmpar_next.search(nmpar, pos)
2194         p1 = pos
2195         if result:
2196           p2 = result.start()
2197         else:
2198           p2 = nmpar_end.search(nmpar, pos).start()
2199         v = nmpar[p1:p2]
2200         nmpars[k] = v
2201       if len(par) > pmax:
2202         par[pmax] = nmpars
2203       return par
2204
2205     f = open(fn, "r")
2206     directive = re.compile(r'^\s*#\.(?P<name>[A-Z_][A-Z_0-9]*)\s+')
2207     report = re.compile(r'^TABLE(?P<num>\d*)_(?P<type>HDR|BODY|FTR)$')
2208     comment = re.compile(r'^\s*#[^.]')
2209     empty = re.compile(r'^\s*$')
2210     lineno = 0
2211     ctx = None
2212     name = ''
2213     default_flags = 0x00
2214     stack = []
2215     while 1:
2216       if not f.closed:
2217         line = f.readline()
2218         lineno += 1
2219       else:
2220         line = None
2221       if not line:
2222         if not f.closed:
2223           f.close()
2224         if stack:
2225           frec = stack.pop()
2226           fn, f, lineno = frec['fn'], frec['f'], frec['lineno']
2227           continue
2228         else: 
2229           break
2230       if comment.search(line): continue
2231       result = directive.search(line)
2232       if result:  # directive
2233         rep_result = report.search(result.group('name'))
2234         if result.group('name') == 'END_OF_CNF':
2235           f.close()
2236         elif result.group('name') == 'OPT':
2237           ctx = result.group('name')
2238           par = get_par(line[result.end():], 0, -1, fn=fn, lineno=lineno)
2239           if not par: continue
2240           self.set_opt(par[0], par[1:], fn, lineno)
2241           ctx = None
2242         elif result.group('name') in ('PDU', 'PDU_NEW', 'REGISTER', 'REGISTER_NEW', 
2243                                     'MODULE', 'MODULE_IMPORT', 
2244                                     'OMIT_ASSIGNMENT', 'NO_OMIT_ASSGN', 
2245                                     'VIRTUAL_ASSGN', 'SET_TYPE',
2246                                     'TYPE_RENAME', 'FIELD_RENAME', 'TF_RENAME', 'IMPORT_TAG',
2247                                     'TYPE_ATTR', 'ETYPE_ATTR', 'FIELD_ATTR', 'EFIELD_ATTR'):
2248           ctx = result.group('name')
2249         elif result.group('name') in ('OMIT_ALL_ASSIGNMENTS', 'OMIT_ASSIGNMENTS_EXCEPT',
2250                                       'OMIT_ALL_TYPE_ASSIGNMENTS', 'OMIT_TYPE_ASSIGNMENTS_EXCEPT',
2251                                       'OMIT_ALL_VALUE_ASSIGNMENTS', 'OMIT_VALUE_ASSIGNMENTS_EXCEPT'):
2252           ctx = result.group('name')
2253           key = '*'
2254           if ctx in ('OMIT_ALL_TYPE_ASSIGNMENTS', 'OMIT_TYPE_ASSIGNMENTS_EXCEPT'):
2255             key += 'T'
2256           if ctx in ('OMIT_ALL_VALUE_ASSIGNMENTS', 'OMIT_VALUE_ASSIGNMENTS_EXCEPT'):
2257             key += 'V'
2258           par = get_par(line[result.end():], 0, 1, fn=fn, lineno=lineno)
2259           if par: 
2260             key += '/' + par[0]
2261           self.add_item('OMIT_ASSIGNMENT', key, omit=True, fn=fn, lineno=lineno)
2262           if ctx in ('OMIT_ASSIGNMENTS_EXCEPT', 'OMIT_TYPE_ASSIGNMENTS_EXCEPT', 'OMIT_VALUE_ASSIGNMENTS_EXCEPT'):
2263             ctx = 'NO_OMIT_ASSGN'
2264           else:
2265             ctx = None
2266         elif result.group('name') in ('EXPORTS', 'USER_DEFINED', 'NO_EMIT'):
2267           ctx = result.group('name')
2268           default_flags = EF_TYPE|EF_VALS
2269           if ctx == 'EXPORTS':
2270             par = get_par(line[result.end():], 0, 5, fn=fn, lineno=lineno)
2271           else:
2272             par = get_par(line[result.end():], 0, 1, fn=fn, lineno=lineno)
2273           if not par: continue
2274           p = 1
2275           if (par[0] == 'WITH_VALS'):      default_flags |= EF_TYPE|EF_VALS
2276           elif (par[0] == 'WITHOUT_VALS'): default_flags |= EF_TYPE; default_flags &= ~EF_TYPE
2277           elif (par[0] == 'ONLY_VALS'):    default_flags &= ~EF_TYPE; default_flags |= EF_VALS
2278           elif (ctx == 'EXPORTS'): p = 0
2279           else: warnings.warn_explicit("Unknown parameter value '%s'" % (par[0]), UserWarning, fn, lineno)
2280           for i in range(p, len(par)):
2281             if (par[i] == 'ONLY_ENUM'):   default_flags &= ~(EF_TYPE|EF_VALS); default_flags |= EF_ENUM
2282             elif (par[i] == 'WITH_ENUM'): default_flags |= EF_ENUM
2283             elif (par[i] == 'VALS_WITH_TABLE'):  default_flags |= EF_TABLE
2284             elif (par[i] == 'WS_VAR'):    default_flags |= EF_WS_VAR
2285             elif (par[i] == 'EXTERN'):    default_flags |= EF_EXTERN
2286             elif (par[i] == 'NO_PROT_PREFIX'): default_flags |= EF_NO_PROT
2287             else: warnings.warn_explicit("Unknown parameter value '%s'" % (par[i]), UserWarning, fn, lineno)
2288         elif result.group('name') in ('MAKE_ENUM', 'MAKE_DEFINES'):
2289           ctx = result.group('name')
2290           default_flags = EF_ENUM
2291           if ctx == 'MAKE_ENUM': default_flags |= EF_NO_PROT|EF_NO_TYPE
2292           if ctx == 'MAKE_DEFINES': default_flags |= EF_DEFINE|EF_UCASE|EF_NO_TYPE
2293           par = get_par(line[result.end():], 0, 3, fn=fn, lineno=lineno)
2294           for i in range(0, len(par)):
2295             if (par[i] == 'NO_PROT_PREFIX'):   default_flags |= EF_NO_PROT
2296             elif (par[i] == 'NO_TYPE_PREFIX'): default_flags |= EF_NO_TYPE
2297             elif (par[i] == 'UPPER_CASE'):     default_flags |= EF_UCASE
2298             elif (par[i] == 'NO_UPPER_CASE'):  default_flags &= ~EF_UCASE
2299             else: warnings.warn_explicit("Unknown parameter value '%s'" % (par[i]), UserWarning, fn, lineno)
2300         elif result.group('name') in ('FN_HDR', 'FN_FTR'):
2301           par = get_par(line[result.end():], 1, 1, fn=fn, lineno=lineno)
2302           if not par: continue
2303           ctx = result.group('name')
2304           name = par[0]
2305         elif result.group('name') == 'FN_BODY':
2306           par = get_par_nm(line[result.end():], 1, 1, fn=fn, lineno=lineno)
2307           if not par: continue
2308           ctx = result.group('name')
2309           name = par[0]
2310           if len(par) > 1:
2311             self.add_item('FN_PARS', name, pars=par[1], fn=fn, lineno=lineno)
2312         elif result.group('name') == 'FN_PARS':
2313           par = get_par_nm(line[result.end():], 0, 1, fn=fn, lineno=lineno)
2314           ctx = result.group('name')
2315           if not par:
2316             name = None
2317           elif len(par) == 1:
2318             name = par[0]
2319             self.add_item(ctx, name, pars={}, fn=fn, lineno=lineno)
2320           elif len(par) > 1:
2321             self.add_item(ctx, par[0], pars=par[1], fn=fn, lineno=lineno)
2322             ctx = None
2323         elif result.group('name') == 'CLASS':
2324           par = get_par(line[result.end():], 1, 1, fn=fn, lineno=lineno)
2325           if not par: continue
2326           ctx = result.group('name')
2327           name = par[0]
2328           add_class_ident(name)
2329           if not name.isupper():
2330             warnings.warn_explicit("No lower-case letters shall be included in information object class name (%s)" % (name),
2331                                     UserWarning, fn, lineno)
2332         elif result.group('name') == 'ASSIGNED_OBJECT_IDENTIFIER':
2333           par = get_par(line[result.end():], 1, 1, fn=fn, lineno=lineno)
2334           if not par: continue
2335           self.update_item('ASSIGNED_ID', 'OBJECT_IDENTIFIER', ids={par[0] : par[0]}, fn=fn, lineno=lineno)
2336         elif rep_result:  # Reports
2337           num = rep_result.group('num')
2338           type = rep_result.group('type')
2339           if type == 'BODY':
2340             par = get_par(line[result.end():], 1, 1, fn=fn, lineno=lineno)
2341             if not par: continue
2342           else:
2343             par = get_par(line[result.end():], 0, 0, fn=fn, lineno=lineno)
2344           rep = { 'type' : type, 'var' : None, 'text' : '', 'fn' : fn, 'lineno' : lineno }
2345           if len(par) > 0:
2346             rep['var'] = par[0]
2347           self.report.setdefault(num, []).append(rep)
2348           ctx = 'TABLE'
2349           name = num
2350         elif result.group('name') == 'INCLUDE':
2351           par = get_par(line[result.end():], 1, 1, fn=fn, lineno=lineno)
2352           if not par: 
2353             warnings.warn_explicit("INCLUDE requires parameter", UserWarning, fn, lineno)
2354             continue
2355           fname = par[0]
2356           #print "Try include: %s" % (fname)
2357           if (not os.path.exists(fname)):
2358             fname = os.path.join(os.path.split(fn)[0], par[0])
2359           #print "Try include: %s" % (fname)
2360           i = 0
2361           while not os.path.exists(fname) and (i < len(self.include_path)):
2362             fname = os.path.join(self.include_path[i], par[0])
2363             #print "Try include: %s" % (fname)
2364             i += 1
2365           if (not os.path.exists(fname)):
2366             fname = par[0]
2367           fnew = open(fname, "r")
2368           stack.append({'fn' : fn, 'f' : f, 'lineno' : lineno})
2369           fn, f, lineno = par[0], fnew, 0
2370         elif result.group('name') == 'END':
2371           ctx = None
2372         else:
2373           warnings.warn_explicit("Unknown directive '%s'" % (result.group('name')), UserWarning, fn, lineno)
2374         continue
2375       if not ctx:
2376         if not empty.match(line):
2377           warnings.warn_explicit("Non-empty line in empty context", UserWarning, fn, lineno)
2378       elif ctx == 'OPT':
2379         if empty.match(line): continue
2380         par = get_par(line, 1, -1, fn=fn, lineno=lineno)
2381         if not par: continue
2382         self.set_opt(par[0], par[1:], fn, lineno)
2383       elif ctx in ('EXPORTS', 'USER_DEFINED', 'NO_EMIT'):
2384         if empty.match(line): continue
2385         if ctx == 'EXPORTS':
2386           par = get_par(line, 1, 6, fn=fn, lineno=lineno)
2387         else:
2388           par = get_par(line, 1, 2, fn=fn, lineno=lineno)
2389         if not par: continue
2390         flags = default_flags
2391         p = 2
2392         if (len(par)>=2):
2393           if (par[1] == 'WITH_VALS'):      flags |= EF_TYPE|EF_VALS
2394           elif (par[1] == 'WITHOUT_VALS'): flags |= EF_TYPE; flags &= ~EF_TYPE
2395           elif (par[1] == 'ONLY_VALS'):    flags &= ~EF_TYPE; flags |= EF_VALS
2396           elif (ctx == 'EXPORTS'): p = 1
2397           else: warnings.warn_explicit("Unknown parameter value '%s'" % (par[1]), UserWarning, fn, lineno)
2398         for i in range(p, len(par)):
2399           if (par[i] == 'ONLY_ENUM'):        flags &= ~(EF_TYPE|EF_VALS); flags |= EF_ENUM
2400           elif (par[i] == 'WITH_ENUM'):      flags |= EF_ENUM
2401           elif (par[i] == 'VALS_WITH_TABLE'):  flags |= EF_TABLE
2402           elif (par[i] == 'WS_VAR'):         flags |= EF_WS_VAR
2403           elif (par[i] == 'EXTERN'):         flags |= EF_EXTERN
2404           elif (par[i] == 'NO_PROT_PREFIX'): flags |= EF_NO_PROT
2405           else: warnings.warn_explicit("Unknown parameter value '%s'" % (par[i]), UserWarning, fn, lineno)
2406         self.add_item(ctx, par[0], flag=flags, fn=fn, lineno=lineno)
2407       elif ctx in ('MAKE_ENUM', 'MAKE_DEFINES'):
2408         if empty.match(line): continue
2409         par = get_par(line, 1, 4, fn=fn, lineno=lineno)
2410         if not par: continue
2411         flags = default_flags
2412         for i in range(1, len(par)):
2413           if (par[i] == 'NO_PROT_PREFIX'):   flags |= EF_NO_PROT
2414           elif (par[i] == 'NO_TYPE_PREFIX'): flags |= EF_NO_TYPE
2415           elif (par[i] == 'UPPER_CASE'):     flags |= EF_UCASE
2416           elif (par[i] == 'NO_UPPER_CASE'):  flags &= ~EF_UCASE
2417           else: warnings.warn_explicit("Unknown parameter value '%s'" % (par[i]), UserWarning, fn, lineno)
2418         self.add_item('MAKE_ENUM', par[0], flag=flags, fn=fn, lineno=lineno)
2419       elif ctx in ('PDU', 'PDU_NEW'):
2420         if empty.match(line): continue
2421         par = get_par(line, 1, 5, fn=fn, lineno=lineno)
2422         if not par: continue
2423         is_new = False
2424         if (ctx == 'PDU_NEW'): is_new = True
2425         self.add_pdu(par[0:2], is_new, fn, lineno)
2426         if (len(par)>=3):
2427           self.add_register(par[0], par[2:5], fn, lineno)
2428       elif ctx in ('REGISTER', 'REGISTER_NEW'):
2429         if empty.match(line): continue
2430         par = get_par(line, 3, 4, fn=fn, lineno=lineno)
2431         if not par: continue
2432         if not self.check_item('PDU', par[0]):
2433           is_new = False
2434           if (ctx == 'REGISTER_NEW'): is_new = True
2435           self.add_pdu(par[0:1], is_new, fn, lineno)
2436         self.add_register(par[0], par[1:4], fn, lineno)
2437       elif ctx in ('MODULE', 'MODULE_IMPORT'):
2438         if empty.match(line): continue
2439         par = get_par(line, 2, 2, fn=fn, lineno=lineno)
2440         if not par: continue
2441         self.add_item('MODULE', par[0], proto=par[1], fn=fn, lineno=lineno)
2442       elif ctx == 'IMPORT_TAG':
2443         if empty.match(line): continue
2444         par = get_par(line, 3, 3, fn=fn, lineno=lineno)
2445         if not par: continue
2446         self.add_item(ctx, par[0], ttag=(par[1], par[2]), fn=fn, lineno=lineno)
2447       elif ctx == 'OMIT_ASSIGNMENT':
2448         if empty.match(line): continue
2449         par = get_par(line, 1, 1, fn=fn, lineno=lineno)
2450         if not par: continue
2451         self.add_item(ctx, par[0], omit=True, fn=fn, lineno=lineno)
2452       elif ctx == 'NO_OMIT_ASSGN':
2453         if empty.match(line): continue
2454         par = get_par(line, 1, 1, fn=fn, lineno=lineno)
2455         if not par: continue
2456         self.add_item(ctx, par[0], omit=False, fn=fn, lineno=lineno)
2457       elif ctx == 'VIRTUAL_ASSGN':
2458         if empty.match(line): continue
2459         par = get_par(line, 2, -1, fn=fn, lineno=lineno)
2460         if not par: continue
2461         if (len(par[1].split('/')) > 1) and not self.check_item('SET_TYPE', par[1]):
2462           self.add_item('SET_TYPE', par[1], type=par[0], fn=fn, lineno=lineno)
2463         self.add_item('VIRTUAL_ASSGN', par[1], name=par[0], fn=fn, lineno=lineno)
2464         for nm in par[2:]:
2465           self.add_item('SET_TYPE', nm, type=par[0], fn=fn, lineno=lineno)
2466         if not par[0][0].isupper():
2467           warnings.warn_explicit("Virtual assignment should have uppercase name (%s)" % (par[0]),
2468                                   UserWarning, fn, lineno)
2469       elif ctx == 'SET_TYPE':
2470         if empty.match(line): continue
2471         par = get_par(line, 2, 2, fn=fn, lineno=lineno)
2472         if not par: continue
2473         if not self.check_item('VIRTUAL_ASSGN', par[0]):
2474           self.add_item('SET_TYPE', par[0], type=par[1], fn=fn, lineno=lineno)
2475         if not par[1][0].isupper():
2476           warnings.warn_explicit("Set type should have uppercase name (%s)" % (par[1]),
2477                                   UserWarning, fn, lineno)
2478       elif ctx == 'TYPE_RENAME':
2479         if empty.match(line): continue
2480         par = get_par(line, 2, 2, fn=fn, lineno=lineno)
2481         if not par: continue
2482         self.add_item('TYPE_RENAME', par[0], eth_name=par[1], fn=fn, lineno=lineno)
2483         if not par[1][0].isupper():
2484           warnings.warn_explicit("Type should be renamed to uppercase name (%s)" % (par[1]),
2485                                   UserWarning, fn, lineno)
2486       elif ctx == 'FIELD_RENAME':
2487         if empty.match(line): continue
2488         par = get_par(line, 2, 2, fn=fn, lineno=lineno)
2489         if not par: continue
2490         self.add_item('FIELD_RENAME', par[0], eth_name=par[1], fn=fn, lineno=lineno)
2491         if not par[1][0].islower():
2492           warnings.warn_explicit("Field should be renamed to lowercase name (%s)" % (par[1]),
2493                                   UserWarning, fn, lineno)
2494       elif ctx == 'TF_RENAME':
2495         if empty.match(line): continue
2496         par = get_par(line, 2, 2, fn=fn, lineno=lineno)
2497         if not par: continue
2498         tmpu = par[1][0].upper() + par[1][1:]
2499         tmpl = par[1][0].lower() + par[1][1:]
2500         self.add_item('TYPE_RENAME', par[0], eth_name=tmpu, fn=fn, lineno=lineno)
2501         if not tmpu[0].isupper():
2502           warnings.warn_explicit("Type should be renamed to uppercase name (%s)" % (par[1]),
2503                                   UserWarning, fn, lineno)
2504         self.add_item('FIELD_RENAME', par[0], eth_name=tmpl, fn=fn, lineno=lineno)
2505         if not tmpl[0].islower():
2506           warnings.warn_explicit("Field should be renamed to lowercase name (%s)" % (par[1]),
2507                                   UserWarning, fn, lineno)
2508       elif ctx in ('TYPE_ATTR', 'ETYPE_ATTR', 'FIELD_ATTR', 'EFIELD_ATTR'):
2509         if empty.match(line): continue
2510         par = get_par_nm(line, 1, 1, fn=fn, lineno=lineno)
2511         if not par: continue
2512         self.add_item(ctx, par[0], attr=par[1], fn=fn, lineno=lineno)
2513       elif ctx == 'FN_PARS':
2514         if empty.match(line): continue
2515         if name:
2516           par = get_par_nm(line, 0, 0, fn=fn, lineno=lineno)
2517         else:
2518           par = get_par_nm(line, 1, 1, fn=fn, lineno=lineno)
2519         if not par: continue
2520         if name:
2521           self.update_item(ctx, name, pars=par[0], fn=fn, lineno=lineno)
2522         else:
2523           self.add_item(ctx, par[0], pars=par[1], fn=fn, lineno=lineno)
2524       elif ctx in ('FN_HDR', 'FN_FTR', 'FN_BODY'):
2525         self.add_fn_line(name, ctx, line, fn=fn, lineno=lineno)
2526       elif ctx == 'CLASS':
2527         if empty.match(line): continue
2528         par = get_par(line, 1, 3, fn=fn, lineno=lineno)
2529         if not par: continue
2530         if not set_type_to_class(name, par[0], par[1:]):
2531           warnings.warn_explicit("Could not set type of class member %s.&%s to %s" % (name, par[0], par[1]),
2532                                   UserWarning, fn, lineno)
2533       elif ctx == 'TABLE':
2534         self.report[name][-1]['text'] += line
2535
2536   def set_opt(self, opt, par, fn, lineno):
2537     #print "set_opt: %s, %s" % (opt, par)
2538     if opt in ("-I",):
2539       par = self.check_par(par, 1, 1, fn, lineno)
2540       if not par: return
2541       self.include_path.append(par[0])
2542     elif opt in ("-b", "BER", "CER", "DER"):
2543       par = self.check_par(par, 0, 0, fn, lineno)
2544       self.ectx.encoding = 'ber'
2545     elif opt in ("-X", "NEW_BER"):
2546       par = self.check_par(par, 0, 0, fn, lineno)
2547       self.ectx.new_ber = True
2548     elif opt in ("PER",):
2549       par = self.check_par(par, 0, 0, fn, lineno)
2550       self.ectx.encoding = 'per'
2551     elif opt in ("-p", "PROTO"):
2552       par = self.check_par(par, 1, 1, fn, lineno)
2553       if not par: return
2554       self.ectx.proto_opt = par[0]
2555       self.ectx.merge_modules = True
2556     elif opt in ("-F", "CREATE_FIELDS"):
2557       par = self.check_par(par, 0, 1, fn, lineno)
2558       tnm = '*'
2559       if (len(par) > 0): tnm = par[0]
2560       self.ectx.fld_opt[tnm] = True
2561     elif opt in ("-T",):
2562       par = self.check_par(par, 0, 0, fn, lineno)
2563       self.ectx.tag_opt = True
2564     elif opt in ("ALIGNED",):
2565       par = self.check_par(par, 0, 0, fn, lineno)
2566       self.ectx.aligned = True
2567     elif opt in ("-u", "UNALIGNED"):
2568       par = self.check_par(par, 0, 0, fn, lineno)
2569       self.ectx.aligned = False
2570     elif opt in ("-d",):
2571       par = self.check_par(par, 1, 1, fn, lineno)
2572       if not par: return
2573       self.ectx.dbgopt = par[0]
2574     elif opt in ("-e",):
2575       par = self.check_par(par, 0, 0, fn, lineno)
2576       self.ectx.expcnf = True
2577     elif opt in ("-S",):
2578       par = self.check_par(par, 0, 0, fn, lineno)
2579       self.ectx.merge_modules = True
2580     elif opt in ("GROUP_BY_PROT",):
2581       par = self.check_par(par, 0, 0, fn, lineno)
2582       self.ectx.group_by_prot = True
2583     elif opt in ("-o",):
2584       par = self.check_par(par, 1, 1, fn, lineno)
2585       if not par: return
2586       self.ectx.outnm_opt = par[0]
2587     elif opt in ("-O",):
2588       par = self.check_par(par, 1, 1, fn, lineno)
2589       if not par: return
2590       self.ectx.output.outdir = par[0]
2591     elif opt in ("-s",):
2592       par = self.check_par(par, 1, 1, fn, lineno)
2593       if not par: return
2594       self.ectx.output.single_file = par[0]
2595     elif opt in ("-k",):
2596       par = self.check_par(par, 0, 0, fn, lineno)
2597       self.ectx.output.keep = True
2598     elif opt in ("-L",):
2599       par = self.check_par(par, 0, 0, fn, lineno)
2600       self.suppress_line = True
2601     elif opt in ("EMBEDDED_PDV_CB",):
2602       par = self.check_par(par, 1, 1, fn, lineno)
2603       if not par: return
2604       self.ectx.default_embedded_pdv_cb = par[0]
2605     elif opt in ("EXTERNAL_TYPE_CB",):
2606       par = self.check_par(par, 1, 1, fn, lineno)
2607       if not par: return
2608       self.ectx.default_external_type_cb = par[0]
2609     else:
2610       warnings.warn_explicit("Unknown option %s" % (opt),
2611                              UserWarning, fn, lineno)
2612
2613   def dbg_print(self):
2614     print "\n# Conformance values"
2615     print "%-15s %-4s %-15s %-20s %s" % ("File", "Line", "Table", "Key", "Value")
2616     print "-" * 100
2617     tbls = self.table.keys()
2618     tbls.sort()
2619     for t in tbls:
2620       keys = self.table[t].keys()
2621       keys.sort()
2622       for k in keys:
2623         print "%-15s %4s %-15s %-20s %s" % (
2624               self.table[t][k]['fn'], self.table[t][k]['lineno'], t, k, str(self.table[t][k][self.tblcfg[t]['val_nm']]))
2625
2626   def unused_report(self):
2627     tbls = self.table.keys()
2628     tbls.sort()
2629     for t in tbls:
2630       if not self.tblcfg[t]['chk_use']: continue
2631       keys = self.table[t].keys()
2632       keys.sort()
2633       for k in keys:
2634         if not self.table[t][k]['used']:
2635           warnings.warn_explicit("Unused %s for %s" % (t, k),
2636                                   UserWarning, self.table[t][k]['fn'], self.table[t][k]['lineno'])
2637     fnms = self.fn.keys()
2638     fnms.sort()
2639     for f in fnms:
2640       keys = self.fn[f].keys()
2641       keys.sort()
2642       for k in keys:
2643         if not self.fn[f][k]: continue
2644         if not self.fn[f][k]['used']:
2645           warnings.warn_explicit("Unused %s for %s" % (k, f),
2646                                   UserWarning, self.fn[f][k]['fn'], self.fn[f][k]['lineno'])
2647
2648 #--- EthOut -------------------------------------------------------------------
2649 class EthOut:
2650   def __init__(self):
2651     self.ectx = None
2652     self.outnm = None
2653     self.outdir = '.'
2654     self.single_file = None
2655     self.created_files = {}
2656     self.created_files_ord = []
2657     self.keep = False
2658
2659   def outcomment(self, ln, comment=None):
2660     if comment:
2661       return '%s %s\n' % (comment, ln)
2662     else:
2663       return '/* %-74s */\n' % (ln)
2664
2665   def created_file_add(self, name, keep_anyway):
2666     name = os.path.normcase(os.path.abspath(name))
2667     if not self.created_files.has_key(name):
2668       self.created_files_ord.append(name)
2669       self.created_files[name] = keep_anyway
2670     else:
2671       self.created_files[name] = self.created_files[name] or keep_anyway
2672
2673   def created_file_exists(self, name):
2674     name = os.path.normcase(os.path.abspath(name))
2675     return self.created_files.has_key(name)
2676
2677   #--- output_fname -------------------------------------------------------
2678   def output_fname(self, ftype, ext='c'):
2679     fn = ''
2680     if not ext in ('cnf',):
2681       fn += 'packet-' 
2682     fn += self.outnm
2683     if (ftype):
2684       fn += '-' + ftype
2685     fn += '.' + ext
2686     return fn
2687   #--- output_fullname -------------------------------------------------------
2688   def output_fullname(self, ftype, ext='c'):
2689     return os.path.join(self.outdir, self.output_fname(ftype, ext=ext))
2690   #--- file_open -------------------------------------------------------
2691   def file_open(self, ftype, ext='c'):
2692     fn = self.output_fullname(ftype, ext=ext)
2693     if self.created_file_exists(fn):
2694       fx = file(fn, 'a')
2695     else:
2696       fx = file(fn, 'w')
2697     comment = None
2698     if ext in ('cnf',):
2699       comment = '#'
2700       fx.write(self.fhdr(fn, comment = comment))
2701     else:
2702       if (not self.single_file and not self.created_file_exists(fn)):
2703         fx.write(self.fhdr(fn))
2704     if not self.ectx.merge_modules:
2705       fx.write('\n')
2706       mstr = "--- "
2707       if self.ectx.groups():
2708         mstr += "Module"
2709         if (len(self.ectx.modules) > 1):
2710           mstr += "s"
2711         for (m, p) in self.ectx.modules:
2712           mstr += " %s" % (m)
2713       else:
2714         mstr += "Module %s" % (self.ectx.Module())
2715       mstr += " --- --- ---"
2716       fx.write(self.outcomment(mstr, comment))
2717       fx.write('\n')
2718     return fx
2719   #--- file_close -------------------------------------------------------
2720   def file_close(self, fx, discard=False, keep_anyway=False):
2721     fx.close()
2722     if discard and not self.created_file_exists(fx.name): 
2723       os.unlink(fx.name)
2724     else:
2725       self.created_file_add(fx.name, keep_anyway)
2726   #--- fhdr -------------------------------------------------------
2727   def fhdr(self, fn, comment=None):
2728     out = ''
2729     out += self.outcomment('Do not modify this file.', comment)
2730     out += self.outcomment('It is created automatically by the ASN.1 to Wireshark dissector compiler', comment)
2731     out += self.outcomment(fn, comment)
2732     out += self.outcomment(' '.join(sys.argv), comment)
2733     out += '\n'
2734     return out
2735
2736   #--- dbg_print -------------------------------------------------------
2737   def dbg_print(self):
2738     print "\n# Output files"
2739     print "\n".join(self.created_files_ord)
2740     print "\n"
2741
2742   #--- make_single_file -------------------------------------------------------
2743   def make_single_file(self):
2744     if (not self.single_file): return
2745     in_nm = self.single_file + '.c'
2746     out_nm = self.output_fullname('')
2747     self.do_include(out_nm, in_nm)
2748     in_nm = self.single_file + '.h'
2749     if (os.path.exists(in_nm)):
2750       out_nm = self.output_fullname('', ext='h')
2751       self.do_include(out_nm, in_nm)
2752     if (not self.keep):
2753       for fn in self.created_files_ord:
2754         if not self.created_files[fn]:
2755           os.unlink(fn)
2756
2757   #--- do_include -------------------------------------------------------
2758   def do_include(self, out_nm, in_nm):
2759     def check_file(fn, fnlist):
2760       fnfull = os.path.normcase(os.path.abspath(fn))
2761       if (fnlist.has_key(fnfull) and os.path.exists(fnfull)):
2762         return os.path.normpath(fn)
2763       return None
2764     fin = file(in_nm, "r")
2765     fout = file(out_nm, "w")
2766     fout.write(self.fhdr(out_nm))
2767     fout.write('/* Input file: ' + in_nm +' */\n')
2768     fout.write('\n')
2769     fout.write('#line 1 "%s"\n' % (in_nm))
2770
2771     include = re.compile(r'^\s*#\s*include\s+[<"](?P<fname>[^>"]+)[>"]', re.IGNORECASE)
2772
2773     cont_linenum = 0;
2774
2775     while (True):
2776       cont_linenum = cont_linenum + 1;
2777       line = fin.readline()
2778       if (line == ''): break
2779       ifile = None
2780       result = include.search(line)
2781       #if (result): print os.path.normcase(os.path.abspath(result.group('fname')))
2782       if (result):
2783         ifile = check_file(os.path.join(os.path.split(in_nm)[0], result.group('fname')), self.created_files)
2784         if (not ifile):
2785           ifile = check_file(os.path.join(self.outdir, result.group('fname')), self.created_files)
2786         if (not ifile):
2787           ifile = check_file(result.group('fname'), self.created_files)
2788       if (ifile):
2789         fout.write('\n')
2790         fout.write('/*--- Included file: ' + ifile + ' ---*/\n')
2791         fout.write('#line 1 "' + ifile + '"\n')
2792         finc = file(ifile, "r")
2793         fout.write(finc.read())
2794         fout.write('\n')
2795         fout.write('/*--- End of included file: ' + ifile + ' ---*/\n')
2796         fout.write('#line %i "%s"\n' % (cont_linenum+1,in_nm) )
2797         finc.close()
2798       else:
2799         fout.write(line)
2800
2801     fout.close()
2802     fin.close()
2803
2804
2805 #--- Node ---------------------------------------------------------------------
2806 class Node:
2807     def __init__(self,*args, **kw):
2808         if len (args) == 0:
2809             self.type = self.__class__.__name__
2810         else:
2811             assert (len(args) == 1)
2812             self.type = args[0]
2813         self.__dict__.update (kw)
2814     def str_child (self, key, child, depth):
2815         indent = " " * (2 * depth)
2816         keystr = indent + key + ": "
2817         if key == 'type': # already processed in str_depth
2818             return ""
2819         if isinstance (child, Node): # ugh
2820             return keystr + "\n" + child.str_depth (depth+1)
2821         if type (child) == type ([]):
2822             l = []
2823             for x in child:
2824               if isinstance (x, Node):
2825                 l.append (x.str_depth (depth+1))
2826               else:
2827                 l.append (indent + "  " + str(x) + "\n")
2828             return keystr + "[\n" + ''.join(l) + indent + "]\n"
2829         else:
2830             return keystr + str (child) + "\n"
2831     def str_depth (self, depth): # ugh
2832         indent = " " * (2 * depth)
2833         l = ["%s%s" % (indent, self.type)]
2834         l.append ("".join (map (lambda (k,v): self.str_child (k, v, depth + 1),
2835                                 self.__dict__.items ())))
2836         return "\n".join (l)
2837     def __repr__(self):
2838         return "\n" + self.str_depth (0)
2839     def to_python (self, ctx):
2840         return self.str_depth (ctx.indent_lev)
2841
2842     def eth_reg(self, ident, ectx):
2843         pass
2844
2845     def fld_obj_repr(self, ectx):
2846         return "/* TO DO %s */" % (str(self))
2847
2848 #--- ValueAssignment -------------------------------------------------------------
2849 class ValueAssignment (Node):
2850   def __init__(self,*args, **kw) :
2851     Node.__init__ (self,*args, **kw)
2852
2853   def eth_reg(self, ident, ectx):
2854     if ectx.conform.omit_assignment('V', self.ident, ectx.Module()): return # Assignment to omit
2855     ectx.eth_reg_vassign(self)
2856     ectx.eth_reg_value(self.ident, self.typ, self.val)
2857
2858 #--- ObjectAssignment -------------------------------------------------------------
2859 class ObjectAssignment (Node):
2860   def __init__(self,*args, **kw) :
2861     Node.__init__ (self,*args, **kw)
2862
2863   def __eq__(self, other):
2864     if self.cls != other.cls:
2865       return False
2866     if len(self.val) != len(other.val):
2867       return False
2868     for f in (self.val.keys()):
2869       if not other.val.has_key(f):
2870         return False
2871       if isinstance(self.val[f], Node) and isinstance(other.val[f], Node):
2872         if not self.val[f].fld_obj_eq(other.val[f]):
2873           return False
2874       else:
2875         if str(self.val[f]) != str(other.val[f]):
2876           return False
2877     return True
2878
2879   def eth_reg(self, ident, ectx):
2880     def make_virtual_type(cls, field, prefix):
2881       if isinstance(self.val, str): return
2882       if self.val.has_key(field) and not isinstance(self.val[field], Type_Ref):
2883         vnm = prefix + '-' + self.ident
2884         virtual_tr = Type_Ref(val = vnm)
2885         t = self.val[field]
2886         self.val[field] = virtual_tr
2887         ectx.eth_reg_assign(vnm, t, virt=True)
2888         ectx.eth_reg_type(vnm, t)
2889         t.eth_reg_sub(vnm, ectx)
2890       if self.val.has_key(field) and ectx.conform.check_item('PDU', cls + '.' + field):
2891         ectx.eth_reg_field(self.val[field].val, self.val[field].val, impl=self.val[field].HasImplicitTag(ectx), pdu=ectx.conform.use_item('PDU', cls + '.' + field))
2892       return
2893     # end of make_virtual_type()
2894     if ectx.conform.omit_assignment('V', self.ident, ectx.Module()): return # Assignment to omit
2895     ectx.eth_reg_oassign(self)
2896     if (self.cls == 'TYPE-IDENTIFIER') or (self.cls == 'ABSTRACT-SYNTAX'):
2897       make_virtual_type(self.cls, '&Type', 'TYPE')
2898     if (self.cls == 'OPERATION'):
2899       make_virtual_type(self.cls, '&ArgumentType', 'ARG')
2900       make_virtual_type(self.cls, '&ResultType', 'RES')
2901     if (self.cls == 'ERROR'):
2902       make_virtual_type(self.cls, '&ParameterType', 'PAR')
2903
2904
2905 #--- Type ---------------------------------------------------------------------
2906 class Type (Node):
2907   def __init__(self,*args, **kw) :
2908     self.name = None
2909     self.constr = None
2910     self.tags = []
2911     self.named_list = None
2912     Node.__init__ (self,*args, **kw)
2913
2914   def IsNamed(self):
2915     if self.name is None :
2916       return False
2917     else:
2918       return True
2919
2920   def HasConstraint(self):
2921     if self.constr is None :
2922       return False
2923     else :
2924       return True
2925
2926   def HasSizeConstraint(self):
2927     return self.HasConstraint() and self.constr.IsSize()
2928
2929   def HasValueConstraint(self):
2930     return self.HasConstraint() and self.constr.IsValue()
2931
2932   def HasPermAlph(self):
2933     return self.HasConstraint() and self.constr.IsPermAlph()
2934
2935   def HasContentsConstraint(self):
2936     return self.HasConstraint() and self.constr.IsContents()
2937
2938   def HasOwnTag(self):
2939     return len(self.tags) > 0
2940
2941   def HasImplicitTag(self, ectx):
2942     return (self.HasOwnTag() and self.tags[0].IsImplicit(ectx))
2943
2944   def IndetermTag(self, ectx):
2945     return False
2946
2947   def AddTag(self, tag):
2948     self.tags[0:0] = [tag]
2949
2950   def GetTag(self, ectx):
2951     #print "GetTag(%s)\n" % self.name;
2952     if (self.HasOwnTag()):
2953       return self.tags[0].GetTag(ectx)
2954     else:
2955       return self.GetTTag(ectx)
2956
2957   def GetTTag(self, ectx):
2958     print "#Unhandled  GetTTag() in %s" % (self.type)
2959     print self.str_depth(1)
2960     return ('BER_CLASS_unknown', 'TAG_unknown')
2961
2962   def SetName(self, name):
2963     self.name = name
2964
2965   def AddConstraint(self, constr):
2966     if not self.HasConstraint():
2967       self.constr = constr
2968     else:
2969       self.constr = Constraint(type = 'Intersection', subtype = [self.constr, constr])
2970
2971   def eth_tname(self):
2972     return '#' + self.type + '_' + str(id(self))
2973
2974   def eth_ftype(self, ectx):
2975     return ('FT_NONE', 'BASE_NONE')
2976
2977   def eth_strings(self):
2978     return 'NULL'
2979
2980   def eth_need_tree(self):
2981     return False
2982
2983   def eth_has_vals(self):
2984     return False
2985
2986   def eth_has_enum(self, tname, ectx):
2987     return self.eth_has_vals() and (ectx.eth_type[tname]['enum'] & EF_ENUM)
2988
2989   def eth_need_pdu(self, ectx):
2990     return None
2991
2992   def eth_named_bits(self):
2993     return None
2994
2995   def eth_reg_sub(self, ident, ectx):
2996     pass
2997
2998   def get_components(self, ectx):
2999     print "#Unhandled  get_components() in %s" % (self.type)
3000     print self.str_depth(1)
3001     return []
3002
3003   def sel_req(self, sel, ectx):
3004     print "#Selection '%s' required for non-CHOICE type %s" % (sel, self.type)
3005     print self.str_depth(1)
3006     
3007   def fld_obj_eq(self, other):
3008     return isinstance(other, Type) and (self.eth_tname() == other.eth_tname())
3009
3010   def eth_reg(self, ident, ectx, tstrip=0, tagflag=False, selflag=False, idx='', parent=None):
3011     #print "eth_reg(): %s, ident=%s, tstrip=%d, tagflag=%s, selflag=%s, parent=%s" %(self.type, ident, tstrip, str(tagflag), str(selflag), str(parent))
3012     if (ectx.Tag() and (len(self.tags) > tstrip)):
3013       tagged_type = TaggedType(val=self, tstrip=tstrip)
3014       tagged_type.AddTag(self.tags[tstrip])
3015       if not tagflag:  # 1st tagged level
3016         if self.IsNamed() and not selflag:
3017           tagged_type.SetName(self.name)
3018       tagged_type.eth_reg(ident, ectx, tstrip=1, tagflag=tagflag, idx=idx, parent=parent)
3019       return
3020     nm = ''
3021     if ident and self.IsNamed() and not tagflag and not selflag:
3022       nm = ident + '/' + self.name
3023     elif ident:
3024       nm = ident
3025     elif self.IsNamed():
3026       nm = self.name
3027     if not ident and ectx.conform.omit_assignment('T', nm, ectx.Module()): return # Assignment to omit
3028     if not ident:  # Assignment
3029       ectx.eth_reg_assign(nm, self)
3030       if self.type == 'Type_Ref':
3031         ectx.eth_reg_type(nm, self)
3032     virtual_tr = Type_Ref(val=ectx.conform.use_item('SET_TYPE', nm))
3033     if (self.type == 'Type_Ref') or ectx.conform.check_item('SET_TYPE', nm):
3034       if ident and (ectx.conform.check_item('TYPE_RENAME', nm) or ectx.conform.get_fn_presence(nm) or selflag):
3035         if ectx.conform.check_item('SET_TYPE', nm):
3036           ectx.eth_reg_type(nm, virtual_tr)  # dummy Type Reference
3037         else:
3038           ectx.eth_reg_type(nm, self)  # new type
3039         trnm = nm
3040       elif ectx.conform.check_item('SET_TYPE', nm):
3041         trnm = ectx.conform.use_item('SET_TYPE', nm)
3042       else:
3043         trnm = self.val
3044     else:
3045       ectx.eth_reg_type(nm, self)
3046       trnm = nm
3047     if ectx.conform.check_item('VIRTUAL_ASSGN', nm):
3048       vnm = ectx.conform.use_item('VIRTUAL_ASSGN', nm)
3049       ectx.eth_reg_assign(vnm, self, virt=True)
3050       ectx.eth_reg_type(vnm, self)
3051       self.eth_reg_sub(vnm, ectx)
3052     if parent and (ectx.type[parent]['val'].type == 'TaggedType'):
3053       ectx.type[parent]['val'].eth_set_val_name(parent, trnm, ectx)
3054     if ident and not tagflag:
3055       ectx.eth_reg_field(nm, trnm, idx=idx, parent=parent, impl=self.HasImplicitTag(ectx))
3056     if ectx.conform.check_item('SET_TYPE', nm):
3057       virtual_tr.eth_reg_sub(nm, ectx)
3058     else:
3059       self.eth_reg_sub(nm, ectx)
3060
3061   def eth_get_size_constr(self, ectx):
3062     (minv, maxv, ext) = ('MIN', 'MAX', False)
3063     if self.HasSizeConstraint():
3064       if self.constr.IsSize():
3065         (minv, maxv, ext) = self.constr.GetSize(ectx)
3066       if (self.constr.type == 'Intersection'):
3067         if self.constr.subtype[0].IsSize():
3068           (minv, maxv, ext) = self.constr.subtype[0].GetSize(ectx)
3069         elif self.constr.subtype[1].IsSize():
3070           (minv, maxv, ext) = self.constr.subtype[1].GetSize(ectx)
3071     if minv == 'MIN': minv = 'NO_BOUND'
3072     if maxv == 'MAX': maxv = 'NO_BOUND'
3073     if (ext): ext = 'TRUE'
3074     else: ext = 'FALSE'
3075     return (minv, maxv, ext)
3076
3077   def eth_get_value_constr(self, ectx):
3078     (minv, maxv, ext) = ('MIN', 'MAX', False)
3079     if self.HasValueConstraint():
3080       (minv, maxv, ext) = self.constr.GetValue(ectx)
3081     if minv == 'MIN': minv = 'NO_BOUND'
3082     if maxv == 'MAX': maxv = 'NO_BOUND'
3083     if str(minv).isdigit(): minv += 'U'
3084     if str(maxv).isdigit(): maxv += 'U'
3085     if (ext): ext = 'TRUE'
3086     else: ext = 'FALSE'
3087     return (minv, maxv, ext)
3088
3089   def eth_get_alphabet_constr(self, ectx):
3090     (alph, alphlen) = ('NULL', '0')
3091     if self.HasPermAlph():
3092       alph = self.constr.GetPermAlph(ectx)
3093       if not alph:
3094         alph = 'NULL'
3095       if (alph != 'NULL'):
3096         if (((alph[0] + alph[-1]) == '""') and (not alph.count('"', 1, -1))):
3097           alphlen = str(len(alph) - 2)
3098         else:
3099           alphlen = 'strlen(%s)' % (alph)
3100     return (alph, alphlen)
3101
3102   def eth_type_vals(self, tname, ectx):
3103     if self.eth_has_vals():
3104       print "#Unhandled  eth_type_vals('%s') in %s" % (tname, self.type)
3105       print self.str_depth(1)
3106     return ''
3107
3108   def eth_type_enum(self, tname, ectx):
3109     if self.eth_has_enum(tname, ectx):
3110       print "#Unhandled  eth_type_enum('%s') in %s" % (tname, self.type)
3111       print self.str_depth(1)
3112     return ''
3113
3114   def eth_type_default_table(self, ectx, tname):
3115     return ''
3116
3117   def eth_type_default_body(self, ectx):
3118     print "#Unhandled  eth_type_default_body() in %s" % (self.type)
3119     print self.str_depth(1)
3120     return ''
3121
3122   def eth_type_default_pars(self, ectx, tname):
3123     pars = {
3124       'TNAME' : tname,
3125       'ER' : ectx.encp(),
3126       'FN_VARIANT' : '',
3127       'TREE' : 'tree', 
3128       'TVB' : 'tvb', 
3129       'OFFSET' : 'offset',
3130       'ACTX' : 'actx',
3131       'HF_INDEX' : 'hf_index',
3132       'VAL_PTR' : 'NULL',
3133       'IMPLICIT_TAG' : 'implicit_tag',
3134     }
3135     if (ectx.eth_type[tname]['tree']):
3136       pars['ETT_INDEX'] = ectx.eth_type[tname]['tree']
3137     if (ectx.merge_modules):
3138       pars['PROTOP'] = ''
3139     else:
3140       pars['PROTOP'] = ectx.eth_type[tname]['proto'] + '_'
3141     return pars
3142
3143   def eth_type_fn(self, proto, tname, ectx):
3144     body = self.eth_type_default_body(ectx, tname)
3145     pars = self.eth_type_default_pars(ectx, tname)
3146     if ectx.conform.check_item('FN_PARS', tname):
3147       pars.update(ectx.conform.use_item('FN_PARS', tname))
3148     elif ectx.conform.check_item('FN_PARS', ectx.eth_type[tname]['ref'][0]):
3149       pars.update(ectx.conform.use_item('FN_PARS', ectx.eth_type[tname]['ref'][0]))
3150     pars['DEFAULT_BODY'] = body
3151     for i in range(4):
3152       for k in pars.keys(): 
3153         try:
3154           pars[k] = pars[k] % pars
3155         except (TypeError):
3156           raise sys.exc_type, "%s\n%s" % (str(pars), sys.exc_value)
3157     out = '\n'
3158     out += self.eth_type_default_table(ectx, tname) % pars
3159     out += ectx.eth_type_fn_hdr(tname)
3160     out += ectx.eth_type_fn_body(tname, body, pars=pars)
3161     out += ectx.eth_type_fn_ftr(tname)
3162     return out
3163
3164 #--- Value --------------------------------------------------------------------
3165 class Value (Node):
3166   def __init__(self,*args, **kw) :
3167     self.name = None
3168     Node.__init__ (self,*args, **kw)
3169
3170   def SetName(self, name) :
3171     self.name = name
3172
3173   def to_str(self, ectx):
3174     return str(self.val)
3175
3176   def get_dep(self):
3177     return None
3178
3179   def fld_obj_repr(self, ectx):
3180     return self.to_str(ectx)
3181
3182 #--- Value_Ref -----------------------------------------------------------------
3183 class Value_Ref (Value):
3184   def to_str(self, ectx):
3185     return asn2c(self.val)
3186
3187 #--- ObjectClass ---------------------------------------------------------------------
3188 class ObjectClass (Node):
3189   def __init__(self,*args, **kw) :
3190     self.name = None
3191     Node.__init__ (self,*args, **kw)
3192
3193   def SetName(self, name):
3194     self.name = name
3195     add_class_ident(self.name)
3196
3197   def eth_reg(self, ident, ectx):
3198     if ectx.conform.omit_assignment('C', self.name, ectx.Module()): return # Assignment to omit
3199     ectx.eth_reg_objectclass(self.name, self)
3200
3201 #--- Class_Ref -----------------------------------------------------------------
3202 class Class_Ref (ObjectClass):
3203   pass
3204
3205 #--- ObjectClassDefn ---------------------------------------------------------------------
3206 class ObjectClassDefn (ObjectClass):
3207   def reg_types(self):
3208     for fld in self.fields:
3209       repr = fld.fld_repr()
3210       set_type_to_class(self.name, repr[0], repr[1:])
3211
3212
3213 #--- Tag ---------------------------------------------------------------
3214 class Tag (Node):
3215   def to_python (self, ctx):
3216     return 'asn1.TYPE(%s,%s)' % (mk_tag_str (ctx, self.tag.cls,
3217                                                 self.tag_typ,
3218                                                 self.tag.num),
3219                                     self.typ.to_python (ctx))
3220   def IsImplicit(self, ectx):
3221     return ((self.mode == 'IMPLICIT') or ((self.mode == 'default') and (ectx.tag_def == 'IMPLICIT')))
3222
3223   def GetTag(self, ectx):
3224     tc = ''
3225     if (self.cls == 'UNIVERSAL'): tc = 'BER_CLASS_UNI'
3226     elif (self.cls == 'APPLICATION'): tc = 'BER_CLASS_APP'
3227     elif (self.cls == 'CONTEXT'): tc = 'BER_CLASS_CON'
3228     elif (self.cls == 'PRIVATE'): tc = 'BER_CLASS_PRI'
3229     return (tc, self.num)
3230
3231   def eth_tname(self):
3232     n = ''
3233     if (self.cls == 'UNIVERSAL'): n = 'U'
3234     elif (self.cls == 'APPLICATION'): n = 'A'
3235     elif (self.cls == 'CONTEXT'): n = 'C'
3236     elif (self.cls == 'PRIVATE'): n = 'P'
3237     return n + str(self.num)
3238  
3239 #--- Constraint ---------------------------------------------------------------
3240 class Constraint (Node):
3241   def to_python (self, ctx):
3242     print "Ignoring constraint:", self.type
3243     return self.subtype.typ.to_python (ctx)
3244   def __str__ (self):
3245     return "Constraint: type=%s, subtype=%s" % (self.type, self.subtype)
3246
3247   def eth_tname(self):
3248     return '#' + self.type + '_' + str(id(self))
3249
3250   def IsSize(self):
3251     return (self.type == 'Size' and self.subtype.IsValue()) \
3252            or (self.type == 'Intersection' and (self.subtype[0].IsSize() or self.subtype[1].IsSize())) \
3253
3254   def GetSize(self, ectx):
3255     (minv, maxv, ext) = ('MIN', 'MAX', False)
3256     if self.IsSize():
3257       if self.type == 'Size':
3258         (minv, maxv, ext) = self.subtype.GetValue(ectx)
3259       elif self.type == 'Intersection':
3260         if self.subtype[0].IsSize() and not self.subtype[1].IsSize():
3261           (minv, maxv, ext) = self.subtype[0].GetSize(ectx)
3262         elif not self.subtype[0].IsSize() and self.subtype[1].IsSize():
3263           (minv, maxv, ext) = self.subtype[1].GetSize(ectx)
3264     return (minv, maxv, ext)
3265
3266   def IsValue(self):
3267     return self.type == 'SingleValue' \
3268            or self.type == 'ValueRange' \
3269            or (self.type == 'Intersection' and (self.subtype[0].IsValue() or self.subtype[1].IsValue())) \
3270            or (self.type == 'Union' and (self.subtype[0].IsValue() and self.subtype[1].IsValue()))
3271
3272   def GetValue(self, ectx):
3273     (minv, maxv, ext) = ('MIN', 'MAX', False)
3274     if self.IsValue():
3275       if self.type == 'SingleValue':
3276         minv = ectx.value_get_eth(self.subtype)
3277         maxv = ectx.value_get_eth(self.subtype)
3278         ext = hasattr(self, 'ext') and self.ext
3279       elif self.type == 'ValueRange':
3280         minv = ectx.value_get_eth(self.subtype[0])
3281         maxv = ectx.value_get_eth(self.subtype[1])
3282         ext = hasattr(self, 'ext') and self.ext
3283       elif self.type == 'Intersection':
3284         if self.subtype[0].IsValue() and not self.subtype[1].IsValue():
3285           (minv, maxv, ext) = self.subtype[0].GetValue(ectx)
3286         elif not self.subtype[0].IsValue() and self.subtype[1].IsValue():
3287           (minv, maxv, ext) = self.subtype[1].GetValue(ectx)
3288         elif self.subtype[0].IsValue() and self.subtype[1].IsValue():
3289           v0 = self.subtype[0].GetValue(ectx)
3290           v1 = self.subtype[1].GetValue(ectx)
3291           (minv, maxv, ext) = (ectx.value_max(v0[0],v1[0]), ectx.value_min(v0[1],v1[1]), v0[2] and v1[2])
3292       elif self.type == 'Union':
3293         if self.subtype[0].IsValue() and self.subtype[1].IsValue():
3294           v0 = self.subtype[0].GetValue(ectx)
3295           v1 = self.subtype[1].GetValue(ectx)
3296           (minv, maxv, ext) = (ectx.value_min(v0[0],v1[0]), ectx.value_max(v0[1],v1[1]), v0[2] or v1[2])
3297     return (minv, maxv, ext)
3298
3299   def IsAlphabet(self):
3300     return self.type == 'SingleValue' \
3301            or self.type == 'ValueRange' \
3302            or (self.type == 'Intersection' and (self.subtype[0].IsAlphabet() or self.subtype[1].IsAlphabet())) \
3303            or (self.type == 'Union' and (self.subtype[0].IsAlphabet() and self.subtype[1].IsAlphabet()))
3304
3305   def GetAlphabet(self, ectx):
3306     alph = None
3307     if self.IsAlphabet():
3308       if self.type == 'SingleValue':
3309         alph = ectx.value_get_eth(self.subtype)
3310       elif self.type == 'ValueRange':
3311         if ((len(self.subtype[0]) == 3) and ((self.subtype[0][0] + self.subtype[0][-1]) == '""') \
3312             and (len(self.subtype[1]) == 3) and ((self.subtype[1][0] + self.subtype[1][-1]) == '""')):
3313           alph = '"'
3314           for c in range(ord(self.subtype[0][1]), ord(self.subtype[1][1]) + 1):
3315             alph += chr(c)
3316           alph += '"'
3317       elif self.type == 'Union':
3318         if self.subtype[0].IsAlphabet() and self.subtype[1].IsAlphabet():
3319           a0 = self.subtype[0].GetAlphabet(ectx)
3320           a1 = self.subtype[1].GetAlphabet(ectx)
3321           if (((a0[0] + a0[-1]) == '""') and not a0.count('"', 1, -1) \
3322               and ((a1[0] + a1[-1]) == '""') and not a1.count('"', 1, -1)):
3323             alph = '"' + a0[1:-1] + a1[1:-1] + '"'
3324           else:
3325             alph = a0 + ' ' + a1
3326     return alph
3327
3328   def IsPermAlph(self):
3329     return self.type == 'From' and self.subtype.IsAlphabet() \
3330            or (self.type == 'Intersection' and (self.subtype[0].IsPermAlph() or self.subtype[1].IsPermAlph())) \
3331
3332   def GetPermAlph(self, ectx):
3333     alph = None
3334     if self.IsPermAlph():
3335       if self.type == 'From':
3336         alph = self.subtype.GetAlphabet(ectx)
3337       elif self.type == 'Intersection':
3338         if self.subtype[0].IsPermAlph() and not sel