Loading asn2md.py +47 −45 Original line number Diff line number Diff line Loading @@ -5,67 +5,70 @@ import argparse # parse arguments import os.path # getting extension from file import sys # output and stuff import re # for regular expressions import urllib # ## extract doxygen-tag namespace RE_MODULE = re.compile( r'^(\w[\w-]*)[\s{](?:.|\n)*DEFINITIONS(?:.|\n)*::=\s*BEGIN' , re.IGNORECASE | re.VERBOSE | re.DOTALL | re.MULTILINE) RE_EXPORTS = re.compile( r'^\s*EXPORTS .*?;' , re.VERBOSE | re.DOTALL | re.MULTILINE) RE_MODULE = re.compile( r'^\s*([A-Z][\w-]*)\s*({.*?})?\s*DEFINITIONS.*?::=\s*?BEGIN(.*)END', re.VERBOSE | re.MULTILINE | re.DOTALL) RE_IMPORTS = re.compile( r'^\s*IMPORTS .*?;' , re.VERBOSE | re.DOTALL | re.MULTILINE) RE_SPACES = re.compile(r'\s+') RE_END = re.compile( r'^\s*END\s*$' , re.VERBOSE | re.MULTILINE) RE_COMMENTS = re.compile(r'^\s*--.*\n', re.MULTILINE) RE_DOXY_COMMENTS = re.compile( r'^\s*--[-#!]\s' , re.VERBOSE | re.MULTILINE) RE_BASIC_TYPES = re.compile(r'^OCTET\s+STRING|BIT\s+STRING|BOOLEAN|INTEGER|FLOAT') RE_DOXY_C_COMMENTS = re.compile( r'^\s*/\*\*\s(.*?)\*/' , re.VERBOSE | re.MULTILINE | re.DOTALL) RE_FIELDS = re.compile(r'^\s*([\w-]+?)\s+(OCTET\s+STRING|BIT\s+STRING|[A-Z][.\w-]+)?(.*?)(?:,|$)', re.MULTILINE | re.DOTALL) RE_COMMENT = re.compile( r'--.*?(?:--|\n)' , re.VERBOSE | re.MULTILINE) RE_EXPORTS = re.compile(r'^\s*EXPORTS.*?;', re.DOTALL | re.MULTILINE) RE_TYPE = re.compile(r'(([A-Z][\w-]*)\s*::=[\w \t]+(?:{(.*?)})?.*?)\n\s*\n' , re.VERBOSE | re.MULTILINE | re.DOTALL) RE_IMPORTS = re.compile(r'^\s*IMPORTS\s*(.*?);', re.DOTALL | re.MULTILINE) extTypes = {} 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*\*') def indentString(s, indent): lines = s.splitlines() s = '' for c in lines: s += ''.ljust(indent, ' ') + c + '\n' return s RE_DOXY_REF = re.compile(r'@ref\s+([\w-]+)') RE_DOXY_CLASS = re.compile(r'@class\s+([\w-]+)') RE_DOXY_BRIEF = re.compile(r'@brief\s+') RE_TYPE = re.compile(r'(([A-Z][\w-]*)\s*::=[\w \t]+(?:{(.*?)})?.*?)\n\s*\n', re.MULTILINE | re.DOTALL) extTypes = {} def parseText(content, indent=None): # we need to keep only documenting text under the /** */ and --! c = re.sub(r'^\s*--[-!#](:?$|(.*))', '/** \g<1>*/', content, 0, re.MULTILINE) # convert --! comments to C-style ones 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 = re.sub(r'\s*\*', '', l, 1).rstrip() l = RE_DOXY_C_COMMENTS_I.sub('', l, 1).rstrip() ret += ''.ljust(indent or 0) + l + '\n' def repl_ref(m): return '[**{0}**]({1}#{0})'.format(m.group(1), extTypes.get(m.group(1),'')) c = re.sub(r'@ref\s+([\w-]+)', repl_ref, ret, 0, re.VERBOSE | re.MULTILINE) c = RE_DOXY_REF.sub(repl_ref, ret) if c is not None: ret = c c = re.sub(r'@class\s+([\w-]+)', '', ret, 0, re.VERBOSE | re.MULTILINE) c = RE_DOXY_CLASS.sub('', ret) if c is not None: ret = c c = re.sub(r'@brief\s+', '', ret, 0, re.VERBOSE | re.MULTILINE) c = RE_DOXY_BRIEF.sub('', ret) if c is not None: ret = c def repl_category(m): ret = '\n Categories: ' for l in m.group(1).split(','): ret += '[{0}](#{1}) '.format(l.strip(), urllib.quote_plus(l.strip())) return ret + '\n\n' c = re.sub(r'@category:\s+(.+)', repl_category, ret, re.MULTILINE) if c is not None: ret = c return ret Loading @@ -74,23 +77,23 @@ def parseModule(mname, content): global cpos cpos = 0 ret = '' m = re.search(r'^\s*IMPORTS\s*(.*?);', content, re.VERBOSE | re.DOTALL | re.MULTILINE) 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.finditer(r'^([,\s\w-]*?)FROM\s*([\w-]+)\s*({[^}]*}(?:\s+WITH\s+SUCCESSORS)?)?', s, re.VERBOSE | re.MULTILINE): for fm in RE_IMPORT_ELEMENTS.finditer(s): imName = fm.group(2) for im in re.finditer(r'[^,\s]+', fm.group(1), 0): for im in RE_IMPORT_ELEMENT_TYPE.finditer(fm.group(1)): extTypes[im.group(0)] = imName+'.md' ret += ' * **{}** *{}*<br/>\n'.format(imName, re.sub(r'\s+', ' ', fm.group(3) or '', 0, 0)) ret += ' * **{}** *{}*<br/>\n'.format(imName, RE_SPACES.sub(' ', fm.group(3) or '')) ret += parseText(s[pos:fm.start()], 3)+'\n' pos = fm.end() ret += parseText(s[pos:]) cpos = m.end() m = re.search(r'^\s*EXPORTS.*?;', content, re.VERBOSE | re.DOTALL | re.MULTILINE) m = RE_EXPORTS.search(content) if m is not None: if cpos < m.end(): cpos = m.end() Loading @@ -104,18 +107,18 @@ def parseModule(mname, content): if m.group(3) is not None: ret += 'Fields:\n' pos = 0 for fm in re.finditer('^\s*([\w-]+?)\s+(OCTET\s+STRING|BIT\s+STRING|[A-Z][.\w-]+)?(.*?)(?:,|$)', m.group(3), re.VERBOSE | re.MULTILINE | re.DOTALL): for fm in RE_FIELDS.finditer(m.group(3)): if fm.group(2) is not None: f = fm.group(1).strip() t = fm.group(2).strip() if re.match('^OCTET\s+STRING|BIT\s+STRING|BOOLEAN|INTEGER|FLOAT', t, re.VERBOSE|re.MULTILINE) is not None: if RE_BASIC_TYPES.match(t) is not None: ret += '* {0} **{1}** {2}<br>\n'.format(f, t, fm.group(3) or '') else: ret += '* {0} [**{1}**]({2}#{1}) {3}<br>\n'.format(f, t, extTypes.get(t,''), fm.group(3) or '') ret += parseText(fm.string[pos:fm.start()], 3) pos = fm.end() return ret + '```asn1\n' + re.sub(r'^\s*--.*\n', '', m.group(1).strip(), 0, re.MULTILINE) +'\n```\n\n' return ret + '```asn1\n' + RE_COMMENTS.sub('', m.group(1).strip()) +'\n```\n\n' pos = 0 for m in RE_TYPE.finditer(content[cpos:]): Loading @@ -128,10 +131,9 @@ def parseModule(mname, content): def parseAsn(outDir, content) : # iterate modules in the file pos= 0 RE_MODULE=re.compile(r'^\s*([A-Z][\w-]*)\s*({.*?})?\s*DEFINITIONS.*?::=\s*?BEGIN(.*)END', re.VERBOSE | re.MULTILINE | re.DOTALL) cnt = 0 for m in RE_MODULE.finditer(content): ret = '# ASN.1 module {}\n OID: _{}_\n'.format(m.group(1), re.sub(r'\s+', ' ', m.group(2))) ret = '# ASN.1 module {}\n OID: _{}_\n'.format(m.group(1), RE_SPACES.sub(' ', m.group(2))) ret += parseText(content[pos:m.start()]) + '\n' if m.group(3) is not None: ret += parseModule(m.group(1), m.group(3)) Loading Loading
asn2md.py +47 −45 Original line number Diff line number Diff line Loading @@ -5,67 +5,70 @@ import argparse # parse arguments import os.path # getting extension from file import sys # output and stuff import re # for regular expressions import urllib # ## extract doxygen-tag namespace RE_MODULE = re.compile( r'^(\w[\w-]*)[\s{](?:.|\n)*DEFINITIONS(?:.|\n)*::=\s*BEGIN' , re.IGNORECASE | re.VERBOSE | re.DOTALL | re.MULTILINE) RE_EXPORTS = re.compile( r'^\s*EXPORTS .*?;' , re.VERBOSE | re.DOTALL | re.MULTILINE) RE_MODULE = re.compile( r'^\s*([A-Z][\w-]*)\s*({.*?})?\s*DEFINITIONS.*?::=\s*?BEGIN(.*)END', re.VERBOSE | re.MULTILINE | re.DOTALL) RE_IMPORTS = re.compile( r'^\s*IMPORTS .*?;' , re.VERBOSE | re.DOTALL | re.MULTILINE) RE_SPACES = re.compile(r'\s+') RE_END = re.compile( r'^\s*END\s*$' , re.VERBOSE | re.MULTILINE) RE_COMMENTS = re.compile(r'^\s*--.*\n', re.MULTILINE) RE_DOXY_COMMENTS = re.compile( r'^\s*--[-#!]\s' , re.VERBOSE | re.MULTILINE) RE_BASIC_TYPES = re.compile(r'^OCTET\s+STRING|BIT\s+STRING|BOOLEAN|INTEGER|FLOAT') RE_DOXY_C_COMMENTS = re.compile( r'^\s*/\*\*\s(.*?)\*/' , re.VERBOSE | re.MULTILINE | re.DOTALL) RE_FIELDS = re.compile(r'^\s*([\w-]+?)\s+(OCTET\s+STRING|BIT\s+STRING|[A-Z][.\w-]+)?(.*?)(?:,|$)', re.MULTILINE | re.DOTALL) RE_COMMENT = re.compile( r'--.*?(?:--|\n)' , re.VERBOSE | re.MULTILINE) RE_EXPORTS = re.compile(r'^\s*EXPORTS.*?;', re.DOTALL | re.MULTILINE) RE_TYPE = re.compile(r'(([A-Z][\w-]*)\s*::=[\w \t]+(?:{(.*?)})?.*?)\n\s*\n' , re.VERBOSE | re.MULTILINE | re.DOTALL) RE_IMPORTS = re.compile(r'^\s*IMPORTS\s*(.*?);', re.DOTALL | re.MULTILINE) extTypes = {} 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*\*') def indentString(s, indent): lines = s.splitlines() s = '' for c in lines: s += ''.ljust(indent, ' ') + c + '\n' return s RE_DOXY_REF = re.compile(r'@ref\s+([\w-]+)') RE_DOXY_CLASS = re.compile(r'@class\s+([\w-]+)') RE_DOXY_BRIEF = re.compile(r'@brief\s+') RE_TYPE = re.compile(r'(([A-Z][\w-]*)\s*::=[\w \t]+(?:{(.*?)})?.*?)\n\s*\n', re.MULTILINE | re.DOTALL) extTypes = {} def parseText(content, indent=None): # we need to keep only documenting text under the /** */ and --! c = re.sub(r'^\s*--[-!#](:?$|(.*))', '/** \g<1>*/', content, 0, re.MULTILINE) # convert --! comments to C-style ones 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 = re.sub(r'\s*\*', '', l, 1).rstrip() l = RE_DOXY_C_COMMENTS_I.sub('', l, 1).rstrip() ret += ''.ljust(indent or 0) + l + '\n' def repl_ref(m): return '[**{0}**]({1}#{0})'.format(m.group(1), extTypes.get(m.group(1),'')) c = re.sub(r'@ref\s+([\w-]+)', repl_ref, ret, 0, re.VERBOSE | re.MULTILINE) c = RE_DOXY_REF.sub(repl_ref, ret) if c is not None: ret = c c = re.sub(r'@class\s+([\w-]+)', '', ret, 0, re.VERBOSE | re.MULTILINE) c = RE_DOXY_CLASS.sub('', ret) if c is not None: ret = c c = re.sub(r'@brief\s+', '', ret, 0, re.VERBOSE | re.MULTILINE) c = RE_DOXY_BRIEF.sub('', ret) if c is not None: ret = c def repl_category(m): ret = '\n Categories: ' for l in m.group(1).split(','): ret += '[{0}](#{1}) '.format(l.strip(), urllib.quote_plus(l.strip())) return ret + '\n\n' c = re.sub(r'@category:\s+(.+)', repl_category, ret, re.MULTILINE) if c is not None: ret = c return ret Loading @@ -74,23 +77,23 @@ def parseModule(mname, content): global cpos cpos = 0 ret = '' m = re.search(r'^\s*IMPORTS\s*(.*?);', content, re.VERBOSE | re.DOTALL | re.MULTILINE) 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.finditer(r'^([,\s\w-]*?)FROM\s*([\w-]+)\s*({[^}]*}(?:\s+WITH\s+SUCCESSORS)?)?', s, re.VERBOSE | re.MULTILINE): for fm in RE_IMPORT_ELEMENTS.finditer(s): imName = fm.group(2) for im in re.finditer(r'[^,\s]+', fm.group(1), 0): for im in RE_IMPORT_ELEMENT_TYPE.finditer(fm.group(1)): extTypes[im.group(0)] = imName+'.md' ret += ' * **{}** *{}*<br/>\n'.format(imName, re.sub(r'\s+', ' ', fm.group(3) or '', 0, 0)) ret += ' * **{}** *{}*<br/>\n'.format(imName, RE_SPACES.sub(' ', fm.group(3) or '')) ret += parseText(s[pos:fm.start()], 3)+'\n' pos = fm.end() ret += parseText(s[pos:]) cpos = m.end() m = re.search(r'^\s*EXPORTS.*?;', content, re.VERBOSE | re.DOTALL | re.MULTILINE) m = RE_EXPORTS.search(content) if m is not None: if cpos < m.end(): cpos = m.end() Loading @@ -104,18 +107,18 @@ def parseModule(mname, content): if m.group(3) is not None: ret += 'Fields:\n' pos = 0 for fm in re.finditer('^\s*([\w-]+?)\s+(OCTET\s+STRING|BIT\s+STRING|[A-Z][.\w-]+)?(.*?)(?:,|$)', m.group(3), re.VERBOSE | re.MULTILINE | re.DOTALL): for fm in RE_FIELDS.finditer(m.group(3)): if fm.group(2) is not None: f = fm.group(1).strip() t = fm.group(2).strip() if re.match('^OCTET\s+STRING|BIT\s+STRING|BOOLEAN|INTEGER|FLOAT', t, re.VERBOSE|re.MULTILINE) is not None: if RE_BASIC_TYPES.match(t) is not None: ret += '* {0} **{1}** {2}<br>\n'.format(f, t, fm.group(3) or '') else: ret += '* {0} [**{1}**]({2}#{1}) {3}<br>\n'.format(f, t, extTypes.get(t,''), fm.group(3) or '') ret += parseText(fm.string[pos:fm.start()], 3) pos = fm.end() return ret + '```asn1\n' + re.sub(r'^\s*--.*\n', '', m.group(1).strip(), 0, re.MULTILINE) +'\n```\n\n' return ret + '```asn1\n' + RE_COMMENTS.sub('', m.group(1).strip()) +'\n```\n\n' pos = 0 for m in RE_TYPE.finditer(content[cpos:]): Loading @@ -128,10 +131,9 @@ def parseModule(mname, content): def parseAsn(outDir, content) : # iterate modules in the file pos= 0 RE_MODULE=re.compile(r'^\s*([A-Z][\w-]*)\s*({.*?})?\s*DEFINITIONS.*?::=\s*?BEGIN(.*)END', re.VERBOSE | re.MULTILINE | re.DOTALL) cnt = 0 for m in RE_MODULE.finditer(content): ret = '# ASN.1 module {}\n OID: _{}_\n'.format(m.group(1), re.sub(r'\s+', ' ', m.group(2))) ret = '# ASN.1 module {}\n OID: _{}_\n'.format(m.group(1), RE_SPACES.sub(' ', m.group(2))) ret += parseText(content[pos:m.start()]) + '\n' if m.group(3) is not None: ret += parseModule(m.group(1), m.group(3)) Loading