Commit b80f93c4 authored by Denis Filatov's avatar Denis Filatov
Browse files

Merge branch 'WI-001947' into 'WI-001947'

# Conflicts:
#   IMZM-PDU-Descriptions.asn
parents a2ad94fe d949bf98
Loading
Loading
Loading
Loading

.gitlab-ci.mk

0 → 100755
+45 −0
Original line number Original line Diff line number Diff line
ASN1_SRC   :=  IMZM-PDU-Descriptions.asn \
               cam/CAM-PDU-Descriptions.asn \
               vam/VAM-Temp-Imports.asn \
               cdd/ITS-Container.asn

ASN1_SRC_VALIDATE := \
               iso/iso19091_2018.asn \
               iso/iso24534-3_1_2015.asn \
               iso/iso24534-3_2_2015.asn \
               iso/ISO14816_AVIAEINumberingAndDataStructures.asn

ASN1_PDU := IMZM
ASN1_KNOWN := DATE

#ASN1CDIR    ?= $(USERPROFILE)/Work/asn1c-fillabs
ifneq (,$(ASN1CDIR))
  ASN1C := $(ASN1CDIR)/asn1c/.libs/asn1c -S $(ASN1CDIR)/skeletons
else
  ASN1C := asn1c
endif

.PHONY: validate doc build

validate: iso build

doc: docs
	python3 asn2md.py -o docs --brief-as-title $(ASN1_SRC)
		
iso docs:
	mkdir -p $@

build: $(ASN1_SRC) $(ASN1_SRC_VALIDATE)
	$(ASN1C) -E -F -fcompound-names $(addprefix -fknown-extern-type=,$(ASN1_KNOWN)) $(addprefix -pdu=,$(ASN1_PDU)) $^ >/dev/null

iso/iso19091_2018.asn: 
	curl -o $@ 'https://standards.iso.org/iso/ts/19091/ed-2/en/ISO-TS-19091-addgrp-C-2018.asn'

iso/iso24534-3_1_2015.asn:
	curl -o $@ 'https://standards.iso.org/iso/24534/-3/ISO%2024534-3%20ASN.1%20repository/ISO24534-3_ElectronicRegistrationIdentificationVehicleDataModule_ForBallot.asn'

iso/iso24534-3_2_2015.asn:
	curl -o $@ 'https://standards.iso.org/iso/24534/-3/ISO%2024534-3%20ASN.1%20repository/ISO24534-3_ElectronicRegistrationIdentificationEfcVehicleDataModule_ForBallot.asn'

iso/ISO14816_AVIAEINumberingAndDataStructures.asn:
	curl -o $@ 'https://standards.iso.org/iso/14816/ISO14816%20ASN.1%20repository/ISO14816_AVIAEINumberingAndDataStructures.asn'

.gitlab-ci.yml

0 → 100644
+32 −0
Original line number Original line Diff line number Diff line
variables:
 GIT_SUBMODULE_STRATEGY: normal

image: danya25/asn1c:0.0.5

validate:
  stage: test
  script: make -f .gitlab-ci.mk validate
  only:
    changes:
      - "*.asn"

documentation:
  stage: deploy
  script:
    - >
      if ! [ -f asn2md.py ]; then
        curl -o asn2md.py --header "PRIVATE-TOKEN:$CI_JOB_TOKEN" "https://forge.etsi.org/rep/api/v4/projects/592/repository/files/asn2md.py/raw?ref=master"
      fi
    - make -f .gitlab-ci.mk doc
    - git add docs/*.md
    - >
      if [ -z "$(git status --untracked-files=no --porcelain)" ]; then
        echo "No changes found";
      else 
        git commit -m "Documentation update" &&
        git remote rm origin && git remote add origin "https://oauth2:${CI_DOC_TOKEN}@forge.etsi.org/rep/$CI_PROJECT_PATH.git" &&
        git push origin "HEAD:$CI_COMMIT_REF_NAME";
      fi
  only:
    changes:
      - "*.asn"
+39 −41
Original line number Original line Diff line number Diff line
--! @brief Specification of the Interference Management Zone Message ETSI TS 103 724
--! @brief Specification of the Interference Management Zone Message ETSI TS 103 724
--! Latest version available at @url https://forge.etsi.org/rep/ITS/asn1/imzm_ts103724
--! Latest version available at @url https://forge.etsi.org/rep/ITS/asn1/imzm_ts103724


IMZM-PDU-Descriptions {
IMZM-PDU-Descriptions {
@@ -25,8 +25,7 @@ en (302637) cam (2) version (2)
}
}


--! @brief Include ETSI TS 103 300-3
--! @brief Include ETSI TS 103 300-3
--! This is temporary 
--! All data types, imported from `VAM-Temp-Imports` will be imported from the CDD ETSI TS 102 894-2 Release 2 when available  
--! Import from VAM-Temp-Imports will be changed to CDD ETSI TS 102 894-2 Release 2 when available
--! Include references from @url https://forge.etsi.org/rep/ITS/asn1/vam-ts103300_3/blob/master/VAM-Temp-Imports.asn  
--! Include references from @url https://forge.etsi.org/rep/ITS/asn1/vam-ts103300_3/blob/master/VAM-Temp-Imports.asn  
AreaCircular, AreaRectangle, AreaPolygon, OffsetPoint, SemiRangeLength, WGS84AngleValue FROM VAM-Temp-Imports { 
AreaCircular, AreaRectangle, AreaPolygon, OffsetPoint, SemiRangeLength, WGS84AngleValue FROM VAM-Temp-Imports { 
itu-t(0) identified-organization(4) etsi(0) itsDomain(5) wg1(1)  
itu-t(0) identified-organization(4) etsi(0) itsDomain(5) wg1(1)  
@@ -34,25 +33,22 @@ ts(103300) temp-imports(255) version1(1)
}
}
;
;


--! @defgroup IMZM Interference Management Zone Message
--! @{

--! @brief DF: Interference Management Zone Message Root
--! @brief DF: Interference Management Zone Message Root
--! This DF includes DEs for the IMZM protocolVersion, the IMZ message type identifier _messageID_ 
--! This DF includes DEs for the IMZM `protocolVersion`, the IMZ message type identifier `messageID` 
--! and the station identifier _stationID_ of the originating ITS-S. 
--! and the station identifier `stationID` of the originating ITS-S. 
IMZM ::= SEQUENCE {
IMZM ::= SEQUENCE {
    --! @details header
    --! @details header
    --! The DE _protocolVersion_ is used to select the appropriate protocol decoder at the receiving
    --! - The DE `protocolVersion` is used to select the appropriate protocol decoder at the receiving
    --! ITS-S. For TS 103 724 V2.1.1, the value of the DE _protocolVersion_ shall be set to 1.
    --!   ITS-S. For TS 103 724 V2.1.1, the value of the DE `protocolVersion` shall be set to 1.
    --! The DE _messageID_ shall be harmonized with other V2X message identifier definitions.
    --! - The DE `messageID` shall be harmonized with other V2X message identifier definitions.
    --! For IMZM, the DE messageID shall be set to imzm(15).
    --!   For IMZM, the DE messageID shall be set to `imzm(15)`.
   header ItsPduHeader,
   header ItsPduHeader,
   imzm InterferenceManagementZoneMessage
   imzm InterferenceManagementZoneMessage
}
}


--! @brief DF: Interference Management Zone Message
--! @brief DF: Interference Management Zone Message
--! This is the actual IMZM Payload. It shall include the time stamp of the IMZM and the applicable
--! This is the actual IMZM Payload. It shall include the time stamp of the IMZM and the applicable
--! containers of type _BasicContainer_ and _ImzmContainer_.
--! containers of type `BasicContainer` and `ImzmContainer`.
InterferenceManagementZoneMessage ::= SEQUENCE {
InterferenceManagementZoneMessage ::= SEQUENCE {
   generationDeltaTime GenerationDeltaTime, -- from CAM-PDU-Descriptions
   generationDeltaTime GenerationDeltaTime, -- from CAM-PDU-Descriptions
   imzmParameters ImzmParameters
   imzmParameters ImzmParameters
@@ -83,13 +79,14 @@ ImzmContainer ::= SEQUENCE {


--! @brief DF: List of Interference Management Zones
--! @brief DF: List of Interference Management Zones
--! A list of up to 16 interference management zones.  
--! A list of up to 16 interference management zones.  
--! EXAMPLE: An interference management communication zone may be defined around a 
--!
--! **EXAMPLE**: An interference management communication zone may be defined around a 
--!    CEN DSRC road side equipment or an urban rail operational area.
--!    CEN DSRC road side equipment or an urban rail operational area.
--! @category: Infrastructure information, Communication information
--! @category: Infrastructure information, Communication information
InterferenceManagementZones ::= SEQUENCE (SIZE(1..16), ...) OF InterferenceManagementZone
InterferenceManagementZones ::= SEQUENCE (SIZE(1..16), ...) OF InterferenceManagementZone


--! @brief DF: Interference Management Zone
--! @brief DF: Interference Management Zone
--! describes a zone of interferenceManagement inside which the ITS communication should
--! Describes a zone of interferenceManagement inside which the ITS communication should
--! be restricted.
--! be restricted.
--! @category: Infrastructure information, Communication information
--! @category: Infrastructure information, Communication information
InterferenceManagementZone ::= SEQUENCE {
InterferenceManagementZone ::= SEQUENCE {
@@ -98,23 +95,23 @@ InterferenceManagementZone ::= SEQUENCE {
}
}


--! @brief DF: Zone Definition
--! @brief DF: Zone Definition
--! describes the zone where band sharing occurs. When reusing CDD Rel.1 types, names are unchanged.
--! Describes the zone where band sharing occurs. When reusing CDD Rel.1 types, names are unchanged.
--! @category: Infrastructure information, Communication information
--! @category: Infrastructure information, Communication information
ZoneDefinition::= SEQUENCE{     
ZoneDefinition::= SEQUENCE{     
	 --! @details interferenceManagementZoneLatitude
	 --! @details interferenceManagementZoneLatitude
     --! Latitude of the centre point of the interference management zone.
     --! Latitude of the centre point of the interference management zone.
    interferenceManagementZoneLatitude   Latitude, --! from ITS-Container
    interferenceManagementZoneLatitude   Latitude, -- from ITS-Container
     --! @details interferenceManagementZoneLongitude
     --! @details interferenceManagementZoneLongitude
     --! Longitude of the centre point of the interference management zone.
     --! Longitude of the centre point of the interference management zone.
    interferenceManagementZoneLongitude  Longitude, --! from ITS-Container
    interferenceManagementZoneLongitude  Longitude, -- from ITS-Container
     --! @details interferenceManagementZoneRadius
     --! @details interferenceManagementZoneRadius
     --! Radius of the interference management zone in metres. 
     --! Radius of the interference management zone in metres. 
     --! This DE is present if the data is available
     --! This DE is present if the data is available
    interferenceManagementZoneRadius     ProtectedZoneRadius OPTIONAL, --! from ITS-Container
    interferenceManagementZoneRadius     ProtectedZoneRadius OPTIONAL, -- from ITS-Container
     --! @details interferenceManagementZoneID
     --! @details interferenceManagementZoneID
     --! Identification of the interference management zone. 
     --! Identification of the interference management zone. 
     --! This DE is present if the data is available.
     --! This DE is present if the data is available.
    interferenceManagementZoneID         ProtectedZoneID OPTIONAL, --! from ITS-Container
    interferenceManagementZoneID         ProtectedZoneID OPTIONAL, -- from ITS-Container
     --! @details interferenceManagementZoneShape
     --! @details interferenceManagementZoneShape
     --! Shape of the interference management zone. 
     --! Shape of the interference management zone. 
     --! This DF is present if the data is available.
     --! This DF is present if the data is available.
@@ -125,7 +122,8 @@ ZoneDefinition::= SEQUENCE{
--! @brief DF: Interference Management Information
--! @brief DF: Interference Management Information
--! A list of up to 16 definitions containing which interference management may be applied in the zone, 
--! A list of up to 16 definitions containing which interference management may be applied in the zone, 
--! per affected frequency channels.
--! per affected frequency channels.
--! Note: in the case where no mitigation should be applied by the ITS-S, this is indicated 
--!  
--! **Note**: in the case where no mitigation should be applied by the ITS-S, this is indicated 
--! by the value of interferenceManagementMitigationType set to unavailable. 
--! by the value of interferenceManagementMitigationType set to unavailable. 
--! @category: Infrastructure information, Communication information
--! @category: Infrastructure information, Communication information
InterferenceManagementInfo::= SEQUENCE (SIZE(1..16,...)) OF InterferenceManagementInfoPerChannel
InterferenceManagementInfo::= SEQUENCE (SIZE(1..16,...)) OF InterferenceManagementInfoPerChannel
@@ -147,12 +145,12 @@ InterferenceManagementInfoPerChannel ::= SEQUENCE {
     --! @details expiryTime
     --! @details expiryTime
     --! Time at which the validity of the interference management communication zone will expire.
     --! Time at which the validity of the interference management communication zone will expire.
     --! This DE is present when the interference management is temporarily valid
     --! This DE is present when the interference management is temporarily valid
    expiryTime                            TimestampIts OPTIONAL, --! from ITS-Container
    expiryTime                            TimestampIts OPTIONAL, -- from ITS-Container
    ...
    ...
}
}


--! @brief DF: InterferenceManagementChannel
--! @brief DF: InterferenceManagementChannel
--! indicates which shared frequency channel should be applied interference management in the zone. 
--! Indicates which shared frequency channel should be applied interference management in the zone. 
--! @category: Communication information
--! @category: Communication information
InterferenceManagementChannel ::= SEQUENCE {
InterferenceManagementChannel ::= SEQUENCE {
     --! @details centre frequency of the channel
     --! @details centre frequency of the channel
@@ -173,12 +171,12 @@ InterferenceManagementChannel ::= SEQUENCE {
--! @unit: N/A
--! @unit: N/A
--! @category: Communication information
--! @category: Communication information
InterferenceManagementZoneType ::= ENUMERATED {
InterferenceManagementZoneType ::= ENUMERATED {
    permanentCenDsrcTolling(0), --! as specified in ETSI TS 102 792
    permanentCenDsrcTolling(0), --!< as specified in ETSI TS 102 792
    temporaryCenDsrcTolling(1), --! as specified in ETSI TS 102 792
    temporaryCenDsrcTolling(1), --!< as specified in ETSI TS 102 792
    unavailable(2),  --! default value. Set to 2 for backwards compatibility with DSRC tolling
    unavailable(2),             --!< default value. Set to 2 for backwards compatibility with DSRC tolling
    urbanRail(3),    --! as specified in ETSI TS 103 724, clause 7
    urbanRail(3),               --!< as specified in ETSI TS 103 724, clause 7
    satelliteStation(4),  --! as specified in ETSI TS 103 724, clause 7
    satelliteStation(4),        --!< as specified in ETSI TS 103 724, clause 7
    fixedLinks(5),   --! as specified in ETSI TS 103 724, clause 7
    fixedLinks(5),              --!< as specified in ETSI TS 103 724, clause 7
    ...
    ...
}
}


@@ -228,10 +226,10 @@ MitigationPerTechnologyClass ::= SEQUENCE {
--! Access technology to which the mitigation type applies.
--! Access technology to which the mitigation type applies.
--! @category: Communication information
--! @category: Communication information
AccessTechnologyClass ::= ENUMERATED {
AccessTechnologyClass ::= ENUMERATED {
   any(0), --! any access technology class (see clause 7 of TS 103 724).
   any(0),         --!< any access technology class (see clause 7 of TS 103 724).
   itsg5Class(1),  --! ITS-G5 access technology class.
   itsg5Class(1),  --!< ITS-G5 access technology class.
   ltev2xClass(2), --! LTE-V2X access technology class.
   ltev2xClass(2), --!< LTE-V2X access technology class.
   nrv2xClass(3), --! NR-V2X access technology class.
   nrv2xClass(3),  --!< NR-V2X access technology class.
   ...
   ...
}
}


@@ -239,10 +237,10 @@ AccessTechnologyClass ::= ENUMERATED {
--! Bounding box of an interference management  zone
--! Bounding box of an interference management  zone
--! @category: GeoReference information
--! @category: GeoReference information
InterferenceManagementZoneShape::= CHOICE {
InterferenceManagementZoneShape::= CHOICE {
   rectangle    AreaRectangle, --! imported from VAM-Temp-Imports
   rectangle    AreaRectangle, -- imported from VAM-Temp-Imports
   circle       AreaCircular,  --! imported from VAM-Temp-Imports
   circle       AreaCircular,  -- imported from VAM-Temp-Imports
   polygon      AreaPolygon,   --! imported from VAM-Temp-Imports
   polygon      AreaPolygon,   -- imported from VAM-Temp-Imports
   ellipse      AreaEllipse,   --! could not be imported from another specification yet
   ellipse      AreaEllipse,   -- could not be imported from another specification yet
   ...
   ...
}
}


@@ -266,5 +264,5 @@ AreaEllipse ::= SEQUENCE {
    --! Orientation of the semiMajorRangeLength of the ellipse in the WGS84 coordinate system.
    --! Orientation of the semiMajorRangeLength of the ellipse in the WGS84 coordinate system.
    semiMajorRangeOrientation   WGS84AngleValue
    semiMajorRangeOrientation   WGS84AngleValue
}
}
--! @}

END
END

asn2md.py

0 → 100755
+263 −0
Original line number Original line Diff line number Diff line
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import argparse # parse arguments
import os.path  # getting extension from file
import sys      # output and stuff
import re       # for regular expressions
if (sys.version_info > (3, 0)):
	import urllib.parse   #
else:
	import urllib   #

## extract doxygen-tag namespace
RE_MODULE   = re.compile( r'^\s*([A-Z][\w-]*)\s*({.*?})?\s*DEFINITIONS.*?::=\s*?BEGIN(.*)END', re.VERBOSE | re.MULTILINE | re.DOTALL)

RE_SPACES   = re.compile(r'\s+')

RE_COMMENTS = re.compile(r'^\s*--.*?\n|--.*?(?:--|$)|/\*.*?\*/[\t ]*\n?', re.MULTILINE|re.DOTALL)

RE_BASIC_TYPES = re.compile(r'^OCTET\s+STRING|BIT\s+STRING|BOOLEAN|INTEGER|FLOAT|SEQUENCE|SET|NULL')

RE_TYPE_BODY = re.compile(r'.*?{(.*)}\s*(?:\(.*?\)|\s*$)', re.MULTILINE|re.DOTALL)

#RE_FIELDS = re.compile(r'^\s*(?:/\*\*.*?\*/)|^\s*([\w-]+?)\s+(OCTET\s+STRING|BIT\s+STRING|[A-Z][.\w-]+)?(.*?)(?:,((?:\s*--!?<.*?\n)*)|((?:--!?<.*?\n)*)$)', re.MULTILINE | re.DOTALL| re.VERBOSE)
RE_FIELDS = re.compile(r'^\s*/\*.*?\*/|^\s*--\!.*?\n|^\s*([\w-]+)\s+(OCTET\s+STRING|BIT\s+STRING|[A-Z][\w-]+)?((?:{[^}]*}|\([^)]*\)|.)*?)(?:,|(--)|$)', re.MULTILINE | re.DOTALL)

RE_EXPORTS = re.compile(r'^\s*EXPORTS.*?;', re.DOTALL | re.MULTILINE)

RE_IMPORTS = re.compile(r'^\s*IMPORTS\s*(.*?);', re.DOTALL | re.MULTILINE)

RE_IMPORT_ELEMENTS = re.compile(r'^([,\s\w-]*?)FROM\s*([\w-]+)\s*({[^}]*}(?:\s+WITH\s+SUCCESSORS)?)?', re.MULTILINE)

RE_IMPORT_ELEMENT_TYPE = re.compile(r'[^,\s]+')

RE_DOXY_COMMENTS = re.compile(r'^\s*--[-!#](:?$|\s(.*))', re.MULTILINE)

RE_DOXY_C_COMMENTS = re.compile(r'^\s*/\*\*\s(.*?)\*/', re.MULTILINE | re.DOTALL)

RE_DOXY_C_COMMENTS_I = re.compile(r'\s*\*+')

RE_DOXY_REF = re.compile(r'@ref\s+([\w-]+)')
RE_DOXY_CLASS = re.compile(r'@class\s+([\w-]+)')
RE_DOXY_STRIP_SINGLE_TAG = re.compile(r'@(?:brief|url)\s+')
RE_DOXY_DETAILS = re.compile(r'@details\s+[\w-]+')
RE_DOXY_STRIP_TAG = re.compile(r'@(?:details|class|struct)\s+[\w-]+')
RE_DOXY_UNIT = re.compile(r'@unit\s+(.+)', re.MULTILINE)
RE_DOXY_BRIEF = re.compile(r'@brief\s+(.+)\n', re.MULTILINE)
RE_DOXY_CATEGORY = re.compile(r'@category:\s+(.+)', re.MULTILINE)
RE_DOXY_PARAM = re.compile(r'^\s*@(?:param|field)\s+([\w-]+)\s*(.*?)\n\s*$', re.MULTILINE | re.DOTALL)

# RE_TYPE = re.compile(r'(([A-Z][\w-]*)\s*::=[\w \t]+(?:{+(.*?)}+)?.*?)\n\s*\n', re.MULTILINE | re.DOTALL)
RE_TYPE = re.compile(r'^\s*([A-Z][\w-]*)?\s*([{} \t:\w-]*?)?::=([\w \t]+.*?)\n\s*\n', re.MULTILINE | re.DOTALL)

extTypes = {}
cpos = 0
o_args = []

def urlquote(s):
	if (sys.version_info > (3, 0)):
		return urllib.parse.quote_plus(s)
	else:
		return 	urllib.quote_plus(s)

def parseText(content, indent=None):
	s_unit=''
	def repl_ref(m):
		return '[**{0}**]({1}#{0})'.format(m.group(1), extTypes.get(m.group(1),''))
	c = RE_DOXY_REF.sub(repl_ref, content)
	if c is not None:
		content = c
	c = RE_DOXY_STRIP_TAG.sub('', content)
	if c is not None:
		content = c
	c = RE_DOXY_STRIP_SINGLE_TAG.sub('', content)
	if c is not None:
		content = c
	def repl_category(m):
		ret = '\n&nbsp;&nbsp;&nbsp;&nbsp;**Categories**: '
		for l in m.group(1).split(','):
			ret += '[{0}](#{1}) '.format(l.strip(), urlquote(l.strip()))
		return ret + '\n\n'
	c = RE_DOXY_CATEGORY.sub(repl_category, content)
	if c is not None:
		content = c
	def repl_unit(m):
		nonlocal s_unit
		s_unit = '\n&nbsp;&nbsp;&nbsp;&nbsp;**Unit**: _' + m.group(1).strip() + '_'
		return ''
	c = RE_DOXY_UNIT.sub(repl_unit, content)
	if c is not None:
		content = c
	return content + s_unit

def parseInlineComments(content:str, indent=None):
	# keep into account only '--<' comments
	lines = content.splitlines()
	content = ''
	for l in lines:
		l = l.lstrip()
		if l.startswith('--< '):
			content += l[4:] + '\n'
		elif l.startswith('--!< '):
			content += l[5:] + '\n'
		else:
			continue
	return parseText(content, indent)

def parseDoxyComments(content:str, indent=None):
	# keep only '--! ' and /** */ comments
	# convert '--! ' comments to C-style
	c = RE_DOXY_COMMENTS.sub(r'/** \g<1>*/', content)
	if c is not None:
		content = c
	ret = ''
	for m in RE_DOXY_C_COMMENTS.finditer(content):
		lines = m.group(1).splitlines()
		for l in lines:
			l = l.strip().lstrip('*')
			ret += ''.ljust(indent or 0) + l + '\n'
	return parseText(ret, indent)

def parseModule(mname, content):
	global cpos
	cpos = 0
	ret = ''
	m = RE_IMPORTS.search(content)
	if m is not None:
		pos = 0
		if m.group(1) is not None:
			ret += '## Imports:\n'
			s = m.group(1)
			for fm in RE_IMPORT_ELEMENTS.finditer(s):
				imName = fm.group(2)
				for im in RE_IMPORT_ELEMENT_TYPE.finditer(fm.group(1)):
					extTypes[im.group(0)] = imName+'.md'
				ret += ' * **[{0}]({0}.md)** *{1}*<br/>\n'.format(imName, RE_SPACES.sub(' ', fm.group(3) or ''))
				ret += parseDoxyComments(s[pos:fm.start()], 3)+'\n'
				pos = fm.end()
			ret += parseDoxyComments(s[pos:])
		cpos = m.end()

	m = RE_EXPORTS.search(content)
	if m is not None:
		if cpos < m.end():
			cpos = m.end()
	
	# parse types
	def repl_type (m, doc):
		title = t = m.group(1) 
		if doc : # non None and not empty
			def repl_brief (m):
				nonlocal title
				title = m.group(1)
				return '\n'
			if o_args.brief_as_title:
				doc = RE_DOXY_BRIEF.sub(repl_brief, doc, 1)
			doc = parseDoxyComments(doc) + '\n\n'
		else:
			doc = ''

		ret = ''
		if t is not None:
			# parse out @params
			f_params = {}
			def repl_param (m):
				nonlocal f_params
				if m.group(1) is not None and m.group(2) is not None:
					l = m.group(2).lstrip(":, \t\n")
					if len(l):
						f_params[m.group(1)] = l
				return ''
			doc = RE_DOXY_PARAM.sub(repl_param, doc)

			ret = '### <a name="{0}"></a>{1}\n\n'.format(t, title) + doc

			# parse fields and get out fields descriptions
			if m.group(3) is not None:
				# check if contain fields
				fm = RE_TYPE_BODY.search(m.group(3))
				if fm is not None and fm.group(1) is not None:
					typeBody = fm.group(1).strip()	
					if typeBody is not None:
						fTitle = ''
						fields = ''
						pos = 0
						for fm in RE_FIELDS.finditer(typeBody):
							if fm.group(1) is not None:
								# add description to the previous type
								fields += parseInlineComments(fm.string[pos:fm.start()], 3)
								f = fm.group(1).strip()
								ext = fm.group(3) or ''
								if fm.group(2) is not None:
									fTitle = 'Fields:\n'
									t = fm.group(2).strip()
									if RE_BASIC_TYPES.match(t) is not None:
										fields += '* {0} **{1}** {2}<br>\n'.format(f, t, ext)
									else:
										fields += '* {0} [**{1}**]({2}#{1}) {3}<br>\n'.format(f, t, extTypes.get(t,''), ext)
								else:
									fTitle = 'Values:\n'
									fields += '* **{0}** {1}<br>\n'.format(f, ext)
								if f in f_params:
									fields += f_params[f] + '\n\n'
								fields += parseDoxyComments(fm.string[pos:fm.start()], 3)
								pos = fm.end()
								if fm.group(4) is not None:
									# keep '--' for the next round
									pos -= 2
						fields += parseInlineComments(typeBody[pos:], 3)
						if len(fields):
							ret = ret.strip() + '\n\n' + fTitle + fields
		else:
			if title:
				ret = '### {}\n\n'.format(title)
			ret += parseDoxyComments(doc) + '\n\n'
		return ret + '```asn1\n' + RE_COMMENTS.sub('', m.group(0).strip()) +'\n```\n\n'

	pos = 0
	ret += '## Data Elements:\n'
	for m in RE_TYPE.finditer(content[cpos:]):
		ret += repl_type (m, m.string[pos:m.start()])
		pos = m.end()
	return ret


def parseAsn(outDir, content) :
	# iterate modules in the file
	pos= 0
	cnt = 0
	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'
		if m.group(3) is not None:
			ret += parseModule(m.group(1), m.group(3))
		ret += '\n\n'
		open(outDir + '/' + m.group(1) + '.md', "w").write(ret)
		pos = m.end()
		cnt += 1
	return cnt

def main():
	global o_args
	ap = argparse.ArgumentParser(description='ASN.1 to markdown converter')
	ap.add_argument('--out', '-o', type=str, default='.', help='output directory')
	ap.add_argument('--brief-as-title', '-B', default=False, action='store_true', help='Do not treat @brief line as type header')
	ap.add_argument('modules', action='store', nargs='+', help='ASN.1 files')
	o_args = ap.parse_args()

	if not o_args.modules:
		ap.print_help()
		exit(1)

	cnt = 0
	for a in o_args.modules:
		try:
			content = open(a).read()
			cnt += parseAsn(o_args.out, content)
		except IOError as e:
			sys.stderr.write(e[1]+"\n")
	print("{} modules porcessed\n".format(cnt))

if __name__ == '__main__':
	main()
+269 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading