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