- simple Information Objects support
[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
37 from __future__ import nested_scopes
38
39 import warnings
40
41 import re
42 import sys
43 import os
44 import os.path
45 import time
46 import getopt
47
48 import __main__ # XXX blech!
49 import lex
50 import yacc
51
52 # OID name -> number conversion table
53 oid_names = {
54   '/itu-t' : 0,
55   '/itu'   : 0,
56   '/ccitt' : 0,
57   '/itu-r' : 0,
58   '0/recommendation' : 0,
59   '0.0/a' : 1,
60   '0.0/b' : 2,
61   '0.0/c' : 3,
62   '0.0/d' : 4,
63   '0.0/e' : 5,
64   '0.0/f' : 6,
65   '0.0/g' : 7,
66   '0.0/h' : 8,
67   '0.0/i' : 9,
68   '0.0/j' : 10,
69   '0.0/k' : 11,
70   '0.0/l' : 12,
71   '0.0/m' : 13,
72   '0.0/n' : 14,
73   '0.0/o' : 15,
74   '0.0/p' : 16,
75   '0.0/q' : 17,
76   '0.0/r' : 18,
77   '0.0/s' : 19,
78   '0.0/t' : 20,
79   '0.0/tseries' : 20,
80   '0.0/u' : 21,
81   '0.0/v' : 22,
82   '0.0/w' : 23,
83   '0.0/x' : 24,
84   '0.0/y' : 25,
85   '0.0/z' : 26,
86   '0/question' : 1,
87   '0/administration' : 2,
88   '0/network-operator' : 3,
89   '0/identified-organization' : 4,
90   '0/r-recommendation' : 5,
91   '0/data' : 9,
92   '/iso' : 1,
93   '1/standard' : 0,
94   '1/registration-authority' : 1,
95   '1/member-body' : 2,
96   '1/identified-organization' : 3,
97   '/joint-iso-itu-t' : 2,
98   '/joint-iso-ccitt' : 2,
99   '2/presentation' : 0,
100   '2/asn1' : 1,
101   '2/association-control' : 2,
102   '2/reliable-transfer' : 3,
103   '2/remote-operations' : 4,
104   '2/ds' : 5,
105   '2/directory' : 5,
106   '2/mhs' : 6,
107   '2/mhs-motis' : 6,
108   '2/ccr' : 7,
109   '2/oda' : 8,
110   '2/ms' : 9,
111   '2/osi-management' : 9,
112   '2/transaction-processing' : 10,
113   '2/dor' : 11,
114   '2/distinguished-object-reference' : 11,
115   '2/reference-data-transfe' : 12,
116   '2/network-layer' : 13,
117   '2/network-layer-management' : 13,
118   '2/transport-layer' : 14,
119   '2/transport-layer-management' : 14,
120   '2/datalink-layer' : 15,
121   '2/datalink-layer-managemen' : 15,
122   '2/datalink-layer-management-information' : 15,
123   '2/country' : 16,
124   '2/registration-procedures' : 17,
125   '2/registration-procedure' : 17,
126   '2/physical-layer' : 18,
127   '2/physical-layer-management' : 18,
128   '2/mheg' : 19,
129   '2/genericULS' : 20,
130   '2/generic-upper-layers-security' : 20,
131   '2/guls' : 20,
132   '2/transport-layer-security-protocol' : 21,
133   '2/network-layer-security-protocol' : 22,
134   '2/international-organizations' : 23,
135   '2/internationalRA' : 23,
136   '2/sios' : 24,
137   '2/uuid' : 25,
138   '2/odp' : 26,
139   '2/upu' : 40,
140 }
141
142 def asn2c(id):
143   return id.replace('-', '_').replace('.', '_')
144
145 input_file = None
146 lexer = None
147
148 class LexError(Exception):
149   def __init__(self, tok, filename=None):
150     self.tok = tok
151     self.filename = filename
152     self.msg =  "Unexpected character %r" % (self.tok.value[0])
153     Exception.__init__(self, self.msg)
154   def __repr__(self):
155     return "%s:%d: %s" % (self.filename, self.tok.lineno, self.msg)
156   __str__ = __repr__
157
158
159 class ParseError(Exception):
160   def __init__(self, tok, filename=None):
161     self.tok = tok
162     self.filename = filename
163     self.msg =  "Unexpected token %s(%r)" % (self.tok.type, self.tok.value)
164     Exception.__init__(self, self.msg)
165   def __repr__(self):
166     return "%s:%d: %s" % (self.filename, self.tok.lineno, self.msg)
167   __str__ = __repr__
168
169
170 states = (
171   ('braceignore','exclusive'),
172 )
173
174 # 11 ASN.1 lexical items
175
176 static_tokens = {
177   r'::='    : 'ASSIGNMENT',  # 11.16 Assignment lexical item
178   r'\.\.'   : 'RANGE',       # 11.17 Range separator
179   r'\.\.\.' : 'ELLIPSIS',    # 11.18 Ellipsis
180   #r'\[\['   : 'LVERBRACK',   # 11.19 Left version brackets
181   #r'\]\]'   : 'RVERBRACK',   # 11.20 Right version brackets
182   # 11.26 Single character lexical items
183   r'\{' : 'LBRACE',
184   r'\}' : 'RBRACE',
185   r'<'  : 'LT',
186   #r'>'  : 'GT',
187   r','  : 'COMMA',
188   r'\.' : 'DOT',
189   r'\(' : 'LPAREN',
190   r'\)' : 'RPAREN',
191   r'\[' : 'LBRACK',
192   r'\]' : 'RBRACK',
193   r'-'  : 'MINUS',
194 #  r':'  : 'COLON',
195   #r'='  : 'EQ',
196   #r'"'  : 'QUOTATION',
197   #r"'"  : 'APOSTROPHE',
198   r';'  : 'SEMICOLON',
199   r'@'  : 'AT',
200   #r'\!' : 'EXCLAMATION',
201   r'\^' : 'CIRCUMFLEX',
202   r'\&' : 'AMPERSAND'
203 }
204
205 # 11.27 Reserved words
206
207 # all keys in reserved_words must start w/ upper case
208 reserved_words = {
209   'ABSENT'      : 'ABSENT',
210   'ABSTRACT-SYNTAX' : 'ABSTRACT_SYNTAX',
211 #  'ALL'         : 'ALL',
212   'APPLICATION' : 'APPLICATION',
213   'AUTOMATIC'   : 'AUTOMATIC',
214   'BEGIN'       : 'BEGIN',
215   'BIT'         : 'BIT',
216   'BOOLEAN'     : 'BOOLEAN',
217   'BY'          : 'BY',
218   'CHARACTER'   : 'CHARACTER',
219   'CHOICE'      : 'CHOICE',
220   'CLASS'       : 'CLASS',
221   'COMPONENT'   : 'COMPONENT',
222   'COMPONENTS'  : 'COMPONENTS',
223   'CONSTRAINED' : 'CONSTRAINED',
224 #  'CONTAINING'  : 'CONTAINING',
225   'DEFAULT'     : 'DEFAULT',
226   'DEFINITIONS' : 'DEFINITIONS',
227 #  'EMBEDDED'    : 'EMBEDDED',
228 #  'ENCODED'     : 'ENCODED',
229   'END'         : 'END',
230   'ENUMERATED'  : 'ENUMERATED',
231 #  'EXCEPT'      : 'EXCEPT',
232   'EXPLICIT'    : 'EXPLICIT',
233   'EXPORTS'     : 'EXPORTS',
234 #  'EXTENSIBILITY' : 'EXTENSIBILITY',
235   'EXTERNAL'    : 'EXTERNAL',
236   'FALSE'       : 'FALSE',
237   'FROM'        : 'FROM',
238   'GeneralizedTime' : 'GeneralizedTime',
239   'IDENTIFIER'  : 'IDENTIFIER',
240   'IMPLICIT'    : 'IMPLICIT',
241 #  'IMPLIED'     : 'IMPLIED',
242   'IMPORTS'     : 'IMPORTS',
243   'INCLUDES'    : 'INCLUDES',
244 #  'INSTANCE'    : 'INSTANCE',
245   'INTEGER'     : 'INTEGER',
246   'INTERSECTION' : 'INTERSECTION',
247   'MAX'         : 'MAX',
248   'MIN'         : 'MIN',
249   'MINUS-INFINITY' : 'MINUS_INFINITY',
250   'NULL'        : 'NULL',
251   'OBJECT'      : 'OBJECT',
252   'ObjectDescriptor' : 'ObjectDescriptor',
253   'OCTET'       : 'OCTET',
254   'OF'          : 'OF',
255   'OPTIONAL'    : 'OPTIONAL',
256   'PATTERN'     : 'PATTERN',
257 #  'PDV'         : 'PDV',
258   'PLUS-INFINITY' : 'PLUS_INFINITY',
259   'PRESENT'     : 'PRESENT',
260   'PRIVATE'     : 'PRIVATE',
261   'REAL'        : 'REAL',
262 #  'RELATIVE-OID' : 'RELATIVE-OID',
263   'SEQUENCE'    : 'SEQUENCE',
264   'SET'         : 'SET',
265   'SIZE'        : 'SIZE',
266   'STRING'      : 'STRING',
267   'SYNTAX'      : 'SYNTAX',
268   'TAGS'        : 'TAGS',
269   'TRUE'        : 'TRUE',
270   'TYPE-IDENTIFIER' : 'TYPE_IDENTIFIER',
271 #  'UNION'       : 'UNION',
272 #  'UNIQUE'      : 'UNIQUE',
273   'UNIVERSAL'   : 'UNIVERSAL',
274   'UTCTime'     : 'UTCTime',
275   'WITH'        : 'WITH',
276 # obsolete but still used
277   'ANY'         : 'ANY',
278 }
279
280 for k in static_tokens.keys ():
281     if static_tokens [k] == None:
282         static_tokens [k] = k
283
284 StringTypes = ['Numeric', 'Printable', 'IA5', 'BMP', 'Universal', 'UTF8',
285                'Teletex', 'T61', 'Videotex', 'Graphic', 'ISO646', 'Visible',
286                'General']
287
288 for s in StringTypes:
289   reserved_words[s + 'String'] = s + 'String'
290
291 tokens = static_tokens.values() \
292          + reserved_words.values() \
293          + ['BSTRING', 'HSTRING', 'QSTRING',
294             'UCASE_IDENT', 'LCASE_IDENT', 'CLASS_IDENT',
295             'REAL_NUMBER', 'NUMBER', 'PYQUOTE']
296
297
298 for (k, v) in static_tokens.items ():
299   __main__.__dict__['t_' + v] = k
300
301 # 11.10 Binary strings
302 def t_BSTRING (t):
303     r"'[01]*'B"
304     return t
305
306 # 11.12 Hexadecimal strings
307 def t_HSTRING (t):
308     r"'[0-9A-Fa-f]*'H"
309     return t
310
311 def t_QSTRING (t):
312     r'"([^"]|"")*"'
313     return t 
314
315 def t_UCASE_IDENT (t):
316     r"[A-Z](-[a-zA-Z0-9]|[a-zA-Z0-9])*" # can't end w/ '-'
317     if (is_class_ident(t.value)): t.type = 'CLASS_IDENT'
318     t.type = reserved_words.get(t.value, t.type)
319     return t
320
321 def t_LCASE_IDENT (t):
322     r"[a-z](-[a-zA-Z0-9]|[a-zA-Z0-9])*" # can't end w/ '-'
323     return t
324
325 # 11.9 Real numbers
326 def t_REAL_NUMBER (t):
327     r"[0-9]+\.[0-9]*(?!\.)"
328     return t
329
330 # 11.8 Numbers
331 def t_NUMBER (t):
332     r"0|([1-9][0-9]*)"
333     return t
334
335 # 11.6 Comments
336 pyquote_str = 'PYQUOTE'
337 def t_COMMENT(t):
338     r"--(-[^\-\n]|[^\-\n])*(--|\n|-\n|$|-$)"
339     if (t.value.find("\n") >= 0) : t.lexer.lineno += 1
340     if t.value[2:2+len (pyquote_str)] == pyquote_str:
341         t.value = t.value[2+len(pyquote_str):]
342         t.value = t.value.lstrip ()
343         t.type = pyquote_str
344         return t
345     return None
346
347 t_ignore = " \t\r"
348
349 def t_NEWLINE(t):
350     r'\n+'
351     t.lexer.lineno += t.value.count("\n")
352
353 def t_error(t):
354   global input_file
355   raise LexError(t, input_file)
356
357 # state 'braceignore'
358
359 def t_braceignore_lbrace(t):     
360   r'\{'
361   t.lexer.level +=1                
362
363 def t_braceignore_rbrace(t):
364   r'\}'
365   t.lexer.level -=1
366   # If closing brace, return token
367   if t.lexer.level == 0:
368     t.type = 'RBRACE'
369     return t
370
371 def t_braceignore_QSTRING (t):
372   r'"([^"]|"")*"'
373
374 def t_braceignore_COMMENT(t):
375   r"--(-[^\-\n]|[^\-\n])*(--|\n|-\n|$|-$)"
376   if (t.value.find("\n") >= 0) : t.lexer.lineno += 1
377
378 def t_braceignore_nonspace(t):
379    r'[^\s\{\}\"-]+|-(?!-)'
380
381 t_braceignore_ignore = " \t\r"
382
383 def t_braceignore_NEWLINE(t):
384   r'\n+'
385   t.lexer.lineno += t.value.count("\n")
386
387 def t_braceignore_error(t):
388   t.lexer.skip(1)
389
390 class Ctx:
391     def __init__ (self, defined_dict, indent = 0):
392         self.tags_def = 'EXPLICIT' # default = explicit
393         self.indent_lev = 0
394         self.assignments = {}
395         self.dependencies = {}
396         self.pyquotes = []
397         self.defined_dict = defined_dict
398         self.name_ctr = 0
399     def spaces (self):
400         return " " * (4 * self.indent_lev)
401     def indent (self):
402         self.indent_lev += 1
403     def outdent (self):
404         self.indent_lev -= 1
405         assert (self.indent_lev >= 0)
406     def register_assignment (self, ident, val, dependencies):
407         if self.assignments.has_key (ident):
408             raise "Duplicate assignment for " + ident
409         if self.defined_dict.has_key (ident):
410             raise "cross-module duplicates for " + ident
411         self.defined_dict [ident] = 1
412         self.assignments[ident] = val
413         self.dependencies [ident] = dependencies
414         return ""
415     #        return "#%s depends on %s" % (ident, str (dependencies))
416     def register_pyquote (self, val):
417         self.pyquotes.append (val)
418         return ""
419     def output_assignments (self):
420         already_output = {}
421         text_list = []
422         assign_keys = self.assignments.keys()
423         to_output_count = len (assign_keys)
424         while 1:
425             any_output = 0
426             for (ident, val) in self.assignments.iteritems ():
427                 if already_output.has_key (ident):
428                     continue
429                 ok = 1
430                 for d in self.dependencies [ident]:
431                     if (not already_output.has_key (d) and
432                         d in assign_keys):
433                         ok = 0
434                 if ok:
435                     text_list.append ("%s=%s" % (ident,
436                                                 self.assignments [ident]))
437                     already_output [ident] = 1
438                     any_output = 1
439                     to_output_count -= 1
440                     assert (to_output_count >= 0)
441             if not any_output:
442                 if to_output_count == 0:
443                     break
444                 # OK, we detected a cycle
445                 cycle_list = []
446                 for ident in self.assignments.iterkeys ():
447                     if not already_output.has_key (ident):
448                         depend_list = [d for d in self.dependencies[ident] if d in assign_keys]
449                         cycle_list.append ("%s(%s)" % (ident, ",".join (depend_list)))
450                         
451                 text_list.append ("# Cycle XXX " + ",".join (cycle_list))
452                 for (ident, val) in self.assignments.iteritems ():
453                     if not already_output.has_key (ident):
454                         text_list.append ("%s=%s" % (ident, self.assignments [ident]))
455                 break
456
457         return "\n".join (text_list)
458     def output_pyquotes (self):
459         return "\n".join (self.pyquotes)
460     def make_new_name (self):
461         self.name_ctr += 1
462         return "_compiler_generated_name_%d" % (self.name_ctr,)
463
464 #--- Flags for EXPORT, USER_DEFINED, NO_EMIT, MAKE_ENUM -------------------------------
465 EF_TYPE    = 0x0001
466 EF_VALS    = 0x0002
467 EF_ENUM    = 0x0004
468 EF_WS_VAR  = 0x0010
469 EF_EXTERN  = 0x0020
470 EF_NO_PROT = 0x0040
471 EF_NO_TYPE = 0x0080
472 EF_UCASE   = 0x0100
473 EF_TABLE   = 0x0400
474 EF_DEFINE  = 0x0800
475
476 #--- EthCtx -------------------------------------------------------------------
477 class EthCtx:
478   def __init__(self, conform, output, indent = 0):
479     self.conform = conform
480     self.output = output
481     self.conform.ectx = self
482     self.output.ectx = self
483
484   def encp(self):  # encoding protocol
485     encp = self.encoding
486     return encp
487
488   # Encoding
489   def Per(self): return self.encoding == 'per'
490   def Ber(self): return self.encoding == 'ber'
491   def Aligned(self): return self.aligned
492   def Unaligned(self): return not self.aligned
493   def Fld(self, tnm='*'): return self.fld_opt.get('*', False) or self.fld_opt.get(tnm, False) or self.Ber()
494   def Tag(self): return self.tag_opt # or self.Ber() - temporary comment out (experimental feature)
495   def NAPI(self): return False  # disable planned features
496
497   def module(self):  # current module name
498     return self.modules[-1][0]
499
500   def dbg(self, d):
501     if (self.dbgopt.find(d) >= 0):
502       return True
503     else:
504       return False
505
506   def eth_get_type_attr(self, type):
507     types = [type]
508     while (not self.type[type]['import'] 
509            and self.type[type]['val'].type == 'Type_Ref'):
510       type = self.type[type]['val'].val
511       types.append(type)
512     attr = {}
513     while len(types):
514       t = types.pop()
515       attr.update(self.type[t]['attr'])
516       attr.update(self.eth_type[self.type[t]['ethname']]['attr'])
517     return attr
518
519   #--- eth_reg_assign ---------------------------------------------------------
520   def eth_reg_assign(self, ident, val, virt=False):
521     #print "eth_reg_assign(ident='%s')" % (ident)
522     if self.assign.has_key(ident):
523       raise "Duplicate assignment for " + ident
524     self.assign[ident] = { 'val' : val , 'virt' : virt }
525     self.assign_ord.append(ident)
526
527   #--- eth_reg_vassign --------------------------------------------------------
528   def eth_reg_vassign(self, vassign):
529     ident = vassign.ident
530     #print "eth_reg_vassign(ident='%s')" % (ident)
531     if self.vassign.has_key(ident):
532       raise "Duplicate value assignment for " + ident
533     self.vassign[ident] = vassign
534     self.vassign_ord.append(ident)
535
536   #--- eth_import_type --------------------------------------------------------
537   def eth_import_type(self, ident, mod, proto):
538     #print "eth_import_type(ident='%s', mod='%s', prot='%s')" % (ident, mod, proto)
539     if self.type.has_key(ident):
540       #print "already defined import=%s, module=%s" % (str(self.type[ident]['import']), self.type[ident]['module'])
541       if not self.type[ident]['import'] and (self.type[ident]['module'] == mod) :
542         return  # OK - already defined
543       elif self.type[ident]['import'] and (self.type[ident]['import'] == mod) :
544         return  # OK - already imported
545       else:
546         raise "Duplicate type for " + ident
547     self.type[ident] = {'import'  : mod, 'proto' : proto,
548                         'ethname' : '' }
549     self.type[ident]['attr'] = { 'TYPE' : 'FT_NONE', 'DISPLAY' : 'BASE_NONE',
550                                  'STRINGS' : 'NULL', 'BITMASK' : '0' }
551     self.type[ident]['attr'].update(self.conform.use_item('TYPE_ATTR', ident))
552     self.type_imp.append(ident)
553
554   #--- eth_import_class --------------------------------------------------------
555   def eth_import_class(self, ident, mod, proto):
556     #print "eth_import_class(ident='%s', mod='%s', prot='%s')" % (ident, mod, proto)
557     if self.objectclass.has_key(ident):
558       #print "already defined import=%s, module=%s" % (str(self.objectclass[ident]['import']), self.objectclass[ident]['module'])
559       if not self.objectclass[ident]['import'] and (self.objectclass[ident]['module'] == mod) :
560         return  # OK - already defined
561       elif self.objectclass[ident]['import'] and (self.objectclass[ident]['import'] == mod) :
562         return  # OK - already imported
563       else:
564         raise "Duplicate object class for " + ident
565     self.objectclass[ident] = {'import'  : mod, 'proto' : proto,
566                         'ethname' : '' }
567     self.objectclass_imp.append(ident)
568
569   #--- eth_import_value -------------------------------------------------------
570   def eth_import_value(self, ident, mod, proto):
571     #print "eth_import_value(ident='%s', mod='%s', prot='%s')" % (ident, mod, prot)
572     if self.type.has_key(ident):
573       raise "Duplicate value for " + ident
574     self.value[ident] = {'import'  : mod, 'proto' : proto,
575                          'ethname' : ''}
576     self.value_imp.append(ident)
577
578   #--- eth_dep_add ------------------------------------------------------------
579   def eth_dep_add(self, type, dep):
580     if not self.type_dep.has_key(type): 
581       self.type_dep[type] = []
582     self.type_dep[type].append(dep)
583
584   #--- eth_reg_type -----------------------------------------------------------
585   def eth_reg_type(self, ident, val):
586     #print "eth_reg_type(ident='%s', type='%s')" % (ident, val.type)
587     if self.type.has_key(ident):
588       if self.type[ident]['import'] and (self.type[ident]['import'] == self.module()) :
589         # replace imported type
590         del self.type[ident]
591         self.type_imp.remove(ident)
592       else:
593         raise "Duplicate type for " + ident
594     self.type[ident] = { 'val' : val, 'import' : None }
595     self.type[ident]['module'] = self.module()
596     self.type[ident]['proto'] = self.proto
597     if len(ident.split('/')) > 1:
598       self.type[ident]['tname'] = val.eth_tname()
599     else:
600       self.type[ident]['tname'] = asn2c(ident)
601     self.type[ident]['export'] = self.conform.use_item('EXPORTS', ident)
602     self.type[ident]['enum'] = self.conform.use_item('MAKE_ENUM', ident)
603     self.type[ident]['user_def'] = self.conform.use_item('USER_DEFINED', ident)
604     self.type[ident]['no_emit'] = self.conform.use_item('NO_EMIT', ident)
605     self.type[ident]['tname'] = self.conform.use_item('TYPE_RENAME', ident, val_dflt=self.type[ident]['tname'])
606     self.type[ident]['ethname'] = ''
607     if val.type == 'Type_Ref':
608       self.type[ident]['attr'] = {}
609     else:
610       (ftype, display) = val.eth_ftype(self)
611       self.type[ident]['attr'] = { 'TYPE' : ftype, 'DISPLAY' : display,
612                                    'STRINGS' : val.eth_strings(), 'BITMASK' : '0' }
613     self.type[ident]['attr'].update(self.conform.use_item('TYPE_ATTR', ident))
614     self.type_ord.append(ident)
615
616   #--- eth_reg_value ----------------------------------------------------------
617   def eth_reg_value(self, ident, type, value):
618     #print "eth_reg_value(ident='%s')" % (ident)
619     if self.value.has_key(ident):
620       raise "Duplicate value for " + ident
621     self.value[ident] = { 'import' : None, 'proto' : self.proto,
622                           'type' : type, 'value' : value }
623     self.value[ident]['export'] = self.conform.use_item('EXPORTS', ident)
624     self.value[ident]['ethname'] = ''
625     self.value_ord.append(ident)
626
627   #--- eth_reg_field ----------------------------------------------------------
628   def eth_reg_field(self, ident, type, idx='', parent=None, impl=False, pdu=None):
629     #print "eth_reg_field(ident='%s', type='%s')" % (ident, type)
630     if self.field.has_key(ident):
631       raise "Duplicate field for " + ident
632     self.field[ident] = {'type' : type, 'idx' : idx, 'impl' : impl, 'pdu' : pdu,
633                          'modified' : '', 'attr' : {} , 'create_field' : False }
634     name = ident.split('/')[-1]
635     if len(ident.split('/')) > 1 and name == '_item':  # Sequnce/Set of type
636       self.field[ident]['attr']['NAME'] = '"Item"'
637       self.field[ident]['attr']['ABBREV'] = asn2c(ident.split('/')[-2] + name)
638     else:
639       self.field[ident]['attr']['NAME'] = '"%s"' % name
640       self.field[ident]['attr']['ABBREV'] = asn2c(name)
641     if self.conform.check_item('FIELD_ATTR', ident):
642       self.field[ident]['modified'] = '#' + str(id(self))
643       self.field[ident]['attr'].update(self.conform.use_item('FIELD_ATTR', ident))
644     if (pdu):
645       self.pdu_ord.append(ident)
646     else:
647       self.field_ord.append(ident)
648     if parent:
649       self.field[ident]['create_field'] = self.Fld(parent)
650       self.eth_dep_add(parent, type)
651
652   #--- eth_clean --------------------------------------------------------------
653   def eth_clean(self):
654     self.proto = self.proto_opt;
655     #--- ASN.1 tables ----------------
656     self.assign = {}
657     self.assign_ord = []
658     self.field = {}
659     self.pdu_ord = []
660     self.field_ord = []
661     self.type = {}
662     self.type_ord = []
663     self.type_imp = []
664     self.type_dep = {}
665     self.vassign = {}
666     self.vassign_ord = []
667     self.value = {}
668     self.value_ord = []
669     self.value_imp = []
670     self.objectclass = {}
671     self.objectclass_ord = []
672     self.objectclass_imp = []
673     #--- Modules ------------
674     self.modules = []
675     #--- types -------------------
676     self.eth_type = {}
677     self.eth_type_ord = []
678     self.eth_export_ord = []
679     self.eth_type_dupl = {}
680     self.named_bit = []
681     #--- value dependencies -------------------
682     self.value_dep = {}
683     #--- values -------------------
684     self.eth_value = {}
685     self.eth_value_ord = []
686     #--- fields -------------------------
687     self.eth_hf = {}
688     self.eth_hf_ord = []
689     self.eth_hfpdu_ord = []
690     self.eth_hf_dupl = {}
691     #--- type dependencies -------------------
692     self.eth_type_ord1 = []
693     self.eth_dep_cycle = []
694     self.dep_cycle_eth_type = {}
695     #--- value dependencies and export -------------------
696     self.eth_value_ord1 = []
697     self.eth_vexport_ord = []
698
699   #--- eth_prepare ------------------------------------------------------------
700   def eth_prepare(self):
701     self.eproto = asn2c(self.proto)
702
703     #--- dummy types/fields for PDU registration ---
704     nm = 'NULL'
705     if (self.conform.check_item('PDU', nm)):
706       self.eth_reg_type('_dummy/'+nm, NullType())
707       self.eth_reg_field(nm, '_dummy/'+nm, pdu=self.conform.use_item('PDU', nm))
708
709     #--- values -> named values -------------------
710     v_for_remove = []
711     for v in self.value_ord:
712       if (self.value[v]['type'].type == 'Type_Ref'):
713         tnm = self.value[v]['type'].val
714         if self.type.has_key(tnm) \
715            and not self.type[tnm]['import'] \
716            and (self.type[tnm]['val'].type == 'IntegerType'):
717           self.type[tnm]['val'].add_named_value(v, self.value[v]['value'])
718           v_for_remove.append(v)
719     for v in v_for_remove:
720       self.value_ord.remove(v)
721       del self.value[v]
722
723     #--- types -------------------
724     for t in self.type_imp:
725       nm = asn2c(t)
726       self.eth_type[nm] = { 'import' : self.type[t]['import'], 
727                             'proto' : asn2c(self.type[t]['proto']),
728                             'attr' : {}, 'create_field' : False, 'ref' : []}
729       self.eth_type[nm]['attr'].update(self.conform.use_item('ETYPE_ATTR', nm))
730       self.type[t]['ethname'] = nm
731     for t in self.type_ord:
732       nm = self.type[t]['tname']
733       if ((nm.find('#') >= 0) or 
734           ((len(t.split('/'))>1) and 
735            (self.conform.get_fn_presence(t) or self.conform.check_item('FN_PARS', t)) and 
736            not self.conform.check_item('TYPE_RENAME', t))):
737         if len(t.split('/')) == 2 and t.split('/')[1] == '_item':  # Sequnce of type at the 1st level
738           nm = t.split('/')[0] + t.split('/')[1]
739         elif t.split('/')[-1] == '_item':  # Sequnce/Set of type at next levels
740           nm = 'T_' + self.conform.use_item('FIELD_RENAME', '/'.join(t.split('/')[0:-1]), val_dflt=t.split('/')[-2]) + t.split('/')[-1]
741         elif t.split('/')[-1] == '_untag':  # Untagged type
742           nm = self.type['/'.join(t.split('/')[0:-1])]['ethname'] + '_U'
743         else:
744           nm = 'T_' + self.conform.use_item('FIELD_RENAME', t, val_dflt=t.split('/')[-1])
745         nm = asn2c(nm)
746         if self.eth_type.has_key(nm):
747           if self.eth_type_dupl.has_key(nm):
748             self.eth_type_dupl[nm].append(t)
749           else:
750             self.eth_type_dupl[nm] = [self.eth_type[nm]['ref'][0], t]
751           nm += str(len(self.eth_type_dupl[nm])-1)
752       if self.eth_type.has_key(nm):
753         self.eth_type[nm]['ref'].append(t)
754       else:
755         self.eth_type_ord.append(nm)
756         self.eth_type[nm] = { 'import' : None, 'proto' : self.eproto, 'export' : 0, 'enum' : 0,
757                               'user_def' : EF_TYPE|EF_VALS, 'no_emit' : EF_TYPE|EF_VALS, 
758                               'val' : self.type[t]['val'], 
759                               'attr' : {}, 
760                               'create_field' : False, 'ref' : [t]}
761       self.type[t]['ethname'] = nm
762       if (not self.eth_type[nm]['export'] and self.type[t]['export']):  # new export
763         self.eth_export_ord.append(nm)
764       self.eth_type[nm]['export'] |= self.type[t]['export']
765       self.eth_type[nm]['enum'] |= self.type[t]['enum']
766       self.eth_type[nm]['user_def'] &= self.type[t]['user_def']
767       self.eth_type[nm]['no_emit'] &= self.type[t]['no_emit']
768       if self.type[t]['attr'].get('STRINGS') == '$$':
769         self.eth_type[nm]['attr']['STRINGS'] = 'VALS(%s)' % (self.eth_vals_nm(nm))
770       self.eth_type[nm]['attr'].update(self.conform.use_item('ETYPE_ATTR', nm))
771     for t in self.eth_type_ord:
772       bits = self.eth_type[t]['val'].eth_named_bits()
773       if (bits):
774         for (val, id) in bits:
775           self.named_bit.append({'name' : id, 'val' : val,
776                                  'ethname' : 'hf_%s_%s_%s' % (self.eproto, t, asn2c(id)),
777                                  'ftype'   : 'FT_BOOLEAN', 'display' : '8',
778                                  'strings' : 'NULL',
779                                  'bitmask' : '0x'+('80','40','20','10','08','04','02','01')[val%8]})
780       if self.eth_type[t]['val'].eth_need_tree():
781         self.eth_type[t]['tree'] = "ett_%s_%s" % (self.eth_type[t]['proto'], t)
782       else:
783         self.eth_type[t]['tree'] = None
784
785     #--- value dependencies -------------------
786     for v in self.value_ord:
787       if isinstance (self.value[v]['value'], Value):
788         dep = self.value[v]['value'].get_dep()
789       else:
790         dep = self.value[v]['value']
791       if dep and self.value.has_key(dep):
792         self.value_dep.setdefault(v, []).append(dep)
793     
794     #--- exports all necessary values
795     for v in self.value_ord:
796       if not self.value[v]['export']: continue
797       deparr = self.value_dep.get(v, [])
798       while deparr:
799         d = deparr.pop()
800         if not self.value[d]['import']:
801           if not self.value[d]['export']:
802             self.value[d]['export'] = EF_TYPE
803             deparr.extend(self.value_dep.get(d, []))
804
805     #--- values -------------------
806     for v in self.value_imp:
807       nm = asn2c(v)
808       self.eth_value[nm] = { 'import' : self.value[v]['import'], 
809                              'proto' : asn2c(self.value[v]['proto']), 
810                              'ref' : []}
811       self.value[v]['ethname'] = nm
812     for v in self.value_ord:
813       nm = asn2c(v)
814       self.eth_value[nm] = { 'import' : None, 
815                              'proto' : asn2c(self.value[v]['proto']),
816                              'export' : self.value[v]['export'], 'ref' : [v] }
817       if isinstance (self.value[v]['value'], Value):
818         self.eth_value[nm]['value'] = self.value[v]['value'].to_str()
819       else:
820         self.eth_value[nm]['value'] = self.value[v]['value']
821       self.eth_value_ord.append(nm)
822       self.value[v]['ethname'] = nm
823
824     #--- fields -------------------------
825     for f in (self.pdu_ord + self.field_ord):
826       if len(f.split('/')) > 1 and f.split('/')[-1] == '_item':  # Sequnce/Set of type
827         nm = self.conform.use_item('FIELD_RENAME', '/'.join(f.split('/')[0:-1]), val_dflt=f.split('/')[-2]) + f.split('/')[-1]
828       else:
829         nm = f.split('/')[-1]
830       nm = self.conform.use_item('FIELD_RENAME', f, val_dflt=nm)
831       nm = asn2c(nm)
832       if (self.field[f]['pdu']): 
833         nm += '_PDU'
834       t = self.field[f]['type']
835       if self.type.has_key(t):
836         ethtype = self.type[t]['ethname']
837       else:  # undefined type
838         # dummy imported
839         print "Dummy imported: ", t
840         self.type[t] = {'import'  : 'xxx', 'proto' : 'xxx',
841                         'ethname' : t }
842         self.type[t]['attr'] = { 'TYPE' : 'FT_NONE', 'DISPLAY' : 'BASE_NONE',
843                                  'STRINGS' : 'NULL', 'BITMASK' : '0' }
844         self.eth_type[t] = { 'import' : 'xxx', 'proto' : 'xxx' , 'attr' : {}, 'create_field' : False, 'ref' : []}
845         ethtype = t
846       ethtypemod = ethtype + self.field[f]['modified']
847       if self.eth_hf.has_key(nm):
848         if self.eth_hf_dupl.has_key(nm):
849           if self.eth_hf_dupl[nm].has_key(ethtypemod):
850             nm = self.eth_hf_dupl[nm][ethtypemod]
851             self.eth_hf[nm]['create_field'] = self.eth_hf[nm]['create_field'] or self.field[f]['create_field']
852             self.eth_hf[nm]['ref'].append(f)
853             self.field[f]['ethname'] = nm
854             self.eth_type[ethtype]['create_field'] = self.eth_type[ethtype]['create_field'] or self.eth_hf[nm]['create_field']
855             continue
856           else:
857             nmx = nm + str(len(self.eth_hf_dupl[nm]))
858             self.eth_hf_dupl[nm][ethtype] = nmx
859             nm = nmx
860         else:
861           if (self.eth_hf[nm]['ethtype']+self.eth_hf[nm]['modified']) == ethtypemod:
862             self.eth_hf[nm]['create_field'] = self.eth_hf[nm]['create_field'] or self.field[f]['create_field']
863             self.eth_hf[nm]['ref'].append(f)
864             self.field[f]['ethname'] = nm
865             self.eth_type[ethtype]['create_field'] = self.eth_type[ethtype]['create_field'] or self.eth_hf[nm]['create_field']
866             continue
867           else:
868             self.eth_hf_dupl[nm] = {self.eth_hf[nm]['ethtype']+self.eth_hf[nm]['modified'] : nm, \
869                                     ethtypemod : nm+'1'}
870             nm += '1'
871       if (self.field[f]['pdu']):
872         self.eth_hfpdu_ord.append(nm)
873       else:
874         self.eth_hf_ord.append(nm)
875       fullname = "hf_%s_%s" % (self.eproto, nm)
876       attr = self.eth_get_type_attr(self.field[f]['type']).copy()
877       attr.update(self.field[f]['attr'])
878       if (self.NAPI() and attr.has_key('NAME')):
879         attr['NAME'] += self.field[f]['idx']
880       attr.update(self.conform.use_item('EFIELD_ATTR', nm))
881       self.eth_hf[nm] = {'fullname' : fullname, 'pdu' : self.field[f]['pdu'],
882                          'ethtype' : ethtype, 'modified' : self.field[f]['modified'],
883                          'attr' : attr.copy(), 
884                          'create_field' : self.field[f]['create_field'],
885                          'ref' : [f]}
886       self.field[f]['ethname'] = nm
887       self.eth_type[ethtype]['create_field'] = self.eth_type[ethtype]['create_field'] or self.eth_hf[nm]['create_field']
888     #--- type dependencies -------------------
889     x = {}  # already emitted
890     #print '# Dependency computation'
891     for t in self.type_ord:
892       if x.has_key(self.type[t]['ethname']):
893         #print 'Continue: %s : %s' % (t, self.type[t]['ethname'])
894         continue
895       stack = [t]
896       stackx = {t : self.type_dep.get(t, [])[:]}
897       #print 'Push: %s : %s' % (t, str(stackx[t]))
898       while stack:
899         if stackx[stack[-1]]:  # has dependencies
900           d = stackx[stack[-1]].pop(0)
901           if x.has_key(self.type[d]['ethname']) or self.type[d]['import']:
902             continue
903           if stackx.has_key(d):  # cyclic dependency
904             c = stack[:]
905             c.reverse()
906             c = [d] + c[0:c.index(d)+1]
907             c.reverse()
908             self.eth_dep_cycle.append(c)
909             #print 'Cyclic: %s ' % (' -> '.join(c))
910             continue
911           stack.append(d)
912           stackx[d] = self.type_dep.get(d, [])[:]
913           #print 'Push: %s : %s' % (d, str(stackx[d]))
914         else:
915           #print 'Pop: %s' % (stack[-1])
916           del stackx[stack[-1]]
917           e = self.type[stack.pop()]['ethname']
918           if x.has_key(e):
919             continue
920           #print 'Add: %s' % (e)
921           self.eth_type_ord1.append(e)
922           x[e] = True
923     i = 0
924     while i < len(self.eth_dep_cycle):
925       t = self.type[self.eth_dep_cycle[i][0]]['ethname']
926       self.dep_cycle_eth_type.setdefault(t, []).append(i)
927       i += 1
928
929     #--- value dependencies and export -------------------
930     for v in self.eth_value_ord:
931       if self.eth_value[v]['export']:
932         self.eth_vexport_ord.append(v)
933       else:
934         self.eth_value_ord1.append(v)
935
936   #--- eth_vals_nm ------------------------------------------------------------
937   def eth_vals_nm(self, tname):
938     out = ""
939     if (not self.eth_type[tname]['export'] & EF_NO_PROT):
940       out += "%s_" % (self.eproto)
941     out += "%s_vals" % (tname)
942     return out
943
944   #--- eth_vals ---------------------------------------------------------------
945   def eth_vals(self, tname, vals):
946     out = ""
947     has_enum = self.eth_type[tname]['enum'] & EF_ENUM
948     if (not self.eth_type[tname]['export'] & EF_VALS):
949       out += "static "
950     if (self.eth_type[tname]['export'] & EF_VALS) and (self.eth_type[tname]['export'] & EF_TABLE):
951       out += "static "
952     out += "const value_string %s[] = {\n" % (self.eth_vals_nm(tname))
953     for (val, id) in vals:
954       if (has_enum):
955         vval = self.eth_enum_item(tname, id)
956       else:
957         vval = val
958       out += '  { %3s, "%s" },\n' % (vval, id)
959     out += "  { 0, NULL }\n};\n"
960     return out
961
962   #--- eth_enum_prefix ------------------------------------------------------------
963   def eth_enum_prefix(self, tname):
964     out = ""
965     if (self.eth_type[tname]['export'] & EF_ENUM):
966       no_prot = self.eth_type[tname]['export'] & EF_NO_PROT
967     else:
968       no_prot = self.eth_type[tname]['enum'] & EF_NO_PROT
969     if (not no_prot):
970       out += self.eproto
971     if (not self.eth_type[tname]['enum'] & EF_NO_TYPE):
972       if (out): out += '_'
973       out += tname
974     if (self.eth_type[tname]['enum'] & EF_UCASE):
975       out = out.upper()
976     return out
977
978   #--- eth_enum_nm ------------------------------------------------------------
979   def eth_enum_nm(self, tname):
980     out = self.eth_enum_prefix(tname)
981     out += "_enum"
982     return out
983
984   #--- eth_enum_item ---------------------------------------------------------------
985   def eth_enum_item(self, tname, ident):
986     out = self.eth_enum_prefix(tname)
987     out += '_' + asn2c(ident)
988     if (self.eth_type[tname]['enum'] & EF_UCASE):
989       out = out.upper()
990     return out
991
992   #--- eth_enum ---------------------------------------------------------------
993   def eth_enum(self, tname, vals):
994     out = ""
995     if (self.eth_type[tname]['enum'] & EF_DEFINE):
996       out += "/* enumerated values for %s */\n" % (tname)
997       for (val, id) in vals:
998         out += '#define %-12s %3s\n' % (self.eth_enum_item(tname, id), val)
999     else:
1000       out += "typedef enum _%s {\n" % (self.eth_enum_nm(tname))
1001       for (val, id) in vals:
1002         out += '  %-12s %3s,\n' % (self.eth_enum_item(tname, id), val)
1003       out += "} %s;\n" % (self.eth_enum_nm(tname))
1004     return out
1005
1006   #--- eth_bits ---------------------------------------------------------------
1007   def eth_bits(self, tname, bits):
1008     out = ""
1009     out += "static const "
1010     out += "asn_namedbit %(TABLE)s[] = {\n"
1011     for (val, id) in bits:
1012       out += '  { %2d, &hf_%s_%s_%s, -1, -1, "%s", NULL },\n' % (val, self.eproto, tname, asn2c(id), id)
1013     out += "  { 0, NULL, 0, 0, NULL, NULL }\n};\n"
1014     return out
1015
1016   #--- eth_type_fn_h ----------------------------------------------------------
1017   def eth_type_fn_h(self, tname):
1018     out = ""
1019     if (not self.eth_type[tname]['export'] & EF_TYPE):
1020       out += "static "
1021     out += "int "
1022     if (self.Ber()):
1023       out += "dissect_%s_%s(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *tree _U_, int hf_index _U_)" % (self.eth_type[tname]['proto'], tname)
1024     elif (self.Per()):
1025       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)
1026     out += ";\n"
1027     return out
1028
1029   #--- eth_fn_call ------------------------------------------------------------
1030   def eth_fn_call(self, fname, ret=None, indent=2, par=None):
1031     out = indent * ' '
1032     if (ret):
1033       if (ret == 'return'):
1034         out += 'return '
1035       else:
1036         out += ret + ' = '
1037     out += fname + '('
1038     ind = len(out)
1039     for i in range(len(par)):
1040       if (i>0): out += ind * ' '
1041       out += ', '.join(par[i])
1042       if (i<(len(par)-1)): out += ',\n'
1043     out += ');\n'
1044     return out
1045
1046   #--- eth_type_fn_hdr --------------------------------------------------------
1047   def eth_type_fn_hdr(self, tname):
1048     out = '\n'
1049     if (not self.eth_type[tname]['export'] & EF_TYPE):
1050       out += "static "
1051     out += "int\n"
1052     if (self.Ber()):
1053       out += "dissect_%s_%s(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *tree _U_, int hf_index _U_) {\n" % (self.eth_type[tname]['proto'], tname)
1054     elif (self.Per()):
1055       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)
1056     if self.conform.get_fn_presence(tname):
1057       out += self.conform.get_fn_text(tname, 'FN_HDR')
1058     elif self.conform.get_fn_presence(self.eth_type[tname]['ref'][0]):
1059       out += self.conform.get_fn_text(self.eth_type[tname]['ref'][0], 'FN_HDR')
1060     return out
1061
1062   #--- eth_type_fn_ftr --------------------------------------------------------
1063   def eth_type_fn_ftr(self, tname):
1064     out = '\n'
1065     if self.conform.get_fn_presence(tname):
1066       out += self.conform.get_fn_text(tname, 'FN_FTR')
1067     elif self.conform.get_fn_presence(self.eth_type[tname]['ref'][0]):
1068       out += self.conform.get_fn_text(self.eth_type[tname]['ref'][0], 'FN_FTR')
1069     out += "  return offset;\n"
1070     out += "}\n"
1071     return out
1072
1073   #--- eth_type_fn_body -------------------------------------------------------
1074   def eth_type_fn_body(self, tname, body, pars=None):
1075     out = body
1076     if self.conform.get_fn_body_presence(tname):
1077       out = self.conform.get_fn_text(tname, 'FN_BODY')
1078     elif self.conform.get_fn_body_presence(self.eth_type[tname]['ref'][0]):
1079       out = self.conform.get_fn_text(self.eth_type[tname]['ref'][0], 'FN_BODY')
1080     if pars:
1081       try:
1082         out = out % pars
1083       except (TypeError):
1084         pass
1085     return out
1086
1087   #--- eth_output_hf ----------------------------------------------------------
1088   def eth_output_hf (self):
1089     if not len(self.eth_hf_ord) and not len(self.eth_hfpdu_ord) and not len(self.named_bit): return
1090     fx = self.output.file_open('hf')
1091     for f in (self.eth_hfpdu_ord + self.eth_hf_ord):
1092       fx.write("%-50s/* %s */\n" % ("static int %s = -1;  " % (self.eth_hf[f]['fullname']), self.eth_hf[f]['ethtype']))
1093     if (self.named_bit):
1094       fx.write('/* named bits */\n')
1095     for nb in self.named_bit:
1096       fx.write("static int %s = -1;\n" % (nb['ethname']))
1097     self.output.file_close(fx)
1098     
1099   #--- eth_output_hf_arr ------------------------------------------------------
1100   def eth_output_hf_arr (self):
1101     if not len(self.eth_hf_ord) and not len(self.eth_hfpdu_ord) and not len(self.named_bit): return
1102     fx = self.output.file_open('hfarr')
1103     for f in (self.eth_hfpdu_ord + self.eth_hf_ord):
1104       t = self.eth_hf[f]['ethtype']
1105       blurb = '"%s.%s"' % (self.eth_type[t]['proto'], t)
1106       attr = self.eth_hf[f]['attr'].copy()
1107       attr['ABBREV'] = '"%s.%s"' % (self.proto, attr['ABBREV'])
1108       if not attr.has_key('BLURB'):
1109         attr['BLURB'] = blurb
1110       fx.write('    { &%s,\n' % (self.eth_hf[f]['fullname']))
1111       fx.write('      { %(NAME)s, %(ABBREV)s,\n' % attr)
1112       fx.write('        %(TYPE)s, %(DISPLAY)s, %(STRINGS)s, %(BITMASK)s,\n' % attr)
1113       fx.write('        %(BLURB)s, HFILL }},\n' % attr)
1114     for nb in self.named_bit:
1115       blurb = ''
1116       fx.write('    { &%s,\n' % (nb['ethname']))
1117       fx.write('      { "%s", "%s.%s",\n' % (nb['name'], self.proto, nb['name']))
1118       fx.write('        %s, %s, %s, %s,\n' % (nb['ftype'], nb['display'], nb['strings'], nb['bitmask']))
1119       fx.write('        "%s", HFILL }},\n' % (blurb))
1120     self.output.file_close(fx)
1121
1122   #--- eth_output_ett ---------------------------------------------------------
1123   def eth_output_ett (self):
1124     fx = self.output.file_open('ett')
1125     fempty = True
1126     #fx.write("static gint ett_%s = -1;\n" % (self.eproto))
1127     for t in self.eth_type_ord:
1128       if self.eth_type[t]['tree']:
1129         fx.write("static gint %s = -1;\n" % (self.eth_type[t]['tree']))
1130         fempty = False
1131     self.output.file_close(fx, discard=fempty)
1132
1133   #--- eth_output_ett_arr -----------------------------------------------------
1134   def eth_output_ett_arr(self):
1135     fx = self.output.file_open('ettarr')
1136     fempty = True
1137     #fx.write("    &ett_%s,\n" % (self.eproto))
1138     for t in self.eth_type_ord:
1139       if self.eth_type[t]['tree']:
1140         fx.write("    &%s,\n" % (self.eth_type[t]['tree']))
1141         fempty = False
1142     self.output.file_close(fx, discard=fempty)
1143
1144   #--- eth_output_export ------------------------------------------------------
1145   def eth_output_export(self):
1146     if (not len(self.eth_export_ord)): return
1147     fx = self.output.file_open('exp', ext='h')
1148     for t in self.eth_export_ord:  # vals
1149       if (self.eth_type[t]['export'] & EF_ENUM) and self.eth_type[t]['val'].eth_has_enum(t, self):
1150         fx.write(self.eth_type[t]['val'].eth_type_enum(t, self))
1151       if (self.eth_type[t]['export'] & EF_VALS) and self.eth_type[t]['val'].eth_has_vals():
1152         if not self.eth_type[t]['export'] & EF_TABLE:
1153           if self.eth_type[t]['export'] & EF_WS_VAR:
1154             fx.write("WS_VAR_IMPORT ")
1155           else:
1156             fx.write("extern ")
1157           fx.write("const value_string %s[];\n" % (self.eth_vals_nm(t)))
1158         else:
1159           fx.write(self.eth_type[t]['val'].eth_type_vals(t, self))
1160     for t in self.eth_export_ord:  # functions
1161       if (self.eth_type[t]['export'] & EF_TYPE):
1162         if self.eth_type[t]['export'] & EF_EXTERN:
1163           fx.write("extern ")
1164         fx.write(self.eth_type_fn_h(t))
1165     self.output.file_close(fx)
1166
1167   #--- eth_output_expcnf ------------------------------------------------------
1168   def eth_output_expcnf(self):
1169     fx = self.output.file_open('exp', ext='cnf')
1170     fx.write('#.MODULE\n')
1171     maxw = 0
1172     for (m, p) in self.modules:
1173       if (len(m) > maxw): maxw = len(m)
1174     for (m, p) in self.modules:
1175       fx.write("%-*s  %s\n" % (maxw, m, p))
1176     fx.write('#.END\n\n')
1177     if self.Ber():
1178       fx.write('#.IMPORT_TAG\n')
1179       for t in self.eth_export_ord:  # tags
1180         if (self.eth_type[t]['export'] & EF_TYPE):
1181           fx.write('%-24s ' % self.eth_type[t]['ref'][0])
1182           fx.write('%s %s\n' % self.eth_type[t]['val'].GetTag(self))
1183       fx.write('#.END\n\n')
1184     fx.write('#.TYPE_ATTR\n')
1185     for t in self.eth_export_ord:  # attributes
1186       if (self.eth_type[t]['export'] & EF_TYPE):
1187         fx.write('%-24s ' % self.eth_type[t]['ref'][0])
1188         attr = self.eth_get_type_attr(self.eth_type[t]['ref'][0]).copy()
1189         fx.write('TYPE = %(TYPE)-9s  DISPLAY = %(DISPLAY)-9s  STRINGS = %(STRINGS)s  BITMASK = %(BITMASK)s\n' % attr)
1190     fx.write('#.END\n\n')
1191     self.output.file_close(fx, keep_anyway=True)
1192
1193   #--- eth_output_val ------------------------------------------------------
1194   def eth_output_val(self):
1195     if (not len(self.eth_value_ord1)): return
1196     fx = self.output.file_open('val', ext='h')
1197     for v in self.eth_value_ord1:
1198       fx.write("#define %-30s %s\n" % (v, self.eth_value[v]['value']))
1199     self.output.file_close(fx)
1200
1201   #--- eth_output_valexp ------------------------------------------------------
1202   def eth_output_valexp(self):
1203     if (not len(self.eth_vexport_ord)): return
1204     fx = self.output.file_open('valexp', ext='h')
1205     for v in self.eth_vexport_ord:
1206       fx.write("#define %-30s %s\n" % (v, self.eth_value[v]['value']))
1207     self.output.file_close(fx)
1208
1209   #--- eth_output_types -------------------------------------------------------
1210   def eth_output_types(self):
1211     def out_field(f):
1212       t = self.eth_hf[f]['ethtype']
1213       if (self.Ber()):
1214         x = {}
1215         for r in self.eth_hf[f]['ref']:
1216           x[self.field[r]['impl']] = self.field[r]['impl']
1217       else:
1218         x = {False : False}
1219       x = x.values()
1220       x.sort()
1221       out = ''
1222       for i in x:
1223         if (i):
1224           postfix = '_impl'
1225           impl = 'TRUE'
1226         else:
1227           postfix = ''
1228           impl = 'FALSE'
1229         if (self.Ber()):
1230           if (i): postfix = '_impl'; impl = 'TRUE'
1231           else:   postfix = '';      impl = 'FALSE'
1232           out += 'static int dissect_'+f+postfix+'(packet_info *pinfo _U_, proto_tree *tree _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_) {\n'
1233           par=((impl, 'tvb', 'offset', 'pinfo', 'tree', self.eth_hf[f]['fullname']),)
1234         else:
1235           out += 'static int dissect_'+f+'(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_) {\n'
1236           par=(('tvb', 'offset', 'actx', 'tree', self.eth_hf[f]['fullname']),)
1237         out += self.eth_fn_call('dissect_%s_%s' % (self.eth_type[t]['proto'], t), ret='return',
1238                                 par=par)
1239         out += '}\n'
1240       return out
1241     #end out_field()
1242     def out_pdu(f):
1243       t = self.eth_hf[f]['ethtype']
1244       is_new = self.eth_hf[f]['pdu']['new']
1245       impl = 'FALSE'
1246       out = 'static '
1247       if (is_new):
1248         out += 'int'
1249       else:
1250         out += 'void'
1251       out += ' dissect_'+f+'(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_) {\n'
1252       if (is_new):
1253         out += '  int offset = 0;\n'
1254         off_par = 'offset'
1255         ret_par = 'offset'
1256       else:
1257         off_par = '0'
1258         ret_par = None
1259       if (self.Per()):
1260         if (self.Aligned()):
1261           aligned = 'TRUE'
1262         else:
1263           aligned = 'FALSE'
1264         out += "  asn1_ctx_t asn1_ctx;\n"
1265         out += self.eth_fn_call('asn1_ctx_init', par=(('&asn1_ctx', 'ASN1_ENC_PER', aligned, 'pinfo'),))
1266       if (self.Ber()):
1267         par=((impl, 'tvb', off_par, 'pinfo', 'tree', self.eth_hf[f]['fullname']),)
1268       elif (self.Per()):
1269         par=(('tvb', off_par, '&asn1_ctx', 'tree', self.eth_hf[f]['fullname']),)
1270       else:
1271         par=((),)
1272       out += self.eth_fn_call('dissect_%s_%s' % (self.eth_type[t]['proto'], t), ret=ret_par, par=par)
1273       if (self.Per() and is_new):
1274         out += '  offset += 7; offset >>= 3;\n'
1275       if (is_new):
1276         out += '  return offset;\n'
1277       out += '}\n'
1278       return out
1279     #end out_pdu()
1280     fx = self.output.file_open('fn')
1281     pos = fx.tell()
1282     if self.eth_dep_cycle:
1283       fx.write('/*--- Cyclic dependencies ---*/\n\n')
1284       i = 0
1285       while i < len(self.eth_dep_cycle):
1286         t = self.type[self.eth_dep_cycle[i][0]]['ethname']
1287         if self.dep_cycle_eth_type[t][0] != i: i += 1; continue
1288         fx.write(''.join(map(lambda i: '/* %s */\n' % ' -> '.join(self.eth_dep_cycle[i]), self.dep_cycle_eth_type[t])))
1289         fx.write(self.eth_type_fn_h(t))
1290         if (self.Fld() or self.eth_type[t]['create_field']):
1291           fx.write('\n')
1292           for f in self.eth_hf_ord:
1293             if ((self.eth_hf[f]['ethtype'] == t) and (self.Fld() or self.eth_hf[f]['create_field'])):
1294               fx.write(out_field(f))
1295         fx.write('\n')
1296         i += 1
1297       fx.write('\n')
1298     if (self.Fld()):  # fields for imported types
1299       fx.write('/*--- Fields for imported types ---*/\n\n')
1300       for f in self.eth_hf_ord:
1301         if (self.eth_type[self.eth_hf[f]['ethtype']]['import']):
1302           fx.write(out_field(f))
1303       fx.write('\n')
1304     for t in self.eth_type_ord1:
1305       if self.eth_type[t]['import']:
1306         continue
1307       if self.eth_type[t]['val'].eth_has_enum(t, self) and not (self.eth_type[t]['export'] & EF_ENUM):
1308         fx.write(self.eth_type[t]['val'].eth_type_enum(t, self))
1309       if self.eth_type[t]['val'].eth_has_vals():
1310         if self.eth_type[t]['no_emit'] & EF_VALS:
1311           pass
1312         elif self.eth_type[t]['user_def'] & EF_VALS:
1313           fx.write("extern const value_string %s[];\n" % (self.eth_vals_nm(t)))
1314         elif (self.eth_type[t]['export'] & EF_VALS) and (self.eth_type[t]['export'] & EF_TABLE):
1315           pass
1316         else:
1317           fx.write(self.eth_type[t]['val'].eth_type_vals(t, self))
1318       if self.eth_type[t]['no_emit'] & EF_TYPE:
1319         pass
1320       elif self.eth_type[t]['user_def'] & EF_TYPE:
1321         fx.write(self.eth_type_fn_h(t))
1322       else:
1323         fx.write(self.eth_type[t]['val'].eth_type_fn(self.eth_type[t]['proto'], t, self))
1324       if ((self.Fld() or self.eth_type[t]['create_field']) and not self.dep_cycle_eth_type.has_key(t)):
1325         for f in self.eth_hf_ord:
1326           if ((self.eth_hf[f]['ethtype'] == t) and (self.Fld() or self.eth_hf[f]['create_field'])):
1327             fx.write(out_field(f))
1328       fx.write('\n')
1329     if (len(self.eth_hfpdu_ord)):
1330       fx.write('/*--- PDUs ---*/\n\n')
1331       for f in self.eth_hfpdu_ord:
1332         if (self.eth_hf[f]['pdu']):
1333           fx.write(out_pdu(f))
1334       fx.write('\n')
1335     fempty = pos == fx.tell()
1336     self.output.file_close(fx, discard=fempty)
1337
1338   #--- eth_output_dis_hnd -----------------------------------------------------
1339   def eth_output_dis_hnd(self):
1340     fx = self.output.file_open('dis-hnd')
1341     fempty = True
1342     for f in self.eth_hfpdu_ord:
1343       pdu = self.eth_hf[f]['pdu']
1344       if (pdu and pdu['reg'] and not pdu['hidden']):
1345         dis = self.proto
1346         if (pdu['reg'] != '.'):
1347           dis += '.' + pdu['reg']
1348         fx.write('static dissector_handle_t %s_handle;\n' % (asn2c(dis)))
1349         fempty = False
1350     fx.write('\n')
1351     self.output.file_close(fx, discard=fempty)
1352
1353   #--- eth_output_dis_reg -----------------------------------------------------
1354   def eth_output_dis_reg(self):
1355     fx = self.output.file_open('dis-reg')
1356     fempty = True
1357     for f in self.eth_hfpdu_ord:
1358       pdu = self.eth_hf[f]['pdu']
1359       if (pdu and pdu['reg']):
1360         new_prefix = ''
1361         if (pdu['new']): new_prefix = 'new_'
1362         dis = self.proto
1363         if (pdu['reg'] != '.'): dis += '.' + pdu['reg']
1364         fx.write('  %sregister_dissector("%s", dissect_%s, proto_%s);\n' % (new_prefix, dis, f, self.eproto))
1365         if (not pdu['hidden']):
1366           fx.write('  %s_handle = find_dissector("%s");\n' % (asn2c(dis), dis))
1367         fempty = False
1368     fx.write('\n')
1369     self.output.file_close(fx, discard=fempty)
1370
1371   #--- eth_output_dis_tab -----------------------------------------------------
1372   def eth_output_dis_tab(self):
1373     fx = self.output.file_open('dis-tab')
1374     fempty = True
1375     for k in self.conform.get_order('REGISTER'):
1376       reg = self.conform.use_item('REGISTER', k)
1377       if not self.field.has_key(reg['pdu']): continue
1378       f = self.field[reg['pdu']]['ethname']
1379       pdu = self.eth_hf[f]['pdu'] 
1380       new_prefix = ''
1381       if (pdu['new']): new_prefix = 'new_'
1382       if (reg['rtype'] in ('NUM', 'STR')):
1383         rstr = ''
1384         if (reg['rtype'] == 'STR'): rstr = '_string'
1385         if (pdu['reg']):
1386           dis = self.proto
1387           if (pdu['reg'] != '.'): dis += '.' + pdu['reg']
1388           if  (not pdu['hidden']):
1389             hnd = '%s_handle' % (asn2c(dis))
1390           else:
1391             hnd = 'find_dissector("%s")' % (dis)
1392         else:
1393           hnd = '%screate_dissector_handle(dissect_%s, proto_%s)' % (new_prefix, f, self.eproto)
1394         fx.write('  dissector_add%s("%s", %s, %s);\n' % (rstr, reg['rtable'], reg['rport'], hnd))
1395       elif (reg['rtype'] in ('BER', 'PER')):
1396         fx.write('  %sregister_%s_oid_dissector(%s, dissect_%s, proto_%s, %s);\n' % (new_prefix, reg['rtype'].lower(), reg['roid'], f, self.eproto, reg['roidname']))
1397       fempty = False
1398     fx.write('\n')
1399     self.output.file_close(fx, discard=fempty)
1400
1401   #--- dupl_report -----------------------------------------------------
1402   def dupl_report(self):
1403     # types
1404     tmplist = self.eth_type_dupl.keys()
1405     tmplist.sort()
1406     for t in tmplist:
1407       msg = "The same type names for different types. Explicit type renaming is recommended.\n"
1408       msg += t + "\n"
1409       x = ''
1410       for tt in self.eth_type_dupl[t]:
1411         msg += " %-20s %s\n" % (t+str(x), tt)
1412         if not x: x = 1
1413         else: x += 1
1414       warnings.warn_explicit(msg, UserWarning, '', '')
1415     # fields
1416     tmplist = self.eth_hf_dupl.keys()
1417     tmplist.sort()
1418     for f in tmplist:
1419       msg = "The same field names for different types. Explicit field renaming is recommended.\n"
1420       msg += f + "\n"
1421       for tt in self.eth_hf_dupl[f].keys():
1422         msg += " %-20s %-20s " % (self.eth_hf_dupl[f][tt], tt)
1423         msg += ", ".join(self.eth_hf[self.eth_hf_dupl[f][tt]]['ref'])
1424         msg += "\n"
1425       warnings.warn_explicit(msg, UserWarning, '', '')
1426
1427   #--- eth_do_output ------------------------------------------------------------
1428   def eth_do_output(self):
1429     if self.dbg('a'):
1430       print "\n# Assignments"
1431       for a in self.assign_ord:
1432         v = ' '
1433         if (self.assign[a]['virt']): v = '*'
1434         print v, a
1435       print "\n# Value assignments"
1436       print "\n".join(self.vassign_ord)
1437     if self.dbg('t'):
1438       print "\n# Imported Types"
1439       print "%-40s %-24s %-24s" % ("ASN.1 name", "Module", "Protocol")
1440       print "-" * 100
1441       for t in self.type_imp:
1442         print "%-40s %-24s %-24s" % (t, self.type[t]['import'], self.type[t]['proto'])
1443       print "\n# Imported Values"
1444       print "%-40s %-24s %-24s" % ("ASN.1 name", "Module", "Protocol")
1445       print "-" * 100
1446       for t in self.value_imp:
1447         print "%-40s %-24s %-24s" % (t, self.value[t]['import'], self.value[t]['proto'])
1448       print "\n# Imported Object Classes"
1449       print "%-40s %-24s %-24s" % ("ASN.1 name", "Module", "Protocol")
1450       print "-" * 100
1451       for t in self.objectclass_imp:
1452         print "%-40s %-24s %-24s" % (t, self.objectclass[t]['import'], self.objectclass[t]['proto'])
1453       print "\n# Exported Types"
1454       print "%-31s %s" % ("Wireshark type", "Export Flag")
1455       print "-" * 100
1456       for t in self.eth_export_ord:
1457         print "%-31s 0x%02X" % (t, self.eth_type[t]['export'])
1458       print "\n# Exported Values"
1459       print "%-40s %s" % ("Wireshark name", "Value")
1460       print "-" * 100
1461       for v in self.eth_vexport_ord:
1462         print "%-40s %s" % (v, self.eth_value[v]['value'])
1463       print "\n# ASN.1 Types"
1464       print "%-49s %-24s %-24s" % ("ASN.1 unique name", "'tname'", "Wireshark type")
1465       print "-" * 100
1466       for t in self.type_ord:
1467         print "%-49s %-24s %-24s" % (t, self.type[t]['tname'], self.type[t]['ethname'])
1468       print "\n# Wireshark Types"
1469       print "Wireshark type                   References (ASN.1 types)"
1470       print "-" * 100
1471       for t in self.eth_type_ord:
1472         print "%-31s %d" % (t, len(self.eth_type[t]['ref'])),
1473         print ', '.join(self.eth_type[t]['ref'])
1474       print "\n# ASN.1 Values"
1475       print "%-40s %-18s %s" % ("ASN.1 unique name", "Type", "Value")
1476       print "-" * 100
1477       for v in self.value_ord:
1478         if isinstance (self.value[v]['value'], Value):
1479           print "%-40s %-18s %s" % (v, self.value[v]['type'].eth_tname(), self.value[v]['value'].to_str())
1480         else:
1481           print "%-40s %-18s %s" % (v, self.value[v]['type'].eth_tname(), self.value[v]['value'])
1482       print "\n# Wireshark Values"
1483       print "%-40s %s" % ("Wireshark name", "Value")
1484       print "-" * 100
1485       for v in self.eth_value_ord:
1486         print "%-40s %s" % (v, self.eth_value[v]['value'])
1487       print "\n# ASN.1 Fields"
1488       print "ASN.1 unique name                        Wireshark name        ASN.1 type"
1489       print "-" * 100
1490       for f in (self.pdu_ord + self.field_ord):
1491         print "%-40s %-20s %s" % (f, self.field[f]['ethname'], self.field[f]['type'])
1492       print "\n# Wireshark Fields"
1493       print "Wireshark name                  Wireshark type        References (ASN.1 fields)"
1494       print "-" * 100
1495       for f in (self.eth_hfpdu_ord + self.eth_hf_ord):
1496         print "%-30s %-20s %s" % (f, self.eth_hf[f]['ethtype'], len(self.eth_hf[f]['ref'])),
1497         print ', '.join(self.eth_hf[f]['ref'])
1498       #print "\n# Order after dependencies"
1499       #print '\n'.join(self.eth_type_ord1)
1500       print "\n# Cyclic dependencies"
1501       for c in self.eth_dep_cycle:
1502         print ' -> '.join(c)
1503     self.dupl_report()
1504     self.output.outnm = self.outnm_opt
1505     if (not self.output.outnm):
1506       self.output.outnm = self.proto
1507     self.eth_output_hf()
1508     self.eth_output_ett()
1509     self.eth_output_types()
1510     self.eth_output_hf_arr()
1511     self.eth_output_ett_arr()
1512     self.eth_output_export()
1513     if self.expcnf:
1514       self.eth_output_expcnf()
1515     self.eth_output_val()
1516     self.eth_output_valexp()
1517     self.eth_output_dis_hnd()
1518     self.eth_output_dis_reg()
1519     self.eth_output_dis_tab()
1520
1521 #--- EthCnf -------------------------------------------------------------------
1522 class EthCnf:
1523   def __init__(self):
1524     self.ectx = None
1525     self.tblcfg = {}
1526     self.table = {}
1527     self.order = {}
1528     self.fn = {}
1529     self.suppress_line = False
1530     self.include_path = []
1531     #                                   Value name             Default value       Duplicity check   Usage check
1532     self.tblcfg['EXPORTS']         = { 'val_nm' : 'flag',     'val_dflt' : 0,     'chk_dup' : True, 'chk_use' : True }
1533     self.tblcfg['MAKE_ENUM']       = { 'val_nm' : 'flag',     'val_dflt' : 0,     'chk_dup' : True, 'chk_use' : True }
1534     self.tblcfg['PDU']             = { 'val_nm' : 'attr',     'val_dflt' : None,  'chk_dup' : True, 'chk_use' : True }
1535     self.tblcfg['REGISTER']        = { 'val_nm' : 'attr',     'val_dflt' : None,  'chk_dup' : True, 'chk_use' : True }
1536     self.tblcfg['USER_DEFINED']    = { 'val_nm' : 'flag',     'val_dflt' : 0,     'chk_dup' : True, 'chk_use' : True }
1537     self.tblcfg['NO_EMIT']         = { 'val_nm' : 'flag',     'val_dflt' : 0,     'chk_dup' : True, 'chk_use' : True }
1538     self.tblcfg['MODULE']          = { 'val_nm' : 'proto',    'val_dflt' : None,  'chk_dup' : True, 'chk_use' : False }
1539     self.tblcfg['OMIT_ASSIGNMENT'] = { 'val_nm' : 'omit',     'val_dflt' : False, 'chk_dup' : True, 'chk_use' : True }
1540     self.tblcfg['VIRTUAL_ASSGN']   = { 'val_nm' : 'name',     'val_dflt' : None,  'chk_dup' : True, 'chk_use' : True }
1541     self.tblcfg['SET_TYPE']        = { 'val_nm' : 'type',     'val_dflt' : None,  'chk_dup' : True, 'chk_use' : True }
1542     self.tblcfg['TYPE_RENAME']     = { 'val_nm' : 'eth_name', 'val_dflt' : None,  'chk_dup' : True, 'chk_use' : True }
1543     self.tblcfg['FIELD_RENAME']    = { 'val_nm' : 'eth_name', 'val_dflt' : None,  'chk_dup' : True, 'chk_use' : True }
1544     self.tblcfg['IMPORT_TAG']      = { 'val_nm' : 'ttag',     'val_dflt' : (),    'chk_dup' : True, 'chk_use' : False }
1545     self.tblcfg['FN_PARS']         = { 'val_nm' : 'pars',     'val_dflt' : {},    'chk_dup' : True, 'chk_use' : True }
1546     self.tblcfg['TYPE_ATTR']       = { 'val_nm' : 'attr',     'val_dflt' : {},    'chk_dup' : True, 'chk_use' : False }
1547     self.tblcfg['ETYPE_ATTR']      = { 'val_nm' : 'attr',     'val_dflt' : {},    'chk_dup' : True, 'chk_use' : False }
1548     self.tblcfg['FIELD_ATTR']      = { 'val_nm' : 'attr',     'val_dflt' : {},    'chk_dup' : True, 'chk_use' : True }
1549     self.tblcfg['EFIELD_ATTR']     = { 'val_nm' : 'attr',     'val_dflt' : {},    'chk_dup' : True, 'chk_use' : True }
1550
1551
1552     for k in self.tblcfg.keys() :
1553       self.table[k] = {}
1554       self.order[k] = []
1555
1556   def add_item(self, table, key, fn, lineno, **kw):
1557     if self.tblcfg[table]['chk_dup'] and self.table[table].has_key(key):
1558       warnings.warn_explicit("Duplicated %s for %s. Previous one is at %s:%d" % 
1559                              (table, key, self.table[table][key]['fn'], self.table[table][key]['lineno']), 
1560                              UserWarning, fn, lineno)
1561       return
1562     self.table[table][key] = {'fn' : fn, 'lineno' : lineno, 'used' : False}
1563     self.table[table][key].update(kw)
1564     self.order[table].append(key)
1565
1566   def update_item(self, table, key, fn, lineno, **kw):
1567     if not self.table[table].has_key(key):
1568       self.table[table][key] = {'fn' : fn, 'lineno' : lineno, 'used' : False}
1569       self.order[table].append(key)
1570     self.table[table][key][self.tblcfg[table]['val_nm']].update(kw[self.tblcfg[table]['val_nm']])
1571
1572   def get_order(self, table):
1573     return self.order[table]
1574
1575   def check_item(self, table, key):
1576     return self.table[table].has_key(key)
1577
1578   def check_item_value(self, table, key, **kw):
1579     return self.table[table].has_key(key) and self.table[table][key].has_key(kw.get('val_nm', self.tblcfg[table]['val_nm']))
1580
1581   def use_item(self, table, key, **kw):
1582     vdflt = kw.get('val_dflt', self.tblcfg[table]['val_dflt'])
1583     if not self.table[table].has_key(key): return vdflt
1584     vname = kw.get('val_nm', self.tblcfg[table]['val_nm'])
1585     #print "use_item() - set used for %s %s" % (table, key)
1586     self.table[table][key]['used'] = True
1587     return self.table[table][key].get(vname, vdflt)
1588
1589   def add_fn_line(self, name, ctx, line, fn, lineno):
1590     if not self.fn.has_key(name):
1591       self.fn[name] = {'FN_HDR' : None, 'FN_FTR' : None, 'FN_BODY' : None}
1592     if (self.fn[name][ctx]):
1593       self.fn[name][ctx]['text'] += line
1594     else:
1595       self.fn[name][ctx] = {'text' : line, 'used' : False,
1596                              'fn' : fn, 'lineno' : lineno}
1597   def get_fn_presence(self, name):
1598     #print "get_fn_presence('%s'):%s" % (name, str(self.fn.has_key(name)))
1599     #if self.fn.has_key(name): print self.fn[name]
1600     return self.fn.has_key(name)
1601   def get_fn_body_presence(self, name):
1602     return self.fn.has_key(name) and self.fn[name]['FN_BODY']
1603   def get_fn_text(self, name, ctx):
1604     if (not self.fn.has_key(name)):
1605       return '';
1606     if (not self.fn[name][ctx]):
1607       return '';
1608     self.fn[name][ctx]['used'] = True
1609     out = self.fn[name][ctx]['text']
1610     if (not self.suppress_line): 
1611       out = '#line %u "%s"\n%s\n' % (self.fn[name][ctx]['lineno'], self.fn[name][ctx]['fn'], out);
1612     return out
1613
1614   def add_pdu(self, par, is_new, fn, lineno):
1615     #print "add_pdu(par=%s, %s, %d)" % (str(par), fn, lineno)
1616     (reg, hidden) = (None, False)
1617     if (len(par) > 1): reg = par[1]
1618     if (reg and reg[0]=='@'): (reg, hidden) = (reg[1:], True)
1619     attr = {'new' : is_new, 'reg' : reg, 'hidden' : hidden}
1620     self.add_item('PDU', par[0], attr=attr, fn=fn, lineno=lineno)
1621     return
1622
1623   def add_register(self, pdu, par, fn, lineno):
1624     #print "add_register(pdu=%s, par=%s, %s, %d)" % (pdu, str(par), fn, lineno)
1625     if (par[0] in ('N', 'NUM')):   rtype = 'NUM'; (pmin, pmax) = (2, 2)
1626     elif (par[0] in ('S', 'STR')): rtype = 'STR'; (pmin, pmax) = (2, 2)
1627     elif (par[0] in ('B', 'BER')): rtype = 'BER'; (pmin, pmax) = (1, 2)
1628     elif (par[0] in ('P', 'PER')): rtype = 'PER'; (pmin, pmax) = (1, 2)
1629     else: warnings.warn_explicit("Unknown registration type '%s'" % (par[2]), UserWarning, fn, lineno); return
1630     if ((len(par)-1) < pmin):
1631       warnings.warn_explicit("Too few parameters for %s registration type. At least %d parameters are required" % (rtype, pmin), UserWarning, fn, lineno)
1632       return
1633     if ((len(par)-1) > pmax):
1634       warnings.warn_explicit("Too many parameters for %s registration type. Only %d parameters are allowed" % (rtype, pmax), UserWarning, fn, lineno)
1635     attr = {'pdu' : pdu, 'rtype' : rtype}
1636     if (rtype in ('NUM', 'STR')): 
1637       attr['rtable'] = par[1]
1638       attr['rport'] = par[2]
1639       rkey = '/'.join([rtype, attr['rtable'], attr['rport']])
1640     elif (rtype in ('BER', 'PER')): 
1641       attr['roid'] = par[1]
1642       attr['roidname'] = '""'
1643       if (len(par)>=3): attr['roidname'] = par[2]
1644       rkey = '/'.join([rtype, attr['roid']])
1645     self.add_item('REGISTER', rkey, attr=attr, fn=fn, lineno=lineno)
1646
1647   def check_par(self, par, pmin, pmax, fn, lineno):
1648     for i in range(len(par)):
1649       if par[i] == '-':
1650         par[i] = None
1651         continue
1652       if par[i][0] == '#':
1653         par[i:] = []
1654         break
1655     if len(par) < pmin:
1656       warnings.warn_explicit("Too few parameters. At least %d parameters are required" % (pmin), UserWarning, fn, lineno)
1657       return None
1658     if (pmax >= 0) and (len(par) > pmax):
1659       warnings.warn_explicit("Too many parameters. Only %d parameters are allowed" % (pmax), UserWarning, fn, lineno)
1660       return par[0:pmax]
1661     return par
1662
1663   def read(self, fn):
1664     def get_par(line, pmin, pmax, fn, lineno):
1665       par = line.split(None, pmax)
1666       par = self.check_par(par, pmin, pmax, fn, lineno)
1667       return par
1668
1669     def get_par_nm(line, pmin, pmax, fn, lineno):
1670       if pmax:
1671         par = line.split(None, pmax)
1672       else:
1673         par = [line,]
1674       for i in range(len(par)):
1675         if par[i][0] == '#':
1676           par[i:] = []
1677           break
1678       if len(par) < pmin:
1679         warnings.warn_explicit("Too few parameters. At least %d parameters are required" % (pmin), UserWarning, fn, lineno)
1680         return None
1681       if len(par) > pmax:
1682         nmpar = par[pmax]
1683       else:
1684         nmpar = ''
1685       nmpars = {}
1686       nmpar_first = re.compile(r'^\s*(?P<attr>[_A-Z][_A-Z0-9]*)\s*=\s*')
1687       nmpar_next = re.compile(r'\s+(?P<attr>[_A-Z][_A-Z0-9]*)\s*=\s*')
1688       nmpar_end = re.compile(r'\s*$')
1689       result = nmpar_first.search(nmpar)
1690       pos = 0
1691       while result:
1692         k = result.group('attr')
1693         pos = result.end()
1694         result = nmpar_next.search(nmpar, pos)
1695         p1 = pos
1696         if result:
1697           p2 = result.start()
1698         else:
1699           p2 = nmpar_end.search(nmpar, pos).start()
1700         v = nmpar[p1:p2]
1701         nmpars[k] = v
1702       if len(par) > pmax:
1703         par[pmax] = nmpars
1704       return par
1705
1706     f = open(fn, "r")
1707     directive = re.compile(r'^\s*#\.(?P<name>[A-Z_]+)\s+')
1708     comment = re.compile(r'^\s*#[^.]')
1709     empty = re.compile(r'^\s*$')
1710     lineno = 0
1711     ctx = None
1712     name = ''
1713     default_flags = 0x00
1714     stack = []
1715     while 1:
1716       line = f.readline()
1717       lineno += 1
1718       if not line:
1719         f.close()
1720         if stack:
1721           frec = stack.pop()
1722           fn, f, lineno = frec['fn'], frec['f'], frec['lineno']
1723           continue
1724         else: 
1725           break
1726       if comment.search(line): continue
1727       result = directive.search(line)
1728       if result:  # directive
1729         if result.group('name') == 'OPT':
1730           ctx = result.group('name')
1731           par = get_par(line[result.end():], 0, -1, fn=fn, lineno=lineno)
1732           if not par: continue
1733           self.set_opt(par[0], par[1:], fn, lineno)
1734           ctx = None
1735         elif result.group('name') in ('PDU', 'PDU_NEW', 'REGISTER', 'REGISTER_NEW', 
1736                                     'MODULE', 'MODULE_IMPORT', 
1737                                     'OMIT_ASSIGNMENT', 'VIRTUAL_ASSGN', 'SET_TYPE',
1738                                     'TYPE_RENAME', 'FIELD_RENAME', 'TF_RENAME', 'IMPORT_TAG',
1739                                     'TYPE_ATTR', 'ETYPE_ATTR', 'FIELD_ATTR', 'EFIELD_ATTR'):
1740           ctx = result.group('name')
1741         elif result.group('name') in ('EXPORTS', 'USER_DEFINED', 'NO_EMIT'):
1742           ctx = result.group('name')
1743           default_flags = EF_TYPE|EF_VALS
1744           if ctx == 'EXPORTS':
1745             par = get_par(line[result.end():], 0, 5, fn=fn, lineno=lineno)
1746           else:
1747             par = get_par(line[result.end():], 0, 1, fn=fn, lineno=lineno)
1748           if not par: continue
1749           p = 1
1750           if (par[0] == 'WITH_VALS'):      default_flags |= EF_TYPE|EF_VALS
1751           elif (par[0] == 'WITHOUT_VALS'): default_flags |= EF_TYPE; default_flags &= ~EF_TYPE
1752           elif (par[0] == 'ONLY_VALS'):    default_flags &= ~EF_TYPE; default_flags |= EF_VALS
1753           elif (ctx == 'EXPORTS'): p = 0
1754           else: warnings.warn_explicit("Unknown parameter value '%s'" % (par[0]), UserWarning, fn, lineno)
1755           for i in range(p, len(par)):
1756             if (par[i] == 'ONLY_ENUM'):   default_flags &= ~(EF_TYPE|EF_VALS); default_flags |= EF_ENUM
1757             elif (par[i] == 'WITH_ENUM'): default_flags |= EF_ENUM
1758             elif (par[i] == 'VALS_WITH_TABLE'):  default_flags |= EF_TABLE
1759             elif (par[i] == 'WS_VAR'):    default_flags |= EF_WS_VAR
1760             elif (par[i] == 'EXTERN'):    default_flags |= EF_EXTERN
1761             elif (par[i] == 'NO_PROT_PREFIX'): default_flags |= EF_NO_PROT
1762             else: warnings.warn_explicit("Unknown parameter value '%s'" % (par[i]), UserWarning, fn, lineno)
1763         elif result.group('name') in ('MAKE_ENUM', 'MAKE_DEFINES'):
1764           ctx = result.group('name')
1765           default_flags = EF_ENUM
1766           if ctx == 'MAKE_ENUM': default_flags |= EF_NO_PROT
1767           if ctx == 'MAKE_DEFINES': default_flags |= EF_DEFINE|EF_UCASE
1768           par = get_par(line[result.end():], 0, 3, fn=fn, lineno=lineno)
1769           for i in range(0, len(par)):
1770             if (par[i] == 'NO_PROT_PREFIX'):   default_flags |= EF_NO_PROT
1771             elif (par[i] == 'NO_TYPE_PREFIX'): default_flags |= EF_NO_TYPE
1772             elif (par[i] == 'UPPER_CASE'):     default_flags |= EF_UCASE
1773             elif (par[i] == 'NO_UPPER_CASE'):  default_flags &= ~EF_UCASE
1774             else: warnings.warn_explicit("Unknown parameter value '%s'" % (par[i]), UserWarning, fn, lineno)
1775         elif result.group('name') in ('FN_HDR', 'FN_FTR'):
1776           par = get_par(line[result.end():], 1, 1, fn=fn, lineno=lineno)
1777           if not par: continue
1778           ctx = result.group('name')
1779           name = par[0]
1780         elif result.group('name') == 'FN_BODY':
1781           par = get_par_nm(line[result.end():], 1, 1, fn=fn, lineno=lineno)
1782           if not par: continue
1783           ctx = result.group('name')
1784           name = par[0]
1785           if len(par) > 1:
1786             self.add_item('FN_PARS', name, pars=par[1], fn=fn, lineno=lineno)
1787         elif result.group('name') == 'FN_PARS':
1788           par = get_par_nm(line[result.end():], 0, 1, fn=fn, lineno=lineno)
1789           ctx = result.group('name')
1790           if not par:
1791             name = None
1792           elif len(par) == 1:
1793             name = par[0]
1794             self.add_item(ctx, name, pars={}, fn=fn, lineno=lineno)
1795           elif len(par) > 1:
1796             self.add_item(ctx, par[0], pars=par[1], fn=fn, lineno=lineno)
1797             ctx = None
1798         elif result.group('name') == 'CLASS':
1799           par = get_par(line[result.end():], 1, 1, fn=fn, lineno=lineno)
1800           if not par: continue
1801           ctx = result.group('name')
1802           name = par[0]
1803           add_class_ident(name)
1804           if not name.isupper():
1805             warnings.warn_explicit("No lower-case letters shall be included in information object class name (%s)" % (name),
1806                                     UserWarning, fn, lineno)
1807         elif result.group('name') == 'INCLUDE':
1808           par = get_par(line[result.end():], 1, 1, fn=fn, lineno=lineno)
1809           if not par: 
1810             warnings.warn_explicit("INCLUDE requires parameter", UserWarning, fn, lineno)
1811             continue
1812           fname = par[0]
1813           #print "Try include: %s" % (fname)
1814           if (not os.path.exists(fname)):
1815             fname = os.path.join(os.path.split(fn)[0], par[0])
1816           #print "Try include: %s" % (fname)
1817           i = 0
1818           while not os.path.exists(fname) and (i < len(self.include_path)):
1819             fname = os.path.join(self.include_path[i], par[0])
1820             #print "Try include: %s" % (fname)
1821             i += 1
1822           if (not os.path.exists(fname)):
1823             fname = par[0]
1824           fnew = open(fname, "r")
1825           stack.append({'fn' : fn, 'f' : f, 'lineno' : lineno})
1826           fn, f, lineno = par[0], fnew, 0
1827         elif result.group('name') == 'END':
1828           ctx = None
1829         else:
1830           warnings.warn_explicit("Unknown directive '%s'" % (result.group('name')), UserWarning, fn, lineno)
1831         continue
1832       if not ctx:
1833         if not empty.match(line):
1834           warnings.warn_explicit("Non-empty line in empty context", UserWarning, fn, lineno)
1835       elif ctx == 'OPT':
1836         if empty.match(line): continue
1837         par = get_par(line, 1, -1, fn=fn, lineno=lineno)
1838         if not par: continue
1839         self.set_opt(par[0], par[1:], fn, lineno)
1840       elif ctx in ('EXPORTS', 'USER_DEFINED', 'NO_EMIT'):
1841         if empty.match(line): continue
1842         if ctx == 'EXPORTS':
1843           par = get_par(line, 1, 6, fn=fn, lineno=lineno)
1844         else:
1845           par = get_par(line, 1, 2, fn=fn, lineno=lineno)
1846         if not par: continue
1847         flags = default_flags
1848         p = 2
1849         if (len(par)>=2):
1850           if (par[1] == 'WITH_VALS'):      flags |= EF_TYPE|EF_VALS
1851           elif (par[1] == 'WITHOUT_VALS'): flags |= EF_TYPE; flags &= ~EF_TYPE
1852           elif (par[1] == 'ONLY_VALS'):    flags &= ~EF_TYPE; flags |= EF_VALS
1853           elif (ctx == 'EXPORTS'): p = 1
1854           else: warnings.warn_explicit("Unknown parameter value '%s'" % (par[1]), UserWarning, fn, lineno)
1855         for i in range(p, len(par)):
1856           if (par[i] == 'ONLY_ENUM'):        flags &= ~(EF_TYPE|EF_VALS); flags |= EF_ENUM
1857           elif (par[i] == 'WITH_ENUM'):      flags |= EF_ENUM
1858           elif (par[i] == 'VALS_WITH_TABLE'):  flags |= EF_TABLE
1859           elif (par[i] == 'WS_VAR'):         flags |= EF_WS_VAR
1860           elif (par[i] == 'EXTERN'):         flags |= EF_EXTERN
1861           elif (par[i] == 'NO_PROT_PREFIX'): flags |= EF_NO_PROT
1862           else: warnings.warn_explicit("Unknown parameter value '%s'" % (par[i]), UserWarning, fn, lineno)
1863         self.add_item(ctx, par[0], flag=flags, fn=fn, lineno=lineno)
1864       elif ctx in ('MAKE_ENUM', 'MAKE_DEFINES'):
1865         if empty.match(line): continue
1866         par = get_par(line, 1, 4, fn=fn, lineno=lineno)
1867         if not par: continue
1868         flags = default_flags
1869         for i in range(1, len(par)):
1870           if (par[i] == 'NO_PROT_PREFIX'):   flags |= EF_NO_PROT
1871           elif (par[i] == 'NO_TYPE_PREFIX'): flags |= EF_NO_TYPE
1872           elif (par[i] == 'UPPER_CASE'):     flags |= EF_UCASE
1873           elif (par[i] == 'NO_UPPER_CASE'):  flags &= ~EF_UCASE
1874           else: warnings.warn_explicit("Unknown parameter value '%s'" % (par[i]), UserWarning, fn, lineno)
1875         self.add_item('MAKE_ENUM', par[0], flag=flags, fn=fn, lineno=lineno)
1876       elif ctx in ('PDU', 'PDU_NEW'):
1877         if empty.match(line): continue
1878         par = get_par(line, 1, 5, fn=fn, lineno=lineno)
1879         if not par: continue
1880         is_new = False
1881         if (ctx == 'PDU_NEW'): is_new = True
1882         self.add_pdu(par[0:2], is_new, fn, lineno)
1883         if (len(par)>=3):
1884           self.add_register(par[0], par[2:5], fn, lineno)
1885       elif ctx in ('REGISTER', 'REGISTER_NEW'):
1886         if empty.match(line): continue
1887         par = get_par(line, 3, 4, fn=fn, lineno=lineno)
1888         if not par: continue
1889         if not self.check_item('PDU', par[0]):
1890           is_new = False
1891           if (ctx == 'REGISTER_NEW'): is_new = True
1892           self.add_pdu(par[0:1], is_new, fn, lineno)
1893         self.add_register(par[0], par[1:4], fn, lineno)
1894       elif ctx in ('MODULE', 'MODULE_IMPORT'):
1895         if empty.match(line): continue
1896         par = get_par(line, 2, 2, fn=fn, lineno=lineno)
1897         if not par: continue
1898         self.add_item('MODULE', par[0], proto=par[1], fn=fn, lineno=lineno)
1899       elif ctx == 'IMPORT_TAG':
1900         if empty.match(line): continue
1901         par = get_par(line, 3, 3, fn=fn, lineno=lineno)
1902         if not par: continue
1903         self.add_item('IMPORT_TAG', par[0], ttag=(par[1], par[2]), fn=fn, lineno=lineno)
1904       elif ctx == 'OMIT_ASSIGNMENT':
1905         if empty.match(line): continue
1906         par = get_par(line, 1, 1, fn=fn, lineno=lineno)
1907         if not par: continue
1908         self.add_item('OMIT_ASSIGNMENT', par[0], omit=True, fn=fn, lineno=lineno)
1909       elif ctx == 'VIRTUAL_ASSGN':
1910         if empty.match(line): continue
1911         par = get_par(line, 2, -1, fn=fn, lineno=lineno)
1912         if not par: continue
1913         if (len(par[1].split('/')) > 1) and not self.check_item('SET_TYPE', par[1]):
1914           self.add_item('SET_TYPE', par[1], type=par[0], fn=fn, lineno=lineno)
1915         self.add_item('VIRTUAL_ASSGN', par[1], name=par[0], fn=fn, lineno=lineno)
1916         for nm in par[2:]:
1917           self.add_item('SET_TYPE', nm, type=par[0], fn=fn, lineno=lineno)
1918         if not par[0][0].isupper():
1919           warnings.warn_explicit("Virtual assignment should have uppercase name (%s)" % (par[0]),
1920                                   UserWarning, fn, lineno)
1921       elif ctx == 'SET_TYPE':
1922         if empty.match(line): continue
1923         par = get_par(line, 2, 2, fn=fn, lineno=lineno)
1924         if not par: continue
1925         if not self.check_item('VIRTUAL_ASSGN', par[0]):
1926           self.add_item('SET_TYPE', par[0], type=par[1], fn=fn, lineno=lineno)
1927         if not par[1][0].isupper():
1928           warnings.warn_explicit("Set type should have uppercase name (%s)" % (par[1]),
1929                                   UserWarning, fn, lineno)
1930       elif ctx == 'TYPE_RENAME':
1931         if empty.match(line): continue
1932         par = get_par(line, 2, 2, fn=fn, lineno=lineno)
1933         if not par: continue
1934         self.add_item('TYPE_RENAME', par[0], eth_name=par[1], fn=fn, lineno=lineno)
1935         if not par[1][0].isupper():
1936           warnings.warn_explicit("Type should be renamed to uppercase name (%s)" % (par[1]),
1937                                   UserWarning, fn, lineno)
1938       elif ctx == 'FIELD_RENAME':
1939         if empty.match(line): continue
1940         par = get_par(line, 2, 2, fn=fn, lineno=lineno)
1941         if not par: continue
1942         self.add_item('FIELD_RENAME', par[0], eth_name=par[1], fn=fn, lineno=lineno)
1943         if not par[1][0].islower():
1944           warnings.warn_explicit("Field should be renamed to lowercase name (%s)" % (par[1]),
1945                                   UserWarning, fn, lineno)
1946       elif ctx == 'TF_RENAME':
1947         if empty.match(line): continue
1948         par = get_par(line, 2, 2, fn=fn, lineno=lineno)
1949         if not par: continue
1950         tmpu = par[1][0].upper() + par[1][1:]
1951         tmpl = par[1][0].lower() + par[1][1:]
1952         self.add_item('TYPE_RENAME', par[0], eth_name=tmpu, fn=fn, lineno=lineno)
1953         if not tmpu[0].isupper():
1954           warnings.warn_explicit("Type should be renamed to uppercase name (%s)" % (par[1]),
1955                                   UserWarning, fn, lineno)
1956         self.add_item('FIELD_RENAME', par[0], eth_name=tmpl, fn=fn, lineno=lineno)
1957         if not tmpl[0].islower():
1958           warnings.warn_explicit("Field should be renamed to lowercase name (%s)" % (par[1]),
1959                                   UserWarning, fn, lineno)
1960       elif ctx in ('TYPE_ATTR', 'ETYPE_ATTR', 'FIELD_ATTR', 'EFIELD_ATTR'):
1961         if empty.match(line): continue
1962         par = get_par_nm(line, 1, 1, fn=fn, lineno=lineno)
1963         if not par: continue
1964         self.add_item(ctx, par[0], attr=par[1], fn=fn, lineno=lineno)
1965       elif ctx == 'FN_PARS':
1966         if empty.match(line): continue
1967         if name:
1968           par = get_par_nm(line, 0, 0, fn=fn, lineno=lineno)
1969         else:
1970           par = get_par_nm(line, 1, 1, fn=fn, lineno=lineno)
1971         if not par: continue
1972         if name:
1973           self.update_item(ctx, name, pars=par[0], fn=fn, lineno=lineno)
1974         else:
1975           self.add_item(ctx, par[0], pars=par[1], fn=fn, lineno=lineno)
1976       elif ctx in ('FN_HDR', 'FN_FTR', 'FN_BODY'):
1977         self.add_fn_line(name, ctx, line, fn=fn, lineno=lineno)
1978       elif ctx == 'CLASS':
1979         if empty.match(line): continue
1980         par = get_par(line, 1, 3, fn=fn, lineno=lineno)
1981         if not par: continue
1982         if (len(par) < 2): par.append('OpenType')
1983         if (len(par) < 3): par.append(None)
1984         if not set_type_to_class(name, par[0], par[1], par[2]):
1985           warnings.warn_explicit("Could not set type of class member %s.&%s to %s" % (name, par[0], par[1]),
1986                                   UserWarning, fn, lineno)
1987
1988   def set_opt(self, opt, par, fn, lineno):
1989     #print "set_opt: %s, %s" % (opt, par)
1990     if opt in ("-I",):
1991       par = self.check_par(par, 1, 1, fn, lineno)
1992       if not par: return
1993       self.include_path.append(par[0])
1994     elif opt in ("-b", "BER", "CER", "DER"):
1995       par = self.check_par(par, 0, 0, fn, lineno)
1996       self.ectx.encoding = 'ber'
1997     elif opt in ("PER",):
1998       par = self.check_par(par, 0, 0, fn, lineno)
1999       self.ectx.encoding = 'per'
2000     elif opt in ("-p", "PROTO"):
2001       par = self.check_par(par, 1, 1, fn, lineno)
2002       if not par: return
2003       self.ectx.proto_opt = par[0]
2004       self.ectx.merge_modules = True
2005     elif opt in ("-F", "CREATE_FIELDS"):
2006       par = self.check_par(par, 0, 1, fn, lineno)
2007       tnm = '*'
2008       if (len(par) > 0): tnm = par[0]
2009       self.ectx.fld_opt[tnm] = True
2010     elif opt in ("-T",):
2011       par = self.check_par(par, 0, 0, fn, lineno)
2012       self.ectx.tag_opt = True
2013     elif opt in ("ALIGNED",):
2014       par = self.check_par(par, 0, 0, fn, lineno)
2015       self.ectx.aligned = True
2016     elif opt in ("-u", "UNALIGNED"):
2017       par = self.check_par(par, 0, 0, fn, lineno)
2018       self.ectx.aligned = False
2019     elif opt in ("-d",):
2020       par = self.check_par(par, 1, 1, fn, lineno)
2021       if not par: return
2022       self.ectx.dbgopt = par[0]
2023     elif opt in ("-e",):
2024       par = self.check_par(par, 0, 0, fn, lineno)
2025       self.ectx.expcnf = True
2026     elif opt in ("-S",):
2027       par = self.check_par(par, 0, 0, fn, lineno)
2028       self.ectx.merge_modules = True
2029     elif opt in ("-o",):
2030       par = self.check_par(par, 1, 1, fn, lineno)
2031       if not par: return
2032       self.ectx.outnm_opt = par[0]
2033     elif opt in ("-O",):
2034       par = self.check_par(par, 1, 1, fn, lineno)
2035       if not par: return
2036       self.ectx.output.outdir = par[0]
2037     elif opt in ("-s",):
2038       par = self.check_par(par, 1, 1, fn, lineno)
2039       if not par: return
2040       self.ectx.output.single_file = par[0]
2041     elif opt in ("-k",):
2042       par = self.check_par(par, 0, 0, fn, lineno)
2043       self.ectx.output.keep = True
2044     elif opt in ("-L",):
2045       par = self.check_par(par, 0, 0, fn, lineno)
2046       self.suppress_line = True
2047     else:
2048       warnings.warn_explicit("Unknown option %s" % (opt),
2049                              UserWarning, fn, lineno)
2050
2051   def dbg_print(self):
2052     print "\n# Conformance values"
2053     print "%-15s %-4s %-15s %-20s %s" % ("File", "Line", "Table", "Key", "Value")
2054     print "-" * 100
2055     tbls = self.table.keys()
2056     tbls.sort()
2057     for t in tbls:
2058       keys = self.table[t].keys()
2059       keys.sort()
2060       for k in keys:
2061         print "%-15s %4s %-15s %-20s %s" % (
2062               self.table[t][k]['fn'], self.table[t][k]['lineno'], t, k, str(self.table[t][k][self.tblcfg[t]['val_nm']]))
2063
2064   def unused_report(self):
2065     tbls = self.table.keys()
2066     tbls.sort()
2067     for t in tbls:
2068       if not self.tblcfg[t]['chk_use']: continue
2069       keys = self.table[t].keys()
2070       keys.sort()
2071       for k in keys:
2072         if not self.table[t][k]['used']:
2073           warnings.warn_explicit("Unused %s for %s" % (t, k),
2074                                   UserWarning, self.table[t][k]['fn'], self.table[t][k]['lineno'])
2075     fnms = self.fn.keys()
2076     fnms.sort()
2077     for f in fnms:
2078       keys = self.fn[f].keys()
2079       keys.sort()
2080       for k in keys:
2081         if not self.fn[f][k]: continue
2082         if not self.fn[f][k]['used']:
2083           warnings.warn_explicit("Unused %s for %s" % (k, f),
2084                                   UserWarning, self.fn[f][k]['fn'], self.fn[f][k]['lineno'])
2085
2086 #--- EthOut -------------------------------------------------------------------
2087 class EthOut:
2088   def __init__(self):
2089     self.ectx = None
2090     self.outnm = None
2091     self.outdir = '.'
2092     self.single_file = None
2093     self.created_files = []
2094     self.unique_created_files = []
2095     self.keep = False
2096   #--- output_fname -------------------------------------------------------
2097   def output_fname(self, ftype, ext='c'):
2098     fn = ''
2099     if not ext in ('cnf',):
2100       fn += 'packet-' 
2101     fn += self.outnm
2102     if (ftype):
2103       fn += '-' + ftype
2104     fn += '.' + ext
2105     return fn
2106   #--- output_fullname -------------------------------------------------------
2107   def output_fullname(self, ftype, ext='c'):
2108     return os.path.join(self.outdir, self.output_fname(ftype, ext=ext))
2109   #--- file_open -------------------------------------------------------
2110   def file_open(self, ftype, ext='c'):
2111     fn = self.output_fullname(ftype, ext=ext)
2112     fx = file(fn, 'w')
2113     if ext in ('cnf',):
2114       fx.write(self.fhdr(fn, comment = '#'))
2115     else:
2116       if (not self.single_file):
2117         fx.write(self.fhdr(fn))
2118     return fx
2119   #--- file_close -------------------------------------------------------
2120   def file_close(self, fx, discard=False, keep_anyway=False):
2121     fx.close()
2122     if (discard): 
2123       os.unlink(fx.name)
2124     elif (not keep_anyway):
2125       self.created_files.append(os.path.normcase(os.path.abspath(fx.name)))
2126   #--- fhdr -------------------------------------------------------
2127   def fhdr(self, fn, comment=None):
2128     def outln(ln):
2129       if comment:
2130         return '# %s\n' % (ln)
2131       else:
2132         return '/* %-74s */\n' % (ln)
2133     out = ''
2134     out += outln('Do not modify this file.')
2135     out += outln('It is created automatically by the ASN.1 to Wireshark dissector compiler')
2136     out += outln(fn)
2137     out += outln(' '.join(sys.argv))
2138     out += '\n'
2139     return out
2140
2141   #--- dbg_print -------------------------------------------------------
2142   def dbg_print(self):
2143     print "\n# Output files"
2144     print "\n".join(self.created_files)
2145     print "\n"
2146
2147   #--- make_single_file -------------------------------------------------------
2148   def make_single_file(self):
2149     if (not self.single_file): return
2150     in_nm = self.single_file + '.c'
2151     out_nm = self.output_fullname('')
2152     self.do_include(out_nm, in_nm)
2153     in_nm = self.single_file + '.h'
2154     if (os.path.exists(in_nm)):
2155       out_nm = self.output_fullname('', ext='h')
2156       self.do_include(out_nm, in_nm)
2157     if (not self.keep):
2158       self.unique_created_files = []
2159       [self.unique_created_files.append(wrd) for wrd in self.created_files if not self.unique_created_files.count(wrd)]
2160       for fn in self.unique_created_files:
2161         os.unlink(fn)
2162
2163   #--- do_include -------------------------------------------------------
2164   def do_include(self, out_nm, in_nm):
2165     def check_file(fn, fnlist):
2166       fnfull = os.path.normcase(os.path.abspath(fn))
2167       if ((fnfull in fnlist) and os.path.exists(fnfull)):
2168         return os.path.normpath(fn)
2169       return None
2170     fin = file(in_nm, "r")
2171     fout = file(out_nm, "w")
2172     fout.write(self.fhdr(out_nm))
2173     fout.write('/* Input file: ' + in_nm +' */\n')
2174     fout.write('\n')
2175     fout.write('#line 1 "%s"\n' % (in_nm))
2176
2177     include = re.compile(r'^\s*#\s*include\s+[<"](?P<fname>[^>"]+)[>"]', re.IGNORECASE)
2178
2179     cont_linenum = 0;
2180
2181     while (True):
2182       cont_linenum = cont_linenum + 1;
2183       line = fin.readline()
2184       if (line == ''): break
2185       ifile = None
2186       result = include.search(line)
2187       #if (result): print os.path.normcase(os.path.abspath(result.group('fname')))
2188       if (result):
2189         ifile = check_file(os.path.join(os.path.split(in_nm)[0], result.group('fname')), self.created_files)
2190         if (not ifile):
2191           ifile = check_file(os.path.join(self.outdir, result.group('fname')), self.created_files)
2192         if (not ifile):
2193           ifile = check_file(result.group('fname'), self.created_files)
2194       if (ifile):
2195         fout.write('\n')
2196         fout.write('/*--- Included file: ' + ifile + ' ---*/\n')
2197         fout.write('#line 1 "' + ifile + '"\n')
2198         finc = file(ifile, "r")
2199         fout.write(finc.read())
2200         fout.write('\n')
2201         fout.write('/*--- End of included file: ' + ifile + ' ---*/\n')
2202         fout.write('#line %i "%s"\n' % (cont_linenum+1,in_nm) )
2203         finc.close()
2204       else:
2205         fout.write(line)
2206
2207     fout.close()
2208     fin.close()
2209
2210
2211 #--- Node ---------------------------------------------------------------------
2212 class Node:
2213     def __init__(self,*args, **kw):
2214         if len (args) == 0:
2215             self.type = self.__class__.__name__
2216         else:
2217             assert (len(args) == 1)
2218             self.type = args[0]
2219         self.__dict__.update (kw)
2220     def str_child (self, key, child, depth):
2221         indent = " " * (2 * depth)
2222         keystr = indent + key + ": "
2223         if key == 'type': # already processed in str_depth
2224             return ""
2225         if isinstance (child, Node): # ugh
2226             return keystr + "\n" + child.str_depth (depth+1)
2227         if type (child) == type ([]):
2228             l = []
2229             for x in child:
2230               if isinstance (x, Node):
2231                 l.append (x.str_depth (depth+1))
2232               else:
2233                 l.append (indent + "  " + str(x) + "\n")
2234             return keystr + "[\n" + ''.join(l) + indent + "]\n"
2235         else:
2236             return keystr + str (child) + "\n"
2237     def str_depth (self, depth): # ugh
2238         indent = " " * (2 * depth)
2239         l = ["%s%s" % (indent, self.type)]
2240         l.append ("".join (map (lambda (k,v): self.str_child (k, v, depth + 1),
2241                                 self.__dict__.items ())))
2242         return "\n".join (l)
2243     def __str__(self):
2244         return "\n" + self.str_depth (0)
2245     def to_python (self, ctx):
2246         return self.str_depth (ctx.indent_lev)
2247
2248     def eth_reg(self, ident, ectx):
2249         pass
2250
2251 #--- value_assign -------------------------------------------------------------
2252 class value_assign (Node):
2253   def __init__(self,*args, **kw) :
2254     Node.__init__ (self,*args, **kw)
2255
2256   def eth_reg(self, ident, ectx):
2257     if ectx.conform.use_item('OMIT_ASSIGNMENT', self.ident): return # Assignment to omit
2258     ectx.eth_reg_vassign(self)
2259     ectx.eth_reg_value(self.ident, self.typ, self.val)
2260
2261
2262 #--- Type ---------------------------------------------------------------------
2263 class Type (Node):
2264   def __init__(self,*args, **kw) :
2265     self.name = None
2266     self.constr = None
2267     self.tags = []
2268     Node.__init__ (self,*args, **kw)
2269
2270   def IsNamed(self):
2271     if self.name is None :
2272       return False
2273     else:
2274       return True
2275
2276   def HasConstraint(self):
2277     if self.constr is None :
2278       return False
2279     else :
2280       return True
2281
2282   def HasOwnTag(self):
2283     return len(self.tags) > 0
2284
2285   def HasImplicitTag(self, ectx):
2286     return (self.HasOwnTag() and self.tags[0].IsImplicit(ectx))
2287
2288   def IndetermTag(self, ectx):
2289     return False
2290
2291   def AddTag(self, tag):
2292     self.tags[0:0] = [tag]
2293
2294   def GetTag(self, ectx):
2295     #print "GetTag(%s)\n" % self.name;
2296     if (self.HasOwnTag()):
2297       return self.tags[0].GetTag(ectx)
2298     else:
2299       return self.GetTTag(ectx)
2300
2301   def GetTTag(self, ectx):
2302     print "#Unhandled  GetTTag() in %s" % (self.type)
2303     print self.str_depth(1)
2304     return ('BER_CLASS_unknown', 'TAG_unknown')
2305
2306   def SetName(self, name):
2307     self.name = name
2308
2309   def AddConstraint(self, constr):
2310     if not self.HasConstraint():
2311       self.constr = constr
2312     else:
2313       self.constr = Constraint(type = 'Intersection', subtype = [self.constr, constr])
2314
2315   def eth_tname(self):
2316     return '#' + self.type + '_' + str(id(self))
2317
2318   def eth_ftype(self, ectx):
2319     return ('FT_NONE', 'BASE_NONE')
2320
2321   def eth_strings(self):
2322     return 'NULL'
2323
2324   def eth_need_tree(self):
2325     return False
2326
2327   def eth_has_vals(self):
2328     return False
2329
2330   def eth_has_enum(self, tname, ectx):
2331     return self.eth_has_vals() and (ectx.eth_type[tname]['enum'] & EF_ENUM)
2332
2333   def eth_named_bits(self):
2334     return None
2335
2336   def eth_reg_sub(self, ident, ectx):
2337     pass
2338
2339   def eth_reg(self, ident, ectx, tstrip=0, tagflag=False, idx='', parent=None):
2340     #print "eth_reg(): %s, ident=%s, tstrip=%d, tagflag=%s, parent=%s" %(self.type, ident, tstrip, str(tagflag), str(parent))
2341     if (ectx.Tag() and (len(self.tags) > tstrip)):
2342       tagged_type = TaggedType(val=self, tstrip=tstrip)
2343       tagged_type.AddTag(self.tags[tstrip])
2344       if not tagflag:  # 1st tagged level
2345         if self.IsNamed():
2346           tagged_type.SetName(self.name)
2347       tagged_type.eth_reg(ident, ectx, tstrip=1, tagflag=tagflag, idx=idx, parent=parent)
2348       return
2349     nm = ''
2350     if ident and self.IsNamed() and not tagflag:
2351       nm = ident + '/' + self.name
2352     elif ident:
2353       nm = ident
2354     elif self.IsNamed():
2355       nm = self.name
2356     if not ident and ectx.conform.use_item('OMIT_ASSIGNMENT', nm): return # Assignment to omit
2357     if not ident:  # Assignment
2358       ectx.eth_reg_assign(nm, self)
2359       if self.type == 'Type_Ref':
2360         ectx.eth_reg_type(nm, self)
2361       if (ectx.conform.check_item('PDU', nm)):
2362         ectx.eth_reg_field(nm, nm, impl=self.HasImplicitTag(ectx), pdu=ectx.conform.use_item('PDU', nm))
2363     virtual_tr = Type_Ref(val=ectx.conform.use_item('SET_TYPE', nm))
2364     if (self.type == 'Type_Ref') or ectx.conform.check_item('SET_TYPE', nm):
2365       if ectx.conform.check_item('TYPE_RENAME', nm) or ectx.conform.get_fn_presence(nm):
2366         if ectx.conform.check_item('SET_TYPE', nm):
2367           ectx.eth_reg_type(nm, virtual_tr)  # dummy Type Reference
2368         else:
2369           ectx.eth_reg_type(nm, self)  # new type
2370         trnm = nm
2371       elif ectx.conform.check_item('SET_TYPE', nm):
2372         trnm = ectx.conform.use_item('SET_TYPE', nm)
2373       else:
2374         trnm = self.val
2375     else:
2376       ectx.eth_reg_type(nm, self)
2377       trnm = nm
2378     if ectx.conform.check_item('VIRTUAL_ASSGN', nm):
2379       vnm = ectx.conform.use_item('VIRTUAL_ASSGN', nm)
2380       ectx.eth_reg_assign(vnm, self, virt=True)
2381       ectx.eth_reg_type(vnm, self)
2382       self.eth_reg_sub(vnm, ectx)
2383     if parent and (ectx.type[parent]['val'].type == 'TaggedType'):
2384       ectx.type[parent]['val'].eth_set_val_name(parent, trnm, ectx)
2385     if ident and not tagflag:
2386       ectx.eth_reg_field(nm, trnm, idx=idx, parent=parent, impl=self.HasImplicitTag(ectx))
2387     if ectx.conform.check_item('SET_TYPE', nm):
2388       virtual_tr.eth_reg_sub(nm, ectx)
2389     else:
2390       self.eth_reg_sub(nm, ectx)
2391
2392   def eth_get_size_constr(self):
2393     (minv, maxv, ext) = ('NO_BOUND', 'NO_BOUND', 'FALSE')
2394     if not self.HasConstraint():
2395       (minv, maxv, ext) = ('NO_BOUND', 'NO_BOUND', 'FALSE')
2396     elif self.constr.IsSize():
2397       (minv, maxv, ext) = self.constr.GetSize()
2398     elif (self.constr.type == 'Intersection'):
2399       if self.constr.subtype[0].IsSize():
2400         (minv, maxv, ext) = self.constr.subtype[0].GetSize()
2401       elif self.constr.subtype[1].IsSize():
2402         (minv, maxv, ext) = self.constr.subtype[1].GetSize()
2403     return (minv, maxv, ext)
2404
2405   def eth_get_value_constr(self):
2406     (minv, maxv, ext) = ('NO_BOUND', 'NO_BOUND', 'FALSE')
2407     if not self.HasConstraint():
2408       (minv, maxv, ext) = ('NO_BOUND', 'NO_BOUND', 'FALSE')
2409     elif self.constr.IsValue():
2410       (minv, maxv, ext) = self.constr.GetValue()
2411     return (minv, maxv, ext)
2412
2413   def eth_type_vals(self, tname, ectx):
2414     if self.eth_has_vals():
2415       print "#Unhandled  eth_type_vals('%s') in %s" % (tname, self.type)
2416       print self.str_depth(1)
2417     return ''
2418
2419   def eth_type_enum(self, tname, ectx):
2420     if self.eth_has_enum(tname, ectx):
2421       print "#Unhandled  eth_type_enum('%s') in %s" % (tname, self.type)
2422       print self.str_depth(1)
2423     return ''
2424
2425   def eth_type_default_table(self, ectx, tname):
2426     return ''
2427
2428   def eth_type_default_body(self, ectx):
2429     print "#Unhandled  eth_type_default_body() in %s" % (self.type)
2430     print self.str_depth(1)
2431     return ''
2432
2433   def eth_type_default_pars(self, ectx, tname):
2434     pars = {
2435       'TNAME' : tname,
2436       'ER' : ectx.encp(),
2437       'FN_VARIANT' : '',
2438       'TREE' : 'tree', 
2439       'TVB' : 'tvb', 
2440       'OFFSET' : 'offset',
2441       'ACTX' : 'actx',
2442       'HF_INDEX' : 'hf_index',
2443       'VAL_PTR' : 'NULL',
2444       'IMPLICIT_TAG' : 'implicit_tag',
2445     }
2446     if (ectx.eth_type[tname]['tree']):
2447       pars['ETT_INDEX'] = ectx.eth_type[tname]['tree']
2448     if (not ectx.Per()):
2449       pars['PINFO'] = 'pinfo'
2450     return pars
2451
2452   def eth_type_fn(self, proto, tname, ectx):
2453     body = self.eth_type_default_body(ectx, tname)
2454     pars = self.eth_type_default_pars(ectx, tname)
2455     if ectx.conform.check_item('FN_PARS', tname):
2456       pars.update(ectx.conform.use_item('FN_PARS', tname))
2457     elif ectx.conform.check_item('FN_PARS', ectx.eth_type[tname]['ref'][0]):
2458       pars.update(ectx.conform.use_item('FN_PARS', ectx.eth_type[tname]['ref'][0]))
2459     pars['DEFAULT_BODY'] = body
2460     for i in range(4):
2461       for k in pars.keys(): pars[k] = pars[k] % pars
2462     out = '\n'
2463     out += self.eth_type_default_table(ectx, tname) % pars
2464     out += ectx.eth_type_fn_hdr(tname)
2465     out += ectx.eth_type_fn_body(tname, body, pars=pars)
2466     out += ectx.eth_type_fn_ftr(tname)
2467     return out
2468
2469 #--- Value --------------------------------------------------------------------
2470 class Value (Node):
2471   def __init__(self,*args, **kw) :
2472     self.name = None
2473     Node.__init__ (self,*args, **kw)
2474
2475   def SetName(self, name) :
2476     self.name = name
2477
2478   def to_str(self):
2479     return str(self)
2480
2481   def get_dep(self):
2482     return None
2483
2484 #--- ObjectClass ---------------------------------------------------------------------
2485 class ObjectClass (Node):
2486   def __init__(self,*args, **kw) :
2487     self.name = None
2488     Node.__init__ (self,*args, **kw)
2489
2490   def SetName(self, name):
2491     self.name = name
2492     add_class_ident(self.name)
2493
2494 #--- Tag ---------------------------------------------------------------
2495 class Tag (Node):
2496   def to_python (self, ctx):
2497     return 'asn1.TYPE(%s,%s)' % (mk_tag_str (ctx, self.tag.cls,
2498                                                 self.tag_typ,
2499                                                 self.tag.num),
2500                                     self.typ.to_python (ctx))
2501   def IsImplicit(self, ectx):
2502     return ((self.mode == 'IMPLICIT') or ((self.mode == 'default') and (ectx.tag_def == 'IMPLICIT')))
2503
2504   def GetTag(self, ectx):
2505     tc = ''
2506     if (self.cls == 'UNIVERSAL'): tc = 'BER_CLASS_UNI'
2507     elif (self.cls == 'APPLICATION'): tc = 'BER_CLASS_APP'
2508     elif (self.cls == 'CONTEXT'): tc = 'BER_CLASS_CON'
2509     elif (self.cls == 'PRIVATE'): tc = 'BER_CLASS_PRI'
2510     return (tc, self.num)
2511
2512   def eth_tname(self):
2513     n = ''
2514     if (self.cls == 'UNIVERSAL'): n = 'U'
2515     elif (self.cls == 'APPLICATION'): n = 'A'
2516     elif (self.cls == 'CONTEXT'): n = 'C'
2517     elif (self.cls == 'PRIVATE'): n = 'P'
2518     return n + str(self.num)
2519  
2520 #--- Constraint ---------------------------------------------------------------
2521 class Constraint (Node):
2522   def to_python (self, ctx):
2523     print "Ignoring constraint:", self.type
2524     return self.subtype.typ.to_python (ctx)
2525   def __str__ (self):
2526     return "Constraint: type=%s, subtype=%s" % (self.type, self.subtype)
2527
2528   def IsSize(self):
2529     return self.type == 'Size' and (self.subtype.type == 'SingleValue' or self.subtype.type == 'ValueRange')
2530
2531   def GetSize(self):
2532     minv = 'NO_BOUND'
2533     maxv = 'NO_BOUND'
2534     ext = 'FALSE'
2535     if self.IsSize():
2536       if self.subtype.type == 'SingleValue':
2537         minv = self.subtype.subtype
2538         maxv = self.subtype.subtype
2539       else:
2540         minv = self.subtype.subtype[0]
2541         maxv = self.subtype.subtype[1]
2542       if hasattr(self.subtype, 'ext') and self.subtype.ext:
2543         ext = 'TRUE'
2544       else:
2545         ext = 'FALSE'
2546     return (minv, maxv, ext)
2547
2548   def IsValue(self):
2549     return self.type == 'SingleValue' or self.type == 'ValueRange'
2550
2551   def GetValue(self):
2552     minv = 'NO_BOUND'
2553     maxv = 'NO_BOUND'
2554     ext = 'FALSE'
2555     if self.IsValue():
2556       if self.type == 'SingleValue':
2557         minv = self.subtype
2558         maxv = self.subtype
2559       else:
2560         if self.subtype[0] == 'MIN':
2561           minv = 'NO_BOUND'
2562         else:
2563           minv = self.subtype[0]
2564         if self.subtype[1] == 'MAX':
2565           maxv = 'NO_BOUND'
2566         else:
2567           maxv = self.subtype[1]
2568       if str(minv).isdigit(): minv += 'U'
2569       if str(maxv).isdigit(): maxv += 'U'
2570       if hasattr(self, 'ext') and self.ext:
2571         ext = 'TRUE'
2572       else:
2573         ext = 'FALSE'
2574     return (minv, maxv, ext)
2575
2576   def IsNegativ(self):
2577     def is_neg(sval):
2578       return sval[0] == '-'
2579     if self.type == 'SingleValue':
2580       return is_neg(self.subtype)
2581     elif self.type == 'ValueRange':
2582       if self.subtype[0] == 'MIN': return True
2583       return is_neg(self.subtype[0])
2584     return FALSE
2585
2586   def IsPermAlph(self):
2587     return self.type == 'From' and self.subtype.type == 'SingleValue'
2588
2589   def eth_constrname(self):
2590     def int2str(val):
2591       try:
2592         if (int(val) < 0):
2593           return 'M' + str(-int(val))
2594         else:
2595           return str(val)
2596       except (ValueError, TypeError):
2597         return str(val)
2598
2599     ext = ''
2600     if hasattr(self, 'ext') and self.ext:
2601       ext = '_'
2602     if self.type == 'SingleValue':
2603       return int2str(self.subtype) + ext
2604     elif self.type == 'ValueRange':
2605       return int2str(self.subtype[0]) + '_' + int2str(self.subtype[1]) + ext
2606     elif self.type == 'Size':
2607       return 'SIZE_' + self.subtype.eth_constrname() + ext
2608     else:
2609       return 'CONSTR' + str(id(self)) + ext
2610
2611
2612 class Module (Node):
2613   def to_python (self, ctx):
2614     ctx.tag_def = self.tag_def.dfl_tag
2615     return """#%s
2616 %s""" % (self.ident, self.body.to_python (ctx))
2617
2618   def to_eth (self, ectx):
2619     ectx.tags_def = 'EXPLICIT' # default = explicit
2620     if (not ectx.proto):
2621       ectx.proto = ectx.conform.use_item('MODULE', self.ident.val, val_dflt=self.ident.val)
2622     ectx.tag_def = self.tag_def.dfl_tag
2623     ectx.modules.append((self.ident.val, ectx.proto))
2624     self.body.to_eth(ectx)
2625
2626 class Module_Body (Node):
2627     def to_python (self, ctx):
2628         # XXX handle exports, imports.
2629         l = map (lambda x: x.to_python (ctx), self.assign_list)
2630         l = [a for a in l if a <> '']
2631         return "\n".join (l)
2632
2633     def to_eth(self, ectx):
2634         for i in self.imports:
2635           mod = i.module.val
2636           proto = ectx.conform.use_item('MODULE', mod, val_dflt=mod)
2637           for s in i.symbol_list:
2638             if isinstance(s, Type_Ref):
2639               ectx.eth_import_type(s.val, mod, proto)
2640             elif isinstance(s, Class_Ref):
2641               ectx.eth_import_class(s.val, mod, proto)
2642             else:
2643               ectx.eth_import_value(s, mod, proto)
2644         for a in self.assign_list:
2645           a.eth_reg('', ectx)
2646
2647 class Default_Tags (Node):
2648     def to_python (self, ctx): # not to be used directly
2649         assert (0)
2650
2651 # XXX should just calculate dependencies as we go along.
2652 def calc_dependencies (node, dict, trace = 0):
2653     if not hasattr (node, '__dict__'):
2654         if trace: print "#returning, node=", node
2655         return
2656     if isinstance (node, Type_Ref):
2657         dict [node.val] = 1
2658         if trace: print "#Setting", node.val
2659         return
2660     for (a, val) in node.__dict__.items ():
2661         if trace: print "# Testing node ", node, "attr", a, " val", val
2662         if a[0] == '_':
2663             continue
2664         elif isinstance (val, Node):
2665             calc_dependencies (val, dict, trace)
2666         elif isinstance (val, type ([])):
2667             for v in val:
2668                 calc_dependencies (v, dict, trace)
2669     
2670                           
2671 class Type_Assign (Node):
2672     def __init__ (self, *args, **kw):
2673         Node.__init__ (self, *args, **kw)
2674         if isinstance (self.val, Tag): # XXX replace with generalized get_typ_ignoring_tag (no-op for Node, override in Tag)
2675             to_test = self.val.typ
2676         else:
2677             to_test = self.val
2678         if isinstance (to_test, SequenceType):
2679             to_test.sequence_name = self.name.name
2680             
2681     def to_python (self, ctx):
2682         dep_dict = {}
2683         calc_dependencies (self.val, dep_dict, 0)
2684         depend_list = dep_dict.keys ()
2685         return ctx.register_assignment (self.name.name,
2686                                         self.val.to_python (ctx),
2687                                         depend_list)
2688
2689 class PyQuote (Node):
2690     def to_python (self, ctx):
2691         return ctx.register_pyquote (self.val)
2692
2693 #--- Class_Ref -----------------------------------------------------------------
2694 class Class_Ref (Type):
2695   def to_python (self, ctx):
2696     return self.val
2697
2698   def eth_tname(self):
2699     return asn2c(self.val)
2700
2701 #--- Type_Ref -----------------------------------------------------------------
2702 class Type_Ref (Type):
2703   def to_python (self, ctx):
2704     return self.val
2705
2706   def eth_reg_sub(self, ident, ectx):
2707     ectx.eth_dep_add(ident, self.val)
2708
2709   def eth_tname(self):
2710     return asn2c(self.val)
2711
2712   def GetTTag(self, ectx):
2713     #print "GetTTag(%s)\n" % self.val;
2714     if (ectx.type[self.val]['import']):
2715       if not ectx.type[self.val].has_key('ttag'):
2716         if not ectx.conform.check_item('IMPORT_TAG', self.val):
2717           msg = 'Missing tag information for imported type %s from %s (%s)' % (self.val, ectx.type[self.val]['import'], ectx.type[self.val]['proto'])
2718           warnings.warn_explicit(msg, UserWarning, '', '')
2719         ectx.type[self.val]['ttag'] = ectx.conform.use_item('IMPORT_TAG', self.val, val_dflt=('-1 /*imported*/', '-1 /*imported*/'))
2720       return ectx.type[self.val]['ttag']
2721     else:
2722       return ectx.type[self.val]['val'].GetTag(ectx)
2723
2724   def IndetermTag(self, ectx):
2725     if (ectx.type[self.val]['import']):
2726       return False
2727     else:
2728       return ectx.type[self.val]['val'].IndetermTag(ectx)
2729
2730   def eth_type_default_pars(self, ectx, tname):
2731     pars = Type.eth_type_default_pars(self, ectx, tname)
2732     t = ectx.type[self.val]['ethname']
2733     pars['TYPE_REF_PROTO'] = ectx.eth_type[t]['proto']
2734     pars['TYPE_REF_TNAME'] = t
2735     pars['TYPE_REF_FN'] = 'dissect_%(TYPE_REF_PROTO)s_%(TYPE_REF_TNAME)s'
2736     return pars
2737
2738   def eth_type_default_body(self, ectx, tname):
2739     if (ectx.Ber()):
2740       body = ectx.eth_fn_call('%(TYPE_REF_FN)s', ret='offset',
2741                               par=(('%(IMPLICIT_TAG)s', '%(TVB)s', '%(OFFSET)s', '%(PINFO)s', '%(TREE)s', '%(HF_INDEX)s'),))
2742     elif (ectx.Per()):
2743       body = ectx.eth_fn_call('%(TYPE_REF_FN)s', ret='offset',
2744                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),))
2745     else:
2746       body = '#error Can not decode %s' % (tname)
2747     return body
2748
2749 #--- TaggedType -----------------------------------------------------------------
2750 class TaggedType (Type):
2751   def eth_tname(self):
2752     tn = ''
2753     for i in range(self.tstrip, len(self.val.tags)):
2754       tn += self.val.tags[i].eth_tname()
2755       tn += '_'
2756     tn += self.val.eth_tname()
2757     return tn
2758
2759   def eth_set_val_name(self, ident, val_name, ectx):
2760     #print "TaggedType::eth_set_val_name(): ident=%s, val_name=%s" % (ident, val_name)
2761     self.val_name = val_name
2762     ectx.eth_dep_add(ident, self.val_name)
2763
2764   def eth_reg_sub(self, ident, ectx):
2765     self.val_name = ident + '/' + '_untag'
2766     self.val.eth_reg(self.val_name, ectx, tstrip=self.tstrip+1, tagflag=True, parent=ident)
2767
2768   def eth_ftype(self, ectx):
2769     return self.val.eth_ftype(ectx)
2770
2771   def eth_type_default_pars(self, ectx, tname):
2772     pars = Type.eth_type_default_pars(self, ectx, tname)
2773     t = ectx.type[self.val_name]['ethname']
2774     pars['TYPE_REF_PROTO'] = ectx.eth_type[t]['proto']
2775     pars['TYPE_REF_TNAME'] = t
2776     pars['TYPE_REF_FN'] = 'dissect_%(TYPE_REF_PROTO)s_%(TYPE_REF_TNAME)s'
2777     (pars['TAG_CLS'], pars['TAG_TAG']) = self.GetTag(ectx)
2778     if self.HasImplicitTag(ectx):
2779       pars['TAG_IMPL'] = 'TRUE'
2780     else:
2781       pars['TAG_IMPL'] = 'FALSE'
2782     return pars
2783
2784   def eth_type_default_body(self, ectx, tname):
2785     if (ectx.Ber()):
2786       body = ectx.eth_fn_call('dissect_%(ER)s_tagged_type', ret='offset',
2787                               par=(('%(IMPLICIT_TAG)s', '%(PINFO)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s'),
2788                                    ('%(HF_INDEX)s', '%(TAG_CLS)s', '%(TAG_TAG)s', '%(TAG_IMPL)s', '%(TYPE_REF_FN)s',),))
2789     else:
2790       body = '#error Can not decode %s' % (tname)
2791     return body
2792
2793 #--- SqType -----------------------------------------------------------
2794 class SqType (Type):
2795   def out_item(self, f, val, optional, ext, ectx):
2796     ef = ectx.field[f]['ethname']
2797     t = ectx.eth_hf[ef]['ethtype']
2798     efd = ef
2799     if (ectx.Ber() and ectx.field[f]['impl']):
2800       efd += '_impl'
2801     if (ectx.Ber()):
2802       #print "optional=%s, e.val.HasOwnTag()=%s, e.val.IndetermTag()=%s" % (str(e.optional), str(e.val.HasOwnTag()), str(e.val.IndetermTag(ectx)))
2803       #print val.str_depth(1)
2804       opt = ''
2805       if (optional):
2806         opt = 'BER_FLAGS_OPTIONAL'
2807       if (not val.HasOwnTag()):
2808         if (opt): opt += '|'
2809         opt += 'BER_FLAGS_NOOWNTAG'
2810       elif (val.HasImplicitTag(ectx)):
2811         if (opt): opt += '|'
2812         opt += 'BER_FLAGS_IMPLTAG'
2813       if (val.IndetermTag(ectx)):
2814         if (opt): opt += '|'
2815         opt += 'BER_FLAGS_NOTCHKTAG'
2816       if (not opt): opt = '0'
2817     else:
2818       if optional:
2819         opt = 'ASN1_OPTIONAL'
2820       else:
2821         opt = 'ASN1_NOT_OPTIONAL'
2822     if (ectx.Ber()):
2823       (tc, tn) = val.GetTag(ectx)
2824       out = '  { %-13s, %s, %s, dissect_%s },\n' \
2825             % (tc, tn, opt, efd)
2826     elif (ectx.Per()):
2827       out = '  { %-24s, %-23s, %-17s, dissect_%s_%s },\n' \
2828             % ('&'+ectx.eth_hf[ef]['fullname'], ext, opt, ectx.eth_type[t]['proto'], t)
2829     else:
2830       out = ''
2831     return out   
2832
2833 #--- SeqType -----------------------------------------------------------
2834 class SeqType (SqType):
2835   def eth_type_default_table(self, ectx, tname):
2836     #print "eth_type_default_table(tname='%s')" % (tname)
2837     fname = ectx.eth_type[tname]['ref'][0]
2838     table = "static const %(ER)s_sequence_t %(TABLE)s[] = {\n"
2839     if hasattr(self, 'ext_list'):
2840       ext = 'ASN1_EXTENSION_ROOT'
2841     else:
2842       ext = 'ASN1_NO_EXTENSIONS'
2843     for e in (self.elt_list):
2844       f = fname + '/' + e.val.name
2845       table += self.out_item(f, e.val, e.optional, ext, ectx)
2846     if hasattr(self, 'ext_list'):
2847       for e in (self.ext_list):
2848         f = fname + '/' + e.val.name
2849         table += self.out_item(f, e.val, e.optional, 'ASN1_NOT_EXTENSION_ROOT', ectx)
2850     if (ectx.Ber()):
2851       table += "  { 0, 0, 0, NULL }\n};\n"
2852     else:
2853       table += "  { NULL, 0, 0, NULL }\n};\n"
2854     return table
2855
2856 #--- SeqOfType -----------------------------------------------------------
2857 class SeqOfType (SqType):
2858   def eth_type_default_table(self, ectx, tname):
2859     #print "eth_type_default_table(tname='%s')" % (tname)
2860     fname = ectx.eth_type[tname]['ref'][0]
2861     if self.val.IsNamed ():
2862       f = fname + '/' + self.val.name
2863     else:
2864       f = fname + '/' + '_item'
2865     table = "static const %(ER)s_sequence_t %(TABLE)s[1] = {\n"
2866     table += self.out_item(f, self.val, False, 'ASN1_NO_EXTENSIONS', ectx)
2867     table += "};\n"
2868     return table
2869
2870 #--- SequenceOfType -----------------------------------------------------------
2871 class SequenceOfType (SeqOfType):
2872   def to_python (self, ctx):
2873     # name, tag (None for no tag, EXPLICIT() for explicit), typ)
2874     # or '' + (1,) for optional
2875     sizestr = ''
2876     if self.size_constr <> None:
2877         print "#Ignoring size constraint:", self.size_constr.subtype
2878     return "%sasn1.SEQUENCE_OF (%s%s)" % (ctx.spaces (),
2879                                           self.val.to_python (ctx),
2880                                           sizestr)
2881
2882   def eth_reg_sub(self, ident, ectx):
2883     itmnm = ident
2884     if not self.val.IsNamed ():
2885       itmnm += '/' + '_item'
2886     self.val.eth_reg(itmnm, ectx, tstrip=1, idx='[##]', parent=ident)
2887
2888   def eth_tname(self):
2889     if self.val.type != 'Type_Ref':
2890       return '#' + self.type + '_' + str(id(self))
2891     if not self.HasConstraint():
2892       return "SEQUENCE_OF_" + self.val.eth_tname()
2893     elif self.constr.IsSize():
2894       return 'SEQUENCE_' + self.constr.eth_constrname() + '_OF_' + self.val.eth_tname()
2895     else:
2896       return '#' + self.type + '_' + str(id(self))
2897
2898   def eth_ftype(self, ectx):
2899     return ('FT_UINT32', 'BASE_DEC')
2900
2901   def eth_need_tree(self):
2902     return True
2903
2904   def GetTTag(self, ectx):
2905     return ('BER_CLASS_UNI', 'BER_UNI_TAG_SEQUENCE')
2906
2907   def eth_type_default_pars(self, ectx, tname):
2908     pars = Type.eth_type_default_pars(self, ectx, tname)
2909     (pars['MIN_VAL'], pars['MAX_VAL'], pars['EXT']) = self.eth_get_size_constr()
2910     pars['TABLE'] = '%(TNAME)s_sequence_of'
2911     return pars
2912
2913   def eth_type_default_body(self, ectx, tname):
2914     if (ectx.Ber()):
2915       body = ectx.eth_fn_call('dissect_%(ER)s_sequence_of', ret='offset',
2916                               par=(('%(IMPLICIT_TAG)s', '%(PINFO)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s'),
2917                                    ('%(TABLE)s', '%(HF_INDEX)s', '%(ETT_INDEX)s',),))
2918     elif (ectx.Per() and not self.HasConstraint()):
2919       body = ectx.eth_fn_call('dissect_%(ER)s_sequence_of', ret='offset',
2920                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
2921                                    ('%(ETT_INDEX)s', '%(TABLE)s',),))
2922     elif (ectx.Per() and self.constr.type == 'Size'):
2923       body = ectx.eth_fn_call('dissect_%(ER)s_constrained_sequence_of', ret='offset',
2924                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
2925                                    ('%(ETT_INDEX)s', '%(TABLE)s',),
2926                                    ('%(MIN_VAL)s', '%(MAX_VAL)s',),))
2927     else:
2928       body = '#error Can not decode %s' % (tname)
2929     return body
2930
2931
2932 #--- SetOfType ----------------------------------------------------------------
2933 class SetOfType (SeqOfType):
2934   def eth_reg_sub(self, ident, ectx):
2935     itmnm = ident
2936     if not self.val.IsNamed ():
2937       itmnm += '/' + '_item'
2938     self.val.eth_reg(itmnm, ectx, tstrip=1, idx='(##)', parent=ident)
2939
2940   def eth_tname(self):
2941     if self.val.type != 'Type_Ref':
2942       return '#' + self.type + '_' + str(id(self))
2943     if not self.HasConstraint():
2944       return "SET_OF_" + self.val.eth_tname()
2945     elif self.constr.IsSize():
2946       return 'SET_' + self.constr.eth_constrname() + '_OF_' + self.val.eth_tname()
2947     else:
2948       return '#' + self.type + '_' + str(id(self))
2949
2950   def eth_ftype(self, ectx):
2951     return ('FT_UINT32', 'BASE_DEC')
2952
2953   def eth_need_tree(self):
2954     return True
2955
2956   def GetTTag(self, ectx):
2957     return ('BER_CLASS_UNI', 'BER_UNI_TAG_SET')
2958
2959   def eth_type_default_pars(self, ectx, tname):
2960     pars = Type.eth_type_default_pars(self, ectx, tname)
2961     (pars['MIN_VAL'], pars['MAX_VAL'], pars['EXT']) = self.eth_get_size_constr()
2962     pars['TABLE'] = '%(TNAME)s_set_of'
2963     return pars
2964
2965   def eth_type_default_body(self, ectx, tname):
2966     if (ectx.Ber()):
2967       body = ectx.eth_fn_call('dissect_%(ER)s_set_of', ret='offset',
2968                               par=(('%(IMPLICIT_TAG)s', '%(PINFO)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s'),
2969                                    ('%(TABLE)s', '%(HF_INDEX)s', '%(ETT_INDEX)s',),))
2970     elif (ectx.Per() and not self.HasConstraint()):
2971       body = ectx.eth_fn_call('dissect_%(ER)s_set_of', ret='offset',
2972                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
2973                                    ('%(ETT_INDEX)s', '%(TABLE)s',),))
2974     elif (ectx.Per() and self.constr.type == 'Size'):
2975       body = ectx.eth_fn_call('dissect_%(ER)s_constrained_set_of', ret='offset',
2976                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
2977                                    ('%(ETT_INDEX)s', '%(TABLE)s',),
2978                                    ('%(MIN_VAL)s', '%(MAX_VAL)s',),))
2979     else:
2980       body = '#error Can not decode %s' % (tname)
2981     return body
2982
2983 def mk_tag_str (ctx, cls, typ, num):
2984
2985     # XXX should do conversion to int earlier!
2986     val = int (num)
2987     typ = typ.upper()
2988     if typ == 'DEFAULT':
2989         typ = ctx.tags_def
2990     return 'asn1.%s(%d,cls=asn1.%s_FLAG)' % (typ, val, cls) # XXX still ned
2991
2992 #--- SequenceType -------------------------------------------------------------
2993 class SequenceType (SeqType):
2994   def to_python (self, ctx):
2995       # name, tag (None for no tag, EXPLICIT() for explicit), typ)
2996       # or '' + (1,) for optional
2997       # XXX should also collect names for SEQUENCE inside SEQUENCE or
2998       # CHOICE or SEQUENCE_OF (where should the SEQUENCE_OF name come
2999       # from?  for others, element or arm name would be fine)
3000       seq_name = getattr (self, 'sequence_name', None)
3001       if seq_name == None:
3002           seq_name = 'None'
3003       else:
3004           seq_name = "'" + seq_name + "'"
3005       if self.__dict__.has_key('ext_list'):
3006         return "%sasn1.SEQUENCE ([%s], ext=[%s], seq_name = %s)" % (ctx.spaces (), 
3007                                  self.elts_to_py (self.elt_list, ctx),
3008                                  self.elts_to_py (self.ext_list, ctx), seq_name)
3009       else:
3010         return "%sasn1.SEQUENCE ([%s]), seq_name = %s" % (ctx.spaces (), 
3011                                  self.elts_to_py (self.elt_list, ctx), seq_name)
3012   def elts_to_py (self, list, ctx):
3013       # we have elt_type, val= named_type, maybe default=, optional=
3014       # named_type node: either ident = or typ =
3015       # need to dismember these in order to generate Python output syntax.
3016       ctx.indent ()
3017       def elt_to_py (e):
3018           assert (e.type == 'elt_type')
3019           nt = e.val
3020           optflag = e.optional
3021           #assert (not hasattr (e, 'default')) # XXX add support for DEFAULT!
3022           assert (nt.type == 'named_type')
3023           tagstr = 'None'
3024           identstr = nt.ident
3025           if hasattr (nt.typ, 'type') and nt.typ.type == 'tag': # ugh
3026               tagstr = mk_tag_str (ctx,nt.typ.tag.cls,
3027                                    nt.typ.tag.tag_typ,nt.typ.tag.num)
3028       
3029
3030               nt = nt.typ
3031           return "('%s',%s,%s,%d)" % (identstr, tagstr,
3032                                     nt.typ.to_python (ctx), optflag)
3033       indentstr = ",\n" + ctx.spaces ()
3034       rv = indentstr.join ([elt_to_py (e) for e in list])
3035       ctx.outdent ()
3036       return rv
3037
3038   def eth_reg_sub(self, ident, ectx):
3039       for e in (self.elt_list):
3040           e.val.eth_reg(ident, ectx, tstrip=1, parent=ident)
3041       if hasattr(self, 'ext_list'):
3042           for e in (self.ext_list):
3043               e.val.eth_reg(ident, ectx, tstrip=1, parent=ident)
3044
3045   def eth_need_tree(self):
3046     return True
3047
3048   def GetTTag(self, ectx):
3049     return ('BER_CLASS_UNI', 'BER_UNI_TAG_SEQUENCE')
3050
3051   def eth_type_default_pars(self, ectx, tname):
3052     pars = Type.eth_type_default_pars(self, ectx, tname)
3053     pars['TABLE'] = '%(TNAME)s_sequence'
3054     return pars
3055
3056   def eth_type_default_body(self, ectx, tname):
3057     if (ectx.Ber()):
3058       body = ectx.eth_fn_call('dissect_%(ER)s_sequence', ret='offset',
3059                               par=(('%(IMPLICIT_TAG)s', '%(PINFO)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s'),
3060                                    ('%(TABLE)s', '%(HF_INDEX)s', '%(ETT_INDEX)s',),))
3061     elif (ectx.Per()):
3062       body = ectx.eth_fn_call('dissect_%(ER)s_sequence', ret='offset',
3063                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
3064                                    ('%(ETT_INDEX)s', '%(TABLE)s',),))
3065     else:
3066       body = '#error Can not decode %s' % (tname)
3067     return body
3068
3069 #--- SetType ------------------------------------------------------------------
3070 class SetType(SeqType):
3071   def eth_reg_sub(self, ident, ectx):
3072     for e in (self.elt_list):
3073       e.val.eth_reg(ident, ectx, tstrip=1, parent=ident)
3074     if hasattr(self, 'ext_list'):
3075       for e in (self.ext_list):
3076         e.val.eth_reg(ident, ectx, tstrip=1, parent=ident)
3077
3078   def eth_need_tree(self):
3079     return True
3080
3081   def GetTTag(self, ectx):
3082     return ('BER_CLASS_UNI', 'BER_UNI_TAG_SET')
3083
3084   def eth_type_default_pars(self, ectx, tname):
3085     pars = Type.eth_type_default_pars(self, ectx, tname)
3086     pars['TABLE'] = '%(TNAME)s_set'
3087     return pars
3088
3089   def eth_type_default_body(self, ectx, tname):
3090     if (ectx.Ber()):
3091       body = ectx.eth_fn_call('dissect_%(ER)s_set', ret='offset',
3092                               par=(('%(IMPLICIT_TAG)s', '%(PINFO)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s'),
3093                                    ('%(TABLE)s', '%(HF_INDEX)s', '%(ETT_INDEX)s',),))
3094     elif (ectx.Per()):
3095       body = ectx.eth_fn_call('dissect_%(ER)s_set', ret='offset',
3096                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
3097                                    ('%(ETT_INDEX)s', '%(TABLE)s',),))
3098     else:
3099       body = '#error Can not decode %s' % (tname)
3100     return body
3101
3102 #--- ChoiceType ---------------------------------------------------------------
3103 class ChoiceType (Type):
3104   def to_python (self, ctx):
3105       # name, tag (None for no tag, EXPLICIT() for explicit), typ)
3106       # or '' + (1,) for optional
3107       if self.__dict__.has_key('ext_list'):
3108         return "%sasn1.CHOICE ([%s], ext=[%s])" % (ctx.spaces (), 
3109                                self.elts_to_py (self.elt_list, ctx),
3110                                self.elts_to_py (self.ext_list, ctx))
3111       else:
3112         return "%sasn1.CHOICE ([%s])" % (ctx.spaces (), self.elts_to_py (self.elt_list, ctx))
3113   def elts_to_py (self, list, ctx):
3114       ctx.indent ()
3115       def elt_to_py (nt):
3116           assert (nt.type == 'named_type')
3117           tagstr = 'None'
3118           if hasattr (nt, 'ident'):
3119               identstr = nt.ident
3120           else:
3121               if hasattr (nt.typ, 'val'):
3122                   identstr = nt.typ.val # XXX, making up name
3123               elif hasattr (nt.typ, 'name'):
3124                   identstr = nt.typ.name
3125               else:
3126                   identstr = ctx.make_new_name ()
3127
3128           if hasattr (nt.typ, 'type') and nt.typ.type == 'tag': # ugh
3129               tagstr = mk_tag_str (ctx,nt.typ.tag.cls,
3130                                    nt.typ.tag.tag_typ,nt.typ.tag.num)
3131       
3132
3133               nt = nt.typ
3134           return "('%s',%s,%s)" % (identstr, tagstr,
3135                                     nt.typ.to_python (ctx))
3136       indentstr = ",\n" + ctx.spaces ()
3137       rv =  indentstr.join ([elt_to_py (e) for e in list])
3138       ctx.outdent ()
3139       return rv
3140
3141   def eth_reg_sub(self, ident, ectx):
3142       #print "eth_reg_sub(ident='%s')" % (ident)
3143       for e in (self.elt_list):
3144           e.eth_reg(ident, ectx, tstrip=1, parent=ident)
3145       if hasattr(self, 'ext_list'):
3146           for e in (self.ext_list):
3147               e.eth_reg(ident, ectx, tstrip=1, parent=ident)
3148
3149   def eth_ftype(self, ectx):
3150     return ('FT_UINT32', 'BASE_DEC')
3151
3152   def eth_strings(self):
3153     return '$$'
3154
3155   def eth_need_tree(self):
3156     return True
3157
3158   def eth_has_vals(self):
3159     return True
3160
3161   def GetTTag(self, ectx):
3162     lst = self.elt_list
3163     cls = 'BER_CLASS_ANY/*choice*/'
3164     #if hasattr(self, 'ext_list'):
3165     #  lst.extend(self.ext_list)
3166     #if (len(lst) > 0):
3167     #  cls = lst[0].GetTag(ectx)[0]
3168     #for e in (lst):
3169     #  if (e.GetTag(ectx)[0] != cls):
3170     #    cls = '-1/*choice*/'
3171     return (cls, '-1/*choice*/')
3172
3173   def IndetermTag(self, ectx):
3174     #print "Choice IndetermTag()=%s" % (str(not self.HasOwnTag()))
3175     return not self.HasOwnTag()
3176
3177   def get_vals(self, ectx):
3178     tagval = False
3179     if (ectx.Ber()):
3180       lst = self.elt_list
3181       if hasattr(self, 'ext_list'):
3182         lst.extend(self.ext_list)
3183       if (len(lst) > 0):
3184         t = lst[0].GetTag(ectx)[0]
3185         tagval = True
3186       if (t == 'BER_CLASS_UNI'):
3187         tagval = False
3188       for e in (lst):
3189         if (e.GetTag(ectx)[0] != t):
3190           tagval = False
3191     vals = []
3192     cnt = 0
3193     for e in (self.elt_list):
3194       if (tagval): val = e.GetTag(ectx)[1]
3195       else: val = str(cnt)
3196       vals.append((val, e.name))
3197       cnt += 1
3198     if hasattr(self, 'ext_list'):
3199       for e in (self.ext_list):
3200         if (tagval): val = e.GetTag(ectx)[1]
3201         else: val = str(cnt)
3202         vals.append((val, e.name))
3203         cnt += 1
3204     return vals
3205
3206   def eth_type_vals(self, tname, ectx):
3207     out = '\n'
3208     vals = self.get_vals(ectx)
3209     out += ectx.eth_vals(tname, vals)
3210     return out
3211
3212   def eth_type_enum(self, tname, ectx):
3213     out = '\n'
3214     vals = self.get_vals(ectx)
3215     out += ectx.eth_enum(tname, vals)
3216     return out
3217
3218   def eth_type_default_pars(self, ectx, tname):
3219     pars = Type.eth_type_default_pars(self, ectx, tname)
3220     pars['TABLE'] = '%(TNAME)s_choice'
3221     return pars
3222
3223   def eth_type_default_table(self, ectx, tname):
3224     def out_item(val, e, ext, ectx):
3225       has_enum = ectx.eth_type[tname]['enum'] & EF_ENUM
3226       if (has_enum):
3227         vval = ectx.eth_enum_item(tname, e.name)
3228       else:
3229         vval = val
3230       f = fname + '/' + e.name
3231       ef = ectx.field[f]['ethname']
3232       t = ectx.eth_hf[ef]['ethtype']
3233       efd = ef
3234       if (ectx.field[f]['impl']):
3235         efd += '_impl'
3236       if (ectx.Ber()):
3237         opt = ''
3238         if (not e.HasOwnTag()):
3239           opt = 'BER_FLAGS_NOOWNTAG'
3240         elif (e.HasImplicitTag(ectx)):
3241           if (opt): opt += '|'
3242           opt += 'BER_FLAGS_IMPLTAG'
3243         if (not opt): opt = '0'
3244       if (ectx.Ber()):
3245         (tc, tn) = e.GetTag(ectx)
3246         out = '  { %3s, %-13s, %s, %s, dissect_%s },\n' \
3247               % (vval, tc, tn, opt, efd)
3248       elif (ectx.Per()):
3249         out = '  { %3s, %-24s, %-23s, dissect_%s_%s },\n' \
3250               % (vval, '&'+ectx.eth_hf[ef]['fullname'], ext, ectx.eth_type[t]['proto'], t)
3251       else:
3252         out = ''
3253       return out   
3254     # end out_item()
3255     #print "eth_type_default_table(tname='%s')" % (tname)
3256     fname = ectx.eth_type[tname]['ref'][0]
3257     tagval = False
3258     if (ectx.Ber()):
3259       lst = self.elt_list
3260       if hasattr(self, 'ext_list'):
3261         lst.extend(self.ext_list)
3262       if (len(lst) > 0):
3263         t = lst[0].GetTag(ectx)[0]
3264         tagval = True
3265       if (t == 'BER_CLASS_UNI'):
3266         tagval = False
3267       for e in (lst):
3268         if (e.GetTag(ectx)[0] != t):
3269           tagval = False
3270     table = "static const %(ER)s_choice_t %(TABLE)s[] = {\n"
3271     cnt = 0
3272     if hasattr(self, 'ext_list'):
3273       ext = 'ASN1_EXTENSION_ROOT'
3274     else:
3275       ext = 'ASN1_NO_EXTENSIONS'
3276     for e in (self.elt_list):
3277       if (tagval): val = e.GetTag(ectx)[1]
3278       else: val = str(cnt)
3279       table += out_item(val, e, ext, ectx)
3280       cnt += 1
3281     if hasattr(self, 'ext_list'):
3282       for e in (self.ext_list):
3283         if (tagval): val = e.GetTag(ectx)[1]
3284         else: val = str(cnt)
3285         table += out_item(val, e, 'ASN1_NOT_EXTENSION_ROOT', ectx)
3286         cnt += 1
3287     if (ectx.Ber()):
3288       table += "  { 0, 0, 0, 0, NULL }\n};\n"
3289     else:
3290       table += "  { 0, NULL, 0, NULL }\n};\n"
3291     return table
3292
3293   def eth_type_default_body(self, ectx, tname):
3294     if (ectx.Ber()):
3295       body = ectx.eth_fn_call('dissect_%(ER)s_choice', ret='offset',
3296                               par=(('%(PINFO)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s'),
3297                                    ('%(TABLE)s', '%(HF_INDEX)s', '%(ETT_INDEX)s'),
3298                                    ('%(VAL_PTR)s',),))
3299     elif (ectx.Per()):
3300       body = ectx.eth_fn_call('dissect_%(ER)s_choice', ret='offset',
3301                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
3302                                    ('%(ETT_INDEX)s', '%(TABLE)s',),
3303                                    ('%(VAL_PTR)s',),))
3304     else:
3305       body = '#error Can not decode %s' % (tname)
3306     return body
3307    
3308 #--- EnumeratedType -----------------------------------------------------------
3309 class EnumeratedType (Type):
3310   def to_python (self, ctx):
3311     def strify_one (named_num):
3312       return "%s=%s" % (named_num.ident, named_num.val)
3313     return "asn1.ENUM(%s)" % ",".join (map (strify_one, self.val))
3314
3315   def eth_ftype(self, ectx):
3316     return ('FT_UINT32', 'BASE_DEC')
3317
3318   def eth_strings(self):
3319     return '$$'
3320
3321   def eth_has_vals(self):
3322     return True
3323
3324   def GetTTag(self, ectx):
3325     return ('BER_CLASS_UNI', 'BER_UNI_TAG_ENUMERATED')
3326
3327   def get_vals_etc(self, ectx):
3328     vals = []
3329     lastv = 0
3330     used = {}
3331     maxv = 0
3332     root_num = 0
3333     ext_num = 0
3334     map_table = []
3335     for e in (self.val):
3336       if e.type == 'NamedNumber':
3337         used[int(e.val)] = True
3338     for e in (self.val):
3339       if e.type == 'NamedNumber':
3340         val = int(e.val)
3341       else:
3342         while used.has_key(lastv):
3343           lastv += 1
3344         val = lastv
3345         used[val] = True
3346       vals.append((val, e.ident))
3347       map_table.append(val)
3348       root_num += 1
3349       if val > maxv:
3350         maxv = val
3351     if self.ext is not None:
3352       for e in (self.ext):
3353         if e.type == 'NamedNumber':
3354           used[int(e.val)] = True
3355       for e in (self.ext):
3356         if e.type == 'NamedNumber':
3357           val = int(e.val)
3358         else:
3359           while used.has_key(lastv):
3360             lastv += 1
3361           val = lastv
3362           used[val] = True
3363         vals.append((val, e.ident))
3364         map_table.append(val)
3365         ext_num += 1
3366         if val > maxv:
3367           maxv = val
3368     need_map = False
3369     for i in range(len(map_table)):
3370       need_map = need_map or (map_table[i] != i)
3371     if (not need_map):
3372       map_table = None
3373     return (vals, root_num, ext_num, map_table)
3374
3375   def eth_type_vals(self, tname, ectx):
3376     out = '\n'
3377     vals = self.get_vals_etc(ectx)[0]
3378     out += ectx.eth_vals(tname, vals)
3379     return out
3380
3381   def eth_type_enum(self, tname, ectx):
3382     out = '\n'
3383     vals = self.get_vals_etc(ectx)[0]
3384     out += ectx.eth_enum(tname, vals)
3385     return out
3386
3387   def eth_type_default_pars(self, ectx, tname):
3388     pars = Type.eth_type_default_pars(self, ectx, tname)
3389     (root_num, ext_num, map_table) = self.get_vals_etc(ectx)[1:]
3390     if (self.ext != None):
3391       ext = 'TRUE'
3392     else:
3393       ext = 'FALSE'
3394     pars['ROOT_NUM'] = str(root_num)
3395     pars['EXT'] = ext
3396     pars['EXT_NUM'] = str(ext_num)
3397     if (map_table):
3398       pars['TABLE'] = '%(TNAME)s_value_map'
3399     else:
3400       pars['TABLE'] = 'NULL'
3401     return pars
3402
3403   def eth_type_default_table(self, ectx, tname):
3404     if (not ectx.Per()): return ''
3405     map_table = self.get_vals_etc(ectx)[3]
3406     if (map_table == None): return ''
3407     table = "static guint32 %(TABLE)s[%(ROOT_NUM)s+%(EXT_NUM)s] = {"
3408     table += ", ".join([str(v) for v in map_table])
3409     table += "};\n"
3410     return table
3411
3412   def eth_type_default_body(self, ectx, tname):
3413     if (ectx.Ber()):
3414       body = ectx.eth_fn_call('dissect_%(ER)s_integer', ret='offset',
3415                               par=(('%(IMPLICIT_TAG)s', '%(PINFO)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s', '%(HF_INDEX)s'),
3416                                    ('%(VAL_PTR)s',),))
3417     elif (ectx.Per()):
3418       body = ectx.eth_fn_call('dissect_%(ER)s_enumerated', ret='offset',
3419                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
3420                                    ('%(ROOT_NUM)s', '%(VAL_PTR)s', '%(EXT)s', '%(EXT_NUM)s', '%(TABLE)s',),))
3421     else:
3422       body = '#error Can not decode %s' % (tname)
3423     return body
3424
3425 #--- ExternalType -----------------------------------------------------------
3426 class ExternalType (Type):
3427   def eth_tname(self):
3428     return 'EXTERNAL'
3429
3430   def eth_ftype(self, ectx):
3431     return ('FT_NONE', 'BASE_NONE')
3432
3433   def eth_type_default_pars(self, ectx, tname):
3434     pars = Type.eth_type_default_pars(self, ectx, tname)
3435     pars['TYPE_REF_FN'] = 'NULL'
3436     return pars
3437
3438   def eth_type_default_body(self, ectx, tname):
3439     if (ectx.Ber()):  
3440       body = ectx.eth_fn_call('dissect_%(ER)s_external_type', ret='offset',
3441                               par=(('%(IMPLICIT_TAG)s', '%(PINFO)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(HF_INDEX)s', '%(TYPE_REF_FN)s',),))
3442     elif (ectx.Per()):
3443       body = ectx.eth_fn_call('dissect_%(ER)s_external_type', ret='offset',
3444                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s', '%(TYPE_REF_FN)s',),))
3445     else:
3446       body = '#error Can not decode %s' % (tname)
3447     return body
3448
3449 #--- OpenType -----------------------------------------------------------
3450 class OpenType (Type):
3451   def to_python (self, ctx):
3452     return "asn1.ANY"
3453
3454   def single_type(self):
3455     if (self.HasConstraint() and 
3456         self.constr.type == 'Type' and 
3457         self.constr.subtype.type == 'Type_Ref'):
3458       return self.constr.subtype.val
3459     return None
3460
3461   def eth_reg_sub(self, ident, ectx):
3462     t = self.single_type()
3463     if t:
3464       ectx.eth_dep_add(ident, t)
3465
3466   def eth_tname(self):
3467     t = self.single_type()
3468     if t:
3469       return 'OpenType_' + t
3470     else:
3471       return Type.eth_tname(self)
3472
3473   def eth_ftype(self, ectx):
3474     return ('FT_NONE', 'BASE_NONE')
3475
3476   def GetTTag(self, ectx):
3477     return ('BER_CLASS_ANY', '0')
3478
3479   def eth_type_default_pars(self, ectx, tname):
3480     pars = Type.eth_type_default_pars(self, ectx, tname)
3481     t = self.single_type()
3482     if t:
3483       t = ectx.type[t]['ethname']
3484       pars['TYPE_REF_PROTO'] = ectx.eth_type[t]['proto']
3485       pars['TYPE_REF_TNAME'] = t
3486       pars['TYPE_REF_FN'] = 'dissect_%(TYPE_REF_PROTO)s_%(TYPE_REF_TNAME)s'
3487     else:
3488       pars['TYPE_REF_FN'] = 'NULL'
3489     return pars
3490
3491   def eth_type_default_body(self, ectx, tname):
3492     if (ectx.Per()):
3493       body = ectx.eth_fn_call('dissect_%(ER)s_open_type', ret='offset',
3494                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s', '%(TYPE_REF_FN)s',),))
3495     else:
3496       body = '#error Can not decode %s' % (tname)
3497     return body
3498
3499 #--- AnyType -----------------------------------------------------------
3500 class AnyType (Type):
3501   def to_python (self, ctx):
3502     return "asn1.ANY"
3503
3504   def eth_ftype(self, ectx):
3505     return ('FT_NONE', 'BASE_NONE')
3506
3507   def GetTTag(self, ectx):
3508     return ('BER_CLASS_ANY', '0')
3509
3510   def eth_type_default_body(self, ectx, tname):
3511     body = '#error Can not decode %s' % (tname)
3512     return body
3513
3514 class Literal (Node):
3515     def to_python (self, ctx):
3516         return self.val
3517
3518 #--- NullType -----------------------------------------------------------------
3519 class NullType (Type):
3520   def to_python (self, ctx):
3521     return 'asn1.NULL'
3522
3523   def eth_tname(self):
3524     return 'NULL'
3525
3526   def GetTTag(self, ectx):
3527     return ('BER_CLASS_UNI', 'BER_UNI_TAG_NULL')
3528
3529   def eth_type_default_body(self, ectx, tname):
3530     if (ectx.Ber()):
3531       body = ectx.eth_fn_call('dissect_%(ER)s_null', ret='offset',
3532                               par=(('%(IMPLICIT_TAG)s', '%(PINFO)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s', '%(HF_INDEX)s'),))
3533     elif (ectx.Per()):
3534       body = ectx.eth_fn_call('dissect_%(ER)s_null', ret='offset',
3535                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),))
3536     else:
3537       body = '#error Can not decode %s' % (tname)
3538     return body
3539
3540 #--- RealType -----------------------------------------------------------------
3541 class RealType (Type):
3542   def to_python (self, ctx):
3543     return 'asn1.REAL'
3544
3545   def eth_tname(self):
3546     return 'REAL'
3547
3548   def GetTTag(self, ectx):
3549     return ('BER_CLASS_UNI', 'BER_UNI_TAG_REAL')
3550
3551   def eth_ftype(self, ectx):
3552     return ('FT_DOUBLE', 'BASE_NONE')
3553
3554   def eth_type_default_body(self, ectx, tname):
3555     if (ectx.Ber()):
3556       body = ectx.eth_fn_call('dissect_%(ER)s_real', ret='offset',
3557                               par=(('%(IMPLICIT_TAG)s', '%(PINFO)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s', '%(HF_INDEX)s'),
3558                                    ('%(VAL_PTR)s',),))
3559     elif (ectx.Per()):
3560       body = ectx.eth_fn_call('dissect_%(ER)s_real', ret='offset',
3561                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s', '%(VAL_PTR)s',),))
3562     else:
3563       body = '#error Can not decode %s' % (tname)
3564     return body
3565
3566 #--- BooleanType --------------------------------------------------------------
3567 class BooleanType (Type):
3568   def to_python (self, ctx):
3569     return 'asn1.BOOLEAN'
3570
3571   def eth_tname(self):
3572     return 'BOOLEAN'
3573
3574   def GetTTag(self, ectx):
3575     return ('BER_CLASS_UNI', 'BER_UNI_TAG_BOOLEAN')
3576
3577   def eth_ftype(self, ectx):
3578     return ('FT_BOOLEAN', '8')
3579
3580   def eth_type_default_body(self, ectx, tname):
3581     if (ectx.Ber()):
3582       body = ectx.eth_fn_call('dissect_%(ER)s_boolean', ret='offset',
3583                               par=(('%(IMPLICIT_TAG)s', '%(PINFO)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s', '%(HF_INDEX)s'),))
3584     elif (ectx.Per()):
3585       body = ectx.eth_fn_call('dissect_%(ER)s_boolean', ret='offset',
3586                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s', '%(VAL_PTR)s',),))
3587     else:
3588       body = '#error Can not decode %s' % (tname)
3589     return body
3590
3591 #--- OctetStringType ----------------------------------------------------------
3592 class OctetStringType (Type):
3593   def to_python (self, ctx):
3594     return 'asn1.OCTSTRING'
3595
3596   def eth_tname(self):
3597     if not self.HasConstraint():
3598       return 'OCTET_STRING'
3599     elif self.constr.IsSize():
3600       return 'OCTET_STRING' + '_' + self.constr.eth_constrname()
3601     else:
3602       return '#' + self.type + '_' + str(id(self))
3603
3604   def eth_ftype(self, ectx):
3605     return ('FT_BYTES', 'BASE_HEX')
3606
3607   def GetTTag(self, ectx):
3608     return ('BER_CLASS_UNI', 'BER_UNI_TAG_OCTETSTRING')
3609
3610   def eth_type_default_pars(self, ectx, tname):
3611     pars = Type.eth_type_default_pars(self, ectx, tname)
3612     (pars['MIN_VAL'], pars['MAX_VAL'], pars['EXT']) = self.eth_get_size_constr()
3613     return pars
3614
3615   def eth_type_default_body(self, ectx, tname):
3616     if (ectx.Ber()):
3617       body = ectx.eth_fn_call('dissect_%(ER)s_octet_string', ret='offset',
3618                               par=(('%(IMPLICIT_TAG)s', '%(PINFO)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s', '%(HF_INDEX)s'),
3619                                    ('%(VAL_PTR)s',),))
3620     elif (ectx.Per()):
3621       body = ectx.eth_fn_call('dissect_%(ER)s_octet_string', ret='offset',
3622                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
3623                                    ('%(MIN_VAL)s', '%(MAX_VAL)s', '%(VAL_PTR)s',),))
3624     else:
3625       body = '#error Can not decode %s' % (tname)
3626     return body
3627
3628 #--- CharacterStringType ------------------------------------------------------
3629 class CharacterStringType (Type):
3630   def eth_tname(self):
3631     if not self.HasConstraint():
3632       return self.eth_tsname()
3633     elif self.constr.IsSize():
3634       return self.eth_tsname() + '_' + self.constr.eth_constrname()
3635     else:
3636       return '#' + self.type + '_' + str(id(self))
3637
3638   def eth_ftype(self, ectx):
3639     return ('FT_STRING', 'BASE_NONE')
3640
3641 class RestrictedCharacterStringType (CharacterStringType):
3642   def to_python (self, ctx):
3643     return 'asn1.' + self.eth_tsname()
3644
3645   def GetTTag(self, ectx):
3646     return ('BER_CLASS_UNI', 'BER_UNI_TAG_' + self.eth_tsname())
3647
3648   def HasPermAlph(self):
3649     return (self.HasConstraint() and 
3650             (self.constr.IsPermAlph() or 
3651              (self.constr.type == 'Intersection' and (self.constr.subtype[0].IsPermAlph() or self.constr.subtype[1].IsPermAlph()))
3652             )
3653            )
3654
3655   def eth_type_default_pars(self, ectx, tname):
3656     pars = Type.eth_type_default_pars(self, ectx, tname)
3657     (pars['MIN_VAL'], pars['MAX_VAL'], pars['EXT']) = self.eth_get_size_constr()
3658     (pars['STRING_TYPE'], pars['STRING_TAG']) = (self.eth_tsname(), self.GetTTag(ectx)[1])
3659     (pars['ALPHABET'], pars['ALPHABET_LEN']) = ('NULL', '0')
3660     if self.HasPermAlph():
3661       if self.constr.IsPermAlph():
3662         pars['ALPHABET'] = self.constr.subtype.subtype
3663       elif self.constr.subtype[0].IsPermAlph():
3664         pars['ALPHABET'] = self.constr.subtype[0].subtype.subtype
3665       elif self.constr.subtype[1].IsPermAlph():
3666         pars['ALPHABET'] = self.constr.subtype[1].subtype.subtype
3667       pars['ALPHABET_LEN'] = 'strlen(%(ALPHABET)s)'
3668     return pars
3669
3670   def eth_type_default_body(self, ectx, tname):
3671     if (ectx.Ber()):
3672       body = ectx.eth_fn_call('dissect_%(ER)s_restricted_string', ret='offset',
3673                               par=(('%(IMPLICIT_TAG)s', '%(STRING_TAG)s'),
3674                                    ('%(PINFO)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s', '%(HF_INDEX)s'),
3675                                    ('%(VAL_PTR)s',),))
3676     elif (ectx.Per() and self.HasPermAlph()):
3677       body = ectx.eth_fn_call('dissect_%(ER)s_restricted_character_string', ret='offset',
3678                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
3679                                    ('%(MIN_VAL)s', '%(MAX_VAL)s', '%(ALPHABET)s', '%(ALPHABET_LEN)s'),
3680                                    ('%(VAL_PTR)s',),))
3681     elif (ectx.Per()):
3682       if (self.eth_tsname() == 'GeneralString'):
3683         body = ectx.eth_fn_call('dissect_%(ER)s_%(STRING_TYPE)s', ret='offset',
3684                                 par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),))
3685       elif (self.eth_tsname() == 'GeneralizedTime'):
3686         body = ectx.eth_fn_call('dissect_%(ER)s_VisibleString', ret='offset',
3687                                 par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
3688                                      ('%(MIN_VAL)s', '%(MAX_VAL)s',),))
3689       elif (self.eth_tsname() == 'UTCTime'):
3690         body = ectx.eth_fn_call('dissect_%(ER)s_VisibleString', ret='offset',
3691                                 par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
3692                                      ('%(MIN_VAL)s', '%(MAX_VAL)s',),))
3693       else:
3694         body = ectx.eth_fn_call('dissect_%(ER)s_%(STRING_TYPE)s', ret='offset',
3695                                 par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
3696                                      ('%(MIN_VAL)s', '%(MAX_VAL)s',),))
3697     else:
3698       body = '#error Can not decode %s' % (tname)
3699     return body
3700
3701 class BMPStringType (RestrictedCharacterStringType):
3702   def eth_tsname(self):
3703     return 'BMPString'
3704
3705 class GeneralStringType (RestrictedCharacterStringType):
3706   def eth_tsname(self):
3707     return 'GeneralString'
3708
3709 class GraphicStringType (RestrictedCharacterStringType):
3710   def eth_tsname(self):
3711     return 'GraphicString'
3712
3713 class IA5StringType (RestrictedCharacterStringType):
3714   def eth_tsname(self):
3715     return 'IA5String'
3716
3717 class NumericStringType (RestrictedCharacterStringType):
3718   def eth_tsname(self):
3719     return 'NumericString'
3720
3721 class PrintableStringType (RestrictedCharacterStringType):
3722   def eth_tsname(self):
3723     return 'PrintableString'
3724
3725 class TeletexStringType (RestrictedCharacterStringType):
3726   def eth_tsname(self):
3727     return 'TeletexString'
3728
3729 class T61StringType (RestrictedCharacterStringType):
3730   def eth_tsname(self):
3731     return 'T61String'
3732   def GetTTag(self, ectx):
3733     return ('BER_CLASS_UNI', 'BER_UNI_TAG_TeletexString')
3734
3735 class UniversalStringType (RestrictedCharacterStringType):
3736   def eth_tsname(self):
3737     return 'UniversalString'
3738
3739 class UTF8StringType (RestrictedCharacterStringType):
3740   def eth_tsname(self):
3741     return 'UTF8String'
3742
3743 class VideotexStringType (RestrictedCharacterStringType):
3744   def eth_tsname(self):
3745     return 'VideotexString'
3746
3747 class VisibleStringType (RestrictedCharacterStringType):
3748   def eth_tsname(self):
3749     return 'VisibleString'
3750
3751 class ISO646StringType (RestrictedCharacterStringType):
3752   def eth_tsname(self):
3753     return 'ISO646String'
3754   def GetTTag(self, ectx):
3755     return ('BER_CLASS_UNI', 'BER_UNI_TAG_VisibleString')
3756
3757 class UnrestrictedCharacterStringType (CharacterStringType):
3758   def to_python (self, ctx):
3759     return 'asn1.UnrestrictedCharacterString'
3760   def eth_tsname(self):
3761     return 'CHARACTER_STRING'
3762
3763 #--- UsefulType ---------------------------------------------------------------
3764 class GeneralizedTime (RestrictedCharacterStringType):
3765   def eth_tsname(self):
3766     return 'GeneralizedTime'
3767
3768   def eth_type_default_body(self, ectx, tname):
3769     if (ectx.Ber()):
3770       body = ectx.eth_fn_call('dissect_%(ER)s_%(STRING_TYPE)s', ret='offset',
3771                               par=(('%(IMPLICIT_TAG)s', '%(PINFO)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s', '%(HF_INDEX)s'),))
3772       return body
3773     else:
3774       return RestrictedCharacterStringType.eth_type_default_body(self, ectx, tname)
3775
3776 class UTCTime (RestrictedCharacterStringType):
3777   def eth_tsname(self):
3778     return 'UTCTime'
3779
3780 class ObjectDescriptor (RestrictedCharacterStringType):
3781   def eth_tsname(self):
3782     return 'ObjectDescriptor'
3783
3784   def eth_type_default_body(self, ectx, tname):
3785     if (ectx.Ber()):
3786       body = RestrictedCharacterStringType.eth_type_default_body(self, ectx, tname)
3787     elif (ectx.Per()):
3788       body = ectx.eth_fn_call('dissect_%(ER)s_object_descriptor', ret='offset',
3789                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s', '%(VAL_PTR)s',),))
3790     else:
3791       body = '#error Can not decode %s' % (tname)
3792     return body
3793
3794 #--- ObjectIdentifierType -----------------------------------------------------
3795 class ObjectIdentifierType (Type):
3796   def to_python (self, ctx):
3797     return 'asn1.OBJECT_IDENTIFIER'
3798
3799   def eth_tname(self):
3800     return 'OBJECT_IDENTIFIER'
3801
3802   def eth_ftype(self, ectx):
3803     return ('FT_OID', 'BASE_NONE')
3804
3805   def GetTTag(self, ectx):
3806     return ('BER_CLASS_UNI', 'BER_UNI_TAG_OID')
3807
3808   def eth_type_default_body(self, ectx, tname):
3809     if (ectx.Ber()):
3810       body = ectx.eth_fn_call('dissect_%(ER)s_object_identifier%(FN_VARIANT)s', ret='offset',
3811                               par=(('%(IMPLICIT_TAG)s', '%(PINFO)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s', '%(HF_INDEX)s', '%(VAL_PTR)s',),))
3812     elif (ectx.Per()):
3813       body = ectx.eth_fn_call('dissect_%(ER)s_object_identifier%(FN_VARIANT)s', ret='offset',
3814                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s', '%(VAL_PTR)s',),))
3815     else:
3816       body = '#error Can not decode %s' % (tname)
3817     return body
3818
3819 #--- ObjectIdentifierValue ----------------------------------------------------
3820 class ObjectIdentifierValue (Value):
3821   def get_num(self, path, val):
3822     return str(oid_names.get(path + '/' + val, val))
3823
3824   def to_str(self):
3825     out = ''
3826     path = ''
3827     first = True
3828     sep = ''
3829     for v in self.comp_list:
3830       if isinstance(v, Node) and (v.type == 'name_and_number'):
3831         vstr = v.number
3832       elif v.isdigit():
3833         vstr = v
3834       else:
3835         vstr = self.get_num(path, v)
3836       if first:
3837         if vstr.isdigit():
3838           out += '"' + vstr
3839         else:
3840           out += vstr + '"'
3841       else:
3842        out += sep + vstr
3843       path += sep + vstr
3844       first = False
3845       sep = '.'
3846     out += '"'
3847     return out
3848
3849   def get_dep(self):
3850     v = self.comp_list[0]
3851     if isinstance(v, Node) and (v.type == 'name_and_number'):
3852       return None
3853     elif v.isdigit():
3854       return None
3855     else:
3856       vstr = self.get_num('', v)
3857     if vstr.isdigit():
3858       return None
3859     else:
3860       return vstr
3861
3862 class NamedNumber(Node):
3863     def to_python (self, ctx):
3864         return "('%s',%s)" % (self.ident, self.val)
3865
3866 class NamedNumListBase(Node):
3867     def to_python (self, ctx):
3868         return "asn1.%s_class ([%s])" % (self.asn1_typ,",".join (
3869             map (lambda x: x.to_python (ctx), self.named_list)))
3870
3871 #--- IntegerType --------------------------------------------------------------
3872 class IntegerType (Type):
3873   def to_python (self, ctx):
3874         return "asn1.INTEGER_class ([%s])" % (",".join (
3875             map (lambda x: x.to_python (ctx), self.named_list)))
3876
3877   def add_named_value(self, ident, val):
3878     e = NamedNumber(ident = ident, val = val)
3879     if not self.named_list: 
3880       self.named_list = []
3881     self.named_list.append(e)
3882
3883   def eth_tname(self):
3884     if self.named_list:
3885       return Type.eth_tname(self)
3886     if not self.HasConstraint():
3887       return 'INTEGER'
3888     elif self.constr.type == 'SingleValue' or self.constr.type == 'ValueRange':
3889       return 'INTEGER' + '_' + self.constr.eth_constrname()
3890     else:
3891       return 'INTEGER' + '_' + self.constr.eth_tname()
3892
3893   def GetTTag(self, ectx):
3894     return ('BER_CLASS_UNI', 'BER_UNI_TAG_INTEGER')
3895
3896
3897   def eth_ftype(self, ectx):
3898     if self.HasConstraint():
3899       if not self.constr.IsNegativ():
3900         return ('FT_UINT32', 'BASE_DEC')
3901     return ('FT_INT32', 'BASE_DEC')
3902
3903   def eth_strings(self):
3904     if (self.named_list):
3905       return '$$'
3906     else:
3907       return 'NULL'
3908
3909   def eth_has_vals(self):
3910     if (self.named_list):
3911       return True
3912     else:
3913       return False
3914
3915   def get_vals(self, ectx):
3916     vals = []
3917     for e in (self.named_list):
3918       vals.append((int(e.val), e.ident))
3919     return vals
3920
3921   def eth_type_vals(self, tname, ectx):
3922     if not self.eth_has_vals(): return ''
3923     out = '\n'
3924     vals = self.get_vals(ectx)
3925     out += ectx.eth_vals(tname, vals)
3926     return out
3927
3928   def eth_type_enum(self, tname, ectx):
3929     if not self.eth_has_enum(tname, ectx): return ''
3930     out = '\n'
3931     vals = self.get_vals(ectx)
3932     out += ectx.eth_enum(tname, vals)
3933     return out
3934
3935   def eth_type_default_pars(self, ectx, tname):
3936     pars = Type.eth_type_default_pars(self, ectx, tname)
3937     if self.HasConstraint() and self.constr.IsValue():
3938       (pars['MIN_VAL'], pars['MAX_VAL'], pars['EXT']) = self.eth_get_value_constr()
3939     return pars
3940
3941   def eth_type_default_body(self, ectx, tname):
3942     if (ectx.Ber()):
3943       body = ectx.eth_fn_call('dissect_%(ER)s_integer', ret='offset',
3944                               par=(('%(IMPLICIT_TAG)s', '%(PINFO)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s', '%(HF_INDEX)s'),
3945                                    ('%(VAL_PTR)s',),))
3946     elif (ectx.Per() and not self.HasConstraint()):
3947       body = ectx.eth_fn_call('dissect_%(ER)s_integer', ret='offset',
3948                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s', '%(VAL_PTR)s'),))
3949     elif (ectx.Per() and ((self.constr.type == 'SingleValue') or (self.constr.type == 'ValueRange'))):
3950       body = ectx.eth_fn_call('dissect_%(ER)s_constrained_integer', ret='offset',
3951                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
3952                                    ('%(MIN_VAL)s', '%(MAX_VAL)s', '%(VAL_PTR)s', '%(EXT)s'),))
3953     else:
3954       body = '#error Can not decode %s' % (tname)
3955     return body
3956
3957 #--- BitStringType ------------------------------------------------------------
3958 class BitStringType (Type):
3959   def to_python (self, ctx):
3960         return "asn1.BITSTRING_class ([%s])" % (",".join (
3961             map (lambda x: x.to_python (ctx), self.named_list)))
3962
3963   def eth_tname(self):
3964     if self.named_list:
3965       return Type.eth_tname(self)
3966     elif not self.HasConstraint():
3967       return 'BIT_STRING'
3968     elif self.constr.IsSize():
3969       return 'BIT_STRING' + '_' + self.constr.eth_constrname()
3970     else:
3971       return '#' + self.type + '_' + str(id(self))
3972
3973   def GetTTag(self, ectx):
3974     return ('BER_CLASS_UNI', 'BER_UNI_TAG_BITSTRING')
3975
3976   def eth_ftype(self, ectx):
3977     return ('FT_BYTES', 'BASE_HEX')
3978
3979   def eth_need_tree(self):
3980     return self.named_list
3981
3982   def eth_named_bits(self):
3983     bits = []
3984     if (self.named_list):
3985       for e in (self.named_list):
3986         bits.append((int(e.val), e.ident))
3987     return bits
3988
3989   def eth_type_default_pars(self, ectx, tname):
3990     pars = Type.eth_type_default_pars(self, ectx, tname)
3991     (pars['MIN_VAL'], pars['MAX_VAL'], pars['EXT']) = self.eth_get_size_constr()
3992     if not pars.has_key('ETT_INDEX'):
3993       pars['ETT_INDEX'] = '-1'
3994     pars['TABLE'] = 'NULL'
3995     if self.eth_named_bits():
3996       pars['TABLE'] = '%(TNAME)s_bits'
3997     return pars
3998
3999   def eth_type_default_table(self, ectx, tname):
4000     #print "eth_type_default_table(tname='%s')" % (tname)
4001     table = ''
4002     bits = self.eth_named_bits()
4003     if (bits):
4004       table = ectx.eth_bits(tname, bits)
4005     return table
4006
4007   def eth_type_default_body(self, ectx, tname):
4008     if (ectx.Ber()):
4009       body = ectx.eth_fn_call('dissect_%(ER)s_bitstring', ret='offset',
4010                               par=(('%(IMPLICIT_TAG)s', '%(PINFO)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s'),
4011                                    ('%(TABLE)s', '%(HF_INDEX)s', '%(ETT_INDEX)s',),
4012                                    ('%(VAL_PTR)s',),))
4013     elif (ectx.Per()):
4014       body = ectx.eth_fn_call('dissect_%(ER)s_bit_string', ret='offset',
4015                               par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
4016                                    ('%(MIN_VAL)s', '%(MAX_VAL)s','%(EXT)s','%(VAL_PTR)s'),))
4017     else:
4018       body = '#error Can not decode %s' % (tname)
4019     return body
4020
4021
4022 #==============================================================================
4023     
4024 def p_module_list_1 (t):
4025     'module_list : module_list module_def'
4026     t[0] = t[1] + [t[2]]
4027
4028 def p_module_list_2 (t):
4029     'module_list : module_def'
4030     t[0] = [t[1]]
4031
4032
4033 #--- ITU-T Recommendation X.680 -----------------------------------------------
4034
4035
4036 # 11 ASN.1 lexical items --------------------------------------------------------
4037
4038 # 11.2 Type references
4039 def p_type_ref (t):
4040   'type_ref : UCASE_IDENT'
4041   t[0] = Type_Ref(val=t[1])
4042
4043 # 11.3 Identifiers
4044 def p_identifier (t):
4045   'identifier : LCASE_IDENT'
4046   t[0] = t[1]
4047
4048 # 11.4 Value references
4049 def p_valuereference (t):
4050   'valuereference : LCASE_IDENT'
4051   t[0] = t[1]
4052
4053 # 11.5 Module references
4054 def p_modulereference (t):
4055   'modulereference : UCASE_IDENT'
4056   t[0] = t[1]
4057
4058
4059 # 12 Module definition --------------------------------------------------------
4060
4061 # 12.1
4062 def p_module_def (t):
4063     'module_def : ModuleIdentifier DEFINITIONS TagDefault ASSIGNMENT BEGIN module_body END'
4064     t[0] = Module (ident = t[1], tag_def = t[3], body = t[6])
4065
4066 def p_TagDefault_1 (t):
4067   '''TagDefault : EXPLICIT TAGS
4068   | IMPLICIT TAGS
4069   | AUTOMATIC TAGS'''
4070   t[0] = Default_Tags (dfl_tag = t[1])
4071
4072 def p_TagDefault_2 (t):
4073   'TagDefault : '
4074   # 12.2 The "TagDefault" is taken as EXPLICIT TAGS if it is "empty".
4075   t[0] = Default_Tags (dfl_tag = 'EXPLICIT') 
4076
4077 def p_ModuleIdentifier_1 (t):
4078   'ModuleIdentifier : modulereference DefinitiveIdentifier' # name, oid
4079   t [0] = Node('module_ident', val = t[1], ident = t[2])
4080
4081 def p_ModuleIdentifier_2 (t):
4082   'ModuleIdentifier : modulereference' # name, oid
4083   t [0] = Node('module_ident', val = t[1], ident = None)
4084
4085 def p_DefinitiveIdentifier (t):
4086   'DefinitiveIdentifier : ObjectIdentifierValue'
4087   t[0] = t[1]
4088
4089 # XXX originally we had both type_ref and module_ref, but that caused
4090 # a reduce/reduce conflict (because both were UCASE_IDENT).  Presumably
4091 # this didn't cause a problem in the original ESNACC grammar because it
4092 # was LALR(1) and PLY is (as of 1.1) only SLR.
4093
4094 #def p_module_ref (t):
4095 #    'module_ref : UCASE_IDENT'
4096 #    t[0] = t[1]
4097
4098 def p_assigned_ident_1 (t):
4099     'assigned_ident : ObjectIdentifierValue'
4100     t[0] = t[1]
4101
4102 def p_assigned_ident_2 (t):
4103     'assigned_ident : LCASE_IDENT'
4104     t[0] = t[1]
4105
4106 def p_assigned_ident_3 (t):
4107     'assigned_ident : '
4108     pass
4109
4110 def p_module_body_1 (t):
4111     'module_body : exports Imports AssignmentList'
4112     t[0] = Module_Body (exports = t[1], imports = t[2], assign_list = t[3])
4113
4114 def p_module_body_2 (t):
4115     'module_body : '
4116     t[0] = Node ('module_body', exports = [], imports = [],
4117                  assign_list = [])
4118
4119 def p_exports_1 (t):
4120     'exports : EXPORTS syms_exported SEMICOLON'
4121     t[0] = t[2]
4122
4123 def p_exports_2 (t):
4124     'exports : '
4125     t[0] = []
4126
4127 def p_syms_exported_1 (t):
4128     'syms_exported : exp_sym_list'
4129     t[0] = t[1]
4130
4131 def p_syms_exported_2 (t):
4132     'syms_exported : '
4133     t[0] = []
4134
4135 def p_exp_sym_list_1 (t):
4136     'exp_sym_list : Symbol'
4137     t[0] = [t[1]]
4138
4139 def p_exp_sym_list_2 (t):
4140     'exp_sym_list : exp_sym_list COMMA Symbol'
4141     t[0] = t[1] + [t[3]]
4142     
4143
4144 def p_Imports_1(t):
4145   'Imports : IMPORTS SymbolsImported SEMICOLON'
4146   t[0] = t[2]
4147
4148 def p_Imports_2 (t):
4149   'Imports : '
4150   t[0] = []
4151
4152 def p_SymbolsImported_1(t):
4153   'SymbolsImported : '
4154   t[0] = []
4155
4156 def p_SymbolsImported_2 (t):
4157   'SymbolsImported : SymbolsFromModuleList'
4158   t[0] = t[1]
4159
4160 def p_SymbolsFromModuleList_1 (t):
4161    'SymbolsFromModuleList : SymbolsFromModuleList SymbolsFromModule'
4162    t[0] = t[1] + [t[2]]
4163
4164 def p_SymbolsFromModuleList_2 (t):
4165    'SymbolsFromModuleList : SymbolsFromModule'
4166    t[0] = [t[1]]
4167
4168 def p_SymbolsFromModule (t):
4169   'SymbolsFromModule : SymbolList FROM GlobalModuleReference'
4170   t[0] = Node ('SymbolList', symbol_list = t[1], module = t[3])
4171
4172 def p_GlobalModuleReference (t):
4173   'GlobalModuleReference : modulereference assigned_ident'
4174   t [0] = Node('module_ident', val = t[1], ident = t[2])
4175
4176 def p_SymbolList_1 (t):
4177   'SymbolList : Symbol'
4178   t[0] = [t[1]]
4179
4180 def p_SymbolList_2 (t):
4181   'SymbolList : SymbolList COMMA Symbol'
4182   t[0] = t[1] + [t[3]]
4183
4184 def p_Symbol (t):
4185   '''Symbol : Reference
4186             | ParameterizedReference'''
4187   t[0] = t[1]
4188
4189 def p_Reference (t):
4190   '''Reference : type_ref
4191                | valuereference
4192                | objectclassreference'''
4193   t[0] = t[1]
4194
4195 def p_AssignmentList_1 (t):
4196   'AssignmentList : AssignmentList Assignment'
4197   t[0] = t[1] + [t[2]]
4198
4199 def p_AssignmentList_2 (t):
4200   'AssignmentList : Assignment SEMICOLON'
4201   t[0] = [t[1]]
4202
4203 def p_AssignmentList_3 (t):
4204   'AssignmentList : Assignment'
4205   t[0] = [t[1]]
4206
4207 def p_Assignment (t):
4208   '''Assignment : TypeAssignment
4209                 | ValueAssignment
4210                 | ObjectClassAssignment
4211                 | ObjectAssignment
4212                 | ObjectSetAssignment
4213                 | ParameterizedTypeAssignment
4214                 | pyquote'''
4215   t[0] = t[1]
4216
4217
4218 # 13 Referencing type and value definitions -----------------------------------
4219
4220 # 13.1
4221 def p_DefinedType (t): 
4222   '''DefinedType : ext_type_ref
4223   | type_ref
4224   | ParameterizedType'''
4225   t[0] = t[1]
4226
4227 def p_DefinedValue(t):
4228   '''DefinedValue : ext_val_ref
4229                   | identifier'''
4230   t[0] = t[1]
4231
4232
4233 # 15 Assigning types and values -----------------------------------------------
4234
4235 # 15.1
4236 def p_TypeAssignment (t):
4237   'TypeAssignment : UCASE_IDENT ASSIGNMENT Type'
4238   t[0] = t[3]
4239   t[0].SetName(t[1])
4240
4241 # 15.2
4242 def p_ValueAssignment (t):
4243   'ValueAssignment : valuereference Type ASSIGNMENT Value'
4244   t[0] = value_assign (ident = t[1], typ = t[2], val = t[4])
4245
4246
4247 # 16 Definition of types and values -------------------------------------------
4248
4249 # 16.1
4250 def p_Type (t):
4251   '''Type : BuiltinType
4252           | ReferencedType
4253           | ConstrainedType'''
4254   t[0] = t[1]
4255
4256 # 16.2
4257 def p_BuiltinType (t):
4258   '''BuiltinType : AnyType
4259                  | BitStringType
4260                  | BooleanType
4261                  | CharacterStringType
4262                  | ChoiceType
4263                  | EnumeratedType
4264                  | ExternalType
4265                  | IntegerType
4266                  | NullType
4267                  | ObjectClassFieldType
4268                  | ObjectIdentifierType
4269                  | OctetStringType
4270                  | RealType
4271                  | SequenceType
4272                  | SequenceOfType
4273                  | SetType
4274                  | SetOfType
4275                  | selection_type
4276                  | TaggedType'''
4277   t[0] = t[1]
4278
4279 # 16.3
4280 def p_ReferencedType (t):
4281   '''ReferencedType : DefinedType
4282                     | UsefulType'''
4283   t[0] = t[1]
4284
4285 def p_ext_type_ref (t):
4286     'ext_type_ref : type_ref DOT type_ref'
4287     # XXX coerce 1st type_ref to module_ref
4288     t[0] = Node ('ext_type_ref', module = t[1], typ = t[3])
4289
4290 # 16.5
4291 def p_NamedType (t):
4292   'NamedType : identifier Type'
4293   t[0] = t[2]
4294   t[0].SetName (t[1]) 
4295
4296 # 16.7
4297 def p_Value (t):
4298   '''Value : BuiltinValue
4299            | ReferencedValue'''
4300   t[0] = t[1]
4301
4302 # 16.9
4303 def p_BuiltinValue (t):
4304   '''BuiltinValue : BooleanValue
4305                   | IntegerValue
4306                   | ObjectIdentifierValue
4307                   | RealValue
4308                   | SequenceValue
4309                   | hex_string
4310                   | binary_string
4311                   | char_string''' # XXX we don't support {data} here
4312   t[0] = t[1]
4313
4314 # 16.11
4315 def p_ReferencedValue (t):
4316   '''ReferencedValue : DefinedValue'''
4317   t[0] = t[1]
4318
4319 # 16.13
4320 #def p_NamedValue (t):
4321 #  'NamedValue : identifier Value'
4322 #  t[0] = Node ('NamedValue', ident = t[1], value = t[2])
4323
4324
4325 # 17 Notation for the boolean type --------------------------------------------
4326
4327 # 17.1
4328 def p_BooleanType (t):
4329   'BooleanType : BOOLEAN'
4330   t[0] = BooleanType ()
4331
4332 # 17.2
4333 def p_BooleanValue (t):
4334   '''BooleanValue : TRUE
4335                   | FALSE'''
4336   t[0] = t[1]
4337
4338
4339 # 18 Notation for the integer type --------------------------------------------
4340
4341 # 18.1
4342 def p_IntegerType_1 (t):
4343   'IntegerType : INTEGER'
4344   t[0] = IntegerType (named_list = None)
4345
4346 def p_IntegerType_2 (t):
4347   'IntegerType : INTEGER LBRACE NamedNumberList RBRACE'
4348   t[0] = IntegerType(named_list = t[3])
4349
4350 def p_NamedNumberList_1 (t):
4351   'NamedNumberList : NamedNumber'
4352   t[0] = [t[1]]
4353
4354 def p_NamedNumberList_2 (t):
4355   'NamedNumberList : NamedNumberList COMMA NamedNumber'
4356   t[0] = t[1] + [t[3]]
4357
4358 def p_NamedNumber (t):
4359   '''NamedNumber : identifier LPAREN SignedNumber RPAREN
4360                  | identifier LPAREN DefinedValue RPAREN'''
4361   t[0] = NamedNumber(ident = t[1], val = t[3])
4362
4363 def p_SignedNumber_1 (t):
4364   'SignedNumber : NUMBER'
4365   t[0] = t [1]
4366
4367 def p_SignedNumber_2 (t):
4368   'SignedNumber : MINUS NUMBER'
4369   t[0] = '-' + t[2]
4370
4371 # 18.9
4372 def p_IntegerValue (t):
4373   'IntegerValue : SignedNumber'
4374   t[0] = t [1]
4375
4376 # 19 Notation for the enumerated type -----------------------------------------
4377
4378 # 19.1
4379 def p_EnumeratedType (t):
4380     'EnumeratedType : ENUMERATED LBRACE Enumerations RBRACE'
4381     t[0] = EnumeratedType (val = t[3]['val'], ext = t[3]['ext'])
4382
4383 def p_Enumerations_1 (t):
4384     'Enumerations : Enumeration'
4385     t[0] = { 'val' : t[1], 'ext' : None }
4386
4387 def p_Enumerations_2 (t):
4388     'Enumerations : Enumeration COMMA ELLIPSIS ExceptionSpec'
4389     t[0] = { 'val' : t[1], 'ext' : [] }
4390
4391 def p_Enumerations_3 (t):
4392     'Enumerations : Enumeration COMMA ELLIPSIS ExceptionSpec COMMA Enumeration'
4393     t[0] = { 'val' : t[1], 'ext' : t[6] }
4394
4395 def p_Enumeration_1 (t):
4396     'Enumeration : EnumerationItem'
4397     t[0] = [t[1]]
4398
4399 def p_Enumeration_2 (t):
4400     'Enumeration : Enumeration COMMA EnumerationItem'
4401     t[0] = t[1] + [t[3]]
4402
4403 def p_EnumerationItem (t):
4404     '''EnumerationItem : Identifier
4405                        | NamedNumber'''
4406     t[0] = t[1]
4407
4408 def p_Identifier (t):
4409     'Identifier : identifier'
4410     t[0] = Node ('Identifier', ident = t[1])
4411
4412
4413 # 20 Notation for the real type -----------------------------------------------
4414
4415 # 20.1
4416 def p_RealType (t):
4417   'RealType : REAL'
4418   t[0] = RealType ()
4419
4420 # 20.6
4421 def p_RealValue (t):
4422   '''RealValue : REAL_NUMBER
4423                | SpecialRealValue'''
4424   t[0] = t [1]
4425
4426 def p_SpecialRealValue (t):
4427   '''SpecialRealValue : PLUS_INFINITY
4428                       | MINUS_INFINITY'''
4429   t[0] = t[1]
4430
4431
4432 # 21 Notation for the bitstring type ------------------------------------------
4433
4434 # 21.1
4435 def p_BitStringType_1 (t):
4436     'BitStringType : BIT STRING'
4437     t[0] = BitStringType (named_list = None)
4438
4439 def p_BitStringType_2 (t):
4440     'BitStringType : BIT STRING LBRACE NamedBitList RBRACE'
4441     t[0] = BitStringType (named_list = t[4])
4442
4443 def p_NamedBitList_1 (t):
4444     'NamedBitList : NamedBit'
4445     t[0] = [t[1]]
4446
4447 def p_NamedBitList_2 (t):
4448     'NamedBitList : NamedBitList COMMA NamedBit'
4449     t[0] = t[1] + [t[3]]
4450
4451 def p_NamedBit (t):
4452     '''NamedBit : identifier LPAREN NUMBER RPAREN
4453                 | identifier LPAREN DefinedValue RPAREN'''
4454     t[0] = NamedNumber (ident = t[1], val = t[3])
4455
4456
4457 # 22 Notation for the octetstring type ----------------------------------------
4458
4459 # 22.1
4460 def p_OctetStringType (t):
4461     'OctetStringType : OCTET STRING'
4462     t[0] = OctetStringType ()
4463
4464
4465 # 23 Notation for the null type -----------------------------------------------
4466
4467 # 23.1
4468 def p_NullType (t):
4469     'NullType : NULL'
4470     t[0] = NullType ()
4471
4472 # 23.3
4473 #def p_NullValue (t):
4474 #    'NullValue : NULL'
4475 #    t[0] = t[1]
4476
4477
4478 # 24 Notation for sequence types ----------------------------------------------
4479
4480 # 24.1
4481 def p_SequenceType_1 (t):
4482     'SequenceType : SEQUENCE LBRACE RBRACE'
4483     t[0] = SequenceType (elt_list = [])
4484
4485 def p_SequenceType_2 (t):
4486     'SequenceType : SEQUENCE LBRACE ComponentTypeLists RBRACE'
4487     if t[3].has_key('ext_list'):
4488         t[0] = SequenceType (elt_list = t[3]['elt_list'], ext_list = t[3]['ext_list'])
4489     else:
4490         t[0] = SequenceType (elt_list = t[3]['elt_list'])
4491
4492 def p_ExtensionAndException_1 (t):
4493     'ExtensionAndException : ELLIPSIS'
4494     t[0] = []
4495
4496 def p_OptionalExtensionMarker_1 (t):
4497     'OptionalExtensionMarker : COMMA ELLIPSIS'
4498     t[0] = True
4499
4500 def p_OptionalExtensionMarker_2 (t):
4501     'OptionalExtensionMarker : '
4502     t[0] = False
4503
4504 def p_ComponentTypeLists_1 (t):
4505     'ComponentTypeLists : element_type_list'
4506     t[0] = {'elt_list' : t[1]}
4507
4508 def p_ComponentTypeLists_2 (t):
4509     'ComponentTypeLists : element_type_list COMMA ExtensionAndException extension_additions OptionalExtensionMarker'
4510     t[0] = {'elt_list' : t[1], 'ext_list' : t[4]}
4511
4512 def p_ComponentTypeLists_3 (t):
4513     'ComponentTypeLists : ExtensionAndException extension_additions OptionalExtensionMarker'
4514     t[0] = {'elt_list' : [], 'ext_list' : t[2]}
4515
4516 def p_extension_additions_1 (t):
4517     'extension_additions : extension_addition_list'
4518     t[0] = t[1]
4519
4520 def p_extension_additions_2 (t):
4521     'extension_additions : '
4522     t[0] = []
4523
4524 def p_extension_addition_list_1 (t):
4525     'extension_addition_list : COMMA extension_addition'
4526     t[0] = [t[2]]
4527
4528 def p_extension_addition_list_2 (t):
4529     'extension_addition_list : extension_addition_list COMMA extension_addition'
4530     t[0] = t[1] + [t[3]]
4531
4532 def p_extension_addition_1 (t):
4533     'extension_addition : element_type'
4534     t[0] = t[1]
4535
4536 def p_element_type_list_1 (t):
4537     'element_type_list : element_type'
4538     t[0] = [t[1]]
4539
4540 def p_element_type_list_2 (t):
4541     'element_type_list : element_type_list COMMA element_type'
4542     t[0] = t[1] + [t[3]]
4543
4544 def p_element_type_1 (t):
4545     'element_type : NamedType'
4546     t[0] = Node ('elt_type', val = t[1], optional = 0)
4547
4548 def p_element_type_2 (t):
4549     'element_type : NamedType OPTIONAL'
4550     t[0] = Node ('elt_type', val = t[1], optional = 1)
4551
4552 def p_element_type_3 (t):
4553     'element_type : NamedType DEFAULT Value'
4554     t[0] = Node ('elt_type', val = t[1], optional = 1, default = t[3])
4555 #          /*
4556 #           * this rules uses NamedValue instead of Value
4557 #           * for the stupid choice value syntax (fieldname value)
4558 #           * it should be like a set/seq value (ie with
4559 #           * enclosing { }
4560 #           */
4561
4562 # XXX get to COMPONENTS later
4563
4564 # 24.17
4565 def p_SequenceValue_1 (t):
4566   'SequenceValue : LBRACE RBRACE'
4567   t[0] = []
4568
4569
4570 #def p_SequenceValue_2 (t):
4571 #  'SequenceValue : LBRACE ComponentValueList RBRACE'
4572 #  t[0] = t[2]
4573     
4574 #def p_ComponentValueList_1 (t):
4575 #    'ComponentValueList : NamedValue'
4576 #    t[0] = [t[1]]
4577
4578 #def p_ComponentValueList_2 (t):
4579 #    'ComponentValueList : ComponentValueList COMMA NamedValue'
4580 #    t[0] = t[1] + [t[3]]
4581
4582
4583 # 25 Notation for sequence-of types -------------------------------------------
4584
4585 # 25.1
4586 def p_SequenceOfType (t):
4587     '''SequenceOfType : SEQUENCE OF Type
4588                       | SEQUENCE OF NamedType'''
4589     t[0] = SequenceOfType (val = t[3], size_constr = None)
4590
4591
4592 # 26 Notation for set types ---------------------------------------------------
4593
4594 # 26.1
4595 def p_SetType_1 (t):
4596     'SetType : SET LBRACE RBRACE'
4597     if t[3].has_key('ext_list'):
4598         t[0] = SetType (elt_list = [])
4599
4600 def p_SetType_2 (t):
4601     'SetType : SET LBRACE ComponentTypeLists RBRACE'
4602     if t[3].has_key('ext_list'):
4603         t[0] = SetType (elt_list = t[3]['elt_list'], ext_list = t[3]['ext_list'])
4604     else:
4605         t[0] = SetType (elt_list = t[3]['elt_list'])
4606
4607
4608 # 27 Notation for set-of types ------------------------------------------------
4609
4610 # 27.1
4611 def p_SetOfType (t):
4612     '''SetOfType : SET OF Type
4613                  | SET OF NamedType'''
4614     t[0] = SetOfType (val = t[3])
4615
4616 # 28 Notation for choice types ------------------------------------------------
4617
4618 # 28.1
4619 def p_ChoiceType (t):
4620     'ChoiceType : CHOICE LBRACE alternative_type_lists RBRACE'
4621     if t[3].has_key('ext_list'):
4622         t[0] = ChoiceType (elt_list = t[3]['elt_list'], ext_list = t[3]['ext_list'])
4623     else:
4624         t[0] = ChoiceType (elt_list = t[3]['elt_list'])
4625
4626 def p_alternative_type_lists_1 (t):
4627     'alternative_type_lists : alternative_type_list'
4628     t[0] = {'elt_list' : t[1]}
4629
4630 def p_alternative_type_lists_2 (t):
4631     '''alternative_type_lists : alternative_type_list COMMA ExtensionAndException extension_addition_alternatives OptionalExtensionMarker'''
4632     t[0] = {'elt_list' : t[1], 'ext_list' : t[4]}
4633
4634 def p_extension_addition_alternatives_1 (t):
4635     'extension_addition_alternatives : extension_addition_alternatives_list'
4636     t[0] = t[1]
4637
4638 def p_extension_addition_alternatives_2 (t):
4639     'extension_addition_alternatives : '
4640     t[0] = []
4641
4642 def p_extension_addition_alternatives_list_1 (t):
4643     'extension_addition_alternatives_list : COMMA extension_addition_alternative'
4644     t[0] = [t[2]]
4645
4646 def p_extension_addition_alternatives_list_2 (t):
4647     'extension_addition_alternatives_list : extension_addition_alternatives_list COMMA extension_addition_alternative'
4648     t[0] = t[1] + [t[3]]
4649
4650 def p_extension_addition_alternative_1 (t):
4651     'extension_addition_alternative : NamedType'
4652     t[0] = t[1]
4653
4654 def p_alternative_type_list_1 (t):
4655     'alternative_type_list : NamedType'
4656     t[0] = [t[1]]
4657
4658 def p_alternative_type_list_2 (t):
4659     'alternative_type_list : alternative_type_list COMMA NamedType'
4660     t[0] = t[1] + [t[3]]
4661
4662 def p_selection_type (t): # XXX what is this?
4663     'selection_type : identifier LT Type'
4664     return Node ('seltype', ident = t[1], typ = t[3])
4665
4666 # 30 Notation for tagged types ------------------------------------------------
4667
4668 # 30.1
4669 def p_TaggedType_1 (t):
4670     'TaggedType : Tag Type'
4671     t[1].mode = 'default'
4672     t[0] = t[2]
4673     t[0].AddTag(t[1])
4674
4675 def p_TaggedType_2 (t):
4676     '''TaggedType : Tag IMPLICIT Type
4677                   | Tag EXPLICIT Type'''
4678     t[1].mode = t[2]
4679     t[0] = t[3]
4680     t[0].AddTag(t[1])
4681
4682 def p_Tag (t):
4683     'Tag : LBRACK Class ClassNumber RBRACK'
4684     t[0] = Tag(cls = t[2], num = t[3])
4685
4686 def p_ClassNumber_1 (t):
4687     'ClassNumber : number'
4688     t[0] = t[1]
4689
4690 def p_ClassNumber_2 (t):
4691     'ClassNumber : DefinedValue'
4692     t[0] = t[1]
4693
4694 def p_Class_1 (t):
4695     '''Class : UNIVERSAL
4696              | APPLICATION
4697              | PRIVATE'''
4698     t[0] = t[1]
4699
4700 def p_Class_2 (t):
4701     'Class :'
4702     t[0] = 'CONTEXT'
4703
4704
4705 def p_AnyType (t):
4706     'AnyType : ANY'
4707     t[0] = AnyType ()
4708
4709
4710 # 31 Notation for the object identifier type ----------------------------------
4711
4712 # 31.1
4713 def p_ObjectIdentifierType (t):
4714   'ObjectIdentifierType : OBJECT IDENTIFIER'
4715   t[0] = ObjectIdentifierType()
4716
4717 # 31.3
4718 def p_ObjectIdentifierValue (t):
4719     'ObjectIdentifierValue : LBRACE oid_comp_list RBRACE'
4720     t[0] = ObjectIdentifierValue (comp_list=t[2])
4721
4722 def p_oid_comp_list_1 (t):
4723     'oid_comp_list : oid_comp_list ObjIdComponents'
4724     t[0] = t[1] + [t[2]]
4725
4726 def p_oid_comp_list_2 (t):
4727     'oid_comp_list : ObjIdComponents'
4728     t[0] = [t[1]]
4729
4730 def p_ObjIdComponents (t):
4731   '''ObjIdComponents : NameForm
4732                      | NumberForm
4733                      | NameAndNumberForm'''
4734   t[0] = t[1]
4735
4736 def p_NameForm (t):
4737   'NameForm : LCASE_IDENT'
4738   t [0] = t[1]
4739
4740 def p_NumberForm (t):
4741   '''NumberForm : NUMBER'''
4742 #                | DefinedValue'''
4743   t [0] = t[1]
4744
4745 def p_NameAndNumberForm (t):
4746   'NameAndNumberForm : LCASE_IDENT LPAREN NumberForm RPAREN'
4747   t[0] = Node('name_and_number', ident = t[1], number = t[3])
4748
4749 # 34 Notation for the external type -------------------------------------------
4750
4751 # 34.1
4752 def p_ExternalType (t):
4753   'ExternalType : EXTERNAL'
4754   t[0] = ExternalType()
4755
4756 # 36 Notation for character string types --------------------------------------
4757
4758 # 36.1
4759 def p_CharacterStringType (t):
4760     '''CharacterStringType : RestrictedCharacterStringType
4761     | UnrestrictedCharacterStringType'''
4762     t[0] = t[1]
4763
4764
4765 # 37 Definition of restricted character string types --------------------------
4766
4767 def p_RestrictedCharacterStringType_1 (t):
4768     'RestrictedCharacterStringType : BMPString'
4769     t[0] = BMPStringType ()
4770 def p_RestrictedCharacterStringType_2 (t):
4771     'RestrictedCharacterStringType : GeneralString'
4772     t[0] = GeneralStringType ()
4773 def p_RestrictedCharacterStringType_3 (t):
4774     'RestrictedCharacterStringType : GraphicString'
4775     t[0] = GraphicStringType ()
4776 def p_RestrictedCharacterStringType_4 (t):
4777     'RestrictedCharacterStringType : IA5String'
4778     t[0] = IA5StringType ()
4779 def p_RestrictedCharacterStringType_5 (t):
4780     'RestrictedCharacterStringType : ISO646String'
4781     t[0] = ISO646StringType ()
4782 def p_RestrictedCharacterStringType_6 (t):
4783     'RestrictedCharacterStringType : NumericString'
4784     t[0] = NumericStringType ()
4785 def p_RestrictedCharacterStringType_7 (t):
4786     'RestrictedCharacterStringType : PrintableString'
4787     t[0] = PrintableStringType ()
4788 def p_RestrictedCharacterStringType_8 (t):
4789     'RestrictedCharacterStringType : TeletexString'
4790     t[0] = TeletexStringType ()
4791 def p_RestrictedCharacterStringType_9 (t):
4792     'RestrictedCharacterStringType : T61String'
4793     t[0] = T61StringType ()
4794 def p_RestrictedCharacterStringType_10 (t):
4795     'RestrictedCharacterStringType : UniversalString'
4796     t[0] = UniversalStringType ()
4797 def p_RestrictedCharacterStringType_11 (t):
4798     'RestrictedCharacterStringType : UTF8String'
4799     t[0] = UTF8StringType ()
4800 def p_RestrictedCharacterStringType_12 (t):
4801     'RestrictedCharacterStringType : VideotexString'
4802     t[0] = VideotexStringType ()
4803 def p_RestrictedCharacterStringType_13 (t):
4804     'RestrictedCharacterStringType : VisibleString'
4805     t[0] = VisibleStringType ()
4806
4807
4808 # 40 Definition of unrestricted character string types ------------------------
4809
4810 # 40.1
4811 def p_UnrestrictedCharacterStringType (t):
4812     'UnrestrictedCharacterStringType : CHARACTER STRING'
4813     t[0] = UnrestrictedCharacterStringType ()
4814
4815
4816 # 41 Notation for types defined in clauses 42 to 44 ---------------------------
4817
4818 # 42 Generalized time ---------------------------------------------------------
4819
4820 def p_UsefulType_1 (t):
4821   'UsefulType : GeneralizedTime'
4822   t[0] = GeneralizedTime()
4823
4824 # 43 Universal time -----------------------------------------------------------
4825
4826 def p_UsefulType_2 (t):
4827   'UsefulType : UTCTime'
4828   t[0] = UTCTime()
4829
4830 # 44 The object descriptor type -----------------------------------------------
4831
4832 def p_UsefulType_3 (t):
4833   'UsefulType : ObjectDescriptor'
4834   t[0] = ObjectDescriptor()
4835
4836
4837 # 45 Constrained types --------------------------------------------------------
4838
4839 # 45.1
4840 def p_ConstrainedType_1 (t):
4841     'ConstrainedType : Type Constraint'
4842     t[0] = t[1]
4843     t[0].AddConstraint(t[2])
4844
4845 def p_ConstrainedType_2 (t):
4846     'ConstrainedType : TypeWithConstraint'
4847     t[0] = t[1]
4848
4849 # 45.5
4850 def p_TypeWithConstraint_1 (t):
4851     '''TypeWithConstraint : SET Constraint OF Type
4852                           | SET SizeConstraint OF Type'''
4853     t[0] = SetOfType (val = t[4], constr = t[2])
4854
4855 def p_TypeWithConstraint_2 (t):
4856     '''TypeWithConstraint : SEQUENCE Constraint OF Type
4857                           | SEQUENCE SizeConstraint OF Type'''
4858     t[0] = SequenceOfType (val = t[4], constr = t[2])
4859
4860 def p_TypeWithConstraint_3 (t):
4861     '''TypeWithConstraint : SET Constraint OF NamedType
4862                           | SET SizeConstraint OF NamedType'''
4863     t[0] = SetOfType (val = t[4], constr = t[2])
4864
4865 def p_TypeWithConstraint_4 (t):
4866     '''TypeWithConstraint : SEQUENCE Constraint OF NamedType
4867                           | SEQUENCE SizeConstraint OF NamedType'''
4868     t[0] = SequenceOfType (val = t[4], constr = t[2])
4869
4870 # 45.6
4871 # 45.7
4872 def p_Constraint (t):
4873     'Constraint : LPAREN ConstraintSpec ExceptionSpec RPAREN'
4874     t[0] = t[2]
4875
4876 def p_ConstraintSpec (t):
4877     '''ConstraintSpec : ElementSetSpecs
4878                       | GeneralConstraint'''
4879     t[0] = t[1]
4880
4881 # 46 Element set specification ------------------------------------------------
4882
4883 # 46.1
4884 def p_ElementSetSpecs_1 (t):
4885     'ElementSetSpecs : RootElementSetSpec'
4886     t[0] = t[1]
4887
4888 def p_ElementSetSpecs_2 (t):
4889     'ElementSetSpecs : RootElementSetSpec COMMA ELLIPSIS'
4890     t[0] = t[1]
4891     t[0].ext = True
4892
4893 def p_ElementSetSpecs_3 (t):
4894     'ElementSetSpecs : RootElementSetSpec COMMA ELLIPSIS COMMA ElementSetSpecs'
4895     t[0] = t[1]
4896     t[0].ext = True
4897
4898 # skip compound constraints, only simple ones are supported
4899
4900 def p_RootElementSetSpec_1 (t):
4901     'RootElementSetSpec : SubtypeElements'
4902     t[0] = t[1]
4903
4904 def p_RootElementSetSpec_2 (t):
4905     'RootElementSetSpec : SubtypeElements IntersectionMark SubtypeElements'
4906     t[0] = Constraint(type = 'Intersection', subtype = [t[1], t[3]])
4907
4908 def p_IntersectionMark (t):
4909     '''IntersectionMark : CIRCUMFLEX
4910                         | INTERSECTION'''
4911
4912 # 47 Subtype elements ---------------------------------------------------------
4913
4914 # 47.1 General
4915 def p_SubtypeElements (t):
4916     '''SubtypeElements : SingleValue
4917                        | ContainedSubtype
4918                        | ValueRange
4919                        | PermittedAlphabet
4920                        | SizeConstraint
4921                        | TypeConstraint
4922                        | InnerTypeConstraints
4923                        | PatternConstraint'''
4924     t[0] = t[1]
4925
4926 # 47.2 Single value
4927 # 47.2.1
4928 def p_SingleValue (t):
4929     'SingleValue : Value'
4930     t[0] = Constraint(type = 'SingleValue', subtype = t[1]) 
4931
4932 # 47.3 Contained subtype
4933 # 47.3.1
4934 def p_ContainedSubtype (t):
4935     'ContainedSubtype : Includes Type'
4936     t[0] = Constraint(type = 'ContainedSubtype', subtype = t[2]) 
4937
4938 def p_Includes (t):
4939     '''Includes : INCLUDES 
4940                 | '''
4941
4942 # 47.4 Value range
4943 # 47.4.1
4944 def p_ValueRange (t):
4945     'ValueRange : lower_end_point RANGE upper_end_point'
4946     t[0] = Constraint(type = 'ValueRange', subtype = [t[1], t[3]])
4947
4948 # 47.4.3
4949 def p_lower_end_point_1 (t):
4950     'lower_end_point : lower_end_value '
4951     t[0] = t[1]
4952
4953 def p_lower_end_point_2 (t):
4954     'lower_end_point : lower_end_value LT' # XXX LT first?
4955     t[0] = t[1] # but not inclusive range
4956     
4957 def p_upper_end_point_1 (t):
4958     'upper_end_point : upper_end_value'
4959     t[0] = t[1]
4960
4961 def p_upper_end_point_2 (t):
4962     'upper_end_point : LT upper_end_value'
4963     t[0] = t[1] # but not inclusive range
4964
4965 def p_lower_end_value (t):
4966     '''lower_end_value : Value
4967                        | MIN'''
4968     t[0] = t[1] # XXX
4969
4970 def p_upper_end_value (t):
4971     '''upper_end_value : Value
4972                        | MAX'''
4973     t[0] = t[1]
4974
4975 # 47.5 Size constraint
4976 # 47.5.1
4977 def p_SizeConstraint (t):
4978     'SizeConstraint : SIZE Constraint'
4979     t[0] = Constraint (type = 'Size', subtype = t[2])
4980
4981 # 47.6 Type constraint
4982 # 47.6.1
4983 def p_TypeConstraint (t):
4984     'TypeConstraint : Type'
4985     t[0] = Constraint (type = 'Type', subtype = t[1])
4986
4987 # 47.7 Permitted alphabet
4988 # 47.7.1
4989 def p_PermittedAlphabet (t):
4990     'PermittedAlphabet : FROM Constraint'
4991     t[0] = Constraint (type = 'From', subtype = t[2])
4992
4993 # 47.8 Inner subtyping
4994 # 47.8.1
4995 def p_InnerTypeConstraints (t):
4996     '''InnerTypeConstraints : WITH COMPONENT SingleTypeConstraint
4997                             | WITH COMPONENTS MultipleTypeConstraints'''
4998     pass # ignore PER invisible constraint
4999
5000 # 47.8.3
5001 def p_SingleTypeConstraint (t):
5002     'SingleTypeConstraint : Constraint'
5003     t[0] = t[1]
5004
5005 # 47.8.4
5006 def p_MultipleTypeConstraints (t):
5007     '''MultipleTypeConstraints : FullSpecification
5008                                | PartialSpecification'''
5009     t[0] = t[1]
5010
5011 def p_FullSpecification (t):
5012     'FullSpecification : LBRACE TypeConstraints RBRACE'
5013     t[0] = t[2]
5014
5015 def p_PartialSpecification (t):
5016     'PartialSpecification : LBRACE ELLIPSIS COMMA TypeConstraints RBRACE'
5017     t[0] = t[4]
5018
5019 def p_TypeConstraints_1 (t):
5020     'TypeConstraints : named_constraint'
5021     t [0] = [t[1]]
5022
5023 def p_TypeConstraints_2 (t):
5024     'TypeConstraints : TypeConstraints COMMA named_constraint'
5025     t[0] = t[1] + [t[3]]
5026
5027 def p_named_constraint_1 (t):
5028     'named_constraint : identifier constraint'
5029     return Node ('named_constraint', ident = t[1], constr = t[2])
5030
5031 def p_named_constraint_2 (t):
5032     'named_constraint : constraint'
5033     return Node ('named_constraint', constr = t[1])
5034
5035 def p_constraint (t):
5036     'constraint : value_constraint presence_constraint'
5037     t[0] = Node ('constraint', value = t[1], presence = t[2])
5038
5039 def p_value_constraint_1 (t):
5040     'value_constraint : Constraint'
5041     t[0] = t[1]
5042
5043 def p_value_constraint_2 (t):
5044     'value_constraint : '
5045     pass
5046
5047 def p_presence_constraint_1 (t):
5048     '''presence_constraint : PRESENT
5049                  | ABSENT
5050                  | OPTIONAL'''
5051     t[0] = t[1]
5052     
5053 def p_presence_constraint_2 (t):
5054     '''presence_constraint : '''
5055     pass
5056
5057 # 47.9 Pattern constraint
5058 # 47.9.1
5059 def p_PatternConstraint (t):
5060     'PatternConstraint : PATTERN Value'
5061     t[0] = Constraint (type = 'Pattern', subtype = t[2])
5062
5063 # 49 The exception identifier
5064
5065 # 49.4
5066 def p_ExceptionSpec (t):
5067     'ExceptionSpec : '
5068     pass
5069
5070 #  /*-----------------------------------------------------------------------*/
5071 #  /* Value Notation Productions */
5072 #  /*-----------------------------------------------------------------------*/
5073
5074
5075
5076
5077 def p_ext_val_ref (t):
5078     'ext_val_ref : type_ref DOT identifier'
5079     # XXX coerce type_ref to module_ref
5080     return Node ('ext_val_ref', module = t[1], ident = t[3])
5081
5082
5083 # see X.208 if you are dubious about lcase only for identifier 
5084
5085 def p_binary_string (t):
5086     'binary_string : BSTRING'
5087     t[0] = t[1]
5088
5089 def p_hex_string (t):
5090     'hex_string : HSTRING'
5091     t[0] = t[1]
5092
5093 def p_char_string (t):
5094     'char_string : QSTRING'
5095     t[0] = t[1]
5096
5097 def p_number (t):
5098   'number : NUMBER'
5099   t[0] = t[1]
5100
5101
5102 #--- ITU-T Recommendation X.681 -----------------------------------------------
5103
5104 # 7 ASN.1 lexical items -------------------------------------------------------
5105
5106 # 7.1 Information object class references
5107
5108 def p_objectclassreference (t):
5109   'objectclassreference : CLASS_IDENT'
5110   t[0] = Class_Ref(val=t[1])
5111
5112 # 7.2 Information object references
5113
5114 #def p_objectreference (t):
5115 #  'objectreference : LCASE_IDENT'
5116 #  t[0] = t[1]
5117
5118 # 7.3 Information object set references
5119
5120 def p_objectsetreference (t):
5121   'objectsetreference : UCASE_IDENT'
5122   t[0] = t[1]
5123
5124 # 7.4 Type field references
5125
5126 def p_typefieldreference (t):
5127   'typefieldreference : AMPERSAND UCASE_IDENT'
5128   t[0] = t[2]
5129
5130 # 7.5 Value field references
5131
5132 def p_valuefieldreference (t):
5133   'valuefieldreference : AMPERSAND LCASE_IDENT'
5134   t[0] = t[2]
5135
5136 # 8 Referencing definitions
5137
5138 # 8.1
5139 def p_DefinedObjectClass (t):
5140   '''DefinedObjectClass : objectclassreference
5141                         | UsefulObjectClassReference'''
5142   t[0] = t[1]
5143
5144 # 8.4
5145 def p_UsefulObjectClassReference (t):
5146   '''UsefulObjectClassReference : TYPE_IDENTIFIER 
5147                                 | ABSTRACT_SYNTAX'''
5148   t[0] = t[1]
5149
5150 # 9 Information object class definition and assignment
5151
5152 # 9.1
5153 def p_ObjectClassAssignment (t):
5154   '''ObjectClassAssignment : CLASS_IDENT ASSIGNMENT ObjectClass
5155                            | UCASE_IDENT ASSIGNMENT ObjectClass'''
5156   t[0] = t[3]
5157   t[0].SetName(t[1])
5158
5159 # 9.2
5160 def p_ObjectClass (t):
5161   '''ObjectClass : ObjectClassDefn'''
5162   t[0] = t[1]
5163
5164 # 9.3
5165 def p_ObjectClassDefn (t):
5166   '''ObjectClassDefn : CLASS lbraceignore rbraceignore
5167                      | CLASS lbraceignore rbraceignore WithSyntaxSpec'''
5168   t[0] = ObjectClass()
5169
5170 def p_WithSyntaxSpec (t):
5171   'WithSyntaxSpec : WITH SYNTAX lbraceignore rbraceignore'
5172   t[0] = None
5173
5174 # 9.14
5175 def p_FieldName (t):
5176   '''FieldName : typefieldreference
5177                | valuefieldreference'''
5178   t[0] = t[1]
5179
5180 # 11 Information object definition and assignment
5181
5182 # 11.1
5183 def p_ObjectAssignment (t):
5184   'ObjectAssignment : valuereference CLASS_IDENT ASSIGNMENT Object'
5185   t[0] = Node('ObjectAssignment', name=t[1], cls=t[2], val=t[4])
5186
5187 # 11.4
5188 def p_Object (t):
5189   'Object : lbraceignore rbraceignore'
5190   t[0] = None
5191
5192 # 12 Information object set definition and assignment
5193
5194 # 12.1
5195 def p_ObjectSetAssignment (t):
5196   'ObjectSetAssignment : objectsetreference CLASS_IDENT ASSIGNMENT ObjectSet'
5197   t[0] = Node('ObjectSetAssignment', name=t[1], cls=t[2], val=t[4])
5198
5199 # 12.3
5200 def p_ObjectSet (t):
5201   'ObjectSet : lbraceignore rbraceignore'
5202   t[0] = None
5203
5204 # 14 Notation for the object class field type ---------------------------------
5205
5206 # 14.1
5207 def p_ObjectClassFieldType (t):
5208   'ObjectClassFieldType : DefinedObjectClass DOT FieldName'
5209   t[0] = get_type_from_class(t[1], t[3])
5210
5211 class_names = {
5212 }
5213
5214 useful_object_class_types = {
5215   # Annex A
5216   'TYPE-IDENTIFIER/id'   : lambda : ObjectIdentifierType(),
5217   'TYPE-IDENTIFIER/Type' : lambda : OpenType(),
5218   # Annex B
5219   'ABSTRACT-SYNTAX/id'       : lambda : ObjectIdentifierType(),
5220   'ABSTRACT-SYNTAX/Type'     : lambda : OpenType(),
5221   'ABSTRACT-SYNTAX/property' : lambda : BitStringType(),
5222 }
5223
5224 object_class_types = {
5225 }
5226
5227 object_class_typerefs = {
5228 }
5229
5230 class_types_creator = {
5231   'ObjectIdentifierType' : lambda : ObjectIdentifierType(),
5232   'OpenType'             : lambda : OpenType(),
5233 }
5234
5235 def is_class_ident(name):
5236   return class_names.has_key(name)
5237
5238 def add_class_ident(name):
5239   class_names[name] = name
5240
5241 def get_type_from_class(cls, fld):
5242   if (isinstance(cls, Class_Ref)):
5243     key = cls.val + '/' + fld
5244   else:
5245     key = cls + '/' + fld
5246
5247   if object_class_typerefs.has_key(key):
5248     return Type_Ref(val=object_class_typerefs[key])
5249
5250   creator = lambda : AnyType()
5251   creator = useful_object_class_types.get(key, creator)
5252   creator = object_class_types.get(key, creator)
5253   return creator()
5254
5255 def set_type_to_class(cls, fld, typename, typeref = None):
5256   key = cls + '/' + fld
5257   if object_class_types.has_key(key): return False
5258   if object_class_typerefs.has_key(key): return False
5259
5260   if (typename == 'TypeReference'):
5261     if not typeref: return False
5262     object_class_typerefs[key] = typeref
5263     return True
5264
5265   creator = class_types_creator.get(typename)
5266   if creator:
5267     object_class_types[key] = creator
5268     return True
5269   else:
5270     return False
5271
5272 #--- ITU-T Recommendation X.682 -----------------------------------------------
5273
5274 # 8 General constraint specification ------------------------------------------
5275
5276 # 8.1
5277 def p_GeneralConstraint (t):
5278   '''GeneralConstraint : UserDefinedConstraint
5279                        | TableConstraint'''
5280 #                         | ContentsConstraint''
5281   t[0] = t[1]
5282
5283 # 9 User-defined constraints --------------------------------------------------
5284
5285 # 9.1
5286 def p_UserDefinedConstraint (t):
5287   'UserDefinedConstraint : CONSTRAINED BY LBRACE UserDefinedConstraintParameterList RBRACE'
5288   t[0] = Constraint(type = 'UserDefined', subtype = t[4]) 
5289
5290 def p_UserDefinedConstraintParameterList_1 (t):
5291   'UserDefinedConstraintParameterList : '
5292   t[0] = []
5293
5294 def p_UserDefinedConstraintParameterList_2 (t):
5295   'UserDefinedConstraintParameterList : UserDefinedConstraintParameter'
5296   t[0] = [t[1]]
5297
5298 def p_UserDefinedConstraintParameterList_3 (t):
5299   'UserDefinedConstraintParameterList : UserDefinedConstraintParameterList COMMA UserDefinedConstraintParameter'
5300   t[0] = t[1] + [t[3]]
5301
5302 # 9.3
5303 def p_UserDefinedConstraintParameter (t):
5304   'UserDefinedConstraintParameter : type_ref'
5305   t[0] = t[1]
5306
5307 # 10 Table constraints, including component relation constraints
5308
5309 # 10.3
5310 def p_TableConstraint (t):
5311   '''TableConstraint : SimpleTableConstraint
5312                      | ComponentRelationConstraint'''
5313   t[0] = Constraint(type = 'Table', subtype = t[1]) 
5314
5315 def p_SimpleTableConstraint (t):
5316   'SimpleTableConstraint : LBRACE UCASE_IDENT RBRACE'
5317   t[0] = t[2]
5318
5319 # 10.7
5320 def p_ComponentRelationConstraint (t):
5321   'ComponentRelationConstraint : LBRACE UCASE_IDENT RBRACE LBRACE AT LCASE_IDENT RBRACE'
5322   t[0] = t[2] + '@' + t[6]
5323
5324 #--- ITU-T Recommendation X.683 -----------------------------------------------
5325
5326 # 8 Parameterized assignments -------------------------------------------------
5327
5328 # 8.1
5329
5330 # 8.2
5331 def p_ParameterizedTypeAssignment (t):
5332   'ParameterizedTypeAssignment : UCASE_IDENT ParameterList ASSIGNMENT Type'
5333   t[0] = t[4]
5334   t[0].SetName(t[1])  # t[0].SetName(t[1] + 'xxx')
5335
5336 # 8.3
5337 def p_ParameterList (t):
5338   'ParameterList : lbraceignore rbraceignore'
5339
5340 #def p_ParameterList (t):
5341 #  'ParameterList : LBRACE Parameters RBRACE'
5342 #  t[0] = t[2]
5343
5344 #def p_Parameters_1 (t):
5345 #  'Parameters : Parameter'
5346 #  t[0] = [t[1]]
5347
5348 #def p_Parameters_2 (t):
5349 #  'Parameters : Parameters COMMA Parameter'
5350 #  t[0] = t[1] + [t[3]]
5351
5352 #def p_Parameter_1 (t):
5353 #  'Parameter : Type COLON Reference'
5354 #  t[0] = [t[1], t[3]]
5355
5356 #def p_Parameter_2 (t):
5357 #  'Parameter : Reference'
5358 #  t[0] = t[1]
5359
5360
5361 # 9 Referencing parameterized definitions -------------------------------------
5362
5363 # 9.1
5364 def p_ParameterizedReference (t):
5365   'ParameterizedReference : type_ref LBRACE RBRACE'
5366   t[0] = t[1]
5367   #t[0].val += 'xxx'
5368
5369 # 9.2
5370 def p_ParameterizedType (t):
5371   'ParameterizedType : type_ref ActualParameterList'
5372   t[0] = t[1]
5373   #t[0].val += 'xxx'
5374
5375 # 9.5
5376 def p_ActualParameterList (t):
5377   'ActualParameterList : lbraceignore rbraceignore'
5378
5379 #def p_ActualParameterList (t):
5380 #  'ActualParameterList : LBRACE ActualParameters RBRACE'
5381 #  t[0] = t[2]
5382
5383 #def p_ActualParameters_1 (t):
5384 #  'ActualParameters : ActualParameter'
5385 #  t[0] = [t[1]]
5386
5387 #def p_ActualParameters_2 (t):
5388 #  'ActualParameters : ActualParameters COMMA ActualParameter'
5389 #  t[0] = t[1] + [t[3]]
5390
5391 #def p_ActualParameter (t):
5392 #  '''ActualParameter : Type
5393 #                     | Value'''
5394 #  t[0] = t[1]
5395
5396
5397 #  {...} block to be ignored
5398 def p_lbraceignore(t):
5399   'lbraceignore : braceignorebegin LBRACE'
5400   t[0] = t[1]
5401
5402 def p_braceignorebegin(t):
5403   'braceignorebegin : '
5404   global lexer
5405   lexer.level = 1
5406   lexer.begin('braceignore')
5407
5408 def p_rbraceignore(t):
5409   'rbraceignore : braceignoreend RBRACE'
5410   t[0] = t[2]
5411
5412 def p_braceignoreend(t):
5413   'braceignoreend : '
5414   global lexer
5415   lexer.begin('INITIAL')
5416
5417 def p_error(t):
5418   global input_file
5419   raise ParseError(t, input_file)
5420
5421 def p_pyquote (t):
5422     '''pyquote : PYQUOTE'''
5423     t[0] = PyQuote (val = t[1])
5424
5425
5426 def testlex (s):
5427     lexer.input (s)
5428     while 1:
5429         token = lexer.token ()
5430         if not token:
5431             break
5432         print token
5433
5434
5435 def do_module (ast, defined_dict):
5436     assert (ast.type == 'Module')
5437     ctx = Ctx (defined_dict)
5438     print ast.to_python (ctx)
5439     print ctx.output_assignments ()
5440     print ctx.output_pyquotes ()
5441
5442 def eth_do_module (ast, ectx):
5443     assert (ast.type == 'Module')
5444     if ectx.dbg('s'): print ast.str_depth(0)
5445     ast.to_eth(ectx)
5446
5447 def testyacc(s, fn, defined_dict):
5448     ast = yacc.parse(s, debug=0)
5449     time_str = time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime())
5450     print """#!/usr/bin/env python
5451 # Auto-generated from %s at %s
5452 from PyZ3950 import asn1""" % (fn, time_str)
5453     for module in ast:
5454       eth_do_module (module, defined_dict)
5455
5456
5457 # Wireshark compiler
5458 def eth_usage():
5459   print """
5460 asn2wrs [-h|?] [-d dbg] [-b] [-p proto] [-c conform_file] [-e] input_file(s) ...
5461   -h|?          : usage
5462   -b            : BER (default is PER)
5463   -u            : unaligned (default is aligned)
5464   -p proto      : protocol name (implies -S)
5465                   default is module-name from input_file (renamed by #.MODULE if present)
5466   -F            : create 'field functions'
5467   -T            : tagged type support (experimental)
5468   -o name       : output files name core (default is <proto>)
5469   -O dir        : output directory
5470   -c conform_file : conformation file
5471   -I path       : path for conformance file includes
5472   -e            : create conformation file for exported types
5473   -S            : single output for multiple modules
5474   -s template   : single file output (template is input file without .c/.h extension)
5475   -k            : keep intermediate files though single file output is used
5476   -L            : suppress #line directive from .cnf file
5477   input_file(s) : input ASN.1 file(s)
5478
5479   -d dbg     : debug output, dbg = [l][y][p][s][a][t][c][o]
5480                l - lex 
5481                y - yacc
5482                p - parsing
5483                s - internal ASN.1 structure
5484                a - list of assignments
5485                t - tables
5486                c - conformance values
5487                o - list of output files
5488 """
5489
5490 def eth_main():
5491   global input_file
5492   global lexer
5493   print "ASN.1 to Wireshark dissector compiler";
5494   try:
5495     opts, args = getopt.getopt(sys.argv[1:], "h?d:buXp:FTo:O:c:I:eSs:kL");
5496   except getopt.GetoptError:
5497     eth_usage(); sys.exit(2)
5498   if len(args) < 1:
5499     eth_usage(); sys.exit(2)
5500
5501   conform = EthCnf()
5502   conf_to_read = None
5503   output = EthOut()
5504   ectx = EthCtx(conform, output)
5505   ectx.encoding = 'per'
5506   ectx.proto_opt = None
5507   ectx.fld_opt = {}
5508   ectx.tag_opt = False
5509   ectx.outnm_opt = None
5510   ectx.aligned = True
5511   ectx.dbgopt = ''
5512   ectx.new = True
5513   ectx.expcnf = False
5514   ectx.merge_modules = False
5515   ectx.conform.suppress_line = False;
5516   ectx.output.outnm = None
5517   ectx.output.single_file = None
5518   for o, a in opts:
5519     if o in ("-h", "-?"):
5520       eth_usage(); sys.exit(2)
5521     if o in ("-c",):
5522       conf_to_read = a
5523     if o in ("-I",):
5524       ectx.conform.include_path.append(a)
5525     if o in ("-X",):
5526         warnings.warn("Command line option -X is obsolete and can be removed")
5527
5528   if conf_to_read:
5529     ectx.conform.read(conf_to_read)
5530
5531   for o, a in opts:
5532     if o in ("-h", "-?", "-c", "-I", "-X"):
5533       pass  # already processed
5534     else:
5535       par = []
5536       if a: par.append(a)
5537       ectx.conform.set_opt(o, par, "commandline", 0)
5538
5539   (ld, yd, pd) = (0, 0, 0); 
5540   if ectx.dbg('l'): ld = 1
5541   if ectx.dbg('y'): yd = 1
5542   if ectx.dbg('p'): pd = 2
5543   lexer = lex.lex(debug=ld)
5544   yacc.yacc(method='LALR', debug=yd)
5545   ast = []
5546   for fn in args:
5547     input_file = fn
5548     f = open (fn, "r")
5549     ast.extend(yacc.parse(f.read(), lexer=lexer, debug=pd))
5550     f.close ()
5551   ectx.eth_clean()
5552   for module in ast:
5553     eth_do_module(module, ectx)
5554     if (not ectx.merge_modules):  # output for each module
5555       ectx.eth_prepare()
5556       ectx.eth_do_output()
5557       ectx.eth_clean()
5558   if (ectx.merge_modules):  # common output for all module
5559     ectx.eth_prepare()
5560     ectx.eth_do_output()
5561
5562   if ectx.dbg('c'):
5563     ectx.conform.dbg_print()
5564   ectx.conform.unused_report()
5565
5566   if ectx.dbg('o'):
5567     ectx.output.dbg_print()
5568   ectx.output.make_single_file()
5569     
5570
5571 # Python compiler
5572 def main():
5573     testfn = testyacc
5574     if len (sys.argv) == 1:
5575         while 1:
5576             s = raw_input ('Query: ')
5577             if len (s) == 0:
5578                 break
5579             testfn (s, 'console', {})
5580     else:
5581         defined_dict = {}
5582         for fn in sys.argv [1:]:
5583             f = open (fn, "r")
5584             testfn (f.read (), fn, defined_dict)
5585             f.close ()
5586             lexer.lineno = 1
5587   
5588
5589 #--- BODY ---------------------------------------------------------------------
5590
5591 if __name__ == '__main__':
5592   if (os.path.splitext(os.path.basename(sys.argv[0]))[0].lower() in ('asn2wrs', 'asn2eth')):
5593     eth_main()
5594   else:
5595     main()
5596
5597 #------------------------------------------------------------------------------