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