Commit c42ea069 authored by Maxime Perrotin's avatar Maxime Perrotin

Pretty print ASN.1 files

parent 864c581d
/*
Pretty print ASN.1 files in HTML with anchors
Type names use underscores
*/
group icd_uper;
//delimiters "$", "$"
Infinity() ::= "&#8734"
NewLine() ::= "<br/>"
Orange() ::= "#FF8f00"
Blue() ::= "#379CEE"
ItemNumber(nIndex) ::= "Item #$nIndex$"
Integer() ::= "INTEGER"
BitString() ::= "BIT-STRING"
OctetString() ::= "OCTET-STRING"
Boolean() ::= "BOOLEAN"
Choice() ::= "CHOICE"
Enumerated() ::= "ENUMERATED"
IA5String() ::= "IA5String"
NumericString() ::= "NumericString"
NullType() ::= "NULL"
Real() ::= "REAL"
Sequence() ::= "SEQUENCE"
SequenceOf() ::= "SEQUENCE-OF"
// HTML formatting for the input ASN.1 grammar (new in version 3.2.x)
// Lower/greater than symbols (< and >) must be replaced with HTML code
LeftDiple() ::= "&lt;"
RightDiple() ::= "&gt;"
BlueTas(sBlueTasC,sTasName) ::= <<
<a name="ASN1_$sBlueTasC$">$sTasName$</a>
>>
Asn1Token(sKeyword) ::= <<
<b><font color="#5F9EA0">$sKeyword$</font></b>
>>
StringLiteral(sStringLiteral) ::= <<
<font color="#A31515">$sStringLiteral$</font>
>>
TasName(sTasName, sTasNameC) ::= <<
<a name="ASN1_$sTasNameC$"></a><font color="#B8860B"><b>$sTasNameC$</b></font></a>
>>
TasName2(sTasName, sTasNameC) ::= <<
<a href="#ASN1_$sTasNameC$"><font color="#000000">$sTasNameC$</font></a>
>>
Comment(sComment) ::= <<
<font color="#008000"><i>$sComment$</i></font>
>>
// End HTML formatting for the ACN grammar
RealSizeExplained() ::= <<
>>
IntSizeExplained() ::= <<
>>
ArraySizeExplained() ::= <<
>>
ZeroSizeExplained() ::= <<
>>
EmitEnumItem(sName, nValue) ::= <<
>>
EmitEnumItemWithComment(sName, nValue, sComment) ::= <<
>>
EmitEnumInternalContents(arrsItems) ::= <<
>>
// applicable to Integers, booleans, reals
EmitPrimitiveType(sColor, sTasName, sTasNameC, sAsnKindName, sMinBytes, sMaxBytes, sMaxBitsExplained, sCommentLine, sAsn1Constraints, sMinBits, sMaxBits, arrsComments) ::= <<
>>
EmitSequence(sColor, sTasName, sTasNameC, sMinBytes, sMaxBytes, sMaxBitsExplained, sCommentLine, arrsChildren, arrsComments) ::= <<
>>
EmmitSeqChild_RefType(sRefName, sRefNameC) ::= <<
>>
OddRow() ::= ""
EvenRow() ::= ""
EmmitSequenceChild(sCssClass, nIndex, sName, sComment, sOptionality, sType, sConstraint, sMin, sMax) ::= <<
>>
EmmitSequencePreambleSingleComment(nIndex, sOptChildName) ::= <<
>>
EmmitSequencePreambleComment(arrsOptChildren) ::= <<
>>
/* *** CHOICE ****/
EmitChoice(sColor, sTasName, sTasNameC, sMinBytes, sMaxBytes, sMaxBitsExplained, sCommentLine, arrsChildren, arrsComments) ::= <<
>>
EmmitChoiceChild(sCssClass, nIndex, sName, sComment, sType, sConstraint, sMin, sMax) ::= <<
>>
EmmitChoiceIndexSingleComment(nIndex, sChildName) ::= <<
>>
EmmitChoiceIndexComment(arrsOptChildren) ::= <<
>>
/* *********** CHOICE END ********** */
/* *********** SEQUENCE OF, OCTET STRING etc ********** */
EmitSizeable(sColor, sTasName, sTasNameC, sKind, sMinBytes, sMaxBytes, sMaxBitsExplained, sCommentLine, arrsRows, arrsComments) ::= <<
>>
EmitRowWith3Dots() ::= <<
>>
EmmitTass(sTypeContent) ::= <<
$sTypeContent$
&nbsp;<br/>
>>
EmmitModule(sModName, arrsComments, arrsTases) ::= <<
<div style="width: 100%">
<h2 >Module : $sModName$</h2>
<font face="Courier" color="DimGray"><pre>
$arrsComments;separator="\n"$
</pre></font>
$arrsTases;separator="\n"$
</div>
>>
EmmitFile(sAsnFileName, arrsModules) ::= <<
<div style="width: 100%">
<h1 >Asn1 file : $sAsnFileName$</h1>
$arrsModules;separator="\n"$
</div>
>>
EmmitFilePart2(sFileName, sAsn1Content) ::= <<
<div style="width: 100%">
<h1 >$sFileName$</h1>
<div style="width: 100%; white-space:pre; font-size:medium">
$sAsn1Content$
</div>
</div>
>>
RootHtml(arrsFiles1, arrsFiles2, bIntegerSizeMustBeExplained, bRealSizeMustBeExplained, bLengthSizeMustBeExplained, bWithComponentMustBeExplained, bZeroBitsMustBeExplained) ::= <<
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>ICD</title>
<style type="text/css">
h1
{
color: #033a7a;
}
h2
{
color: #033a7a;
}
</style>
</head>
<body>
$arrsFiles2;separator="\n"$
</body>
</html>
>>
......@@ -27,5 +27,6 @@
<file>fonts/Ubuntu-R.ttf</file>
<file>fonts/Ubuntu-RI.ttf</file>
<file>misc/lander.mp3</file>
<file>misc/pretty_print_asn1.stg</file>
</qresource>
</RCC>
......@@ -21,8 +21,9 @@ import distutils.spawn as spawn
import sys
import importlib
import logging
from PySide.QtCore import QProcess
from PySide.QtCore import QProcess, QFile
import icons
LOG = logging.getLogger(__name__)
terminal_formatter = logging.Formatter(fmt="[%(levelname)s] %(message)s")
......@@ -80,6 +81,7 @@ def parse_asn1(*files, **options):
ast_version = options.get('ast_version', ASN1.UniqueEnumeratedNames)
rename_policy = options.get('rename_policy', ASN1.NoRename)
flags = options.get('flags', [ASN1.AstOnly])
pprint = options.get('pretty_print', False)
assert isinstance(ast_version, ASN1)
assert isinstance(rename_policy, ASN1)
assert isinstance(flags, list)
......@@ -109,9 +111,21 @@ def parse_asn1(*files, **options):
stg = asn1scc_root + os.sep + 'python.stg'
if pprint:
# Generate an html file with pretty-printed ASN.1 types
stg_qrc = QFile(':misc/pretty_print_asn1.stg')
stg_qrc.open(1)
content = stg_qrc.readAll()
stgfile = tempdir + os.sep + 'pretty_print_asn1.stg'
with open(stgfile, 'w') as tmpfile:
tmpfile.write(content.data())
out_html = tempdir + os.sep + 'dataview.html'
html = ['-customIcdUper', stgfile + '::' + out_html]
else:
html = []
args = [arg0, '-customStgAstVerion', str(ast_version.value),
'-customStg', stg + '::' + filepath,
'-renamePolicy', str(rename_policy.value)] + list(*files)
'-renamePolicy', str(rename_policy.value)] + html + list(*files)
asn1scc = QProcess()
LOG.debug(os.getcwd())
LOG.debug(binary + ' ' + ' '.join(args))
......@@ -126,6 +140,9 @@ def parse_asn1(*files, **options):
else:
ast = importlib.import_module(filename)
AST[filename] = ast
if pprint:
# add the path to the optionally-gernated pretty-printed HTML file
ast.html = out_html
return ast
......
This diff is collapsed.
......@@ -1023,6 +1023,8 @@ class AST(object):
# Refs to the ASN.1 dataview AST (set with USE clauses)
self.dataview = None
self.asn1Modules = None
# DV is the Asn1scc imported module
self.DV = None
# ASN.1-defined constants (constants in Ada but variables in C)
# dictionnary: {ConstantName: type } - copied from dataview.py
self.asn1_constants = {}
......
......@@ -161,7 +161,8 @@ def set_global_DV(asn1_filenames):
DV = parse_asn1(tuple(asn1_filenames),
ast_version=ASN1.UniqueEnumeratedNames,
rename_policy=rename_policy,
flags=[ASN1.AstOnly])
flags=[ASN1.AstOnly],
pretty_print=True)
except (ImportError, NameError) as err:
# Can happen if DataView.py is not there
LOG.error('Error loading ASN.1 model')
......@@ -4362,6 +4363,7 @@ def pr_file(root):
# and not just after the ASN1 specific parsing
ast.dataview = types()
ast.asn1_constants = DV.variables
ast.DV = DV
return ast, errors, warnings
......
......@@ -2191,51 +2191,61 @@ class OG_MainWindow(QtGui.QMainWindow, object):
def set_asn1_view(self, ast):
''' Display the ASN.1 types in the dedicated scene '''
# Update the dock widget with ASN.1 files content
types = []
try:
for each in ast.asn1_filenames:
with open(each, 'r') as file_handler:
types.append('-- ' + each)
types.append(file_handler.read())
if types:
self.asn1_area.text.setPlainText('\n'.join(types))
# ASN.1 text area is read-only:
self.asn1_area.text.setTextInteractionFlags(
QtCore.Qt.TextBrowserInteraction)
text = unicode(self.asn1_area.text)
for each in chain(ast.dataview, ast.asn1_constants):
# Replace dash with underscore of all types and constants
text = re.sub(each, each.replace('-', '_'), text)
children = []
try:
children.extend(ast.dataview[each].type.Children)
except (AttributeError, KeyError):
pass
try:
children.extend(ast.dataview[each].type.EnumValues)
except (AttributeError, KeyError):
pass
for ch in children:
text = re.sub(ch, ch.replace('-', '_'), text)
self.asn1_area.text.setPlainText(text)
self.asn1_area.text.try_resize()
except IOError as err:
LOG.warning('ASN.1 file(s) could not be loaded : ' + str(err))
except AttributeError as err:
LOG.warning('No AST, check input files:' + str(err))
else:
# Update the data dictionary
item = self.datadict.topLevelItem(0)
item.takeChildren() # remove old children
for name, sort in ast.dataview.viewitems():
basic = ogParser.find_basic_type(sort.type).kind[:-4].upper()
QtGui.QTreeWidgetItem(item, [name.replace('-', '_'), basic])
item = self.datadict.topLevelItem(1)
item.takeChildren()
for name, sort in ast.asn1_constants.viewitems():
QtGui.QTreeWidgetItem(item, [name.replace('-', '_'),
sort.type.ReferencedTypeName])
self.datadict.resizeColumnToContents(0)
html_file = open(ast.DV.html, 'r')
html_content = html_file.read()
self.asn1_area.text.setHtml(html_content)
self.asn1_area.text.setTextInteractionFlags(
QtCore.Qt.TextBrowserInteraction)
self.asn1_area.text.try_resize()
# types = []
# try:
# for each in ast.asn1_filenames:
# with open(each, 'r') as file_handler:
# types.append('-- ' + each)
# types.append(file_handler.read())
# if types:
# self.asn1_area.text.setPlainText('\n'.join(types))
# # ASN.1 text area is read-only:
# self.asn1_area.text.setTextInteractionFlags(
# QtCore.Qt.TextBrowserInteraction)
# text = unicode(self.asn1_area.text)
# for each in chain(ast.dataview, ast.asn1_constants):
# # Replace dash with underscore of all types and constants
# text = re.sub(each, each.replace('-', '_'), text)
# children = []
# try:
# children.extend(ast.dataview[each].type.Children)
# except (AttributeError, KeyError):
# pass
# try:
# children.extend(ast.dataview[each].type.EnumValues)
# except (AttributeError, KeyError):
# pass
# for ch in children:
# text = re.sub(ch, ch.replace('-', '_'), text)
# self.asn1_area.text.setPlainText(text)
# self.asn1_area.text.try_resize()
# except IOError as err:
# LOG.warning('ASN.1 file(s) could not be loaded : ' + str(err))
# except AttributeError as err:
# LOG.warning('No AST, check input files:' + str(err))
# else:
# Update the data dictionary
item = self.datadict.topLevelItem(0)
item.takeChildren() # remove old children
for name, sort in ast.dataview.viewitems():
basic = ogParser.find_basic_type(sort.type).kind[:-4].upper()
new_item = QtGui.QTreeWidgetItem(item,
[name.replace('-', '_'),
basic])
# Save type pointer
new_item.setData(0, Qt.UserRole + 1, sort)
item = self.datadict.topLevelItem(1)
item.takeChildren()
for name, sort in ast.asn1_constants.viewitems():
QtGui.QTreeWidgetItem(item, [name.replace('-', '_'),
sort.type.ReferencedTypeName])
self.datadict.resizeColumnToContents(0)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment