Loading DENM-PDU-Descriptions.asn +111 −116 Original line number Diff line number Diff line -- Draft DENM TS 103 831 ASN.1 module -- Based on the official Release 1 version available at @url https://forge.etsi.org/rep/ITS/asn1/cam_en302637_2/-/tree/v1.4.1 -- Modified to import from the draft CDD module major-version-3 -- Date 04.07.2022 DENM-PDU-Description {itu-t (0) identified-organization (4) etsi (0) itsDomain (5) wg1 (1) denmPduRelease2 (103831) major-version-2 (2) minor-version-1 (1)} DEFINITIONS AUTOMATIC TAGS ::= Loading @@ -11,7 +6,7 @@ BEGIN IMPORTS ActionId, ActionIdList, CauseCodeV2, ClosedLanes, DangerousGoodsExtended, DeltaReferencePosition, DeltaTimeMilliSecondPos, DeltaTimeSecond, ActionId, ActionIdList, CauseCodeV2, ClosedLanes, DangerousGoodsExtended, DeltaReferencePosition, DeltaTimeMilliSecondPositive, DeltaTimeSecond, EnergyStorageType, EventZone, HeightLonCarr, InformationQuality, ItsPduHeader, LanePosition, LightBarSirenInUse, ItineraryPath, NumberOfOccupants, PosLonCarr, PosCentMass, PositionOfPillars, PositioningSolutionType, PosFrontAx, PositionOfOccupants, RequestResponseIndication, ReferencePosition, RestrictedTypes, RoadType, StandardLength3b, StationType, Speed, SpeedLimit, StationarySince, TimestampIts, Traces, Loading Loading @@ -42,7 +37,7 @@ ManagementContainer ::= SEQUENCE { awarenessDistance StandardLength3b OPTIONAL, awarenessTrafficDirection TrafficDirection OPTIONAL, validityDuration DeltaTimeSecond DEFAULT defaultValidity, transmissionInterval DeltaTimeMilliSecondPos OPTIONAL, transmissionInterval DeltaTimeMilliSecondPositive OPTIONAL, stationType StationType, ... } Loading asn2md.py +42 −19 Original line number Diff line number Diff line Loading @@ -41,6 +41,7 @@ RE_DOXY_C_COMMENTS = re.compile(r'^\s*/\*\*\s(.*?)\*/', re.MULTILINE | re.DOTALL RE_DOXY_C_COMMENTS_I = re.compile(r'\s*\*+') RE_STRIPSTAR = re.compile(r'^\s*\*', re.MULTILINE) RE_POWER_SIGN = re.compile('\^(-?\w+|\(.*?\))') RE_DOXY_REF = re.compile(r'@ref\s+([\w-]+)') Loading @@ -63,6 +64,7 @@ RE_OPTIONS = re.compile(r'^\s*@options[\s:]+(.+)', re.MULTILINE) extTypes = {} cpos = 0 o_args = [] m_options = [] def urlquote(s): if (sys.version_info > (3, 0)): Loading @@ -87,6 +89,8 @@ def parseText(content, indent=None): content = RE_DOXY_STRIP_SINGLE_TAG.sub('', content) content = RE_POWER_SIGN.sub('<sup>\\1</sup>', content) return indentLines(content, indent) def parseInlineComments(content:str, indent=None): Loading @@ -112,6 +116,14 @@ def parseDoxyComments(content:str): ret += RE_STRIPSTAR.sub('', m.group(1)) return ret def parseOptions(doc, opts): def repl_options(m): if m.group(1) is not None: for o in m.group(1).split(','): setattr(opts, o.strip(), True) return '' return RE_OPTIONS.sub(repl_options, doc) def parseModule(mname, content): global cpos cpos = 0 Loading Loading @@ -139,24 +151,19 @@ def parseModule(mname, content): # parse types def repl_type (m, doc): global m_options title = t = m.group(1) # type name f_params = {} s_unit = '' s_category = '' s_note = '' s_revision = '' options = copy.copy(o_args) options = copy.copy(m_options) if doc : # doc is the prepending comment. Check if not None and not Empty doc = parseDoxyComments(doc) # parse options def repl_options(m): nonlocal options if m.group(1) is not None: for o in m.group(1).split(','): setattr(options, o.strip(), True) return '' doc=RE_OPTIONS.sub(repl_options, doc) doc = parseOptions(doc, options) def repl_section (m): nonlocal title Loading @@ -171,9 +178,12 @@ def parseModule(mname, content): ret = parseText(l) else: if len(l): if len(f_params) == 0: ret = '--((FIELDS))--' f_params[m.group(3)] = parseText(l, 2) elif m.group(1) == 'brief': if o_args.brief_as_title: if options.brief_as_title: title = parseText(l) else: ret = parseText(l) Loading @@ -189,29 +199,31 @@ def parseModule(mname, content): s_category = '\n **Categories**: ' for l in m.group(1).split(','): # s_category += '[{0}](#{1}) '.format(l.strip(), urlquote(l.strip())) s_category += l.strip() + ' ' s_category += parseText(l).strip() + ' ' s_category += '\n' return '' doc = RE_DOXY_CATEGORY.sub(repl_category, doc) def repl_unit(m): nonlocal s_unit s_unit = '\n **Unit**: _' + m.group(1).strip() + '_\n' s_unit = '\n **Unit**: _' + parseText(m.group(1)).strip() + '_\n' return '' doc = RE_DOXY_UNIT.sub(repl_unit, doc) def repl_revision(m): nonlocal s_revision s_revision = '\n **Revision**: _' + m.group(1).strip() + '_\n' s_revision = '\n **Revision**: _' + parseText(m.group(1)).strip() + '_\n' return '' doc = RE_DOXY_REVISION.sub(repl_revision, doc) else: doc = '' doc = [x.strip() for x in doc.split('--((FIELDS))--')] ret = '' if t is not None: fields = '' ret = '\n### <a name="{0}"></a>{1}\n'.format(t, title) + parseText(doc) ret = '\n### <a name="{0}"></a>{1}\n'.format(t, title) + parseText(doc[0]) # parse fields and get out fields descriptions if m.group(3) is not None: Loading @@ -235,15 +247,15 @@ def parseModule(mname, content): field = f_params.pop(f) + '\n\n' if fm.group(2) is not None: fTitle = 'Fields:\n' if len(field) or not o_args.no_auto_fields: if len(field) or not options.no_auto_fields: t = fm.group(2).strip() if RE_BASIC_TYPES.match(t) is not None: field = '* {0} **{1}** {2}<br>\n'.format(f, t, ext) + field field = '* {0} of type **{1}** {2}<br>\n'.format(f, t, ext) + field else: field = '* {0} [**{1}**]({2}#{1}) {3}<br>\n'.format(f, t, extTypes.get(t,''), ext) + field field = '* {0} of type [**{1}**]({2}#{1}) {3}<br>\n'.format(f, t, extTypes.get(t,''), ext) + field else: fTitle = 'Values:\n' if len(field) or not o_args.no_auto_values: if len(field) or not options.no_auto_values: field = '* **{0}** {1}<br>\n'.format(f, ext) + field if len(field): field += parseText(fm.string[pos:fm.start()], 3) Loading @@ -256,9 +268,11 @@ def parseModule(mname, content): if len(field): fields += parseInlineComments(typeBody[pos:], 3) # add all other fields defined as @params if 'force-all-fields' in options or 'force-all-fields' in o_args: if 'force-all-fields' in options: for f in f_params: fields += '* {}<br>\n{}\n\n'.format(f, f_params[f]) if 'no-fields-header' in options: fTitle = '' if len(fields): ret = ret.strip() + '\n\n' + fTitle + fields else: Loading @@ -270,6 +284,12 @@ def parseModule(mname, content): for p in f_params: ret += '* `{0}` {1}\n'.format(p, f_params[p]) try: if len(doc[1]): ret += doc[1] + '\n' except: pass return ret + s_unit + s_category + s_revision + s_note + '```asn1\n' + RE_COMMENTS.sub('', m.group(0).strip()) +'\n```\n\n' pos = 0 Loading @@ -282,11 +302,13 @@ def parseModule(mname, content): def parseAsn(outDir, content) : # iterate modules in the file global m_options pos= 0 cnt = 0 m_options = copy.copy(o_args) for m in RE_MODULE.finditer(content): ret = '# ASN.1 module {}\n OID: _{}_\n'.format(m.group(1), RE_SPACES.sub(' ', m.group(2))) ret += parseDoxyComments(content[pos:m.start()]) + '\n' ret += parseText(parseOptions(parseDoxyComments(content[pos:m.start()]), m_options)) + '\n' if m.group(3) is not None: ret += parseModule(m.group(1), m.group(3)) ret += '\n\n' Loading @@ -303,6 +325,7 @@ def main(): ap.add_argument('--force-all-fields', '-f', default=False,action='store_true', help='Add all fields in the list even if empty') ap.add_argument('--no-auto-fields', '-F', default=False,action='store_true', help='Add fields only if @param or @field is defined') ap.add_argument('--no-auto-values', '-V', default=False,action='store_true', help='Do not add named values or enums') ap.add_argument('--no-fields-header', '-H', default=False,action='store_true', help='Do not add fields and values header') ap.add_argument('modules', action='store', nargs='+', help='ASN.1 files') o_args = ap.parse_args() Loading cdd @ 65955d90 Compare 14e8d7a0 to 65955d90 Original line number Diff line number Diff line Subproject commit 14e8d7a0910c6b90440c1be2fdfc6e7d04f06f9c Subproject commit 65955d90fbba94fe3d52538104e079de76e728e6 Loading
DENM-PDU-Descriptions.asn +111 −116 Original line number Diff line number Diff line -- Draft DENM TS 103 831 ASN.1 module -- Based on the official Release 1 version available at @url https://forge.etsi.org/rep/ITS/asn1/cam_en302637_2/-/tree/v1.4.1 -- Modified to import from the draft CDD module major-version-3 -- Date 04.07.2022 DENM-PDU-Description {itu-t (0) identified-organization (4) etsi (0) itsDomain (5) wg1 (1) denmPduRelease2 (103831) major-version-2 (2) minor-version-1 (1)} DEFINITIONS AUTOMATIC TAGS ::= Loading @@ -11,7 +6,7 @@ BEGIN IMPORTS ActionId, ActionIdList, CauseCodeV2, ClosedLanes, DangerousGoodsExtended, DeltaReferencePosition, DeltaTimeMilliSecondPos, DeltaTimeSecond, ActionId, ActionIdList, CauseCodeV2, ClosedLanes, DangerousGoodsExtended, DeltaReferencePosition, DeltaTimeMilliSecondPositive, DeltaTimeSecond, EnergyStorageType, EventZone, HeightLonCarr, InformationQuality, ItsPduHeader, LanePosition, LightBarSirenInUse, ItineraryPath, NumberOfOccupants, PosLonCarr, PosCentMass, PositionOfPillars, PositioningSolutionType, PosFrontAx, PositionOfOccupants, RequestResponseIndication, ReferencePosition, RestrictedTypes, RoadType, StandardLength3b, StationType, Speed, SpeedLimit, StationarySince, TimestampIts, Traces, Loading Loading @@ -42,7 +37,7 @@ ManagementContainer ::= SEQUENCE { awarenessDistance StandardLength3b OPTIONAL, awarenessTrafficDirection TrafficDirection OPTIONAL, validityDuration DeltaTimeSecond DEFAULT defaultValidity, transmissionInterval DeltaTimeMilliSecondPos OPTIONAL, transmissionInterval DeltaTimeMilliSecondPositive OPTIONAL, stationType StationType, ... } Loading
asn2md.py +42 −19 Original line number Diff line number Diff line Loading @@ -41,6 +41,7 @@ RE_DOXY_C_COMMENTS = re.compile(r'^\s*/\*\*\s(.*?)\*/', re.MULTILINE | re.DOTALL RE_DOXY_C_COMMENTS_I = re.compile(r'\s*\*+') RE_STRIPSTAR = re.compile(r'^\s*\*', re.MULTILINE) RE_POWER_SIGN = re.compile('\^(-?\w+|\(.*?\))') RE_DOXY_REF = re.compile(r'@ref\s+([\w-]+)') Loading @@ -63,6 +64,7 @@ RE_OPTIONS = re.compile(r'^\s*@options[\s:]+(.+)', re.MULTILINE) extTypes = {} cpos = 0 o_args = [] m_options = [] def urlquote(s): if (sys.version_info > (3, 0)): Loading @@ -87,6 +89,8 @@ def parseText(content, indent=None): content = RE_DOXY_STRIP_SINGLE_TAG.sub('', content) content = RE_POWER_SIGN.sub('<sup>\\1</sup>', content) return indentLines(content, indent) def parseInlineComments(content:str, indent=None): Loading @@ -112,6 +116,14 @@ def parseDoxyComments(content:str): ret += RE_STRIPSTAR.sub('', m.group(1)) return ret def parseOptions(doc, opts): def repl_options(m): if m.group(1) is not None: for o in m.group(1).split(','): setattr(opts, o.strip(), True) return '' return RE_OPTIONS.sub(repl_options, doc) def parseModule(mname, content): global cpos cpos = 0 Loading Loading @@ -139,24 +151,19 @@ def parseModule(mname, content): # parse types def repl_type (m, doc): global m_options title = t = m.group(1) # type name f_params = {} s_unit = '' s_category = '' s_note = '' s_revision = '' options = copy.copy(o_args) options = copy.copy(m_options) if doc : # doc is the prepending comment. Check if not None and not Empty doc = parseDoxyComments(doc) # parse options def repl_options(m): nonlocal options if m.group(1) is not None: for o in m.group(1).split(','): setattr(options, o.strip(), True) return '' doc=RE_OPTIONS.sub(repl_options, doc) doc = parseOptions(doc, options) def repl_section (m): nonlocal title Loading @@ -171,9 +178,12 @@ def parseModule(mname, content): ret = parseText(l) else: if len(l): if len(f_params) == 0: ret = '--((FIELDS))--' f_params[m.group(3)] = parseText(l, 2) elif m.group(1) == 'brief': if o_args.brief_as_title: if options.brief_as_title: title = parseText(l) else: ret = parseText(l) Loading @@ -189,29 +199,31 @@ def parseModule(mname, content): s_category = '\n **Categories**: ' for l in m.group(1).split(','): # s_category += '[{0}](#{1}) '.format(l.strip(), urlquote(l.strip())) s_category += l.strip() + ' ' s_category += parseText(l).strip() + ' ' s_category += '\n' return '' doc = RE_DOXY_CATEGORY.sub(repl_category, doc) def repl_unit(m): nonlocal s_unit s_unit = '\n **Unit**: _' + m.group(1).strip() + '_\n' s_unit = '\n **Unit**: _' + parseText(m.group(1)).strip() + '_\n' return '' doc = RE_DOXY_UNIT.sub(repl_unit, doc) def repl_revision(m): nonlocal s_revision s_revision = '\n **Revision**: _' + m.group(1).strip() + '_\n' s_revision = '\n **Revision**: _' + parseText(m.group(1)).strip() + '_\n' return '' doc = RE_DOXY_REVISION.sub(repl_revision, doc) else: doc = '' doc = [x.strip() for x in doc.split('--((FIELDS))--')] ret = '' if t is not None: fields = '' ret = '\n### <a name="{0}"></a>{1}\n'.format(t, title) + parseText(doc) ret = '\n### <a name="{0}"></a>{1}\n'.format(t, title) + parseText(doc[0]) # parse fields and get out fields descriptions if m.group(3) is not None: Loading @@ -235,15 +247,15 @@ def parseModule(mname, content): field = f_params.pop(f) + '\n\n' if fm.group(2) is not None: fTitle = 'Fields:\n' if len(field) or not o_args.no_auto_fields: if len(field) or not options.no_auto_fields: t = fm.group(2).strip() if RE_BASIC_TYPES.match(t) is not None: field = '* {0} **{1}** {2}<br>\n'.format(f, t, ext) + field field = '* {0} of type **{1}** {2}<br>\n'.format(f, t, ext) + field else: field = '* {0} [**{1}**]({2}#{1}) {3}<br>\n'.format(f, t, extTypes.get(t,''), ext) + field field = '* {0} of type [**{1}**]({2}#{1}) {3}<br>\n'.format(f, t, extTypes.get(t,''), ext) + field else: fTitle = 'Values:\n' if len(field) or not o_args.no_auto_values: if len(field) or not options.no_auto_values: field = '* **{0}** {1}<br>\n'.format(f, ext) + field if len(field): field += parseText(fm.string[pos:fm.start()], 3) Loading @@ -256,9 +268,11 @@ def parseModule(mname, content): if len(field): fields += parseInlineComments(typeBody[pos:], 3) # add all other fields defined as @params if 'force-all-fields' in options or 'force-all-fields' in o_args: if 'force-all-fields' in options: for f in f_params: fields += '* {}<br>\n{}\n\n'.format(f, f_params[f]) if 'no-fields-header' in options: fTitle = '' if len(fields): ret = ret.strip() + '\n\n' + fTitle + fields else: Loading @@ -270,6 +284,12 @@ def parseModule(mname, content): for p in f_params: ret += '* `{0}` {1}\n'.format(p, f_params[p]) try: if len(doc[1]): ret += doc[1] + '\n' except: pass return ret + s_unit + s_category + s_revision + s_note + '```asn1\n' + RE_COMMENTS.sub('', m.group(0).strip()) +'\n```\n\n' pos = 0 Loading @@ -282,11 +302,13 @@ def parseModule(mname, content): def parseAsn(outDir, content) : # iterate modules in the file global m_options pos= 0 cnt = 0 m_options = copy.copy(o_args) for m in RE_MODULE.finditer(content): ret = '# ASN.1 module {}\n OID: _{}_\n'.format(m.group(1), RE_SPACES.sub(' ', m.group(2))) ret += parseDoxyComments(content[pos:m.start()]) + '\n' ret += parseText(parseOptions(parseDoxyComments(content[pos:m.start()]), m_options)) + '\n' if m.group(3) is not None: ret += parseModule(m.group(1), m.group(3)) ret += '\n\n' Loading @@ -303,6 +325,7 @@ def main(): ap.add_argument('--force-all-fields', '-f', default=False,action='store_true', help='Add all fields in the list even if empty') ap.add_argument('--no-auto-fields', '-F', default=False,action='store_true', help='Add fields only if @param or @field is defined') ap.add_argument('--no-auto-values', '-V', default=False,action='store_true', help='Do not add named values or enums') ap.add_argument('--no-fields-header', '-H', default=False,action='store_true', help='Do not add fields and values header') ap.add_argument('modules', action='store', nargs='+', help='ASN.1 files') o_args = ap.parse_args() Loading
cdd @ 65955d90 Compare 14e8d7a0 to 65955d90 Original line number Diff line number Diff line Subproject commit 14e8d7a0910c6b90440c1be2fdfc6e7d04f06f9c Subproject commit 65955d90fbba94fe3d52538104e079de76e728e6