summaryrefslogtreecommitdiffstats
path: root/tools/asterix/update-specs.py
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-09-19 04:14:26 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-09-19 04:14:26 +0000
commitc4e8a3222648fcf22ca207f1815ebbf7cd144eeb (patch)
tree93d5c6aa93d9987680dd1adad5685e2ad698f223 /tools/asterix/update-specs.py
parentAdding upstream version 4.2.6. (diff)
downloadwireshark-upstream.tar.xz
wireshark-upstream.zip
Adding upstream version 4.4.0.upstream/4.4.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rwxr-xr-xtools/asterix/update-specs.py189
1 files changed, 82 insertions, 107 deletions
diff --git a/tools/asterix/update-specs.py b/tools/asterix/update-specs.py
index 7af735dc..03850c50 100755
--- a/tools/asterix/update-specs.py
+++ b/tools/asterix/update-specs.py
@@ -20,6 +20,8 @@ import os
import sys
import re
+import convertspec as convert
+
# Path to default upstream repository
upstream_repo = 'https://zoranbosnjak.github.io/asterix-specs'
dissector_file = 'epan/dissectors/packet-asterix.c'
@@ -68,42 +70,15 @@ class Context(object):
self.offset = Offset()
def get_number(value):
- """Get Natural/Real/Rational number as an object."""
- class Integer(object):
- def __init__(self, val):
- self.val = val
- def __str__(self):
- return '{}'.format(self.val)
- def __float__(self):
- return float(self.val)
-
- class Ratio(object):
- def __init__(self, a, b):
- self.a = a
- self.b = b
- def __str__(self):
- return '{}/{}'.format(self.a, self.b)
- def __float__(self):
- return float(self.a) / float(self.b)
-
- class Real(object):
- def __init__(self, val):
- self.val = val
- def __str__(self):
- return '{0:f}'.format(self.val).rstrip('0')
- def __float__(self):
- return float(self.val)
-
t = value['type']
- val = value['value']
-
if t == 'Integer':
- return Integer(int(val))
- if t == 'Ratio':
- x, y = val['numerator'], val['denominator']
- return Ratio(x, y)
- if t == 'Real':
- return Real(float(val))
+ return float(value['value'])
+ if t == 'Div':
+ a = get_number(value['numerator'])
+ b = get_number(value['denominator'])
+ return a/b
+ if t == 'Pow':
+ return float(pow(value['base'], value['exponent']))
raise Exception('unexpected value type {}'.format(t))
def replace_string(s, mapping):
@@ -132,19 +107,10 @@ def safe_string(s):
def get_scaling(content):
"""Get scaling factor from the content."""
- k = content.get('scaling')
- if k is None:
+ lsb = content.get('lsb')
+ if lsb is None:
return None
- k = get_number(k)
-
- fract = content['fractionalBits']
-
- if fract > 0:
- scale = format(float(k) / (pow(2, fract)), '.29f')
- scale = scale.rstrip('0')
- else:
- scale = format(float(k))
- return scale
+ return '{}'.format(get_number(lsb))
def get_fieldpart(content):
"""Get FIELD_PART* from the content."""
@@ -297,14 +263,12 @@ def reference(cat, edition, path):
return('{:03d}_{}'.format(cat, name))
return('{:03d}_V{}_{}_{}'.format(cat, edition['major'], edition['minor'], name))
-def get_content(rule):
+def get_rule(rule):
t = rule['type']
- # Most cases are 'ContextFree', use as specified.
if t == 'ContextFree':
- return rule['content']
- # Handle 'Dependent' contents as 'Raw'.
+ return rule['value']
elif t == 'Dependent':
- return {'type': "Raw"}
+ return rule['default']
else:
raise Exception('unexpected type: {}'.format(t))
@@ -313,7 +277,7 @@ def get_bit_size(item):
if item['spare']:
return item['length']
else:
- return item['variation']['size']
+ return get_rule(item['rule'])['size']
def get_description(item, content=None):
"""Return item description."""
@@ -336,12 +300,18 @@ def generate_group(item, variation=None):
level2['is_generated'] = True
if variation is None:
level1 = copy(item)
- level1['variation'] = {
- 'type': 'Group',
- 'items': [level2],
+ level1['rule'] = {
+ 'type': 'ContextFree',
+ 'value': {
+ 'type': 'Group',
+ 'items': [level2],
+ },
}
else:
- level2['variation'] = variation['variation']
+ level2['rule'] = {
+ 'type': 'ContextFree',
+ 'value': variation,
+ }
level1 = {
'type': "Group",
'items': [level2],
@@ -353,15 +323,18 @@ def is_generated(item):
def ungroup(item):
"""Convert group of items of known size to element"""
- n = sum([get_bit_size(i) for i in item['variation']['items']])
+ n = sum([get_bit_size(i) for i in get_rule(item['rule'])['items']])
result = copy(item)
- result['variation'] = {
- 'rule': {
- 'content': {'type': 'Raw'},
- 'type': 'ContextFree',
+ result['rule'] = {
+ 'type': 'ContextFree',
+ 'value': {
+ 'type': 'Element',
+ 'size': n,
+ 'rule': {
+ 'type': 'ContextFree',
+ 'value': {'type': 'Raw'},
+ },
},
- 'size': n,
- 'type': 'Element',
}
return result
@@ -397,9 +370,9 @@ def part1(ctx, get_ref, catalogue):
return '&I{}_{}'.format(ref, item['name'])
if t == 'Element':
- tell('static int hf_{} = -1;'.format(ref))
+ tell('static int hf_{};'.format(ref))
n = variation['size']
- content = get_content(variation['rule'])
+ content = get_rule(variation['rule'])
scaling = get_scaling(content)
scaling = scaling if scaling is not None else 1.0
fp = get_fieldpart(content)
@@ -425,12 +398,12 @@ def part1(ctx, get_ref, catalogue):
description = get_description(item)
tell_pr(' {} &hf_{}, {} "{}", "asterix.{}", FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL {} {},'.format('{', ref, '{', description, ref, '}', '}'))
- tell('static int hf_{} = -1;'.format(ref))
+ tell('static int hf_{};'.format(ref))
for i in variation['items']:
handle_item(path, i)
# FieldPart[]
- tell('static const FieldPart *I{}_PARTS[] = {}'.format(ref,'{'))
+ tell('static const FieldPart * const I{}_PARTS[] = {}'.format(ref,'{'))
for i in variation['items']:
tell(' {},'.format(part_of(i)))
tell(' NULL')
@@ -450,15 +423,15 @@ def part1(ctx, get_ref, catalogue):
description = get_description(item)
tell_pr(' {} &hf_{}, {} "{}", "asterix.{}", FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL {} {},'.format('{', ref, '{', description, ref, '}', '}'))
- tell('static int hf_{} = -1;'.format(ref))
+ tell('static int hf_{};'.format(ref))
items = []
for i in variation['items']:
if i is None:
items.append(i)
continue
- if i.get('variation') is not None:
- if i['variation']['type'] == 'Group':
+ if i.get('rule') is not None:
+ if get_rule(i['rule'])['type'] == 'Group':
i = ungroup(i)
items.append(i)
@@ -468,7 +441,7 @@ def part1(ctx, get_ref, catalogue):
else:
handle_item(path, i)
- tell('static const FieldPart *I{}_PARTS[] = {}'.format(ref,'{'))
+ tell('static const FieldPart * const I{}_PARTS[] = {}'.format(ref,'{'))
for i in items:
if i is None:
tell(' &IXXX_FX,')
@@ -479,12 +452,10 @@ def part1(ctx, get_ref, catalogue):
tell('};')
# AsterixField
- first_part = list(takewhile(lambda x: x is not None, items))
- n = (sum([get_bit_size(i) for i in first_part]) + 1) // 8
parts = 'I{}_PARTS'.format(ref)
comp = '{ NULL }'
- tell('static const AsterixField I{} = {} FX, {}, 0, {}, &hf_{}, {}, {} {};'.format
- (ref, '{', n, 0, ref, parts, comp, '}'))
+ tell('static const AsterixField I{} = {} FX, 0, 0, 0, &hf_{}, {}, {} {};'.format
+ (ref, '{', ref, parts, comp, '}'))
elif t == 'Repetitive':
ctx.reset_offset()
@@ -492,7 +463,7 @@ def part1(ctx, get_ref, catalogue):
# Group is required below this item.
if variation['variation']['type'] == 'Element':
- subvar = generate_group(item, variation)
+ subvar = generate_group(item, variation['variation'])
else:
subvar = variation['variation']
handle_variation(path, subvar)
@@ -509,14 +480,14 @@ def part1(ctx, get_ref, catalogue):
elif t == 'Explicit':
ctx.reset_offset()
- tell('static int hf_{} = -1;'.format(ref))
+ tell('static int hf_{};'.format(ref))
description = get_description(item)
tell_pr(' {} &hf_{}, {} "{}", "asterix.{}", FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL {} {},'.format('{', ref, '{', description, ref, '}', '}'))
tell('static const AsterixField I{} = {} EXP, 0, 0, 1, &hf_{}, NULL, {} NULL {} {};'.format(ref, '{', ref, '{', '}', '}'))
elif t == 'Compound':
ctx.reset_offset()
- tell('static int hf_{} = -1;'.format(ref))
+ tell('static int hf_{};'.format(ref))
description = get_description(item)
tell_pr(' {} &hf_{}, {} "{}", "asterix.{}", FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL {} {},'.format('{', ref, '{', description, ref, '}', '}'))
comp = '{'
@@ -525,7 +496,7 @@ def part1(ctx, get_ref, catalogue):
comp += ' &IX_SPARE,'
continue
# Group is required below this item.
- if i['variation']['type'] == 'Element':
+ if get_rule(i['rule'])['type'] == 'Element':
subitem = generate_group(i)
else:
subitem = i
@@ -545,30 +516,36 @@ def part1(ctx, get_ref, catalogue):
return
# Group is required on the first level.
- if path == [] and item['variation']['type'] == 'Element':
- variation = generate_group(item)['variation']
+ if path == [] and get_rule(item['rule'])['type'] == 'Element':
+ variation = get_rule(generate_group(item)['rule'])
else:
- variation = item['variation']
+ variation = get_rule(item['rule'])
handle_variation(path + [item['name']], variation)
for item in catalogue:
# adjust 'repetitive fx' item
- if item['variation']['type'] == 'Repetitive' and item['variation']['rep']['type'] == 'Fx':
- var = item['variation']['variation'].copy()
+ if get_rule(item['rule'])['type'] == 'Repetitive' and get_rule(item['rule'])['rep']['type'] == 'Fx':
+ var = get_rule(item['rule'])['variation'].copy()
if var['type'] != 'Element':
raise Exception("Expecting 'Element'")
item = item.copy()
- item['variation'] = {
- 'type': 'Extended',
- 'items': [{
- 'definition': None,
- 'description': None,
- 'name': 'Subitem',
- 'remark': None,
- 'spare': False,
- 'title': 'Subitem',
- 'variation': var,
+ item['rule'] = {
+ 'type': 'ContextFree',
+ 'value': {
+ 'type': 'Extended',
+ 'items': [{
+ 'definition': None,
+ 'description': None,
+ 'name': 'Subitem',
+ 'remark': None,
+ 'spare': False,
+ 'title': 'Subitem',
+ 'rule': {
+ 'type': 'ContextFree',
+ 'value': var,
+ },
}, None]
+ }
}
handle_item([], item)
tell('')
@@ -577,7 +554,6 @@ def part2(ctx, ref, uap):
"""Generate UAPs"""
tell = lambda s: ctx.tell('insert1', s)
- tell('DIAG_OFF_PEDANTIC')
ut = uap['type']
if ut == 'uap':
@@ -588,7 +564,7 @@ def part2(ctx, ref, uap):
raise Exception('unexpected uap type {}'.format(ut))
for var in variations:
- tell('static const AsterixField *I{}_{}[] = {}'.format(ref, var['name'], '{'))
+ tell('static const AsterixField * const I{}_{}[] = {}'.format(ref, var['name'], '{'))
for i in var['items']:
if i is None:
tell(' &IX_SPARE,')
@@ -597,12 +573,11 @@ def part2(ctx, ref, uap):
tell(' NULL')
tell('};')
- tell('static const AsterixField **I{}[] = {}'.format(ref, '{'))
+ tell('static const AsterixField * const * const I{}[] = {}'.format(ref, '{'))
for var in variations:
tell(' I{}_{},'.format(ref, var['name']))
tell(' NULL')
tell('};')
- tell('DIAG_ON_PEDANTIC')
tell('')
def part3(ctx, specs):
@@ -620,9 +595,7 @@ def part3(ctx, specs):
editions = sorted([val['edition'] for val in lst], key = lambda x: (x['major'], x['minor']), reverse=True)
editions_fmt = [fmt_edition(cat, edition) for edition in editions]
editions_str = ', '.join(['I{:03d}'.format(cat)] + editions_fmt)
- tell('DIAG_OFF_PEDANTIC')
- tell('static const AsterixField ***I{:03d}all[] = {} {} {};'.format(cat, '{', editions_str, '}'))
- tell('DIAG_ON_PEDANTIC')
+ tell('static const AsterixField * const * const * const I{:03d}all[] = {} {} {};'.format(cat, '{', editions_str, '}'))
tell('')
tell('static const enum_val_t I{:03d}_versions[] = {}'.format(cat, '{'))
@@ -646,7 +619,7 @@ def part4(ctx, cats):
tell = lambda s: ctx.tell('insert1', s)
tell_pr = lambda s: ctx.tell('insert3', s)
- tell('static const AsterixField ****categories[] = {')
+ tell('static const AsterixField * const * const * const * const categories[] = {')
for i in range(0, 256):
val = 'I{:03d}all'.format(i) if i in cats else 'NULL'
tell(' {}, /* {:03d} */'.format(val, i))
@@ -683,7 +656,7 @@ def remove_rfs(spec):
catalogue = [] # create new catalogue without RFS
rfs_items = []
for i in spec['catalogue']:
- if i['variation']['type'] == 'Rfs':
+ if get_rule(i['rule'])['type'] == 'Rfs':
rfs_items.append(i['name'])
else:
catalogue.append(i)
@@ -716,7 +689,7 @@ def is_valid(spec):
def check_item(item):
if item['spare']:
return True
- return check_variation(item['variation'])
+ return check_variation(get_rule(item['rule']))
def check_variation(variation):
t = variation['type']
if t == 'Element':
@@ -757,6 +730,7 @@ def main():
# read and json-decode input files
jsons = load_jsons(args.paths)
jsons = [json.loads(i) for i in jsons]
+ jsons = [convert.handle_asterix(i) for i in jsons]
jsons = sorted(jsons, key = lambda x: (x['number'], x['edition']['major'], x['edition']['minor']))
jsons = [spec for spec in jsons if spec['type'] == 'Basic']
jsons = [remove_rfs(spec) for spec in jsons]
@@ -780,13 +754,15 @@ def main():
for spec in jsons:
is_latest = spec['edition'] == latest_editions[spec['number']]
- ctx.tell('insert1', '/* Category {:03d}, edition {}.{} */'.format(spec['number'], spec['edition']['major'], spec['edition']['minor']))
+ ctx.tell('insert1', '/* Category {:03d}, edition {}.{} */'.format(
+ spec['number'], spec['edition']['major'], spec['edition']['minor']))
# handle part1
get_ref = lambda path: reference(spec['number'], spec['edition'], path)
part1(ctx, get_ref, spec['catalogue'])
if is_latest:
- ctx.tell('insert1', '/* Category {:03d}, edition {}.{} (latest) */'.format(spec['number'], spec['edition']['major'], spec['edition']['minor']))
+ ctx.tell('insert1', '/* Category {:03d}, edition {}.{} (latest) */'.format(
+ spec['number'], spec['edition']['major'], spec['edition']['minor']))
get_ref = lambda path: reference(spec['number'], None, path)
part1(ctx, get_ref, spec['catalogue'])
@@ -826,4 +802,3 @@ def main():
if __name__ == '__main__':
main()
-