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