dcerpc-nt: add UNION_ALIGN_TO... helpers
[wireshark-sm.git] / tools / asn2wrs.py
blobaa5673cfc7c675d841333e9c414429d0692a6748
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 suports 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 tagval = False
4616 lst = self.elt_list[:]
4617 if hasattr(self, 'ext_list'):
4618 lst.extend(self.ext_list)
4619 if (len(lst) > 0) and (not (ectx.Per() or ectx.Oer()) or lst[0].HasOwnTag()):
4620 t = lst[0].GetTag(ectx)[0]
4621 tagval = True
4622 else:
4623 t = ''
4624 tagval = False
4625 if (t == 'BER_CLASS_UNI'):
4626 tagval = False
4627 for e in (lst):
4628 if not (ectx.Per() or ectx.Oer()) or e.HasOwnTag():
4629 tt = e.GetTag(ectx)[0]
4630 else:
4631 tt = ''
4632 tagval = False
4633 if (tt != t):
4634 tagval = False
4635 return tagval
4637 def get_vals(self, ectx):
4638 tagval = self.detect_tagval(ectx)
4639 vals = []
4640 cnt = 0
4641 for e in (self.elt_list):
4642 if (tagval): val = e.GetTag(ectx)[1]
4643 else: val = str(cnt)
4644 vals.append((val, e.name))
4645 cnt += 1
4646 if hasattr(self, 'ext_list'):
4647 for e in (self.ext_list):
4648 if (tagval): val = e.GetTag(ectx)[1]
4649 else: val = str(cnt)
4650 vals.append((val, e.name))
4651 cnt += 1
4652 return vals
4654 def eth_type_vals(self, tname, ectx):
4655 out = '\n'
4656 vals = self.get_vals(ectx)
4657 out += ectx.eth_vals(tname, vals)
4658 return out
4660 def reg_enum_vals(self, tname, ectx):
4661 vals = self.get_vals(ectx)
4662 for (val, id) in vals:
4663 ectx.eth_reg_value(id, self, val, ethname=ectx.eth_enum_item(tname, id))
4665 def eth_type_enum(self, tname, ectx):
4666 out = '\n'
4667 vals = self.get_vals(ectx)
4668 out += ectx.eth_enum(tname, vals)
4669 return out
4671 def eth_type_default_pars(self, ectx, tname):
4672 pars = Type.eth_type_default_pars(self, ectx, tname)
4673 pars['TABLE'] = '%(PROTOP)s%(TNAME)s_choice'
4674 return pars
4676 def eth_type_default_table(self, ectx, tname):
4677 def out_item(val, e, ext, ectx):
4678 has_enum = ectx.eth_type[tname]['enum'] & EF_ENUM
4679 if (has_enum):
4680 vval = ectx.eth_enum_item(tname, e.name)
4681 else:
4682 vval = val
4683 f = fname + '/' + e.name
4684 ef = ectx.field[f]['ethname']
4685 t = ectx.eth_hf[ef]['ethtype']
4686 if (ectx.Ber()):
4687 opt = ''
4688 if (not e.HasOwnTag()):
4689 opt = 'BER_FLAGS_NOOWNTAG'
4690 elif (e.HasImplicitTag(ectx)):
4691 if (opt): opt += '|'
4692 opt += 'BER_FLAGS_IMPLTAG'
4693 if (not opt): opt = '0'
4694 if (ectx.Ber()):
4695 (tc, tn) = e.GetTag(ectx)
4696 out = ' { %3s, %-24s, %-13s, %s, %s, dissect_%s_%s },\n' \
4697 % (vval, '&'+ectx.eth_hf[ef]['fullname'], tc, tn, opt, ectx.eth_type[t]['proto'], t)
4698 elif (ectx.Per() or ectx.Oer()):
4699 out = ' { %3s, %-24s, %-23s, dissect_%s_%s },\n' \
4700 % (vval, '&'+ectx.eth_hf[ef]['fullname'], ext, ectx.eth_type[t]['proto'], t)
4701 else:
4702 out = ''
4703 return out
4704 # end out_item()
4705 #print "eth_type_default_table(tname='%s')" % (tname)
4706 fname = ectx.eth_type[tname]['ref'][0]
4707 tagval = self.detect_tagval(ectx)
4708 table = "static const %(ER)s_choice_t %(TABLE)s[] = {\n"
4709 cnt = 0
4710 if hasattr(self, 'ext_list'):
4711 ext = 'ASN1_EXTENSION_ROOT'
4712 else:
4713 ext = 'ASN1_NO_EXTENSIONS'
4714 empty_ext_flag = '0'
4715 if (len(self.elt_list)==0) and hasattr(self, 'ext_list') and (len(self.ext_list)==0):
4716 empty_ext_flag = ext
4717 for e in (self.elt_list):
4718 if (tagval): val = e.GetTag(ectx)[1]
4719 else: val = str(cnt)
4720 table += out_item(val, e, ext, ectx)
4721 cnt += 1
4722 if hasattr(self, 'ext_list'):
4723 for e in (self.ext_list):
4724 if (tagval): val = e.GetTag(ectx)[1]
4725 else: val = str(cnt)
4726 table += out_item(val, e, 'ASN1_NOT_EXTENSION_ROOT', ectx)
4727 cnt += 1
4728 if (ectx.Ber()):
4729 table += " { 0, NULL, 0, 0, 0, NULL }\n};\n"
4730 else:
4731 table += " { 0, NULL, %s, NULL }\n};\n" % (empty_ext_flag)
4732 return table
4734 def eth_type_default_body(self, ectx, tname):
4735 if (ectx.Ber()):
4736 body = ectx.eth_fn_call('dissect_%(ER)s_choice', ret='offset',
4737 par=(('%(ACTX)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s'),
4738 ('%(TABLE)s', '%(HF_INDEX)s', '%(ETT_INDEX)s'),
4739 ('%(VAL_PTR)s',),))
4740 elif (ectx.Per() or ectx.Oer()):
4741 body = ectx.eth_fn_call('dissect_%(ER)s_choice', ret='offset',
4742 par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
4743 ('%(ETT_INDEX)s', '%(TABLE)s',),
4744 ('%(VAL_PTR)s',),))
4745 else:
4746 body = '#error Can not decode ChoiceType %s' % (tname)
4747 return body
4749 #--- ChoiceValue ----------------------------------------------------
4750 class ChoiceValue (Value):
4751 def to_str(self, ectx):
4752 return self.val.to_str(ectx)
4754 def fld_obj_eq(self, other):
4755 return isinstance(other, ChoiceValue) and (self.choice == other.choice) and (str(self.val.val) == str(other.val.val))
4757 #--- EnumeratedType -----------------------------------------------------------
4758 class EnumeratedType (Type):
4759 def to_python (self, ctx):
4760 def strify_one (named_num):
4761 return "%s=%s" % (named_num.ident, named_num.val)
4762 return "asn1.ENUM(%s)" % ",".join (map (strify_one, self.val))
4764 def eth_ftype(self, ectx):
4765 return ('FT_UINT32', 'BASE_DEC')
4767 def eth_strings(self):
4768 return '$$'
4770 def eth_has_vals(self):
4771 return True
4773 def GetTTag(self, ectx):
4774 return ('BER_CLASS_UNI', 'BER_UNI_TAG_ENUMERATED')
4776 def get_vals_etc(self, ectx):
4777 vals = []
4778 lastv = 0
4779 used = {}
4780 maxv = 0
4781 root_num = 0
4782 ext_num = 0
4783 map_table = []
4784 for e in (self.val):
4785 if e.type == 'NamedNumber':
4786 used[int(e.val)] = True
4787 for e in (self.val):
4788 if e.type == 'NamedNumber':
4789 val = int(e.val)
4790 else:
4791 while lastv in used:
4792 lastv += 1
4793 val = lastv
4794 used[val] = True
4795 vals.append((val, e.ident))
4796 map_table.append(val)
4797 root_num += 1
4798 if val > maxv:
4799 maxv = val
4800 if self.ext is not None:
4801 for e in (self.ext):
4802 if e.type == 'NamedNumber':
4803 used[int(e.val)] = True
4804 for e in (self.ext):
4805 if e.type == 'NamedNumber':
4806 val = int(e.val)
4807 else:
4808 while lastv in used:
4809 lastv += 1
4810 val = lastv
4811 used[val] = True
4812 vals.append((val, e.ident))
4813 map_table.append(val)
4814 ext_num += 1
4815 if val > maxv:
4816 maxv = val
4817 need_map = False
4818 for i in range(len(map_table)):
4819 need_map = need_map or (map_table[i] != i)
4820 if (not need_map):
4821 map_table = None
4822 return (vals, root_num, ext_num, map_table)
4824 def eth_type_vals(self, tname, ectx):
4825 out = '\n'
4826 vals = self.get_vals_etc(ectx)[0]
4827 out += ectx.eth_vals(tname, vals)
4828 return out
4830 def reg_enum_vals(self, tname, ectx):
4831 vals = self.get_vals_etc(ectx)[0]
4832 for (val, id) in vals:
4833 ectx.eth_reg_value(id, self, val, ethname=ectx.eth_enum_item(tname, id))
4835 def eth_type_enum(self, tname, ectx):
4836 out = '\n'
4837 vals = self.get_vals_etc(ectx)[0]
4838 out += ectx.eth_enum(tname, vals)
4839 return out
4841 def eth_type_default_pars(self, ectx, tname):
4842 pars = Type.eth_type_default_pars(self, ectx, tname)
4843 (root_num, ext_num, map_table) = self.get_vals_etc(ectx)[1:]
4844 if self.ext is not None:
4845 ext = 'true'
4846 else:
4847 ext = 'false'
4848 pars['ROOT_NUM'] = str(root_num)
4849 pars['EXT'] = ext
4850 pars['EXT_NUM'] = str(ext_num)
4851 if (map_table):
4852 pars['TABLE'] = '%(PROTOP)s%(TNAME)s_value_map'
4853 else:
4854 pars['TABLE'] = 'NULL'
4855 return pars
4857 def eth_type_default_table(self, ectx, tname):
4858 if (not ectx.Per() and not ectx.Oer()): return ''
4859 map_table = self.get_vals_etc(ectx)[3]
4860 if map_table is None: return ''
4861 table = "static uint32_t %(TABLE)s[%(ROOT_NUM)s+%(EXT_NUM)s] = {"
4862 table += ", ".join([str(v) for v in map_table])
4863 table += "};\n"
4864 return table
4866 def eth_type_default_body(self, ectx, tname):
4867 if (ectx.Ber()):
4868 if (ectx.constraints_check and self.HasValueConstraint()):
4869 body = ectx.eth_fn_call('dissect_%(ER)s_constrained_integer', ret='offset',
4870 par=(('%(IMPLICIT_TAG)s', '%(ACTX)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s'),
4871 ('%(MIN_VAL)s', '%(MAX_VAL)s', '%(HF_INDEX)s', '%(VAL_PTR)s',),))
4872 else:
4873 body = ectx.eth_fn_call('dissect_%(ER)s_integer', ret='offset',
4874 par=(('%(IMPLICIT_TAG)s', '%(ACTX)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s', '%(HF_INDEX)s'),
4875 ('%(VAL_PTR)s',),))
4876 elif (ectx.Per() or ectx.Oer()):
4877 body = ectx.eth_fn_call('dissect_%(ER)s_enumerated', ret='offset',
4878 par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
4879 ('%(ROOT_NUM)s', '%(VAL_PTR)s', '%(EXT)s', '%(EXT_NUM)s', '%(TABLE)s',),))
4880 else:
4881 body = '#error Can not decode EnumeratedType %s' % (tname)
4882 return body
4884 #--- EmbeddedPDVType -----------------------------------------------------------
4885 class EmbeddedPDVType (Type):
4886 def eth_tname(self):
4887 return 'EMBEDDED_PDV'
4889 def eth_ftype(self, ectx):
4890 return ('FT_NONE', 'BASE_NONE')
4892 def GetTTag(self, ectx):
4893 return ('BER_CLASS_UNI', 'BER_UNI_TAG_EMBEDDED_PDV')
4895 def eth_type_default_pars(self, ectx, tname):
4896 pars = Type.eth_type_default_pars(self, ectx, tname)
4897 if ectx.default_embedded_pdv_cb:
4898 pars['TYPE_REF_FN'] = ectx.default_embedded_pdv_cb
4899 else:
4900 pars['TYPE_REF_FN'] = 'NULL'
4901 return pars
4903 def eth_type_default_body(self, ectx, tname):
4904 if (ectx.Ber()):
4905 body = ectx.eth_fn_call('dissect_%(ER)s_EmbeddedPDV_Type', ret='offset',
4906 par=(('%(IMPLICIT_TAG)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(HF_INDEX)s', '%(TYPE_REF_FN)s',),))
4907 elif (ectx.Per()):
4908 body = ectx.eth_fn_call('dissect_%(ER)s_embedded_pdv', ret='offset',
4909 par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s', '%(TYPE_REF_FN)s',),))
4910 else:
4911 body = '#error Can not decode EmbeddedPDVType %s' % (tname)
4912 return body
4914 #--- ExternalType -----------------------------------------------------------
4915 class ExternalType (Type):
4916 def eth_tname(self):
4917 return 'EXTERNAL'
4919 def eth_ftype(self, ectx):
4920 return ('FT_NONE', 'BASE_NONE')
4922 def GetTTag(self, ectx):
4923 return ('BER_CLASS_UNI', 'BER_UNI_TAG_EXTERNAL')
4925 def eth_type_default_pars(self, ectx, tname):
4926 pars = Type.eth_type_default_pars(self, ectx, tname)
4927 if ectx.default_external_type_cb:
4928 pars['TYPE_REF_FN'] = ectx.default_external_type_cb
4929 else:
4930 pars['TYPE_REF_FN'] = 'NULL'
4931 return pars
4933 def eth_type_default_body(self, ectx, tname):
4934 if (ectx.Ber()):
4935 body = ectx.eth_fn_call('dissect_%(ER)s_external_type', ret='offset',
4936 par=(('%(IMPLICIT_TAG)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(HF_INDEX)s', '%(TYPE_REF_FN)s',),))
4937 elif (ectx.Per()):
4938 body = ectx.eth_fn_call('dissect_%(ER)s_external_type', ret='offset',
4939 par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s', '%(TYPE_REF_FN)s',),))
4940 else:
4941 body = '#error Can not decode ExternalType %s' % (tname)
4942 return body
4944 #--- OpenType -----------------------------------------------------------
4945 class OpenType (Type):
4946 def to_python (self, ctx):
4947 return "asn1.ANY"
4949 def single_type(self):
4950 if (self.HasConstraint() and
4951 self.constr.type == 'Type' and
4952 self.constr.subtype.type == 'Type_Ref'):
4953 return self.constr.subtype.val
4954 return None
4956 def eth_reg_sub(self, ident, ectx):
4957 t = self.single_type()
4958 if t:
4959 ectx.eth_dep_add(ident, t)
4961 def eth_tname(self):
4962 t = self.single_type()
4963 if t:
4964 return 'OpenType_' + t
4965 else:
4966 return Type.eth_tname(self)
4968 def eth_ftype(self, ectx):
4969 return ('FT_NONE', 'BASE_NONE')
4971 def GetTTag(self, ectx):
4972 return ('BER_CLASS_ANY', '0')
4974 def eth_type_default_pars(self, ectx, tname):
4975 pars = Type.eth_type_default_pars(self, ectx, tname)
4976 pars['FN_VARIANT'] = ectx.default_opentype_variant
4977 t = self.single_type()
4978 if t:
4979 t = ectx.type[t]['ethname']
4980 pars['TYPE_REF_PROTO'] = ectx.eth_type[t]['proto']
4981 pars['TYPE_REF_TNAME'] = t
4982 pars['TYPE_REF_FN'] = 'dissect_%(TYPE_REF_PROTO)s_%(TYPE_REF_TNAME)s'
4983 else:
4984 pars['TYPE_REF_FN'] = 'NULL'
4985 return pars
4987 def eth_type_default_body(self, ectx, tname):
4988 if (ectx.Per() or ectx.Oer()):
4989 body = ectx.eth_fn_call('dissect_%(ER)s_open_type%(FN_VARIANT)s', ret='offset',
4990 par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s', '%(TYPE_REF_FN)s',),))
4991 else:
4992 body = '#error Can not decode OpenType %s' % (tname)
4993 return body
4995 #--- InstanceOfType -----------------------------------------------------------
4996 class InstanceOfType (Type):
4997 def eth_tname(self):
4998 return 'INSTANCE_OF'
5000 def eth_ftype(self, ectx):
5001 return ('FT_NONE', 'BASE_NONE')
5003 def GetTTag(self, ectx):
5004 return ('BER_CLASS_UNI', 'BER_UNI_TAG_EXTERNAL')
5006 def eth_type_default_pars(self, ectx, tname):
5007 pars = Type.eth_type_default_pars(self, ectx, tname)
5008 if ectx.default_external_type_cb:
5009 pars['TYPE_REF_FN'] = ectx.default_external_type_cb
5010 else:
5011 pars['TYPE_REF_FN'] = 'NULL'
5012 return pars
5014 def eth_type_default_body(self, ectx, tname):
5015 if (ectx.Ber()):
5016 body = ectx.eth_fn_call('dissect_%(ER)s_external_type', ret='offset',
5017 par=(('%(IMPLICIT_TAG)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(HF_INDEX)s', '%(TYPE_REF_FN)s',),))
5018 else:
5019 body = '#error Can not decode %s' % (tname)
5020 return body
5022 #--- AnyType -----------------------------------------------------------
5023 class AnyType (Type):
5024 def to_python (self, ctx):
5025 return "asn1.ANY"
5027 def eth_ftype(self, ectx):
5028 return ('FT_NONE', 'BASE_NONE')
5030 def GetTTag(self, ectx):
5031 return ('BER_CLASS_ANY', '0')
5033 def eth_type_default_body(self, ectx, tname):
5034 body = '#error Can not decode %s' % (tname)
5035 return body
5037 class Literal (Node):
5038 def to_python (self, ctx):
5039 return self.val
5041 #--- NullType -----------------------------------------------------------------
5042 class NullType (Type):
5043 def to_python (self, ctx):
5044 return 'asn1.NULL'
5046 def eth_tname(self):
5047 return 'NULL'
5049 def GetTTag(self, ectx):
5050 return ('BER_CLASS_UNI', 'BER_UNI_TAG_NULL')
5052 def eth_type_default_body(self, ectx, tname):
5053 if (ectx.Ber()):
5054 body = ectx.eth_fn_call('dissect_%(ER)s_null', ret='offset',
5055 par=(('%(IMPLICIT_TAG)s', '%(ACTX)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s', '%(HF_INDEX)s'),))
5056 elif (ectx.Per() or ectx.Oer()):
5057 body = ectx.eth_fn_call('dissect_%(ER)s_null', ret='offset',
5058 par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),))
5059 else:
5060 body = '#error Can not decode %s' % (tname)
5061 return body
5063 #--- NullValue ----------------------------------------------------
5064 class NullValue (Value):
5065 def to_str(self, ectx):
5066 return 'NULL'
5068 #--- RealType -----------------------------------------------------------------
5069 class RealType (Type):
5070 def to_python (self, ctx):
5071 return 'asn1.REAL'
5073 def eth_tname(self):
5074 return 'REAL'
5076 def GetTTag(self, ectx):
5077 return ('BER_CLASS_UNI', 'BER_UNI_TAG_REAL')
5079 def eth_ftype(self, ectx):
5080 return ('FT_DOUBLE', 'BASE_NONE')
5082 def eth_type_default_body(self, ectx, tname):
5083 if (ectx.Ber()):
5084 body = ectx.eth_fn_call('dissect_%(ER)s_real', ret='offset',
5085 par=(('%(IMPLICIT_TAG)s', '%(ACTX)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s', '%(HF_INDEX)s'),
5086 ('%(VAL_PTR)s',),))
5087 elif (ectx.Per()):
5088 body = ectx.eth_fn_call('dissect_%(ER)s_real', ret='offset',
5089 par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s', '%(VAL_PTR)s',),))
5090 else:
5091 body = '#error Can not decode %s' % (tname)
5092 return body
5094 #--- BooleanType --------------------------------------------------------------
5095 class BooleanType (Type):
5096 def to_python (self, ctx):
5097 return 'asn1.BOOLEAN'
5099 def eth_tname(self):
5100 return 'BOOLEAN'
5102 def GetTTag(self, ectx):
5103 return ('BER_CLASS_UNI', 'BER_UNI_TAG_BOOLEAN')
5105 def eth_ftype(self, ectx):
5106 return ('FT_BOOLEAN', 'BASE_NONE')
5108 def eth_type_default_body(self, ectx, tname):
5109 if (ectx.Ber()):
5110 body = ectx.eth_fn_call('dissect_%(ER)s_boolean', ret='offset',
5111 par=(('%(IMPLICIT_TAG)s', '%(ACTX)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s', '%(HF_INDEX)s', '%(VAL_PTR)s'),))
5112 elif (ectx.Per()):
5113 body = ectx.eth_fn_call('dissect_%(ER)s_boolean', ret='offset',
5114 par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s', '%(VAL_PTR)s',),))
5115 elif (ectx.Oer()):
5116 body = ectx.eth_fn_call('dissect_%(ER)s_boolean', ret='offset',
5117 par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s', '%(VAL_PTR)s',),))
5118 else:
5119 body = '#error Can not decode %s' % (tname)
5120 return body
5122 #--- OctetStringType ----------------------------------------------------------
5123 class OctetStringType (Type):
5124 def to_python (self, ctx):
5125 return 'asn1.OCTSTRING'
5127 def eth_tname(self):
5128 if not self.HasConstraint():
5129 return 'OCTET_STRING'
5130 elif self.constr.type == 'Size':
5131 return 'OCTET_STRING' + '_' + self.constr.eth_constrname()
5132 else:
5133 return '#' + self.type + '_' + str(id(self))
5135 def eth_ftype(self, ectx):
5136 return ('FT_BYTES', 'BASE_NONE')
5138 def GetTTag(self, ectx):
5139 return ('BER_CLASS_UNI', 'BER_UNI_TAG_OCTETSTRING')
5141 def eth_need_pdu(self, ectx):
5142 pdu = None
5143 if self.HasContentsConstraint():
5144 t = self.constr.GetContents(ectx)
5145 if t and (ectx.default_containing_variant in ('_pdu', '_pdu_new')):
5146 pdu = { 'type' : t,
5147 'new' : ectx.default_containing_variant == '_pdu_new' }
5148 return pdu
5150 def eth_type_default_pars(self, ectx, tname):
5151 pars = Type.eth_type_default_pars(self, ectx, tname)
5152 (pars['MIN_VAL'], pars['MAX_VAL'], pars['EXT']) = self.eth_get_size_constr(ectx)
5153 if self.HasContentsConstraint():
5154 pars['FN_VARIANT'] = ectx.default_containing_variant
5155 t = self.constr.GetContents(ectx)
5156 if t:
5157 if pars['FN_VARIANT'] in ('_pdu', '_pdu_new'):
5158 t = ectx.field[t]['ethname']
5159 pars['TYPE_REF_PROTO'] = ''
5160 pars['TYPE_REF_TNAME'] = t
5161 pars['TYPE_REF_FN'] = 'dissect_%(TYPE_REF_TNAME)s'
5162 else:
5163 t = ectx.type[t]['ethname']
5164 pars['TYPE_REF_PROTO'] = ectx.eth_type[t]['proto']
5165 pars['TYPE_REF_TNAME'] = t
5166 pars['TYPE_REF_FN'] = 'dissect_%(TYPE_REF_PROTO)s_%(TYPE_REF_TNAME)s'
5167 else:
5168 pars['TYPE_REF_FN'] = 'NULL'
5169 return pars
5171 def eth_type_default_body(self, ectx, tname):
5172 if (ectx.Ber()):
5173 if (ectx.constraints_check and self.HasSizeConstraint()):
5174 body = ectx.eth_fn_call('dissect_%(ER)s_constrained_octet_string', ret='offset',
5175 par=(('%(IMPLICIT_TAG)s', '%(ACTX)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s'),
5176 ('%(MIN_VAL)s', '%(MAX_VAL)s', '%(HF_INDEX)s', '%(VAL_PTR)s',),))
5177 else:
5178 body = ectx.eth_fn_call('dissect_%(ER)s_octet_string', ret='offset',
5179 par=(('%(IMPLICIT_TAG)s', '%(ACTX)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s', '%(HF_INDEX)s'),
5180 ('%(VAL_PTR)s',),))
5181 elif (ectx.Per() or ectx.Oer()):
5182 if self.HasContentsConstraint():
5183 body = ectx.eth_fn_call('dissect_%(ER)s_octet_string_containing%(FN_VARIANT)s', ret='offset',
5184 par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
5185 ('%(MIN_VAL)s', '%(MAX_VAL)s', '%(EXT)s', '%(TYPE_REF_FN)s',),))
5186 else:
5187 body = ectx.eth_fn_call('dissect_%(ER)s_octet_string', ret='offset',
5188 par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
5189 ('%(MIN_VAL)s', '%(MAX_VAL)s', '%(EXT)s', '%(VAL_PTR)s',),))
5190 else:
5191 body = '#error Can not decode %s' % (tname)
5192 return body
5194 #--- CharacterStringType ------------------------------------------------------
5195 class CharacterStringType (Type):
5196 def eth_tname(self):
5197 if not self.HasConstraint():
5198 return self.eth_tsname()
5199 elif self.constr.type == 'Size':
5200 return self.eth_tsname() + '_' + self.constr.eth_constrname()
5201 else:
5202 return '#' + self.type + '_' + str(id(self))
5204 def eth_ftype(self, ectx):
5205 return ('FT_STRING', 'BASE_NONE')
5207 class RestrictedCharacterStringType (CharacterStringType):
5208 def to_python (self, ctx):
5209 return 'asn1.' + self.eth_tsname()
5211 def GetTTag(self, ectx):
5212 return ('BER_CLASS_UNI', 'BER_UNI_TAG_' + self.eth_tsname())
5214 def eth_type_default_pars(self, ectx, tname):
5215 pars = Type.eth_type_default_pars(self, ectx, tname)
5216 (pars['MIN_VAL'], pars['MAX_VAL'], pars['EXT']) = self.eth_get_size_constr(ectx)
5217 (pars['STRING_TYPE'], pars['STRING_TAG']) = (self.eth_tsname(), self.GetTTag(ectx)[1])
5218 (pars['ALPHABET'], pars['ALPHABET_LEN']) = self.eth_get_alphabet_constr(ectx)
5219 return pars
5221 def eth_type_default_body(self, ectx, tname):
5222 if (ectx.Ber()):
5223 if (ectx.constraints_check and self.HasSizeConstraint()):
5224 body = ectx.eth_fn_call('dissect_%(ER)s_constrained_restricted_string', ret='offset',
5225 par=(('%(IMPLICIT_TAG)s', '%(STRING_TAG)s'),
5226 ('%(ACTX)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s'),
5227 ('%(MIN_VAL)s', '%(MAX_VAL)s', '%(HF_INDEX)s', '%(VAL_PTR)s',),))
5228 else:
5229 body = ectx.eth_fn_call('dissect_%(ER)s_restricted_string', ret='offset',
5230 par=(('%(IMPLICIT_TAG)s', '%(STRING_TAG)s'),
5231 ('%(ACTX)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s', '%(HF_INDEX)s'),
5232 ('%(VAL_PTR)s',),))
5233 elif (ectx.Per() and self.HasPermAlph() and self.eth_tsname() in KnownMultiplierStringTypes):
5234 # XXX: If there is a permitted alphabet but it is extensible,
5235 # then the permitted-alphabet is not PER-visible and should be
5236 # ignored. (X.691 9.3.10, 9.3.18) We don't handle extensible
5237 # permitted-alphabets.
5238 body = ectx.eth_fn_call('dissect_%(ER)s_restricted_character_string', ret='offset',
5239 par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
5240 ('%(MIN_VAL)s', '%(MAX_VAL)s', '%(EXT)s', '%(ALPHABET)s', '%(ALPHABET_LEN)s'),
5241 ('%(VAL_PTR)s',),))
5242 elif (ectx.Per()):
5243 if (self.eth_tsname() == 'GeneralString'):
5244 body = ectx.eth_fn_call('dissect_%(ER)s_%(STRING_TYPE)s', ret='offset',
5245 par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),))
5246 elif (self.eth_tsname() == 'GeneralizedTime' or self.eth_tsname() == 'UTCTime'):
5247 body = ectx.eth_fn_call('dissect_%(ER)s_VisibleString', ret='offset',
5248 par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
5249 ('%(MIN_VAL)s', '%(MAX_VAL)s', '%(EXT)s'),
5250 ('%(VAL_PTR)s',),))
5251 elif (self.eth_tsname() in KnownMultiplierStringTypes):
5252 body = ectx.eth_fn_call('dissect_%(ER)s_%(STRING_TYPE)s', ret='offset',
5253 par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
5254 ('%(MIN_VAL)s', '%(MAX_VAL)s', '%(EXT)s'),
5255 ('%(VAL_PTR)s',),))
5256 else:
5257 body = ectx.eth_fn_call('dissect_%(ER)s_%(STRING_TYPE)s', ret='offset',
5258 par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
5259 ('%(MIN_VAL)s', '%(MAX_VAL)s', '%(EXT)s',),))
5260 elif (ectx.Oer()):
5261 body = ectx.eth_fn_call('dissect_%(ER)s_%(STRING_TYPE)s', ret='offset',
5262 par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
5263 ('%(MIN_VAL)s', '%(MAX_VAL)s', '%(EXT)s',),))
5264 else:
5265 body = '#error Can not decode %s' % (tname)
5266 return body
5268 class BMPStringType (RestrictedCharacterStringType):
5269 def eth_tsname(self):
5270 return 'BMPString'
5272 class GeneralStringType (RestrictedCharacterStringType):
5273 def eth_tsname(self):
5274 return 'GeneralString'
5276 class GraphicStringType (RestrictedCharacterStringType):
5277 def eth_tsname(self):
5278 return 'GraphicString'
5280 class IA5StringType (RestrictedCharacterStringType):
5281 def eth_tsname(self):
5282 return 'IA5String'
5284 class NumericStringType (RestrictedCharacterStringType):
5285 def eth_tsname(self):
5286 return 'NumericString'
5288 class PrintableStringType (RestrictedCharacterStringType):
5289 def eth_tsname(self):
5290 return 'PrintableString'
5292 class TeletexStringType (RestrictedCharacterStringType):
5293 def eth_tsname(self):
5294 return 'TeletexString'
5296 class T61StringType (RestrictedCharacterStringType):
5297 def eth_tsname(self):
5298 return 'T61String'
5299 def GetTTag(self, ectx):
5300 return ('BER_CLASS_UNI', 'BER_UNI_TAG_TeletexString')
5302 class UniversalStringType (RestrictedCharacterStringType):
5303 def eth_tsname(self):
5304 return 'UniversalString'
5306 class UTF8StringType (RestrictedCharacterStringType):
5307 def eth_tsname(self):
5308 return 'UTF8String'
5310 class VideotexStringType (RestrictedCharacterStringType):
5311 def eth_tsname(self):
5312 return 'VideotexString'
5314 class VisibleStringType (RestrictedCharacterStringType):
5315 def eth_tsname(self):
5316 return 'VisibleString'
5318 class ISO646StringType (RestrictedCharacterStringType):
5319 def eth_tsname(self):
5320 return 'ISO646String'
5321 def GetTTag(self, ectx):
5322 return ('BER_CLASS_UNI', 'BER_UNI_TAG_VisibleString')
5324 class UnrestrictedCharacterStringType (CharacterStringType):
5325 def to_python (self, ctx):
5326 return 'asn1.UnrestrictedCharacterString'
5327 def eth_tsname(self):
5328 return 'CHARACTER_STRING'
5330 #--- UsefulType ---------------------------------------------------------------
5331 class GeneralizedTime (RestrictedCharacterStringType):
5332 def eth_tsname(self):
5333 return 'GeneralizedTime'
5335 def eth_ftype(self, ectx):
5336 if (ectx.Ber()):
5337 return ('FT_ABSOLUTE_TIME', 'ABSOLUTE_TIME_LOCAL')
5338 else:
5339 return ('FT_STRING', 'BASE_NONE')
5341 def eth_type_default_body(self, ectx, tname):
5342 if (ectx.Ber()):
5343 body = ectx.eth_fn_call('dissect_%(ER)s_%(STRING_TYPE)s', ret='offset',
5344 par=(('%(IMPLICIT_TAG)s', '%(ACTX)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s', '%(HF_INDEX)s'),))
5345 return body
5346 else:
5347 return RestrictedCharacterStringType.eth_type_default_body(self, ectx, tname)
5349 class UTCTime (RestrictedCharacterStringType):
5350 def eth_tsname(self):
5351 return 'UTCTime'
5353 def eth_type_default_body(self, ectx, tname):
5354 if (ectx.Ber()):
5355 body = ectx.eth_fn_call('dissect_%(ER)s_%(STRING_TYPE)s', ret='offset',
5356 par=(('%(IMPLICIT_TAG)s', '%(ACTX)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s', '%(HF_INDEX)s', 'NULL', 'NULL'),))
5357 return body
5358 else:
5359 return RestrictedCharacterStringType.eth_type_default_body(self, ectx, tname)
5361 class ObjectDescriptor (RestrictedCharacterStringType):
5362 def eth_tsname(self):
5363 return 'ObjectDescriptor'
5365 def eth_type_default_body(self, ectx, tname):
5366 if (ectx.Ber()):
5367 body = RestrictedCharacterStringType.eth_type_default_body(self, ectx, tname)
5368 elif (ectx.Per()):
5369 body = ectx.eth_fn_call('dissect_%(ER)s_object_descriptor', ret='offset',
5370 par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s', '%(VAL_PTR)s',),))
5371 else:
5372 body = '#error Can not decode %s' % (tname)
5373 return body
5375 #--- ObjectIdentifierType -----------------------------------------------------
5376 class ObjectIdentifierType (Type):
5377 def to_python (self, ctx):
5378 return 'asn1.OBJECT_IDENTIFIER'
5380 def eth_tname(self):
5381 return 'OBJECT_IDENTIFIER'
5383 def eth_ftype(self, ectx):
5384 return ('FT_OID', 'BASE_NONE')
5386 def GetTTag(self, ectx):
5387 return ('BER_CLASS_UNI', 'BER_UNI_TAG_OID')
5389 def eth_type_default_pars(self, ectx, tname):
5390 pars = Type.eth_type_default_pars(self, ectx, tname)
5391 pars['FN_VARIANT'] = ectx.default_oid_variant
5392 return pars
5394 def eth_type_default_body(self, ectx, tname):
5395 if (ectx.Ber()):
5396 body = ectx.eth_fn_call('dissect_%(ER)s_object_identifier%(FN_VARIANT)s', ret='offset',
5397 par=(('%(IMPLICIT_TAG)s', '%(ACTX)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s', '%(HF_INDEX)s', '%(VAL_PTR)s',),))
5398 elif (ectx.Per()):
5399 body = ectx.eth_fn_call('dissect_%(ER)s_object_identifier%(FN_VARIANT)s', ret='offset',
5400 par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s', '%(VAL_PTR)s',),))
5401 elif (ectx.Oer()):
5402 body = ectx.eth_fn_call('dissect_%(ER)s_object_identifier%(FN_VARIANT)s', ret='offset',
5403 par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s', '%(VAL_PTR)s',),))
5404 else:
5405 body = '#error Can not decode %s' % (tname)
5406 return body
5408 #--- ObjectIdentifierValue ----------------------------------------------------
5409 class ObjectIdentifierValue (Value):
5410 def get_num(self, path, val):
5411 return str(oid_names.get(path + '/' + val, val))
5413 def to_str(self, ectx):
5414 out = ''
5415 path = ''
5416 first = True
5417 sep = ''
5418 for v in self.comp_list:
5419 if isinstance(v, Node) and (v.type == 'name_and_number'):
5420 vstr = v.number
5421 elif v.isdigit():
5422 vstr = v
5423 else:
5424 vstr = self.get_num(path, v)
5425 if not first and not vstr.isdigit():
5426 vstr = ectx.value_get_val(vstr)
5427 if first:
5428 if vstr.isdigit():
5429 out += '"' + vstr
5430 else:
5431 out += ectx.value_get_eth(vstr) + '"'
5432 else:
5433 out += sep + vstr
5434 path += sep + vstr
5435 first = False
5436 sep = '.'
5437 out += '"'
5438 return out
5440 def get_dep(self):
5441 v = self.comp_list[0]
5442 if isinstance(v, Node) and (v.type == 'name_and_number'):
5443 return None
5444 elif v.isdigit():
5445 return None
5446 else:
5447 vstr = self.get_num('', v)
5448 if vstr.isdigit():
5449 return None
5450 else:
5451 return vstr
5453 class NamedNumber(Node):
5454 def to_python (self, ctx):
5455 return "('%s',%s)" % (self.ident, self.val)
5456 def __lt__(self, other):
5457 return int(self.val) < int(other.val)
5459 class NamedNumListBase(Node):
5460 def to_python (self, ctx):
5461 return "asn1.%s_class ([%s])" % (self.asn1_typ,",".join (
5462 [x.to_python (ctx) for x in self.named_list]))
5464 #--- RelativeOIDType ----------------------------------------------------------
5465 class RelativeOIDType (Type):
5467 def eth_tname(self):
5468 return 'RELATIVE_OID'
5470 def eth_ftype(self, ectx):
5471 return ('FT_REL_OID', 'BASE_NONE')
5473 def GetTTag(self, ectx):
5474 return ('BER_CLASS_UNI', 'BER_UNI_TAG_RELATIVE_OID')
5476 def eth_type_default_pars(self, ectx, tname):
5477 pars = Type.eth_type_default_pars(self, ectx, tname)
5478 pars['FN_VARIANT'] = ectx.default_oid_variant
5479 return pars
5481 def eth_type_default_body(self, ectx, tname):
5482 if (ectx.Ber()):
5483 body = ectx.eth_fn_call('dissect_%(ER)s_relative_oid%(FN_VARIANT)s', ret='offset',
5484 par=(('%(IMPLICIT_TAG)s', '%(ACTX)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s', '%(HF_INDEX)s', '%(VAL_PTR)s',),))
5485 elif (ectx.Per()):
5486 body = ectx.eth_fn_call('dissect_%(ER)s_relative_oid%(FN_VARIANT)s', ret='offset',
5487 par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s', '%(VAL_PTR)s',),))
5488 else:
5489 body = '#error Can not decode relative_oid %s' % (tname)
5490 return body
5493 #--- IntegerType --------------------------------------------------------------
5494 class IntegerType (Type):
5495 def to_python (self, ctx):
5496 return "asn1.INTEGER_class ([%s])" % (",".join (
5497 [x.to_python (ctx) for x in self.named_list]))
5499 def add_named_value(self, ident, val):
5500 e = NamedNumber(ident = ident, val = val)
5501 if not self.named_list:
5502 self.named_list = []
5503 self.named_list.append(e)
5505 def eth_tname(self):
5506 if self.named_list:
5507 return Type.eth_tname(self)
5508 if not self.HasConstraint():
5509 return 'INTEGER'
5510 elif self.constr.type == 'SingleValue' or self.constr.type == 'ValueRange':
5511 return 'INTEGER' + '_' + self.constr.eth_constrname()
5512 else:
5513 return 'INTEGER' + '_' + self.constr.eth_tname()
5515 def GetTTag(self, ectx):
5516 return ('BER_CLASS_UNI', 'BER_UNI_TAG_INTEGER')
5519 def eth_ftype(self, ectx):
5520 if self.HasConstraint():
5521 if not self.constr.IsNegativ():
5522 if self.constr.Needs64b(ectx):
5523 return ('FT_UINT64', 'BASE_DEC')
5524 else:
5525 return ('FT_UINT32', 'BASE_DEC')
5526 if self.constr.Needs64b(ectx):
5527 return ('FT_INT64', 'BASE_DEC')
5528 return ('FT_INT32', 'BASE_DEC')
5530 def eth_strings(self):
5531 if (self.named_list):
5532 return '$$'
5533 else:
5534 return 'NULL'
5536 def eth_has_vals(self):
5537 if (self.named_list):
5538 return True
5539 else:
5540 return False
5542 def get_vals(self, ectx):
5543 vals = []
5544 for e in (self.named_list):
5545 vals.append((int(e.val), e.ident))
5546 return vals
5548 def eth_type_vals(self, tname, ectx):
5549 if not self.eth_has_vals(): return ''
5550 out = '\n'
5551 vals = self.get_vals(ectx)
5552 out += ectx.eth_vals(tname, vals)
5553 return out
5555 def reg_enum_vals(self, tname, ectx):
5556 vals = self.get_vals(ectx)
5557 for (val, id) in vals:
5558 ectx.eth_reg_value(id, self, val, ethname=ectx.eth_enum_item(tname, id))
5560 def eth_type_enum(self, tname, ectx):
5561 if not self.eth_has_enum(tname, ectx): return ''
5562 out = '\n'
5563 vals = self.get_vals(ectx)
5564 out += ectx.eth_enum(tname, vals)
5565 return out
5567 def eth_type_default_pars(self, ectx, tname):
5568 pars = Type.eth_type_default_pars(self, ectx, tname)
5569 if self.HasValueConstraint():
5570 (pars['MIN_VAL'], pars['MAX_VAL'], pars['EXT']) = self.eth_get_value_constr(ectx)
5571 if (pars['FN_VARIANT'] == '') and self.constr.Needs64b(ectx):
5572 if ectx.Ber(): pars['FN_VARIANT'] = '64'
5573 else:
5574 if (ectx.Oer() and pars['MAX_VAL'] == 'NO_BOUND'):
5575 pars['FN_VARIANT'] = '_64b_no_ub'
5576 else:
5577 pars['FN_VARIANT'] = '_64b'
5578 return pars
5580 def eth_type_default_body(self, ectx, tname):
5581 if (ectx.Ber()):
5582 if (ectx.constraints_check and self.HasValueConstraint()):
5583 body = ectx.eth_fn_call('dissect_%(ER)s_constrained_integer%(FN_VARIANT)s', ret='offset',
5584 par=(('%(IMPLICIT_TAG)s', '%(ACTX)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s'),
5585 ('%(MIN_VAL)s', '%(MAX_VAL)s', '%(HF_INDEX)s', '%(VAL_PTR)s',),))
5586 else:
5587 body = ectx.eth_fn_call('dissect_%(ER)s_integer%(FN_VARIANT)s', ret='offset',
5588 par=(('%(IMPLICIT_TAG)s', '%(ACTX)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s', '%(HF_INDEX)s'),
5589 ('%(VAL_PTR)s',),))
5590 elif (ectx.Per() or ectx.Oer()):
5591 if (self.HasValueConstraint()):
5592 body = ectx.eth_fn_call('dissect_%(ER)s_constrained_integer%(FN_VARIANT)s', ret='offset',
5593 par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
5594 ('%(MIN_VAL)s', '%(MAX_VAL)s', '%(VAL_PTR)s', '%(EXT)s'),))
5595 else:
5596 body = ectx.eth_fn_call('dissect_%(ER)s_integer%(FN_VARIANT)s', ret='offset',
5597 par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s', '%(VAL_PTR)s'),))
5598 else:
5599 body = '#error Can not decode %s' % (tname)
5600 return body
5602 #--- BitStringType ------------------------------------------------------------
5603 class BitStringType (Type):
5604 def to_python (self, ctx):
5605 return "asn1.BITSTRING_class ([%s])" % (",".join (
5606 [x.to_python (ctx) for x in self.named_list]))
5608 def eth_tname(self):
5609 if self.named_list:
5610 return Type.eth_tname(self)
5611 elif not self.HasConstraint():
5612 return 'BIT_STRING'
5613 elif self.constr.IsSize():
5614 return 'BIT_STRING' + '_' + self.constr.eth_constrname()
5615 else:
5616 return '#' + self.type + '_' + str(id(self))
5618 def GetTTag(self, ectx):
5619 return ('BER_CLASS_UNI', 'BER_UNI_TAG_BITSTRING')
5621 def eth_ftype(self, ectx):
5622 return ('FT_BYTES', 'BASE_NONE')
5624 def eth_need_tree(self):
5625 return self.named_list
5627 def eth_need_pdu(self, ectx):
5628 pdu = None
5629 if self.HasContentsConstraint():
5630 t = self.constr.GetContents(ectx)
5631 if t and (ectx.default_containing_variant in ('_pdu', '_pdu_new')):
5632 pdu = { 'type' : t,
5633 'new' : ectx.default_containing_variant == '_pdu_new' }
5634 return pdu
5636 def sortNamedBits(self):
5637 return self.named_list.val
5639 def eth_named_bits(self):
5640 bits = []
5641 if (self.named_list):
5642 sorted_list = self.named_list
5643 sorted_list.sort()
5644 expected_bit_no = 0
5645 for e in (sorted_list):
5646 # Fill the table with "spare_bit" for "un named bits"
5647 if (int(e.val) != 0) and (expected_bit_no != int(e.val)):
5648 while ( expected_bit_no < int(e.val)):
5649 bits.append((expected_bit_no, ("spare_bit%u" % (expected_bit_no))))
5650 expected_bit_no = expected_bit_no + 1
5651 #print ("Adding named bits to list %s bit no %d" % (e.ident, int (e.val)))
5652 bits.append((int(e.val), e.ident))
5653 expected_bit_no = int(e.val) + 1
5654 return bits
5656 def eth_type_default_pars(self, ectx, tname):
5657 pars = Type.eth_type_default_pars(self, ectx, tname)
5658 pars['LEN_PTR'] = 'NULL'
5659 (pars['MIN_VAL'], pars['MAX_VAL'], pars['EXT']) = self.eth_get_size_constr(ectx)
5660 if 'ETT_INDEX' not in pars:
5661 pars['ETT_INDEX'] = '-1'
5662 pars['TABLE'] = 'NULL'
5663 if self.eth_named_bits():
5664 pars['TABLE'] = '%(PROTOP)s%(TNAME)s_bits'
5665 if self.HasContentsConstraint():
5666 pars['FN_VARIANT'] = ectx.default_containing_variant
5667 t = self.constr.GetContents(ectx)
5668 if t:
5669 if pars['FN_VARIANT'] in ('_pdu', '_pdu_new'):
5670 t = ectx.field[t]['ethname']
5671 pars['TYPE_REF_PROTO'] = ''
5672 pars['TYPE_REF_TNAME'] = t
5673 pars['TYPE_REF_FN'] = 'dissect_%(TYPE_REF_TNAME)s'
5674 else:
5675 t = ectx.type[t]['ethname']
5676 pars['TYPE_REF_PROTO'] = ectx.eth_type[t]['proto']
5677 pars['TYPE_REF_TNAME'] = t
5678 pars['TYPE_REF_FN'] = 'dissect_%(TYPE_REF_PROTO)s_%(TYPE_REF_TNAME)s'
5679 else:
5680 pars['TYPE_REF_FN'] = 'NULL'
5681 return pars
5683 def eth_type_default_table(self, ectx, tname):
5684 #print ("eth_type_default_table(tname='%s')" % (tname))
5685 table = ''
5686 bits = self.eth_named_bits()
5687 if (bits):
5688 table = ectx.eth_bits(tname, bits)
5689 return table
5691 def eth_type_default_body(self, ectx, tname):
5692 bits = self.eth_named_bits()
5693 if (ectx.Ber()):
5694 if (ectx.constraints_check and self.HasSizeConstraint()):
5695 body = ectx.eth_fn_call('dissect_%(ER)s_constrained_bitstring', ret='offset',
5696 par=(('%(IMPLICIT_TAG)s', '%(ACTX)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s'),
5697 ('%(MIN_VAL)s', '%(MAX_VAL)s', '%(TABLE)s', '%s' % len(bits),'%(HF_INDEX)s', '%(ETT_INDEX)s',),
5698 ('%(VAL_PTR)s',),))
5699 else:
5700 body = ectx.eth_fn_call('dissect_%(ER)s_bitstring', ret='offset',
5701 par=(('%(IMPLICIT_TAG)s', '%(ACTX)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s'),
5702 ('%(TABLE)s', '%s' % len(bits), '%(HF_INDEX)s', '%(ETT_INDEX)s',),
5703 ('%(VAL_PTR)s',),))
5704 elif (ectx.Per() or ectx.Oer()):
5705 if self.HasContentsConstraint():
5706 body = ectx.eth_fn_call('dissect_%(ER)s_bit_string_containing%(FN_VARIANT)s', ret='offset',
5707 par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
5708 ('%(MIN_VAL)s', '%(MAX_VAL)s', '%(EXT)s', '%(TYPE_REF_FN)s'),))
5709 else:
5710 body = ectx.eth_fn_call('dissect_%(ER)s_bit_string', ret='offset',
5711 par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
5712 ('%(MIN_VAL)s', '%(MAX_VAL)s', '%(EXT)s','%(TABLE)s', '%s' % len(bits), '%(VAL_PTR)s', '%(LEN_PTR)s'),))
5713 else:
5714 body = '#error Can not decode %s' % (tname)
5715 return body
5717 #--- BStringValue ------------------------------------------------------------
5718 bstring_tab = {
5719 '0000' : '0',
5720 '0001' : '1',
5721 '0010' : '2',
5722 '0011' : '3',
5723 '0100' : '4',
5724 '0101' : '5',
5725 '0110' : '6',
5726 '0111' : '7',
5727 '1000' : '8',
5728 '1001' : '9',
5729 '1010' : 'A',
5730 '1011' : 'B',
5731 '1100' : 'C',
5732 '1101' : 'D',
5733 '1110' : 'E',
5734 '1111' : 'F',
5736 class BStringValue (Value):
5737 def to_str(self, ectx):
5738 v = self.val[1:-2]
5739 if len(v) % 8:
5740 v += '0' * (8 - len(v) % 8)
5741 vv = '0x'
5742 for i in (list(range(0, len(v), 4))):
5743 vv += bstring_tab[v[i:i+4]]
5744 return vv
5746 #--- HStringValue ------------------------------------------------------------
5747 class HStringValue (Value):
5748 def to_str(self, ectx):
5749 vv = '0x'
5750 vv += self.val[1:-2]
5751 return vv
5752 def __int__(self):
5753 return int(self.val[1:-2], 16)
5755 #--- FieldSpec ----------------------------------------------------------------
5756 class FieldSpec (Node):
5757 def __init__(self,*args, **kw) :
5758 self.name = None
5759 Node.__init__ (self,*args, **kw)
5761 def SetName(self, name):
5762 self.name = name
5764 def get_repr(self):
5765 return ['#UNSUPPORTED_' + self.type]
5767 def fld_repr(self):
5768 repr = [self.name]
5769 repr.extend(self.get_repr())
5770 return repr
5772 class TypeFieldSpec (FieldSpec):
5773 def get_repr(self):
5774 return []
5776 class FixedTypeValueFieldSpec (FieldSpec):
5777 def get_repr(self):
5778 if isinstance(self.typ, Type_Ref):
5779 repr = ['TypeReference', self.typ.val]
5780 else:
5781 repr = [self.typ.type]
5782 return repr
5784 class VariableTypeValueFieldSpec (FieldSpec):
5785 def get_repr(self):
5786 return ['_' + self.type]
5788 class FixedTypeValueSetFieldSpec (FieldSpec):
5789 def get_repr(self):
5790 return ['_' + self.type]
5792 class ObjectFieldSpec (FieldSpec):
5793 def get_repr(self):
5794 return ['ClassReference', self.cls.val]
5796 class ObjectSetFieldSpec (FieldSpec):
5797 def get_repr(self):
5798 return ['ClassReference', self.cls.val]
5800 #==============================================================================
5802 def p_module_list_1 (t):
5803 'module_list : module_list ModuleDefinition'
5804 t[0] = t[1] + [t[2]]
5806 def p_module_list_2 (t):
5807 'module_list : ModuleDefinition'
5808 t[0] = [t[1]]
5811 #--- ITU-T Recommendation X.680 -----------------------------------------------
5814 # 11 ASN.1 lexical items --------------------------------------------------------
5816 # 11.2 Type references
5817 def p_type_ref (t):
5818 'type_ref : UCASE_IDENT'
5819 t[0] = Type_Ref(val=t[1])
5821 # 11.3 Identifiers
5822 def p_identifier (t):
5823 'identifier : LCASE_IDENT'
5824 t[0] = t[1]
5826 # 11.4 Value references
5827 # cause reduce/reduce conflict
5828 #def p_valuereference (t):
5829 # 'valuereference : LCASE_IDENT'
5830 # t[0] = Value_Ref(val=t[1])
5832 # 11.5 Module references
5833 def p_modulereference (t):
5834 'modulereference : UCASE_IDENT'
5835 t[0] = t[1]
5838 # 12 Module definition --------------------------------------------------------
5840 # 12.1
5841 def p_ModuleDefinition (t):
5842 'ModuleDefinition : ModuleIdentifier DEFINITIONS TagDefault ASSIGNMENT ModuleBegin BEGIN ModuleBody END'
5843 t[0] = Module (ident = t[1], tag_def = t[3], body = t[7])
5845 def p_ModuleBegin (t):
5846 'ModuleBegin : '
5847 if t[-4].val == 'Remote-Operations-Information-Objects':
5848 x880_module_begin()
5850 def p_TagDefault_1 (t):
5851 '''TagDefault : EXPLICIT TAGS
5852 | IMPLICIT TAGS
5853 | AUTOMATIC TAGS '''
5854 t[0] = Default_Tags (dfl_tag = t[1])
5856 def p_TagDefault_2 (t):
5857 'TagDefault : '
5858 # 12.2 The "TagDefault" is taken as EXPLICIT TAGS if it is "empty".
5859 t[0] = Default_Tags (dfl_tag = 'EXPLICIT')
5861 def p_ModuleIdentifier_1 (t):
5862 'ModuleIdentifier : modulereference DefinitiveIdentifier' # name, oid
5863 t [0] = Node('module_ident', val = t[1], ident = t[2])
5865 def p_ModuleIdentifier_2 (t):
5866 'ModuleIdentifier : modulereference' # name, oid
5867 t [0] = Node('module_ident', val = t[1], ident = None)
5869 def p_DefinitiveIdentifier (t):
5870 'DefinitiveIdentifier : ObjectIdentifierValue'
5871 t[0] = t[1]
5873 #def p_module_ref (t):
5874 # 'module_ref : UCASE_IDENT'
5875 # t[0] = t[1]
5877 def p_ModuleBody_1 (t):
5878 'ModuleBody : Exports Imports AssignmentList'
5879 t[0] = Module_Body (exports = t[1], imports = t[2], assign_list = t[3])
5881 def p_ModuleBody_2 (t):
5882 'ModuleBody : '
5883 t[0] = Node ('module_body', exports = [], imports = [], assign_list = [])
5885 def p_Exports_1 (t):
5886 'Exports : EXPORTS syms_exported SEMICOLON'
5887 t[0] = t[2]
5889 def p_Exports_2 (t):
5890 'Exports : EXPORTS ALL SEMICOLON'
5891 t[0] = [ 'ALL' ]
5893 def p_Exports_3 (t):
5894 'Exports : '
5895 t[0] = [ 'ALL' ]
5897 def p_syms_exported_1 (t):
5898 'syms_exported : exp_sym_list'
5899 t[0] = t[1]
5901 def p_syms_exported_2 (t):
5902 'syms_exported : '
5903 t[0] = []
5905 def p_exp_sym_list_1 (t):
5906 'exp_sym_list : Symbol'
5907 t[0] = [t[1]]
5909 def p_exp_sym_list_2 (t):
5910 'exp_sym_list : exp_sym_list COMMA Symbol'
5911 t[0] = t[1] + [t[3]]
5914 def p_Imports_1 (t):
5915 'Imports : importsbegin IMPORTS SymbolsImported SEMICOLON'
5916 t[0] = t[3]
5917 global lcase_ident_assigned
5918 lcase_ident_assigned = {}
5920 def p_importsbegin (t):
5921 'importsbegin : '
5922 global lcase_ident_assigned
5923 global g_conform
5924 lcase_ident_assigned = {}
5925 lcase_ident_assigned.update(g_conform.use_item('ASSIGNED_ID', 'OBJECT_IDENTIFIER'))
5927 def p_Imports_2 (t):
5928 'Imports : '
5929 t[0] = []
5931 def p_SymbolsImported_1(t):
5932 'SymbolsImported : '
5933 t[0] = []
5935 def p_SymbolsImported_2 (t):
5936 'SymbolsImported : SymbolsFromModuleList'
5937 t[0] = t[1]
5939 def p_SymbolsFromModuleList_1 (t):
5940 'SymbolsFromModuleList : SymbolsFromModuleList SymbolsFromModule'
5941 t[0] = t[1] + [t[2]]
5943 def p_SymbolsFromModuleList_2 (t):
5944 'SymbolsFromModuleList : SymbolsFromModule'
5945 t[0] = [t[1]]
5947 def p_SymbolsFromModule (t):
5948 '''SymbolsFromModule : SymbolList FROM GlobalModuleReference
5949 | SymbolList FROM GlobalModuleReference WITH SUCCESSORS'''
5950 t[0] = Node ('SymbolList', symbol_list = t[1], module = t[3])
5951 for s in (t[0].symbol_list):
5952 if (isinstance(s, Value_Ref)): lcase_ident_assigned[s.val] = t[3]
5953 import_symbols_from_module(t[0].module, t[0].symbol_list)
5955 def import_symbols_from_module(module, symbol_list):
5956 if module.val == 'Remote-Operations-Information-Objects':
5957 for i in range(len(symbol_list)):
5958 s = symbol_list[i]
5959 if isinstance(s, Type_Ref) or isinstance(s, Class_Ref):
5960 x880_import(s.val)
5961 if isinstance(s, Type_Ref) and is_class_ident(s.val):
5962 symbol_list[i] = Class_Ref (val = s.val)
5963 return
5964 for i in range(len(symbol_list)):
5965 s = symbol_list[i]
5966 if isinstance(s, Type_Ref) and is_class_ident("$%s$%s" % (module.val, s.val)):
5967 import_class_from_module(module.val, s.val)
5968 if isinstance(s, Type_Ref) and is_class_ident(s.val):
5969 symbol_list[i] = Class_Ref (val = s.val)
5971 def p_GlobalModuleReference (t):
5972 'GlobalModuleReference : modulereference AssignedIdentifier'
5973 t [0] = Node('module_ident', val = t[1], ident = t[2])
5975 def p_AssignedIdentifier_1 (t):
5976 'AssignedIdentifier : ObjectIdentifierValue'
5977 t[0] = t[1]
5979 def p_AssignedIdentifier_2 (t):
5980 'AssignedIdentifier : LCASE_IDENT_ASSIGNED'
5981 t[0] = t[1]
5983 def p_AssignedIdentifier_3 (t):
5984 'AssignedIdentifier : '
5985 pass
5987 def p_SymbolList_1 (t):
5988 'SymbolList : Symbol'
5989 t[0] = [t[1]]
5991 def p_SymbolList_2 (t):
5992 'SymbolList : SymbolList COMMA Symbol'
5993 t[0] = t[1] + [t[3]]
5995 def p_Symbol (t):
5996 '''Symbol : Reference
5997 | ParameterizedReference'''
5998 t[0] = t[1]
6000 def p_Reference_1 (t):
6001 '''Reference : type_ref
6002 | objectclassreference '''
6003 t[0] = t[1]
6005 def p_Reference_2 (t):
6006 '''Reference : LCASE_IDENT_ASSIGNED
6007 | identifier ''' # instead of valuereference which causes reduce/reduce conflict
6008 t[0] = Value_Ref(val=t[1])
6010 def p_AssignmentList_1 (t):
6011 'AssignmentList : AssignmentList Assignment'
6012 t[0] = t[1] + [t[2]]
6014 def p_AssignmentList_2 (t):
6015 'AssignmentList : Assignment SEMICOLON'
6016 t[0] = [t[1]]
6018 def p_AssignmentList_3 (t):
6019 'AssignmentList : Assignment'
6020 t[0] = [t[1]]
6022 def p_Assignment (t):
6023 '''Assignment : TypeAssignment
6024 | ValueAssignment
6025 | ValueSetTypeAssignment
6026 | ObjectClassAssignment
6027 | ObjectAssignment
6028 | ObjectSetAssignment
6029 | ParameterizedAssignment
6030 | pyquote '''
6031 t[0] = t[1]
6034 # 13 Referencing type and value definitions -----------------------------------
6036 # 13.1
6037 def p_DefinedType (t):
6038 '''DefinedType : ExternalTypeReference
6039 | type_ref
6040 | ParameterizedType'''
6041 t[0] = t[1]
6043 def p_DefinedValue_1(t):
6044 '''DefinedValue : ExternalValueReference'''
6045 t[0] = t[1]
6047 def p_DefinedValue_2(t):
6048 '''DefinedValue : identifier ''' # instead of valuereference which causes reduce/reduce conflict
6049 t[0] = Value_Ref(val=t[1])
6051 # 13.6
6052 def p_ExternalTypeReference (t):
6053 'ExternalTypeReference : modulereference DOT type_ref'
6054 t[0] = Node ('ExternalTypeReference', module = t[1], typ = t[3])
6056 def p_ExternalValueReference (t):
6057 'ExternalValueReference : modulereference DOT identifier'
6058 t[0] = Node ('ExternalValueReference', module = t[1], ident = t[3])
6061 # 15 Assigning types and values -----------------------------------------------
6063 # 15.1
6064 def p_TypeAssignment (t):
6065 'TypeAssignment : UCASE_IDENT ASSIGNMENT Type'
6066 t[0] = t[3]
6067 t[0].SetName(t[1])
6069 # 15.2
6070 def p_ValueAssignment (t):
6071 'ValueAssignment : LCASE_IDENT ValueType ASSIGNMENT Value'
6072 t[0] = ValueAssignment(ident = t[1], typ = t[2], val = t[4])
6074 # only "simple" types are supported to simplify grammar
6075 def p_ValueType (t):
6076 '''ValueType : type_ref
6077 | BooleanType
6078 | IntegerType
6079 | ObjectIdentifierType
6080 | OctetStringType
6081 | RealType '''
6083 t[0] = t[1]
6085 # 15.6
6086 def p_ValueSetTypeAssignment (t):
6087 'ValueSetTypeAssignment : UCASE_IDENT ValueType ASSIGNMENT ValueSet'
6088 t[0] = Node('ValueSetTypeAssignment', name=t[1], typ=t[2], val=t[4])
6090 # 15.7
6091 def p_ValueSet (t):
6092 'ValueSet : lbraceignore rbraceignore'
6093 t[0] = None
6096 # 16 Definition of types and values -------------------------------------------
6098 # 16.1
6099 def p_Type (t):
6100 '''Type : BuiltinType
6101 | ReferencedType
6102 | ConstrainedType'''
6103 t[0] = t[1]
6105 # 16.2
6106 def p_BuiltinType (t):
6107 '''BuiltinType : AnyType
6108 | BitStringType
6109 | BooleanType
6110 | CharacterStringType
6111 | ChoiceType
6112 | EmbeddedPDVType
6113 | EnumeratedType
6114 | ExternalType
6115 | InstanceOfType
6116 | IntegerType
6117 | NullType
6118 | ObjectClassFieldType
6119 | ObjectIdentifierType
6120 | OctetStringType
6121 | RealType
6122 | RelativeOIDType
6123 | SequenceType
6124 | SequenceOfType
6125 | SetType
6126 | SetOfType
6127 | TaggedType'''
6128 t[0] = t[1]
6130 # 16.3
6131 def p_ReferencedType (t):
6132 '''ReferencedType : DefinedType
6133 | UsefulType
6134 | SelectionType'''
6135 t[0] = t[1]
6137 # 16.5
6138 def p_NamedType (t):
6139 'NamedType : identifier Type'
6140 t[0] = t[2]
6141 t[0].SetName (t[1])
6143 # 16.7
6144 def p_Value (t):
6145 '''Value : BuiltinValue
6146 | ReferencedValue
6147 | ObjectClassFieldValue'''
6148 t[0] = t[1]
6150 # 16.9
6151 def p_BuiltinValue (t):
6152 '''BuiltinValue : BooleanValue
6153 | ChoiceValue
6154 | IntegerValue
6155 | ObjectIdentifierValue
6156 | RealValue
6157 | SequenceValue
6158 | hex_string
6159 | binary_string
6160 | char_string''' # XXX we don't support {data} here
6161 t[0] = t[1]
6163 # 16.11
6164 def p_ReferencedValue (t):
6165 '''ReferencedValue : DefinedValue
6166 | ValueFromObject'''
6167 t[0] = t[1]
6169 # 16.13
6170 #def p_NamedValue (t):
6171 # 'NamedValue : identifier Value'
6172 # t[0] = Node ('NamedValue', ident = t[1], value = t[2])
6175 # 17 Notation for the boolean type --------------------------------------------
6177 # 17.1
6178 def p_BooleanType (t):
6179 'BooleanType : BOOLEAN'
6180 t[0] = BooleanType ()
6182 # 17.2
6183 def p_BooleanValue (t):
6184 '''BooleanValue : TRUE
6185 | FALSE'''
6186 t[0] = t[1]
6189 # 18 Notation for the integer type --------------------------------------------
6191 # 18.1
6192 def p_IntegerType_1 (t):
6193 'IntegerType : INTEGER'
6194 t[0] = IntegerType (named_list = None)
6196 def p_IntegerType_2 (t):
6197 'IntegerType : INTEGER LBRACE NamedNumberList RBRACE'
6198 t[0] = IntegerType(named_list = t[3])
6200 def p_NamedNumberList_1 (t):
6201 'NamedNumberList : NamedNumber'
6202 t[0] = [t[1]]
6204 def p_NamedNumberList_2 (t):
6205 'NamedNumberList : NamedNumberList COMMA NamedNumber'
6206 t[0] = t[1] + [t[3]]
6208 def p_NamedNumber (t):
6209 '''NamedNumber : identifier LPAREN SignedNumber RPAREN
6210 | identifier LPAREN DefinedValue RPAREN'''
6211 t[0] = NamedNumber(ident = t[1], val = t[3])
6213 def p_SignedNumber_1 (t):
6214 'SignedNumber : NUMBER'
6215 t[0] = t [1]
6217 def p_SignedNumber_2 (t):
6218 'SignedNumber : MINUS NUMBER'
6219 t[0] = '-' + t[2]
6221 # 18.9
6222 def p_IntegerValue (t):
6223 'IntegerValue : SignedNumber'
6224 t[0] = t [1]
6226 # 19 Notation for the enumerated type -----------------------------------------
6228 # 19.1
6229 def p_EnumeratedType (t):
6230 'EnumeratedType : ENUMERATED LBRACE Enumerations RBRACE'
6231 t[0] = EnumeratedType (val = t[3]['val'], ext = t[3]['ext'])
6233 def p_Enumerations_1 (t):
6234 'Enumerations : Enumeration'
6235 t[0] = { 'val' : t[1], 'ext' : None }
6237 def p_Enumerations_2 (t):
6238 'Enumerations : Enumeration COMMA ELLIPSIS ExceptionSpec'
6239 t[0] = { 'val' : t[1], 'ext' : [] }
6241 def p_Enumerations_3 (t):
6242 'Enumerations : Enumeration COMMA ELLIPSIS ExceptionSpec COMMA Enumeration'
6243 t[0] = { 'val' : t[1], 'ext' : t[6] }
6245 def p_Enumeration_1 (t):
6246 'Enumeration : EnumerationItem'
6247 t[0] = [t[1]]
6249 def p_Enumeration_2 (t):
6250 'Enumeration : Enumeration COMMA EnumerationItem'
6251 t[0] = t[1] + [t[3]]
6253 def p_EnumerationItem (t):
6254 '''EnumerationItem : Identifier
6255 | NamedNumber'''
6256 t[0] = t[1]
6258 def p_Identifier (t):
6259 'Identifier : identifier'
6260 t[0] = Node ('Identifier', ident = t[1])
6263 # 20 Notation for the real type -----------------------------------------------
6265 # 20.1
6266 def p_RealType (t):
6267 'RealType : REAL'
6268 t[0] = RealType ()
6270 # 20.6
6271 def p_RealValue (t):
6272 '''RealValue : REAL_NUMBER
6273 | SpecialRealValue'''
6274 t[0] = t [1]
6276 def p_SpecialRealValue (t):
6277 '''SpecialRealValue : PLUS_INFINITY
6278 | MINUS_INFINITY'''
6279 t[0] = t[1]
6282 # 21 Notation for the bitstring type ------------------------------------------
6284 # 21.1
6285 def p_BitStringType_1 (t):
6286 'BitStringType : BIT STRING'
6287 t[0] = BitStringType (named_list = None)
6289 def p_BitStringType_2 (t):
6290 'BitStringType : BIT STRING LBRACE NamedBitList RBRACE'
6291 t[0] = BitStringType (named_list = t[4])
6293 def p_NamedBitList_1 (t):
6294 'NamedBitList : NamedBit'
6295 t[0] = [t[1]]
6297 def p_NamedBitList_2 (t):
6298 'NamedBitList : NamedBitList COMMA NamedBit'
6299 t[0] = t[1] + [t[3]]
6301 def p_NamedBit (t):
6302 '''NamedBit : identifier LPAREN NUMBER RPAREN
6303 | identifier LPAREN DefinedValue RPAREN'''
6304 t[0] = NamedNumber (ident = t[1], val = t[3])
6307 # 22 Notation for the octetstring type ----------------------------------------
6309 # 22.1
6310 def p_OctetStringType (t):
6311 'OctetStringType : OCTET STRING'
6312 t[0] = OctetStringType ()
6315 # 23 Notation for the null type -----------------------------------------------
6317 # 23.1
6318 def p_NullType (t):
6319 'NullType : NULL'
6320 t[0] = NullType ()
6322 # 23.3
6323 def p_NullValue (t):
6324 'NullValue : NULL'
6325 t[0] = NullValue ()
6328 # 24 Notation for sequence types ----------------------------------------------
6330 # 24.1
6331 def p_SequenceType_1 (t):
6332 'SequenceType : SEQUENCE LBRACE RBRACE'
6333 t[0] = SequenceType (elt_list = [])
6335 def p_SequenceType_2 (t):
6336 'SequenceType : SEQUENCE LBRACE ComponentTypeLists RBRACE'
6337 t[0] = SequenceType (elt_list = t[3]['elt_list'])
6338 if 'ext_list' in t[3]:
6339 t[0].ext_list = t[3]['ext_list']
6340 if 'elt_list2' in t[3]:
6341 t[0].elt_list2 = t[3]['elt_list2']
6343 def p_ExtensionAndException_1 (t):
6344 'ExtensionAndException : ELLIPSIS'
6345 t[0] = []
6347 def p_OptionalExtensionMarker_1 (t):
6348 'OptionalExtensionMarker : COMMA ELLIPSIS'
6349 t[0] = True
6351 def p_OptionalExtensionMarker_2 (t):
6352 'OptionalExtensionMarker : '
6353 t[0] = False
6355 def p_ComponentTypeLists_1 (t):
6356 'ComponentTypeLists : ComponentTypeList'
6357 t[0] = {'elt_list' : t[1]}
6359 def p_ComponentTypeLists_2 (t):
6360 'ComponentTypeLists : ComponentTypeList COMMA ExtensionAndException OptionalExtensionMarker'
6361 t[0] = {'elt_list' : t[1], 'ext_list' : []}
6363 def p_ComponentTypeLists_3 (t):
6364 'ComponentTypeLists : ComponentTypeList COMMA ExtensionAndException ExtensionAdditionList OptionalExtensionMarker'
6365 t[0] = {'elt_list' : t[1], 'ext_list' : t[4]}
6367 def p_ComponentTypeLists_4 (t):
6368 'ComponentTypeLists : ComponentTypeList COMMA ExtensionAndException ExtensionEndMarker COMMA ComponentTypeList'
6369 t[0] = {'elt_list' : t[1], 'ext_list' : [], 'elt_list2' : t[6]}
6371 def p_ComponentTypeLists_5 (t):
6372 'ComponentTypeLists : ComponentTypeList COMMA ExtensionAndException ExtensionAdditionList ExtensionEndMarker COMMA ComponentTypeList'
6373 t[0] = {'elt_list' : t[1], 'ext_list' : t[4], 'elt_list2' : t[7]}
6375 def p_ComponentTypeLists_6 (t):
6376 'ComponentTypeLists : ExtensionAndException OptionalExtensionMarker'
6377 t[0] = {'elt_list' : [], 'ext_list' : []}
6379 def p_ComponentTypeLists_7 (t):
6380 'ComponentTypeLists : ExtensionAndException ExtensionAdditionList OptionalExtensionMarker'
6381 t[0] = {'elt_list' : [], 'ext_list' : t[2]}
6383 def p_ExtensionEndMarker (t):
6384 'ExtensionEndMarker : COMMA ELLIPSIS'
6385 pass
6387 def p_ExtensionAdditionList_1 (t):
6388 'ExtensionAdditionList : COMMA ExtensionAddition'
6389 t[0] = [t[2]]
6391 def p_ExtensionAdditionList_2 (t):
6392 'ExtensionAdditionList : ExtensionAdditionList COMMA ExtensionAddition'
6393 t[0] = t[1] + [t[3]]
6395 def p_ExtensionAddition_1 (t):
6396 'ExtensionAddition : ExtensionAdditionGroup'
6397 t[0] = Node ('elt_type', val = t[1], optional = 0)
6399 def p_ExtensionAddition_2 (t):
6400 'ExtensionAddition : ComponentType'
6401 t[0] = t[1]
6403 def p_ExtensionAdditionGroup (t):
6404 'ExtensionAdditionGroup : LVERBRACK VersionNumber ComponentTypeList RVERBRACK'
6405 t[0] = ExtensionAdditionGroup (ver = t[2], elt_list = t[3])
6407 def p_VersionNumber_1 (t):
6408 'VersionNumber : '
6410 def p_VersionNumber_2 (t):
6411 'VersionNumber : NUMBER COLON'
6412 t[0] = t[1]
6414 def p_ComponentTypeList_1 (t):
6415 'ComponentTypeList : ComponentType'
6416 t[0] = [t[1]]
6418 def p_ComponentTypeList_2 (t):
6419 'ComponentTypeList : ComponentTypeList COMMA ComponentType'
6420 t[0] = t[1] + [t[3]]
6422 def p_ComponentType_1 (t):
6423 'ComponentType : NamedType'
6424 t[0] = Node ('elt_type', val = t[1], optional = 0)
6426 def p_ComponentType_2 (t):
6427 'ComponentType : NamedType OPTIONAL'
6428 t[0] = Node ('elt_type', val = t[1], optional = 1)
6430 def p_ComponentType_3 (t):
6431 'ComponentType : NamedType DEFAULT DefaultValue'
6432 t[0] = Node ('elt_type', val = t[1], optional = 1, default = t[3])
6434 def p_ComponentType_4 (t):
6435 'ComponentType : COMPONENTS OF Type'
6436 t[0] = Node ('components_of', typ = t[3])
6438 def p_DefaultValue_1 (t):
6439 '''DefaultValue : ReferencedValue
6440 | BooleanValue
6441 | ChoiceValue
6442 | IntegerValue
6443 | RealValue
6444 | hex_string
6445 | binary_string
6446 | char_string
6447 | ObjectClassFieldValue'''
6448 t[0] = t[1]
6450 def p_DefaultValue_2 (t):
6451 'DefaultValue : lbraceignore rbraceignore'
6452 t[0] = ''
6454 # 24.17
6455 def p_SequenceValue_1 (t):
6456 'SequenceValue : LBRACE RBRACE'
6457 t[0] = []
6460 #def p_SequenceValue_2 (t):
6461 # 'SequenceValue : LBRACE ComponentValueList RBRACE'
6462 # t[0] = t[2]
6464 #def p_ComponentValueList_1 (t):
6465 # 'ComponentValueList : NamedValue'
6466 # t[0] = [t[1]]
6468 #def p_ComponentValueList_2 (t):
6469 # 'ComponentValueList : ComponentValueList COMMA NamedValue'
6470 # t[0] = t[1] + [t[3]]
6473 # 25 Notation for sequence-of types -------------------------------------------
6475 # 25.1
6476 def p_SequenceOfType (t):
6477 '''SequenceOfType : SEQUENCE OF Type
6478 | SEQUENCE OF NamedType'''
6479 t[0] = SequenceOfType (val = t[3], size_constr = None)
6482 # 26 Notation for set types ---------------------------------------------------
6484 # 26.1
6485 def p_SetType_1 (t):
6486 'SetType : SET LBRACE RBRACE'
6487 t[0] = SetType (elt_list = [])
6489 def p_SetType_2 (t):
6490 'SetType : SET LBRACE ComponentTypeLists RBRACE'
6491 t[0] = SetType (elt_list = t[3]['elt_list'])
6492 if 'ext_list' in t[3]:
6493 t[0].ext_list = t[3]['ext_list']
6494 if 'elt_list2' in t[3]:
6495 t[0].elt_list2 = t[3]['elt_list2']
6498 # 27 Notation for set-of types ------------------------------------------------
6500 # 27.1
6501 def p_SetOfType (t):
6502 '''SetOfType : SET OF Type
6503 | SET OF NamedType'''
6504 t[0] = SetOfType (val = t[3])
6506 # 28 Notation for choice types ------------------------------------------------
6508 # 28.1
6509 def p_ChoiceType (t):
6510 'ChoiceType : CHOICE LBRACE AlternativeTypeLists RBRACE'
6511 if 'ext_list' in t[3]:
6512 t[0] = ChoiceType (elt_list = t[3]['elt_list'], ext_list = t[3]['ext_list'])
6513 else:
6514 t[0] = ChoiceType (elt_list = t[3]['elt_list'])
6516 def p_AlternativeTypeLists_1 (t):
6517 'AlternativeTypeLists : AlternativeTypeList'
6518 t[0] = {'elt_list' : t[1]}
6520 def p_AlternativeTypeLists_2 (t):
6521 'AlternativeTypeLists : AlternativeTypeList COMMA ExtensionAndException ExtensionAdditionAlternatives OptionalExtensionMarker'
6522 t[0] = {'elt_list' : t[1], 'ext_list' : t[4]}
6524 def p_ExtensionAdditionAlternatives_1 (t):
6525 'ExtensionAdditionAlternatives : ExtensionAdditionAlternativesList'
6526 t[0] = t[1]
6528 def p_ExtensionAdditionAlternatives_2 (t):
6529 'ExtensionAdditionAlternatives : '
6530 t[0] = []
6532 def p_ExtensionAdditionAlternativesList_1 (t):
6533 'ExtensionAdditionAlternativesList : COMMA ExtensionAdditionAlternative'
6534 t[0] = t[2]
6536 def p_ExtensionAdditionAlternativesList_2 (t):
6537 'ExtensionAdditionAlternativesList : ExtensionAdditionAlternativesList COMMA ExtensionAdditionAlternative'
6538 t[0] = t[1] + t[3]
6540 def p_ExtensionAdditionAlternative_1 (t):
6541 'ExtensionAdditionAlternative : NamedType'
6542 t[0] = [t[1]]
6544 def p_ExtensionAdditionAlternative_2 (t):
6545 'ExtensionAdditionAlternative : ExtensionAdditionAlternativesGroup'
6546 t[0] = t[1]
6548 def p_ExtensionAdditionAlternativesGroup (t):
6549 'ExtensionAdditionAlternativesGroup : LVERBRACK VersionNumber AlternativeTypeList RVERBRACK'
6550 t[0] = t[3]
6552 def p_AlternativeTypeList_1 (t):
6553 'AlternativeTypeList : NamedType'
6554 t[0] = [t[1]]
6556 def p_AlternativeTypeList_2 (t):
6557 'AlternativeTypeList : AlternativeTypeList COMMA NamedType'
6558 t[0] = t[1] + [t[3]]
6560 # 28.10
6561 def p_ChoiceValue_1 (t):
6562 '''ChoiceValue : identifier COLON Value
6563 | identifier COLON NullValue '''
6564 val = t[3]
6565 if not isinstance(val, Value):
6566 val = Value(val=val)
6567 t[0] = ChoiceValue (choice = t[1], val = val)
6569 # 29 Notation for selection types
6571 # 29.1
6572 def p_SelectionType (t): #
6573 'SelectionType : identifier LT Type'
6574 t[0] = SelectionType (typ = t[3], sel = t[1])
6576 # 30 Notation for tagged types ------------------------------------------------
6578 # 30.1
6579 def p_TaggedType_1 (t):
6580 'TaggedType : Tag Type'
6581 t[1].mode = 'default'
6582 t[0] = t[2]
6583 t[0].AddTag(t[1])
6585 def p_TaggedType_2 (t):
6586 '''TaggedType : Tag IMPLICIT Type
6587 | Tag EXPLICIT Type'''
6588 t[1].mode = t[2]
6589 t[0] = t[3]
6590 t[0].AddTag(t[1])
6592 def p_Tag (t):
6593 'Tag : LBRACK Class ClassNumber RBRACK'
6594 t[0] = Tag(cls = t[2], num = t[3])
6596 def p_ClassNumber_1 (t):
6597 'ClassNumber : number'
6598 t[0] = t[1]
6600 def p_ClassNumber_2 (t):
6601 'ClassNumber : DefinedValue'
6602 t[0] = t[1]
6604 def p_Class_1 (t):
6605 '''Class : UNIVERSAL
6606 | APPLICATION
6607 | PRIVATE'''
6608 t[0] = t[1]
6610 def p_Class_2 (t):
6611 'Class :'
6612 t[0] = 'CONTEXT'
6615 # 31 Notation for the object identifier type ----------------------------------
6617 # 31.1
6618 def p_ObjectIdentifierType (t):
6619 'ObjectIdentifierType : OBJECT IDENTIFIER'
6620 t[0] = ObjectIdentifierType()
6622 # 31.3
6623 def p_ObjectIdentifierValue (t):
6624 'ObjectIdentifierValue : LBRACE oid_comp_list RBRACE'
6625 t[0] = ObjectIdentifierValue (comp_list=t[2])
6627 def p_oid_comp_list_1 (t):
6628 'oid_comp_list : oid_comp_list ObjIdComponents'
6629 t[0] = t[1] + [t[2]]
6631 def p_oid_comp_list_2 (t):
6632 'oid_comp_list : ObjIdComponents'
6633 t[0] = [t[1]]
6635 def p_ObjIdComponents (t):
6636 '''ObjIdComponents : NameForm
6637 | NumberForm
6638 | NameAndNumberForm'''
6639 t[0] = t[1]
6641 def p_NameForm (t):
6642 '''NameForm : LCASE_IDENT
6643 | LCASE_IDENT_ASSIGNED'''
6644 t [0] = t[1]
6646 def p_NumberForm (t):
6647 '''NumberForm : NUMBER'''
6648 # | DefinedValue'''
6649 t [0] = t[1]
6651 def p_NameAndNumberForm (t):
6652 '''NameAndNumberForm : LCASE_IDENT_ASSIGNED LPAREN NumberForm RPAREN
6653 | LCASE_IDENT LPAREN NumberForm RPAREN'''
6654 t[0] = Node('name_and_number', ident = t[1], number = t[3])
6656 # 32 Notation for the relative object identifier type -------------------------
6658 # 32.1
6659 def p_RelativeOIDType (t):
6660 'RelativeOIDType : RELATIVE_OID'
6661 t[0] = RelativeOIDType()
6663 # 33 Notation for the embedded-pdv type ---------------------------------------
6665 # 33.1
6666 def p_EmbeddedPDVType (t):
6667 'EmbeddedPDVType : EMBEDDED PDV'
6668 t[0] = EmbeddedPDVType()
6670 # 34 Notation for the external type -------------------------------------------
6672 # 34.1
6673 def p_ExternalType (t):
6674 'ExternalType : EXTERNAL'
6675 t[0] = ExternalType()
6677 # 36 Notation for character string types --------------------------------------
6679 # 36.1
6680 def p_CharacterStringType (t):
6681 '''CharacterStringType : RestrictedCharacterStringType
6682 | UnrestrictedCharacterStringType'''
6683 t[0] = t[1]
6686 # 37 Definition of restricted character string types --------------------------
6688 def p_RestrictedCharacterStringType_1 (t):
6689 'RestrictedCharacterStringType : BMPString'
6690 t[0] = BMPStringType ()
6691 def p_RestrictedCharacterStringType_2 (t):
6692 'RestrictedCharacterStringType : GeneralString'
6693 t[0] = GeneralStringType ()
6694 def p_RestrictedCharacterStringType_3 (t):
6695 'RestrictedCharacterStringType : GraphicString'
6696 t[0] = GraphicStringType ()
6697 def p_RestrictedCharacterStringType_4 (t):
6698 'RestrictedCharacterStringType : IA5String'
6699 t[0] = IA5StringType ()
6700 def p_RestrictedCharacterStringType_5 (t):
6701 'RestrictedCharacterStringType : ISO646String'
6702 t[0] = ISO646StringType ()
6703 def p_RestrictedCharacterStringType_6 (t):
6704 'RestrictedCharacterStringType : NumericString'
6705 t[0] = NumericStringType ()
6706 def p_RestrictedCharacterStringType_7 (t):
6707 'RestrictedCharacterStringType : PrintableString'
6708 t[0] = PrintableStringType ()
6709 def p_RestrictedCharacterStringType_8 (t):
6710 'RestrictedCharacterStringType : TeletexString'
6711 t[0] = TeletexStringType ()
6712 def p_RestrictedCharacterStringType_9 (t):
6713 'RestrictedCharacterStringType : T61String'
6714 t[0] = T61StringType ()
6715 def p_RestrictedCharacterStringType_10 (t):
6716 'RestrictedCharacterStringType : UniversalString'
6717 t[0] = UniversalStringType ()
6718 def p_RestrictedCharacterStringType_11 (t):
6719 'RestrictedCharacterStringType : UTF8String'
6720 t[0] = UTF8StringType ()
6721 def p_RestrictedCharacterStringType_12 (t):
6722 'RestrictedCharacterStringType : VideotexString'
6723 t[0] = VideotexStringType ()
6724 def p_RestrictedCharacterStringType_13 (t):
6725 'RestrictedCharacterStringType : VisibleString'
6726 t[0] = VisibleStringType ()
6729 # 40 Definition of unrestricted character string types ------------------------
6731 # 40.1
6732 def p_UnrestrictedCharacterStringType (t):
6733 'UnrestrictedCharacterStringType : CHARACTER STRING'
6734 t[0] = UnrestrictedCharacterStringType ()
6737 # 41 Notation for types defined in clauses 42 to 44 ---------------------------
6739 # 42 Generalized time ---------------------------------------------------------
6741 def p_UsefulType_1 (t):
6742 'UsefulType : GeneralizedTime'
6743 t[0] = GeneralizedTime()
6745 # 43 Universal time -----------------------------------------------------------
6747 def p_UsefulType_2 (t):
6748 'UsefulType : UTCTime'
6749 t[0] = UTCTime()
6751 # 44 The object descriptor type -----------------------------------------------
6753 def p_UsefulType_3 (t):
6754 'UsefulType : ObjectDescriptor'
6755 t[0] = ObjectDescriptor()
6758 # 45 Constrained types --------------------------------------------------------
6760 # 45.1
6761 def p_ConstrainedType_1 (t):
6762 'ConstrainedType : Type Constraint'
6763 t[0] = t[1]
6764 t[0].AddConstraint(t[2])
6766 def p_ConstrainedType_2 (t):
6767 'ConstrainedType : TypeWithConstraint'
6768 t[0] = t[1]
6770 # 45.5
6771 def p_TypeWithConstraint_1 (t):
6772 '''TypeWithConstraint : SET Constraint OF Type
6773 | SET SizeConstraint OF Type'''
6774 t[0] = SetOfType (val = t[4], constr = t[2])
6776 def p_TypeWithConstraint_2 (t):
6777 '''TypeWithConstraint : SEQUENCE Constraint OF Type
6778 | SEQUENCE SizeConstraint OF Type'''
6779 t[0] = SequenceOfType (val = t[4], constr = t[2])
6781 def p_TypeWithConstraint_3 (t):
6782 '''TypeWithConstraint : SET Constraint OF NamedType
6783 | SET SizeConstraint OF NamedType'''
6784 t[0] = SetOfType (val = t[4], constr = t[2])
6786 def p_TypeWithConstraint_4 (t):
6787 '''TypeWithConstraint : SEQUENCE Constraint OF NamedType
6788 | SEQUENCE SizeConstraint OF NamedType'''
6789 t[0] = SequenceOfType (val = t[4], constr = t[2])
6791 # 45.6
6792 # 45.7
6793 def p_Constraint (t):
6794 'Constraint : LPAREN ConstraintSpec ExceptionSpec RPAREN'
6795 t[0] = t[2]
6797 def p_ConstraintSpec (t):
6798 '''ConstraintSpec : ElementSetSpecs
6799 | GeneralConstraint'''
6800 t[0] = t[1]
6802 # 46 Element set specification ------------------------------------------------
6804 # 46.1
6805 def p_ElementSetSpecs_1 (t):
6806 'ElementSetSpecs : RootElementSetSpec'
6807 t[0] = t[1]
6809 def p_ElementSetSpecs_2 (t):
6810 'ElementSetSpecs : RootElementSetSpec COMMA ELLIPSIS'
6811 t[0] = t[1]
6812 t[0].ext = True
6814 def p_ElementSetSpecs_3 (t):
6815 'ElementSetSpecs : RootElementSetSpec COMMA ELLIPSIS COMMA AdditionalElementSetSpec'
6816 t[0] = t[1]
6817 t[0].ext = True
6819 def p_RootElementSetSpec (t):
6820 'RootElementSetSpec : ElementSetSpec'
6821 t[0] = t[1]
6823 def p_AdditionalElementSetSpec (t):
6824 'AdditionalElementSetSpec : ElementSetSpec'
6825 t[0] = t[1]
6827 def p_ElementSetSpec (t):
6828 'ElementSetSpec : Unions'
6829 t[0] = t[1]
6831 def p_Unions_1 (t):
6832 'Unions : Intersections'
6833 t[0] = t[1]
6835 def p_Unions_2 (t):
6836 'Unions : UElems UnionMark Intersections'
6837 # Constraints currently ignored become None, e.g. InnerTypeConstraints
6838 # (WITH COMPONENT[S]). Don't add them to a Union.
6839 if t[3] is None:
6840 t[0] = t[1]
6841 elif t[1] is None:
6842 t[0] = t[3]
6843 else:
6844 t[0] = Constraint(type = 'Union', subtype = [t[1], t[3]])
6846 def p_UElems (t):
6847 'UElems : Unions'
6848 t[0] = t[1]
6850 def p_Intersections_1 (t):
6851 'Intersections : IntersectionElements'
6852 t[0] = t[1]
6854 def p_Intersections_2 (t):
6855 'Intersections : IElems IntersectionMark IntersectionElements'
6856 t[0] = Constraint(type = 'Intersection', subtype = [t[1], t[3]])
6858 def p_IElems (t):
6859 'IElems : Intersections'
6860 t[0] = t[1]
6862 def p_IntersectionElements (t):
6863 'IntersectionElements : Elements'
6864 t[0] = t[1]
6866 def p_UnionMark (t):
6867 '''UnionMark : BAR
6868 | UNION'''
6870 def p_IntersectionMark (t):
6871 '''IntersectionMark : CIRCUMFLEX
6872 | INTERSECTION'''
6874 # 46.5
6875 def p_Elements_1 (t):
6876 'Elements : SubtypeElements'
6877 t[0] = t[1]
6879 def p_Elements_2 (t):
6880 'Elements : LPAREN ElementSetSpec RPAREN'
6881 t[0] = t[2]
6883 # 47 Subtype elements ---------------------------------------------------------
6885 # 47.1 General
6886 def p_SubtypeElements (t):
6887 '''SubtypeElements : SingleValue
6888 | ContainedSubtype
6889 | ValueRange
6890 | PermittedAlphabet
6891 | SizeConstraint
6892 | TypeConstraint
6893 | InnerTypeConstraints
6894 | PatternConstraint'''
6895 t[0] = t[1]
6897 # 47.2 Single value
6898 # 47.2.1
6899 def p_SingleValue (t):
6900 'SingleValue : Value'
6901 t[0] = Constraint(type = 'SingleValue', subtype = t[1])
6903 # 47.3 Contained subtype
6904 # 47.3.1
6905 def p_ContainedSubtype (t):
6906 'ContainedSubtype : Includes Type'
6907 t[0] = Constraint(type = 'ContainedSubtype', subtype = t[2])
6909 def p_Includes (t):
6910 '''Includes : INCLUDES
6911 | '''
6913 # 47.4 Value range
6914 # 47.4.1
6915 def p_ValueRange (t):
6916 'ValueRange : LowerEndpoint RANGE UpperEndpoint'
6917 t[0] = Constraint(type = 'ValueRange', subtype = [t[1], t[3]])
6919 # 47.4.3
6920 def p_LowerEndpoint_1 (t):
6921 'LowerEndpoint : LowerEndValue'
6922 t[0] = t[1]
6924 def p_LowerEndpoint_2 (t):
6925 'LowerEndpoint : LowerEndValue LT'
6926 t[0] = t[1] # but not inclusive range
6928 def p_UpperEndpoint_1 (t):
6929 'UpperEndpoint : UpperEndValue'
6930 t[0] = t[1]
6932 def p_UpperEndpoint_2 (t):
6933 'UpperEndpoint : LT UpperEndValue'
6934 t[0] = t[1] # but not inclusive range
6936 # 47.4.4
6937 def p_LowerEndValue (t):
6938 '''LowerEndValue : Value
6939 | MIN'''
6940 t[0] = t[1] # XXX
6942 def p_UpperEndValue (t):
6943 '''UpperEndValue : Value
6944 | MAX'''
6945 t[0] = t[1]
6947 # 47.5 Size constraint
6948 # 47.5.1
6949 def p_SizeConstraint (t):
6950 'SizeConstraint : SIZE Constraint'
6951 t[0] = Constraint (type = 'Size', subtype = t[2])
6953 # 47.6 Type constraint
6954 # 47.6.1
6955 def p_TypeConstraint (t):
6956 'TypeConstraint : Type'
6957 t[0] = Constraint (type = 'Type', subtype = t[1])
6959 # 47.7 Permitted alphabet
6960 # 47.7.1
6961 def p_PermittedAlphabet (t):
6962 'PermittedAlphabet : FROM Constraint'
6963 t[0] = Constraint (type = 'From', subtype = t[2])
6965 # 47.8 Inner subtyping
6966 # 47.8.1
6967 def p_InnerTypeConstraints (t):
6968 '''InnerTypeConstraints : WITH COMPONENT SingleTypeConstraint
6969 | WITH COMPONENTS MultipleTypeConstraints'''
6970 pass # ignore PER invisible constraint
6972 # 47.8.3
6973 def p_SingleTypeConstraint (t):
6974 'SingleTypeConstraint : Constraint'
6975 t[0] = t[1]
6977 # 47.8.4
6978 def p_MultipleTypeConstraints (t):
6979 '''MultipleTypeConstraints : FullSpecification
6980 | PartialSpecification'''
6981 t[0] = t[1]
6983 def p_FullSpecification (t):
6984 'FullSpecification : LBRACE TypeConstraints RBRACE'
6985 t[0] = t[2]
6987 def p_PartialSpecification (t):
6988 'PartialSpecification : LBRACE ELLIPSIS COMMA TypeConstraints RBRACE'
6989 t[0] = t[4]
6991 def p_TypeConstraints_1 (t):
6992 'TypeConstraints : named_constraint'
6993 t [0] = [t[1]]
6995 def p_TypeConstraints_2 (t):
6996 'TypeConstraints : TypeConstraints COMMA named_constraint'
6997 t[0] = t[1] + [t[3]]
6999 def p_named_constraint_1 (t):
7000 'named_constraint : identifier constraint'
7001 return Node ('named_constraint', ident = t[1], constr = t[2])
7003 def p_named_constraint_2 (t):
7004 'named_constraint : constraint'
7005 return Node ('named_constraint', constr = t[1])
7007 def p_constraint (t):
7008 'constraint : value_constraint presence_constraint'
7009 t[0] = Node ('constraint', value = t[1], presence = t[2])
7011 def p_value_constraint_1 (t):
7012 'value_constraint : Constraint'
7013 t[0] = t[1]
7015 def p_value_constraint_2 (t):
7016 'value_constraint : '
7017 pass
7019 def p_presence_constraint_1 (t):
7020 '''presence_constraint : PRESENT
7021 | ABSENT
7022 | OPTIONAL'''
7023 t[0] = t[1]
7025 def p_presence_constraint_2 (t):
7026 '''presence_constraint : '''
7027 pass
7029 # 47.9 Pattern constraint
7030 # 47.9.1
7031 def p_PatternConstraint (t):
7032 'PatternConstraint : PATTERN Value'
7033 t[0] = Constraint (type = 'Pattern', subtype = t[2])
7035 # 49 The exception identifier
7037 # 49.4
7038 def p_ExceptionSpec_1 (t):
7039 'ExceptionSpec : EXCLAMATION ExceptionIdentification'
7040 pass
7042 def p_ExceptionSpec_2 (t):
7043 'ExceptionSpec : '
7044 pass
7046 def p_ExceptionIdentification (t):
7047 '''ExceptionIdentification : SignedNumber
7048 | DefinedValue
7049 | Type COLON Value '''
7050 pass
7052 # /*-----------------------------------------------------------------------*/
7053 # /* Value Notation Productions */
7054 # /*-----------------------------------------------------------------------*/
7058 def p_binary_string (t):
7059 'binary_string : BSTRING'
7060 t[0] = BStringValue(val = t[1])
7062 def p_hex_string (t):
7063 'hex_string : HSTRING'
7064 t[0] = HStringValue(val = t[1])
7066 def p_char_string (t):
7067 'char_string : QSTRING'
7068 t[0] = t[1]
7070 def p_number (t):
7071 'number : NUMBER'
7072 t[0] = t[1]
7075 #--- ITU-T Recommendation X.208 -----------------------------------------------
7077 # 27 Notation for the any type ------------------------------------------------
7079 # 27.1
7080 def p_AnyType (t):
7081 '''AnyType : ANY
7082 | ANY DEFINED BY identifier'''
7083 t[0] = AnyType()
7085 #--- ITU-T Recommendation X.681 -----------------------------------------------
7087 # 7 ASN.1 lexical items -------------------------------------------------------
7089 # 7.1 Information object class references
7091 def p_objectclassreference (t):
7092 'objectclassreference : CLASS_IDENT'
7093 t[0] = Class_Ref(val=t[1])
7095 # 7.2 Information object references
7097 def p_objectreference (t):
7098 'objectreference : LCASE_IDENT'
7099 t[0] = t[1]
7101 # 7.3 Information object set references
7103 #def p_objectsetreference (t):
7104 # 'objectsetreference : UCASE_IDENT'
7105 # t[0] = t[1]
7107 # 7.4 Type field references
7108 # ucasefieldreference
7109 # 7.5 Value field references
7110 # lcasefieldreference
7111 # 7.6 Value set field references
7112 # ucasefieldreference
7113 # 7.7 Object field references
7114 # lcasefieldreference
7115 # 7.8 Object set field references
7116 # ucasefieldreference
7118 def p_ucasefieldreference (t):
7119 'ucasefieldreference : AMPERSAND UCASE_IDENT'
7120 t[0] = '&' + t[2]
7122 def p_lcasefieldreference (t):
7123 'lcasefieldreference : AMPERSAND LCASE_IDENT'
7124 t[0] = '&' + t[2]
7126 # 8 Referencing definitions
7128 # 8.1
7129 def p_DefinedObjectClass (t):
7130 '''DefinedObjectClass : objectclassreference
7131 | UsefulObjectClassReference'''
7132 t[0] = t[1]
7133 global obj_class
7134 obj_class = t[0].val
7136 def p_DefinedObject (t):
7137 '''DefinedObject : objectreference'''
7138 t[0] = t[1]
7140 # 8.4
7141 def p_UsefulObjectClassReference (t):
7142 '''UsefulObjectClassReference : TYPE_IDENTIFIER
7143 | ABSTRACT_SYNTAX'''
7144 t[0] = Class_Ref(val=t[1])
7146 # 9 Information object class definition and assignment
7148 # 9.1
7149 def p_ObjectClassAssignment (t):
7150 '''ObjectClassAssignment : CLASS_IDENT ASSIGNMENT ObjectClass
7151 | UCASE_IDENT ASSIGNMENT ObjectClass'''
7152 t[0] = t[3]
7153 t[0].SetName(t[1])
7154 if isinstance(t[0], ObjectClassDefn):
7155 t[0].reg_types()
7157 # 9.2
7158 def p_ObjectClass (t):
7159 '''ObjectClass : DefinedObjectClass
7160 | ObjectClassDefn
7161 | ParameterizedObjectClass '''
7162 t[0] = t[1]
7164 # 9.3
7165 def p_ObjectClassDefn (t):
7166 '''ObjectClassDefn : CLASS LBRACE FieldSpecs RBRACE
7167 | CLASS LBRACE FieldSpecs RBRACE WithSyntaxSpec'''
7168 t[0] = ObjectClassDefn(fields = t[3])
7170 def p_FieldSpecs_1 (t):
7171 'FieldSpecs : FieldSpec'
7172 t[0] = [t[1]]
7174 def p_FieldSpecs_2 (t):
7175 'FieldSpecs : FieldSpecs COMMA FieldSpec'
7176 t[0] = t[1] + [t[3]]
7178 def p_WithSyntaxSpec (t):
7179 'WithSyntaxSpec : WITH SYNTAX lbraceignore rbraceignore'
7180 t[0] = None
7182 # 9.4
7183 def p_FieldSpec (t):
7184 '''FieldSpec : TypeFieldSpec
7185 | FixedTypeValueFieldSpec
7186 | VariableTypeValueFieldSpec
7187 | FixedTypeValueSetFieldSpec
7188 | ObjectFieldSpec
7189 | ObjectSetFieldSpec '''
7190 t[0] = t[1]
7192 # 9.5
7193 def p_TypeFieldSpec (t):
7194 '''TypeFieldSpec : ucasefieldreference
7195 | ucasefieldreference TypeOptionalitySpec '''
7196 t[0] = TypeFieldSpec()
7197 t[0].SetName(t[1])
7199 def p_TypeOptionalitySpec_1 (t):
7200 'TypeOptionalitySpec ::= OPTIONAL'
7201 pass
7203 def p_TypeOptionalitySpec_2 (t):
7204 'TypeOptionalitySpec ::= DEFAULT Type'
7205 pass
7207 # 9.6
7208 def p_FixedTypeValueFieldSpec (t):
7209 '''FixedTypeValueFieldSpec : lcasefieldreference Type
7210 | lcasefieldreference Type UNIQUE
7211 | lcasefieldreference Type ValueOptionalitySpec
7212 | lcasefieldreference Type UNIQUE ValueOptionalitySpec '''
7213 t[0] = FixedTypeValueFieldSpec(typ = t[2])
7214 t[0].SetName(t[1])
7216 def p_ValueOptionalitySpec_1 (t):
7217 'ValueOptionalitySpec ::= OPTIONAL'
7218 pass
7220 def p_ValueOptionalitySpec_2 (t):
7221 'ValueOptionalitySpec ::= DEFAULT Value'
7222 pass
7224 # 9.8
7226 def p_VariableTypeValueFieldSpec (t):
7227 '''VariableTypeValueFieldSpec : lcasefieldreference FieldName
7228 | lcasefieldreference FieldName ValueOptionalitySpec '''
7229 t[0] = VariableTypeValueFieldSpec()
7230 t[0].SetName(t[1])
7232 # 9.9
7233 def p_FixedTypeValueSetFieldSpec (t):
7234 '''FixedTypeValueSetFieldSpec : ucasefieldreference Type
7235 | ucasefieldreference Type ValueSetOptionalitySpec '''
7236 t[0] = FixedTypeValueSetFieldSpec()
7237 t[0].SetName(t[1])
7239 def p_ValueSetOptionalitySpec_1 (t):
7240 'ValueSetOptionalitySpec ::= OPTIONAL'
7241 pass
7243 def p_ValueSetOptionalitySpec_2 (t):
7244 'ValueSetOptionalitySpec ::= DEFAULT ValueSet'
7245 pass
7247 # 9.11
7248 def p_ObjectFieldSpec (t):
7249 '''ObjectFieldSpec : lcasefieldreference DefinedObjectClass
7250 | lcasefieldreference DefinedObjectClass ObjectOptionalitySpec '''
7251 t[0] = ObjectFieldSpec(cls=t[2])
7252 t[0].SetName(t[1])
7253 global obj_class
7254 obj_class = None
7256 def p_ObjectOptionalitySpec_1 (t):
7257 'ObjectOptionalitySpec ::= OPTIONAL'
7258 pass
7260 def p_ObjectOptionalitySpec_2 (t):
7261 'ObjectOptionalitySpec ::= DEFAULT Object'
7262 pass
7264 # 9.12
7265 def p_ObjectSetFieldSpec (t):
7266 '''ObjectSetFieldSpec : ucasefieldreference DefinedObjectClass
7267 | ucasefieldreference DefinedObjectClass ObjectSetOptionalitySpec '''
7268 t[0] = ObjectSetFieldSpec(cls=t[2])
7269 t[0].SetName(t[1])
7271 def p_ObjectSetOptionalitySpec_1 (t):
7272 'ObjectSetOptionalitySpec ::= OPTIONAL'
7273 pass
7275 def p_ObjectSetOptionalitySpec_2 (t):
7276 'ObjectSetOptionalitySpec ::= DEFAULT ObjectSet'
7277 pass
7279 # 9.13
7280 def p_PrimitiveFieldName (t):
7281 '''PrimitiveFieldName : ucasefieldreference
7282 | lcasefieldreference '''
7283 t[0] = t[1]
7285 # 9.13
7286 def p_FieldName_1 (t):
7287 'FieldName : PrimitiveFieldName'
7288 t[0] = t[1]
7290 def p_FieldName_2 (t):
7291 'FieldName : FieldName DOT PrimitiveFieldName'
7292 t[0] = t[1] + '.' + t[3]
7294 # 11 Information object definition and assignment
7296 # 11.1
7297 def p_ObjectAssignment (t):
7298 'ObjectAssignment : objectreference DefinedObjectClass ASSIGNMENT Object'
7299 t[0] = ObjectAssignment (ident = t[1], cls=t[2].val, val=t[4])
7300 global obj_class
7301 obj_class = None
7303 # 11.3
7304 def p_Object (t):
7305 '''Object : DefinedObject
7306 | ObjectDefn
7307 | ParameterizedObject'''
7308 t[0] = t[1]
7310 # 11.4
7311 def p_ObjectDefn (t):
7312 'ObjectDefn : lbraceobject bodyobject rbraceobject'
7313 t[0] = t[2]
7315 # {...} block of object definition
7316 def p_lbraceobject(t):
7317 'lbraceobject : braceobjectbegin LBRACE'
7318 t[0] = t[1]
7320 def p_braceobjectbegin(t):
7321 'braceobjectbegin : '
7322 global lexer
7323 global obj_class
7324 if set_class_syntax(obj_class):
7325 state = 'INITIAL'
7326 else:
7327 lexer.level = 1
7328 state = 'braceignore'
7329 lexer.push_state(state)
7331 def p_rbraceobject(t):
7332 'rbraceobject : braceobjectend RBRACE'
7333 t[0] = t[2]
7335 def p_braceobjectend(t):
7336 'braceobjectend : '
7337 global lexer
7338 lexer.pop_state()
7339 set_class_syntax(None)
7341 def p_bodyobject_1 (t):
7342 'bodyobject : '
7343 t[0] = { }
7345 def p_bodyobject_2 (t):
7346 'bodyobject : cls_syntax_list'
7347 t[0] = t[1]
7349 def p_cls_syntax_list_1 (t):
7350 'cls_syntax_list : cls_syntax_list cls_syntax'
7351 t[0] = t[1]
7352 t[0].update(t[2])
7354 def p_cls_syntax_list_2 (t):
7355 'cls_syntax_list : cls_syntax'
7356 t[0] = t[1]
7358 # X.681
7359 def p_cls_syntax_1 (t):
7360 'cls_syntax : Type IDENTIFIED BY Value'
7361 t[0] = { get_class_field(' ') : t[1], get_class_field(' '.join((t[2], t[3]))) : t[4] }
7363 def p_cls_syntax_2 (t):
7364 'cls_syntax : HAS PROPERTY Value'
7365 t[0] = { get_class_field(' '.join(t[1:-1])) : t[-1:][0] }
7367 # X.880
7368 def p_cls_syntax_3 (t):
7369 '''cls_syntax : ERRORS ObjectSet
7370 | LINKED ObjectSet
7371 | RETURN RESULT BooleanValue
7372 | SYNCHRONOUS BooleanValue
7373 | INVOKE PRIORITY Value
7374 | RESULT_PRIORITY Value
7375 | PRIORITY Value
7376 | ALWAYS RESPONDS BooleanValue
7377 | IDEMPOTENT BooleanValue '''
7378 t[0] = { get_class_field(' '.join(t[1:-1])) : t[-1:][0] }
7380 def p_cls_syntax_4 (t):
7381 '''cls_syntax : ARGUMENT Type
7382 | RESULT Type
7383 | PARAMETER Type '''
7384 t[0] = { get_class_field(t[1]) : t[2] }
7386 def p_cls_syntax_5 (t):
7387 'cls_syntax : CODE Value'
7388 fld = get_class_field(t[1])
7389 t[0] = { fld : t[2] }
7390 if isinstance(t[2], ChoiceValue):
7391 fldt = fld + '.' + t[2].choice
7392 t[0][fldt] = t[2]
7394 def p_cls_syntax_6 (t):
7395 '''cls_syntax : ARGUMENT Type OPTIONAL BooleanValue
7396 | RESULT Type OPTIONAL BooleanValue
7397 | PARAMETER Type OPTIONAL BooleanValue '''
7398 t[0] = { get_class_field(t[1]) : t[2], get_class_field(' '.join((t[1], t[3]))) : t[4] }
7400 # 12 Information object set definition and assignment
7402 # 12.1
7403 def p_ObjectSetAssignment (t):
7404 'ObjectSetAssignment : UCASE_IDENT CLASS_IDENT ASSIGNMENT ObjectSet'
7405 t[0] = Node('ObjectSetAssignment', name=t[1], cls=t[2], val=t[4])
7407 # 12.3
7408 def p_ObjectSet (t):
7409 'ObjectSet : lbraceignore rbraceignore'
7410 t[0] = None
7412 # 14 Notation for the object class field type ---------------------------------
7414 # 14.1
7415 def p_ObjectClassFieldType (t):
7416 'ObjectClassFieldType : DefinedObjectClass DOT FieldName'
7417 t[0] = get_type_from_class(t[1], t[3])
7419 # 14.6
7420 def p_ObjectClassFieldValue (t):
7421 '''ObjectClassFieldValue : OpenTypeFieldVal'''
7422 t[0] = t[1]
7424 def p_OpenTypeFieldVal (t):
7425 '''OpenTypeFieldVal : Type COLON Value
7426 | NullType COLON NullValue'''
7427 t[0] = t[3]
7430 # 15 Information from objects -------------------------------------------------
7432 # 15.1
7434 def p_ValueFromObject (t):
7435 'ValueFromObject : LCASE_IDENT DOT FieldName'
7436 t[0] = t[1] + '.' + t[3]
7439 # Annex C - The instance-of type ----------------------------------------------
7441 # C.2
7442 def p_InstanceOfType (t):
7443 'InstanceOfType : INSTANCE OF DefinedObjectClass'
7444 t[0] = InstanceOfType()
7447 # --- tables ---
7449 useful_object_class_types = {
7450 # Annex A
7451 'TYPE-IDENTIFIER.&id' : lambda : ObjectIdentifierType(),
7452 'TYPE-IDENTIFIER.&Type' : lambda : OpenType(),
7453 # Annex B
7454 'ABSTRACT-SYNTAX.&id' : lambda : ObjectIdentifierType(),
7455 'ABSTRACT-SYNTAX.&Type' : lambda : OpenType(),
7456 'ABSTRACT-SYNTAX.&property' : lambda : BitStringType(),
7459 object_class_types = { }
7461 object_class_typerefs = { }
7463 object_class_classrefs = { }
7465 # dummy types
7466 class _VariableTypeValueFieldSpec (AnyType):
7467 pass
7469 class _FixedTypeValueSetFieldSpec (AnyType):
7470 pass
7472 class_types_creator = {
7473 'BooleanType' : lambda : BooleanType(),
7474 'IntegerType' : lambda : IntegerType(),
7475 'ObjectIdentifierType' : lambda : ObjectIdentifierType(),
7476 'OpenType' : lambda : OpenType(),
7477 # dummy types
7478 '_VariableTypeValueFieldSpec' : lambda : _VariableTypeValueFieldSpec(),
7479 '_FixedTypeValueSetFieldSpec' : lambda : _FixedTypeValueSetFieldSpec(),
7482 class_names = { }
7484 x681_syntaxes = {
7485 'TYPE-IDENTIFIER' : {
7486 ' ' : '&Type',
7487 'IDENTIFIED' : 'IDENTIFIED',
7488 #'BY' : 'BY',
7489 'IDENTIFIED BY' : '&id',
7491 'ABSTRACT-SYNTAX' : {
7492 ' ' : '&Type',
7493 'IDENTIFIED' : 'IDENTIFIED',
7494 #'BY' : 'BY',
7495 'IDENTIFIED BY' : '&id',
7496 'HAS' : 'HAS',
7497 'PROPERTY' : 'PROPERTY',
7498 'HAS PROPERTY' : '&property',
7502 class_syntaxes_enabled = {
7503 'TYPE-IDENTIFIER' : True,
7504 'ABSTRACT-SYNTAX' : True,
7507 class_syntaxes = {
7508 'TYPE-IDENTIFIER' : x681_syntaxes['TYPE-IDENTIFIER'],
7509 'ABSTRACT-SYNTAX' : x681_syntaxes['ABSTRACT-SYNTAX'],
7512 class_current_syntax = None
7514 def get_syntax_tokens(syntaxes):
7515 tokens = { }
7516 for s in (syntaxes):
7517 for k in (list(syntaxes[s].keys())):
7518 if k.find(' ') < 0:
7519 tokens[k] = k
7520 tokens[k] = tokens[k].replace('-', '_')
7521 return list(tokens.values())
7523 tokens = tokens + get_syntax_tokens(x681_syntaxes)
7525 def set_class_syntax(syntax):
7526 global class_syntaxes_enabled
7527 global class_current_syntax
7528 #print "set_class_syntax", syntax, class_current_syntax
7529 if class_syntaxes_enabled.get(syntax, False):
7530 class_current_syntax = syntax
7531 return True
7532 else:
7533 class_current_syntax = None
7534 return False
7536 def is_class_syntax(name):
7537 global class_syntaxes
7538 global class_current_syntax
7539 #print "is_class_syntax", name, class_current_syntax
7540 if not class_current_syntax:
7541 return False
7542 return name in class_syntaxes[class_current_syntax]
7544 def get_class_field(name):
7545 if not class_current_syntax:
7546 return None
7547 return class_syntaxes[class_current_syntax][name]
7549 def is_class_ident(name):
7550 return name in class_names
7552 def add_class_ident(name):
7553 #print "add_class_ident", name
7554 class_names[name] = name
7556 def get_type_from_class(cls, fld):
7557 flds = fld.split('.')
7558 if (isinstance(cls, Class_Ref)):
7559 key = cls.val + '.' + flds[0]
7560 else:
7561 key = cls + '.' + flds[0]
7563 if key in object_class_classrefs:
7564 return get_type_from_class(object_class_classrefs[key], '.'.join(flds[1:]))
7566 if key in object_class_typerefs:
7567 return Type_Ref(val=object_class_typerefs[key])
7569 creator = lambda : AnyType()
7570 creator = useful_object_class_types.get(key, creator)
7571 creator = object_class_types.get(key, creator)
7572 return creator()
7574 def set_type_to_class(cls, fld, pars):
7575 #print "set_type_to_class", cls, fld, pars
7576 key = cls + '.' + fld
7577 typename = 'OpenType'
7578 if (len(pars) > 0):
7579 typename = pars[0]
7580 else:
7581 pars.append(typename)
7582 typeref = None
7583 if (len(pars) > 1):
7584 if (isinstance(pars[1], Class_Ref)):
7585 pars[1] = pars[1].val
7586 typeref = pars[1]
7588 msg = None
7589 if key in object_class_types:
7590 msg = object_class_types[key]().type
7591 if key in object_class_typerefs:
7592 msg = "TypeReference " + object_class_typerefs[key]
7593 if key in object_class_classrefs:
7594 msg = "ClassReference " + object_class_classrefs[key]
7596 if msg == ' '.join(pars):
7597 msg = None
7599 if msg:
7600 msg0 = "Can not define CLASS field %s as '%s'\n" % (key, ' '.join(pars))
7601 msg1 = "Already defined as '%s'" % (msg)
7602 raise CompError(msg0 + msg1)
7604 if (typename == 'ClassReference'):
7605 if not typeref: return False
7606 object_class_classrefs[key] = typeref
7607 return True
7609 if (typename == 'TypeReference'):
7610 if not typeref: return False
7611 object_class_typerefs[key] = typeref
7612 return True
7614 creator = class_types_creator.get(typename)
7615 if creator:
7616 object_class_types[key] = creator
7617 return True
7618 else:
7619 return False
7621 def import_class_from_module(mod, cls):
7622 add_class_ident(cls)
7623 mcls = "$%s$%s" % (mod, cls)
7624 for k in list(object_class_classrefs.keys()):
7625 kk = k.split('.', 1)
7626 if kk[0] == mcls:
7627 object_class_classrefs[cls + '.' + kk[0]] = object_class_classrefs[k]
7628 for k in list(object_class_typerefs.keys()):
7629 kk = k.split('.', 1)
7630 if kk[0] == mcls:
7631 object_class_typerefs[cls + '.' + kk[0]] = object_class_typerefs[k]
7632 for k in list(object_class_types.keys()):
7633 kk = k.split('.', 1)
7634 if kk[0] == mcls:
7635 object_class_types[cls + '.' + kk[0]] = object_class_types[k]
7637 #--- ITU-T Recommendation X.682 -----------------------------------------------
7639 # 8 General constraint specification ------------------------------------------
7641 # 8.1
7642 def p_GeneralConstraint (t):
7643 '''GeneralConstraint : UserDefinedConstraint
7644 | TableConstraint
7645 | ContentsConstraint'''
7646 t[0] = t[1]
7648 # 9 User-defined constraints --------------------------------------------------
7650 # 9.1
7651 def p_UserDefinedConstraint (t):
7652 'UserDefinedConstraint : CONSTRAINED BY LBRACE UserDefinedConstraintParameterList RBRACE'
7653 t[0] = Constraint(type = 'UserDefined', subtype = t[4])
7655 def p_UserDefinedConstraintParameterList_1 (t):
7656 'UserDefinedConstraintParameterList : '
7657 t[0] = []
7659 def p_UserDefinedConstraintParameterList_2 (t):
7660 'UserDefinedConstraintParameterList : UserDefinedConstraintParameter'
7661 t[0] = [t[1]]
7663 def p_UserDefinedConstraintParameterList_3 (t):
7664 'UserDefinedConstraintParameterList : UserDefinedConstraintParameterList COMMA UserDefinedConstraintParameter'
7665 t[0] = t[1] + [t[3]]
7667 # 9.3
7668 def p_UserDefinedConstraintParameter (t):
7669 'UserDefinedConstraintParameter : Type'
7670 t[0] = t[1]
7672 # 10 Table constraints, including component relation constraints --------------
7674 # 10.3
7675 def p_TableConstraint (t):
7676 '''TableConstraint : SimpleTableConstraint
7677 | ComponentRelationConstraint'''
7678 t[0] = Constraint(type = 'Table', subtype = t[1])
7680 def p_SimpleTableConstraint (t):
7681 'SimpleTableConstraint : LBRACE UCASE_IDENT RBRACE'
7682 t[0] = t[2]
7684 # 10.7
7685 def p_ComponentRelationConstraint (t):
7686 'ComponentRelationConstraint : LBRACE UCASE_IDENT RBRACE LBRACE AtNotations RBRACE'
7687 t[0] = t[2] + str(t[5])
7689 def p_AtNotations_1 (t):
7690 'AtNotations : AtNotation'
7691 t[0] = [t[1]]
7693 def p_AtNotations_2 (t):
7694 'AtNotations : AtNotations COMMA AtNotation'
7695 t[0] = t[1] + [t[3]]
7697 def p_AtNotation_1 (t):
7698 'AtNotation : AT ComponentIdList'
7699 t[0] = '@' + t[2]
7701 def p_AtNotation_2 (t):
7702 'AtNotation : AT DOT Level ComponentIdList'
7703 t[0] = '@.' + t[3] + t[4]
7705 def p_Level_1 (t):
7706 'Level : DOT Level'
7707 t[0] = '.' + t[2]
7709 def p_Level_2 (t):
7710 'Level : '
7711 t[0] = ''
7713 def p_ComponentIdList_1 (t):
7714 'ComponentIdList : LCASE_IDENT'
7715 t[0] = t[1]
7717 def p_ComponentIdList_2 (t):
7718 'ComponentIdList : ComponentIdList DOT LCASE_IDENT'
7719 t[0] = t[1] + '.' + t[3]
7721 # 11 Contents constraints -----------------------------------------------------
7723 # 11.1
7724 def p_ContentsConstraint (t):
7725 'ContentsConstraint : CONTAINING type_ref'
7726 t[0] = Constraint(type = 'Contents', subtype = t[2])
7729 #--- ITU-T Recommendation X.683 -----------------------------------------------
7731 # 8 Parameterized assignments -------------------------------------------------
7733 # 8.1
7734 def p_ParameterizedAssignment (t):
7735 '''ParameterizedAssignment : ParameterizedTypeAssignment
7736 | ParameterizedObjectClassAssignment
7737 | ParameterizedObjectAssignment
7738 | ParameterizedObjectSetAssignment'''
7739 t[0] = t[1]
7741 # 8.2
7742 def p_ParameterizedTypeAssignment (t):
7743 'ParameterizedTypeAssignment : UCASE_IDENT ParameterList ASSIGNMENT Type'
7744 t[0] = t[4]
7745 t[0].SetName(t[1]) # t[0].SetName(t[1] + 'xxx')
7747 def p_ParameterizedObjectClassAssignment (t):
7748 '''ParameterizedObjectClassAssignment : CLASS_IDENT ParameterList ASSIGNMENT ObjectClass
7749 | UCASE_IDENT ParameterList ASSIGNMENT ObjectClass'''
7750 t[0] = t[4]
7751 t[0].SetName(t[1])
7752 if isinstance(t[0], ObjectClassDefn):
7753 t[0].reg_types()
7755 def p_ParameterizedObjectAssignment (t):
7756 'ParameterizedObjectAssignment : objectreference ParameterList DefinedObjectClass ASSIGNMENT Object'
7757 t[0] = ObjectAssignment (ident = t[1], cls=t[3].val, val=t[5])
7758 global obj_class
7759 obj_class = None
7761 def p_ParameterizedObjectSetAssignment (t):
7762 'ParameterizedObjectSetAssignment : UCASE_IDENT ParameterList DefinedObjectClass ASSIGNMENT ObjectSet'
7763 t[0] = Node('ObjectSetAssignment', name=t[1], cls=t[3].val, val=t[5])
7765 # 8.3
7766 def p_ParameterList (t):
7767 'ParameterList : lbraceignore rbraceignore'
7769 #def p_ParameterList (t):
7770 # 'ParameterList : LBRACE Parameters RBRACE'
7771 # t[0] = t[2]
7773 #def p_Parameters_1 (t):
7774 # 'Parameters : Parameter'
7775 # t[0] = [t[1]]
7777 #def p_Parameters_2 (t):
7778 # 'Parameters : Parameters COMMA Parameter'
7779 # t[0] = t[1] + [t[3]]
7781 #def p_Parameter_1 (t):
7782 # 'Parameter : Type COLON Reference'
7783 # t[0] = [t[1], t[3]]
7785 #def p_Parameter_2 (t):
7786 # 'Parameter : Reference'
7787 # t[0] = t[1]
7790 # 9 Referencing parameterized definitions -------------------------------------
7792 # 9.1
7793 def p_ParameterizedReference (t):
7794 'ParameterizedReference : Reference LBRACE RBRACE'
7795 t[0] = t[1]
7796 #t[0].val += 'xxx'
7798 # 9.2
7799 def p_ParameterizedType (t):
7800 'ParameterizedType : type_ref ActualParameterList'
7801 t[0] = t[1]
7802 #t[0].val += 'xxx'
7805 def p_ParameterizedObjectClass (t):
7806 'ParameterizedObjectClass : DefinedObjectClass ActualParameterList'
7807 t[0] = t[1]
7808 #t[0].val += 'xxx'
7810 def p_ParameterizedObject (t):
7811 'ParameterizedObject : DefinedObject ActualParameterList'
7812 t[0] = t[1]
7813 #t[0].val += 'xxx'
7815 # 9.5
7816 def p_ActualParameterList (t):
7817 'ActualParameterList : lbraceignore rbraceignore'
7819 #def p_ActualParameterList (t):
7820 # 'ActualParameterList : LBRACE ActualParameters RBRACE'
7821 # t[0] = t[2]
7823 #def p_ActualParameters_1 (t):
7824 # 'ActualParameters : ActualParameter'
7825 # t[0] = [t[1]]
7827 #def p_ActualParameters_2 (t):
7828 # 'ActualParameters : ActualParameters COMMA ActualParameter'
7829 # t[0] = t[1] + [t[3]]
7831 #def p_ActualParameter (t):
7832 # '''ActualParameter : Type
7833 # | Value'''
7834 # t[0] = t[1]
7837 #--- ITU-T Recommendation X.880 -----------------------------------------------
7839 x880_classes = {
7840 'OPERATION' : {
7841 '&ArgumentType' : [],
7842 '&argumentTypeOptional' : [ 'BooleanType' ],
7843 '&returnResult' : [ 'BooleanType' ],
7844 '&ResultType' : [],
7845 '&resultTypeOptional' : [ 'BooleanType' ],
7846 '&Errors' : [ 'ClassReference', 'ERROR' ],
7847 '&Linked' : [ 'ClassReference', 'OPERATION' ],
7848 '&synchronous' : [ 'BooleanType' ],
7849 '&idempotent' : [ 'BooleanType' ],
7850 '&alwaysReturns' : [ 'BooleanType' ],
7851 '&InvokePriority' : [ '_FixedTypeValueSetFieldSpec' ],
7852 '&ResultPriority' : [ '_FixedTypeValueSetFieldSpec' ],
7853 '&operationCode' : [ 'TypeReference', 'Code' ],
7855 'ERROR' : {
7856 '&ParameterType' : [],
7857 '&parameterTypeOptional' : [ 'BooleanType' ],
7858 '&ErrorPriority' : [ '_FixedTypeValueSetFieldSpec' ],
7859 '&errorCode' : [ 'TypeReference', 'Code' ],
7861 'OPERATION-PACKAGE' : {
7862 '&Both' : [ 'ClassReference', 'OPERATION' ],
7863 '&Consumer' : [ 'ClassReference', 'OPERATION' ],
7864 '&Supplier' : [ 'ClassReference', 'OPERATION' ],
7865 '&id' : [ 'ObjectIdentifierType' ],
7867 'CONNECTION-PACKAGE' : {
7868 '&bind' : [ 'ClassReference', 'OPERATION' ],
7869 '&unbind' : [ 'ClassReference', 'OPERATION' ],
7870 '&responderCanUnbind' : [ 'BooleanType' ],
7871 '&unbindCanFail' : [ 'BooleanType' ],
7872 '&id' : [ 'ObjectIdentifierType' ],
7874 'CONTRACT' : {
7875 '&connection' : [ 'ClassReference', 'CONNECTION-PACKAGE' ],
7876 '&OperationsOf' : [ 'ClassReference', 'OPERATION-PACKAGE' ],
7877 '&InitiatorConsumerOf' : [ 'ClassReference', 'OPERATION-PACKAGE' ],
7878 '&InitiatorSupplierOf' : [ 'ClassReference', 'OPERATION-PACKAGE' ],
7879 '&id' : [ 'ObjectIdentifierType' ],
7881 'ROS-OBJECT-CLASS' : {
7882 '&Is' : [ 'ClassReference', 'ROS-OBJECT-CLASS' ],
7883 '&Initiates' : [ 'ClassReference', 'CONTRACT' ],
7884 '&Responds' : [ 'ClassReference', 'CONTRACT' ],
7885 '&InitiatesAndResponds' : [ 'ClassReference', 'CONTRACT' ],
7886 '&id' : [ 'ObjectIdentifierType' ],
7890 x880_syntaxes = {
7891 'OPERATION' : {
7892 'ARGUMENT' : '&ArgumentType',
7893 'ARGUMENT OPTIONAL' : '&argumentTypeOptional',
7894 'RESULT' : '&ResultType',
7895 'RESULT OPTIONAL' : '&resultTypeOptional',
7896 'RETURN' : 'RETURN',
7897 'RETURN RESULT' : '&returnResult',
7898 'ERRORS' : '&Errors',
7899 'LINKED' : '&Linked',
7900 'SYNCHRONOUS' : '&synchronous',
7901 'IDEMPOTENT' : '&idempotent',
7902 'ALWAYS' : 'ALWAYS',
7903 'RESPONDS' : 'RESPONDS',
7904 'ALWAYS RESPONDS' : '&alwaysReturns',
7905 'INVOKE' : 'INVOKE',
7906 'PRIORITY' : 'PRIORITY',
7907 'INVOKE PRIORITY' : '&InvokePriority',
7908 'RESULT-PRIORITY': '&ResultPriority',
7909 'CODE' : '&operationCode',
7911 'ERROR' : {
7912 'PARAMETER' : '&ParameterType',
7913 'PARAMETER OPTIONAL' : '&parameterTypeOptional',
7914 'PRIORITY' : '&ErrorPriority',
7915 'CODE' : '&errorCode',
7917 # 'OPERATION-PACKAGE' : {
7918 # },
7919 # 'CONNECTION-PACKAGE' : {
7920 # },
7921 # 'CONTRACT' : {
7922 # },
7923 # 'ROS-OBJECT-CLASS' : {
7924 # },
7927 def x880_module_begin():
7928 #print "x880_module_begin()"
7929 for name in list(x880_classes.keys()):
7930 add_class_ident(name)
7932 def x880_import(name):
7933 if name in x880_syntaxes:
7934 class_syntaxes_enabled[name] = True
7935 class_syntaxes[name] = x880_syntaxes[name]
7936 if name in x880_classes:
7937 add_class_ident(name)
7938 for f in (list(x880_classes[name].keys())):
7939 set_type_to_class(name, f, x880_classes[name][f])
7941 tokens = tokens + get_syntax_tokens(x880_syntaxes)
7943 # {...} OID value
7944 #def p_lbrace_oid(t):
7945 # 'lbrace_oid : brace_oid_begin LBRACE'
7946 # t[0] = t[1]
7948 #def p_brace_oid_begin(t):
7949 # 'brace_oid_begin : '
7950 # global in_oid
7951 # in_oid = True
7953 #def p_rbrace_oid(t):
7954 # 'rbrace_oid : brace_oid_end RBRACE'
7955 # t[0] = t[2]
7957 #def p_brace_oid_end(t):
7958 # 'brace_oid_end : '
7959 # global in_oid
7960 # in_oid = False
7962 # {...} block to be ignored
7963 def p_lbraceignore(t):
7964 'lbraceignore : braceignorebegin LBRACE'
7965 t[0] = t[1]
7967 def p_braceignorebegin(t):
7968 'braceignorebegin : '
7969 global lexer
7970 lexer.level = 1
7971 lexer.push_state('braceignore')
7973 def p_rbraceignore(t):
7974 'rbraceignore : braceignoreend RBRACE'
7975 t[0] = t[2]
7977 def p_braceignoreend(t):
7978 'braceignoreend : '
7979 global lexer
7980 lexer.pop_state()
7982 def p_error(t):
7983 global input_file
7984 raise ParseError(t, input_file)
7986 def p_pyquote (t):
7987 '''pyquote : PYQUOTE'''
7988 t[0] = PyQuote (val = t[1])
7991 def testlex (s):
7992 lexer.input (s)
7993 while True:
7994 token = lexer.token ()
7995 if not token:
7996 break
7997 print(token)
8000 def do_module (ast, defined_dict):
8001 assert (ast.type == 'Module')
8002 ctx = Ctx (defined_dict)
8003 print(ast.to_python (ctx))
8004 print(ctx.output_assignments ())
8005 print(ctx.output_pyquotes ())
8007 def eth_do_module (ast, ectx):
8008 assert (ast.type == 'Module')
8009 if ectx.dbg('s'): print(ast.str_depth(0))
8010 ast.to_eth(ectx)
8012 def testyacc(s, fn, defined_dict):
8013 ast = yacc.parse(s, debug=0)
8014 time_str = time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime())
8015 print("""#!/usr/bin/env python
8016 # Auto-generated from %s at %s
8017 from PyZ3950 import asn1""" % (fn, time_str))
8018 for module in ast:
8019 eth_do_module (module, defined_dict)
8022 # Wireshark compiler
8023 def eth_usage():
8024 print("""
8025 asn2wrs [-h|?] [-d dbg] [-b] [-p proto] [-c cnf_file] [-e] input_file(s) ...
8026 -h|? : Usage
8027 -b : BER (default is PER)
8028 -u : Unaligned (default is aligned)
8029 -p proto : Protocol name (implies -S). Default is module-name
8030 from input_file (renamed by #.MODULE if present)
8031 -o name : Output files name core (default is <proto>)
8032 -O dir : Output directory for dissector
8033 -c cnf_file : Conformance file
8034 -I path : Path for conformance file includes
8035 -e : Create conformance file for exported types
8036 -E : Just create conformance file for exported types
8037 -S : Single output for multiple modules
8038 -s template : Single file output (template is input file
8039 without .c/.h extension)
8040 -k : Keep intermediate files though single file output is used
8041 -L : Suppress #line directive from .cnf file
8042 -D dir : Directory for input_file(s) (default: '.')
8043 -C : Add check for SIZE constraints
8044 -r prefix : Remove the prefix from type names
8046 input_file(s) : Input ASN.1 file(s)
8048 -d dbg : Debug output, dbg = [l][y][p][s][a][t][c][m][o]
8049 l - lex
8050 y - yacc
8051 p - parsing
8052 s - internal ASN.1 structure
8053 a - list of assignments
8054 t - tables
8055 c - conformance values
8056 m - list of compiled modules with dependency
8057 o - list of output files
8058 """)
8061 ## Used to preparse C style comments
8062 ## https://github.com/eerimoq/asn1tools/blob/master/asn1tools/parser.py#L231
8064 def ignore_comments(string):
8065 """Ignore comments in given string by replacing them with spaces. This
8066 reduces the parsing time by roughly a factor of two.
8070 comments = [
8071 (mo.start(), mo.group(0))
8072 for mo in re.finditer(r'(/\*|\*/|\n)', string)
8075 comments.sort()
8077 multi_line_comment_depth = 0
8078 start_offset = 0
8079 non_comment_offset = 0
8080 chunks = []
8082 for offset, kind in comments:
8083 if multi_line_comment_depth > 0:
8084 if kind == '/*':
8085 multi_line_comment_depth += 1
8086 elif kind == '*/':
8087 multi_line_comment_depth -= 1
8089 if multi_line_comment_depth == 0:
8090 offset += 2
8091 chunks.append(' ' * (offset - start_offset))
8092 non_comment_offset = offset
8093 elif kind == '\n':
8094 chunks.append('\n')
8095 non_comment_offset = offset
8096 elif kind == '/*':
8097 multi_line_comment_depth = 1
8098 start_offset = offset
8099 chunks.append(string[non_comment_offset:start_offset])
8101 chunks.append(string[non_comment_offset:])
8103 return ''.join(chunks)
8105 def asn2wrs_main():
8106 global input_file
8107 global g_conform
8108 global lexer
8109 global quiet
8111 try:
8112 opts, args = getopt.getopt(sys.argv[1:], "h?d:D:buXp:qFTo:O:c:I:eESs:kLCr:")
8113 except getopt.GetoptError:
8114 eth_usage(); sys.exit(2)
8115 if len(args) < 1:
8116 eth_usage(); sys.exit(2)
8118 conform = EthCnf()
8119 conf_to_read = None
8120 output = EthOut()
8121 ectx = EthCtx(conform, output)
8122 ectx.encoding = 'per'
8123 ectx.proto_opt = None
8124 ectx.fld_opt = {}
8125 ectx.tag_opt = False
8126 ectx.outnm_opt = None
8127 ectx.aligned = True
8128 ectx.dbgopt = ''
8129 ectx.new = True
8130 ectx.expcnf = False
8131 ectx.justexpcnf = False
8132 ectx.merge_modules = False
8133 ectx.group_by_prot = False
8134 ectx.conform.last_group = 0
8135 ectx.conform.suppress_line = False
8136 ectx.output.outnm = None
8137 ectx.output.single_file = None
8138 ectx.constraints_check = False
8139 for o, a in opts:
8140 if o in ("-h", "-?"):
8141 eth_usage(); sys.exit(2)
8142 if o in ("-c",):
8143 conf_to_read = relpath(a)
8144 if o in ("-I",):
8145 ectx.conform.include_path.append(relpath(a))
8146 if o in ("-E",):
8147 ectx.expcnf = True
8148 ectx.justexpcnf = True
8149 if o in ("-D",):
8150 ectx.srcdir = relpath(a)
8151 if o in ("-C",):
8152 ectx.constraints_check = True
8153 if o in ("-L",):
8154 ectx.conform.suppress_line = True
8155 if o in ("-q",):
8156 quiet = True
8157 if o in ("-X",):
8158 warnings.warn("Command line option -X is obsolete and can be removed")
8159 if o in ("-T",):
8160 warnings.warn("Command line option -T is obsolete and can be removed")
8162 if not quiet:
8163 print("ASN.1 to Wireshark dissector compiler")
8165 if conf_to_read:
8166 ectx.conform.read(conf_to_read)
8168 for o, a in opts:
8169 if o in ("-h", "-?", "-c", "-I", "-E", "-D", "-C", "-q", "-X", "-T"):
8170 pass # already processed
8171 else:
8172 par = []
8173 if a: par.append(a)
8174 ectx.conform.set_opt(o, par, "commandline", 0)
8176 (ld, yd, pd) = (0, 0, 0)
8177 if ectx.dbg('l'): ld = 1
8178 if ectx.dbg('y'): yd = 1
8179 if ectx.dbg('p'): pd = 2
8180 lexer = lex.lex(debug=ld)
8181 parser = yacc.yacc(method='LALR', debug=yd, outputdir='.')
8182 parser.defaulted_states = {}
8183 g_conform = ectx.conform
8184 ast = []
8185 for fn in args:
8186 input_file = fn
8187 lexer.lineno = 1
8188 if (ectx.srcdir): fn = ectx.srcdir + '/' + fn
8189 # Read ASN.1 definition, trying one of the common encodings.
8190 data = open(fn, "rb").read()
8191 try:
8192 data = data.decode('utf-8')
8193 except UnicodeDecodeError:
8194 warnings.warn_explicit(f"Decoding {fn} as UTF-8 failed.", UnicodeWarning, '', 0)
8195 sys.exit(3)
8196 # Py2 compat, name.translate in eth_output_hf_arr fails with unicode
8197 if not isinstance(data, str):
8198 data = data.encode('utf-8')
8199 data = ignore_comments(data)
8200 ast.extend(yacc.parse(data, lexer=lexer, debug=pd))
8201 ectx.eth_clean()
8202 if (ectx.merge_modules): # common output for all module
8203 ectx.eth_clean()
8204 for module in ast:
8205 eth_do_module(module, ectx)
8206 ectx.eth_prepare()
8207 ectx.eth_do_output()
8208 elif (ectx.groups()): # group by protocols/group
8209 groups = []
8210 pr2gr = {}
8211 if (ectx.group_by_prot): # group by protocols
8212 for module in ast:
8213 prot = module.get_proto(ectx)
8214 if prot not in pr2gr:
8215 pr2gr[prot] = len(groups)
8216 groups.append([])
8217 groups[pr2gr[prot]].append(module)
8218 else: # group by groups
8219 pass
8220 for gm in (groups):
8221 ectx.eth_clean()
8222 for module in gm:
8223 eth_do_module(module, ectx)
8224 ectx.eth_prepare()
8225 ectx.eth_do_output()
8226 else: # output for each module
8227 for module in ast:
8228 ectx.eth_clean()
8229 eth_do_module(module, ectx)
8230 ectx.eth_prepare()
8231 ectx.eth_do_output()
8233 if ectx.dbg('m'):
8234 ectx.dbg_modules()
8236 if ectx.dbg('c'):
8237 ectx.conform.dbg_print()
8238 if not ectx.justexpcnf:
8239 ectx.conform.unused_report()
8241 if ectx.dbg('o'):
8242 ectx.output.dbg_print()
8243 ectx.output.make_single_file(ectx.conform.suppress_line)
8246 # Python compiler
8247 def main():
8248 if sys.version_info[0] < 3:
8249 print("This requires Python 3")
8250 sys.exit(2)
8252 testfn = testyacc
8253 if len (sys.argv) == 1:
8254 while True:
8255 s = eval(input ('Query: '))
8256 if len (s) == 0:
8257 break
8258 testfn (s, 'console', {})
8259 else:
8260 defined_dict = {}
8261 for fn in sys.argv [1:]:
8262 f = open (fn, "r")
8263 testfn (f.read (), fn, defined_dict)
8264 f.close ()
8265 lexer.lineno = 1
8268 #--- BODY ---------------------------------------------------------------------
8270 if __name__ == '__main__':
8271 if (os.path.splitext(os.path.basename(sys.argv[0]))[0].lower() in ('asn2wrs', 'asn2eth')):
8272 asn2wrs_main()
8273 else:
8274 main()
8276 #------------------------------------------------------------------------------
8278 # Editor modelines - https://www.wireshark.org/tools/modelines.html
8280 # c-basic-offset: 4; tab-width: 8; indent-tabs-mode: nil
8281 # vi: set shiftwidth=4 tabstop=8 expandtab:
8282 # :indentSize=4:tabSize=8:noTabs=true: