();
String expandAllList= "var expandAllList= [";
boolean macroToggleFlag= false;
//
// Initialize variable for statement listing loop
//
DVStatements.Statement lastStatement= statements.getLastStatement();
int stmtListSize= statements.statementList.size();
int stmtNo= 0;
//
// Start main statement listing loop
//
listing+= "";
boolean eolFlag= true;
listing+= formatCode(" ");
for (DVStatements.Statement s : statements.statementList) {
String stmtName= "stmt_" + s.lines[0].lineNo.replace(".", "_");
String stmtListing= "";
if (s.warning || s.error)
for (DVStatements.Statement xs= s.lines[0].macroParent; xs != null; xs= xs.lines[0].macroParent)
if (! (xs.warning && xs.error))
macroExpansionList.add("stmt_" + xs.lines[0].lineNo.replace(".", "_"));
int macroNestPrev= macroNest;
macroNest= macroNestNext;
if (stmtNo+1 < stmtListSize)
macroNestNext= statements.statementList.get(stmtNo+1).lines[0].lineNo.split("\\.").length;
else
macroNestNext= 1;
String prefix= "";
if (macroNestPrev > macroNest) {
for (int i= 0; i < macroNestPrev-macroNest; i++)
stmtListing+= "
";
stmtListing+= "";
if (macroNest == 1) {
macroName= null;
this.classPrefix= "";
}
prefix= formatCode(" ");
eolFlag= true;
}
if (macroNestPrev < macroNest) {
stmtListing+= "
";
this.classPrefix= "x";
prefix= formatCode(" ");
eolFlag= true;
}
if (macroNest < macroNestNext) {
expandAllList+= "\"" + stmtName + "\",";
macroName= stmtName;
stmtListing+= (eolFlag ? "" : formatCode("\n")) +
"[+]
" +
"[-]
" +
formatCode(" ");
prefix= "";
eolFlag= true;
macroToggleFlag= true;
}
else
macroToggleFlag= false;
stmtListing+= prefix;
if (! eolFlag)
stmtListing+= formatCode("\n ");
stmtListing+= formatShortLong(stmtName, s.lines[0].lineNo, "_lns", "_lnl", 12) +
formatCode(" ") + formatShortLongRight(stmtName,
s.lines[0].macroExtendedName == "" ? "" : ("|" + s.lines[0].macroExtendedName.substring(1)),
"_mcs", "_mcl", 16) + " ";
if (s.symbol == null || s == lastStatement)
stmtListing+= formatCode(DVHtmlListing.getSpaces(lineOffset));
else {
if (s.opCodeProcessor != null) {
if (s.opCodeProcessor.getValueInParm() && ! s.opCodeProcessor.getNeedSection()) {
stmtListing+= formatCode(" ");
if (s.symbol.resultValue == null)
stmtListing+= formatShortLong(stmtName, "*** UNRESOLVED ***", "_ets", "_etl", maxHexCodeLength);
else if (s.symbol.resultValue.type == DVExpression.TokenType.STRING)
stmtListing+= formatShortLong(stmtName, "STRING", "_ets", "_etl", 3) +
formatShortLong(stmtName, " \"" + DVUtil.escapeString(s.symbol.resultValue.stringConstant) +
"\"", "_evs", "_evl", maxHexCodeLength-3);
else if (s.symbol.resultValue.type == DVExpression.TokenType.FLOAT)
stmtListing+= formatShortLong(stmtName, "FLOAT", "_ets", "_etl", 3) + formatShortLong(stmtName,
" " + s.symbol.resultValue.floatConstant.round(DVHtmlListing.precision).toString(),
"_evs", "_evl", maxHexCodeLength-3);
else if (s.symbol.resultValue.type == DVExpression.TokenType.EXTERNAL_VALUE ||
s.symbol.resultValue.type == DVExpression.TokenType.EXTERNAL_VALUE)
stmtListing+= formatShortLong(stmtName, s.symbol.resultValue.type.name(),
"_ets", "_etl", 3) + formatShortLong(stmtName, " " + DVUtil.formatHex(s.symbol.resultValue.intConstant, 8),
"_evs", "_evl", maxHexCodeLength-3);
else {
String type;
if (s.symbol.resultValue.type == DVExpression.TokenType.OFFSET)
type= "OFFSET [" + s.symbol.resultValue.getOffsetSection().name.image + "]";
else
type= s.symbol.resultValue.type.name();
stmtListing+= formatShortLong(stmtName, type, "_ets", "_etl", 3) + formatShortLong(stmtName,
" " + DVUtil.formatHex(s.symbol.resultValue.intConstant, 8),
"_evs", "_evl", maxHexCodeLength-3);
}
stmtListing+= formatCode(" ");
}
else {
stmtListing+= s.symbol.resultValue == null ? formatCode(" ") :
formatCode(" " + DVUtil.formatHex(s.symbol.resultValue.intConstant, 6) + " ");
if (s.genCode != null && s.genCode.hexCode != null)
stmtListing+= formatCode(s.genCode.hexCode + getSpaces(maxHexCodeLength-s.genCode.hexCode.length()) + " ");
else
stmtListing+= formatCode(DVHtmlListing.getSpaces(maxHexCodeLength) + " ");
}
}
else
stmtListing+= formatCode(" " + lineOffsetSpaces);
}
//
// Add statement details
//
if (s.genCode == null || s.genCode.details == null)
stmtListing+= formatCode(new String(s.lines[0].line));
else {
int x;
String d= s.genCode.details;
stmtListing+= "" + new String(s.lines[0].line) + "
";
stmtListing+= "\n";
if (d.charAt(d.length()-1) == '\n')
d= d.substring(0, d.length()-1);
while(d.length() > 0) {
x= d.indexOf('\n');
if (x == -1) {
stmtListing+= detailOffsetSpaces + d;
d= "";
}
else {
stmtListing+= detailOffsetSpaces + d.substring(0, x+1);
d= d.substring(x+1);
}
}
stmtListing+= "
";
}
for (int lineNo= 1; lineNo < s.lines.length; lineNo++)
stmtListing+= formatCode("\n ") + formatShortLong(stmtName, s.lines[lineNo].lineNo, "_lns", "_lnl", 12) +
formatCode(" ") + formatShortLong(stmtName, s.lines[lineNo].macroExtendedName == "" ? "" :
("|" + s.lines[lineNo].macroExtendedName.substring(1)), "_mcs", "_mcl", 16) +
formatCode(DVHtmlListing.getSpaces(lineOffset) +
new String(s.lines[lineNo].line));
//
// Add messages
//
s.firstPhaseMessages.addAll(s.secondPhaseMessages);
if (! s.firstPhaseMessages.isEmpty()) {
char oldC= ' ';
for (String m : s.firstPhaseMessages) {
char c= m.charAt(0);
if (c == ' ')
c= oldC;
else
oldC= c;
if (c == 'E')
stmtListing+= msgOffsetSpaces + "" +
escapeCode(m) +"
";
else if (c == 'W')
stmtListing+= msgOffsetSpaces + "" +
escapeCode(m) +"
";
else
stmtListing+= msgOffsetSpaces + formatCode(m);
}
}
eolFlag= false;
listing+= stmtListing;
stmtNo++;
}
for (int i= 0; i < this.classPrefix.length(); i++)
listing+= "
";
this.classPrefix= "";
listing+= "\n
";
//
// Add section list
//
listing+= "
";
int n= 0;
for (Map.Entry entry : statements.sections.sectionMap.entrySet()) {
DVSections.Section section= entry.getValue();
String id= String.format("sec_%d", n);
listing+= formatCode(" ") + formatShortLong(id, section.name.image,
"_tns", "_tnl", 16) + formatCode(" ") +
formatShortLong(id, section.type.name(), "_tts", "_ttl", 7) +
formatCode(" " + DVUtil.formatHex(section.alignValue, 5) + " " +
DVUtil.formatHex(BigInteger.valueOf(section.size), 8));
if (section.type == DVSections.SectionType.MMAP) {
listing+= formatCode("\n");
continue;
}
String type;
if (section.typeValue == null)
type= "UNRESOLVED";
else if (section.typeValue.equals(DVUtil.sectionTypeProgbits))
type= "PROGBITS ";
else if (section.typeValue.equals(DVUtil.sectionTypeNote))
type= "NOTE ";
else if (section.typeValue.equals(DVUtil.sectionTypeNobits))
type= "NOBITS ";
else
type= DVUtil.formatHex(section.typeValue, 8) + " ";
String attr= "";
if (section.attributeValue == null)
attr= "UNRESOLVED";
else {
if (! section.attributeValue.and(DVUtil.sectionAttributeAlloc).equals(BigInteger.ZERO))
attr+= "ALLOC+";
if (! section.attributeValue.and(DVUtil.sectionAttributeExec).equals(BigInteger.ZERO))
attr+= "EXECUTE+";
if (! section.attributeValue.and(DVUtil.sectionAttributeWrite).equals(BigInteger.ZERO))
attr+= "WRITE+";
if (attr.endsWith("+"))
attr= attr.substring(0, attr.length()-1);
else
attr= DVUtil.formatHex(section.attributeValue, 8);
}
listing+= formatCode(" ") + formatShortLong(id,
(section.externalName == null) ? "" : section.externalName, "_txs", "_txl", 16) +
formatCode(" ") + formatCode(" " + type + " " + attr + "\n");
n++;
}
listing+= "\n
";
//
// Add symbol list
//
listing+= "
";
n= 0;
for (Map.Entry entry : statements.symbols.symbolMap.entrySet()) {
DVSymbols.Symbol symbol= entry.getValue();
if (symbol.name.startsWith("#"))
continue;
String id= String.format("sym_%d", n);
String line= "[+]
" +
"[-]
";
line+= formatCode(" ") + formatShortLong(id, symbol.name, "_sns", "_snl", 24) +
formatCode(" ");
String xname= "";
if (symbol.isExternal || symbol.isCommon)
xname= symbol.externalName;
else if (symbol.isExported)
xname= symbol.exportName;
line+= formatShortLong(id, (xname == null) ? "" : xname, "_xns", "_xnl", 24);
String type= " ";
if (symbol.isExported) {
if (symbol.exportType == null)
type= "UNRESOLVED";
else {
if (symbol.exportType.equals(DVUtil.symbolTypeObject))
type= "OBJECT ";
else if(symbol.exportType.equals(DVUtil.symbolTypeFunc))
type= "FUNCTION ";
else if (symbol.exportType.equals(DVUtil.symbolTypeFile))
type= "FILE ";
else
type= DVUtil.formatHex(symbol.exportType, 2) + " ";
}
}
line+= formatCode(" " + type);
String bind= " ";
if (symbol.isExported) {
if (symbol.exportBind == null)
bind= "UNRESOLVED";
else {
if (symbol.exportBind.equals(DVUtil.symbolBindGlobal))
bind= "GLOBAL ";
else if (symbol.isLocalExported)
bind= "LOCAL ";
else
bind= DVUtil.formatHex(symbol.exportBind, 2) + " ";
}
}
else if (symbol.isExternal) {
if (symbol.externalBind == null)
bind= "UNRESOLVED";
else {
if (symbol.externalBind.equals(DVUtil.symbolBindGlobal))
bind= "GLOBAL ";
else if (symbol.externalBind.equals(DVUtil.symbolBindWeak))
bind= "WEAK ";
else
bind= DVUtil.formatHex(symbol.externalBind, 2) + " ";
}
}
line+= formatCode(" " + bind);
if (symbol.isCommon)
type= "COMMON";
else if(symbol.isExternal)
type= "EXTERNAL";
else if (symbol.owner == null)
type= "UDENFINED";
else
type= symbol.resultValue == null ? "UNRESOLVED" :
(symbol.resultValue.type != DVExpression.TokenType.OFFSET ? symbol.resultValue.type.name() :
"OFFSET [" + symbol.resultValue.getOffsetSection().name.image + "]");
line+= formatCode(" ") + formatShortLong(id, type, "_sts", "_stl", 28) +
formatCode(" " + DVUtil.formatHex(symbol.align, 5)) +
formatCode(" " + DVUtil.formatHex(symbol.length, 5) + " ") +
formatShortLong(id, DVUtil.formatHex(symbol.resultRepl == null ? null : symbol.resultRepl.intConstant, 5),
"_rns", "_rnl", 5);
String size= "";
if (symbol.isCommon)
size= DVUtil.formatHex(symbol.commonSize, 6);
else if (! symbol.isExternal)
size= (symbol.resultRepl == null) ? "UNRESOLVED" :
DVUtil.formatHex(symbol.resultRepl.intConstant.multiply(symbol.length), 6);
line+= formatCode(" ") + formatShortLong(id, size, "_sss", "_ssl", 6);
String value= "";
if (symbol.resultValue == null) {
if (symbol.isExternal || symbol.isCommon)
value= "";
else
value= "UNRESOLVED";
}
else if (symbol.resultValue.type == DVExpression.TokenType.STRING)
value= "\"" + DVUtil.escapeString(symbol.resultValue.stringConstant) + "\"";
else if (symbol.resultValue.type == DVExpression.TokenType.FLOAT)
value= symbol.resultValue.floatConstant.round(DVHtmlListing.precision).toString();
else
value= DVUtil.formatHex(symbol.resultValue.intConstant, 8);
line+= formatCode(" ") + formatShortLong(id, value, "_szs", "_szl", 30);
//
// Print symbol cross references
//
this.classPrefix= "x";
line+= "
";
line+= formatCode(" Defined in Statement: " + (symbol.owner == null ? " N/A" :
symbol.owner.lines[0].lineNo));
for (Map.Entry stmtEntry : symbol.referenceMap.entrySet()) {
line+= formatCode("\n Referenced in Statement: " + stmtEntry.getKey());
}
line+= "
";
this.classPrefix= "";
n++;
listing+= line;
}
listing+= "
";
//
// Add relocation
//
listing+= "
";
n= 0;
for (Map.Entry entry : statements.sections.sectionMap.entrySet()) {
DVSections.Section section= entry.getValue();
if (section.type == DVSections.SectionType.MMAP)
continue;
for (DVSections.Section.Relocation relocation : section.relocationList) {
String id= String.format("rel_%d", n);
listing+= formatCode(" ") +
formatShortLong(id, section.name.image, "_rts", "_rtl", 16) +
formatCode(" " + DVUtil.formatHex(relocation.offset, 8) + " " ) +
formatShortLong(id, relocation.symbol.name, "_rns", "_rnl", 24) + formatCode(" ") +
formatShortLong(id, (relocation.symbol.externalName == null) ? "UNDEFINED" :
relocation.symbol.externalName, "_rns", "_rnl", 24) + formatCode(" ") +
formatShortLong(id, relocation.relocationID.nameID, "_ris", "_ril", 18) +
formatCode(" " + DVUtil.formatHex(relocation.addEnd, 16) + "\n");
n++;
}
}
listing+= "\n
" +
formatCode("\n ----- End of DVASM listing -----\n\n" +
" CopyRight Roberti & Parau Enterprises, Inc. 2021\n\n" +
" This work is licensed under the Creative Commons Attribution-NoDerivatives 4.0 International License.\n" +
" To view a copy of this license, visit ") +
"http://creativecommons.org/licenses/by-nd/4.0" +
formatCode("\n" +
" or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.\n\n" +
" DVASM™ is a trademark of Roberti & Parau Enterprises, Inc.\n\n") +
DVHtmlListing.htmlTrailer_1 +
expandAllList.substring(0, expandAllList.length()-1) + "];\n" ;
//
// Add macro expansions for macro with warnnings or errors
//
for (String s : macroExpansionList)
listing+= " toggleMacroExpand('" + s + "');\n";
//
// Return the whole HTML listing file
//
return listing + DVHtmlListing.htmlTrailer_2;
}
//
// Macro enry for nested macro stack
//
class MacroEntry {
private MacroEntry(String name, boolean warnErrFlag) {
this.name= name;
this.warnErrFlag= warnErrFlag;
}
private String name;
private boolean warnErrFlag;
}
//
// Utility methods
//
private static String formatLog(String logEntry) {
String logPrint= "";
int x;
while((x= logEntry.indexOf('\n')) >= 0) {
if (logEntry.length() == 1)
return logPrint + "\n";
logPrint+= " " + logEntry.substring(0, x+1);
logEntry= logEntry.substring(x+1);
}
if (logPrint.toUpperCase().indexOf("WARNING") >= 0)
logPrint= "" + logPrint + "
";
else if (logPrint.toUpperCase().indexOf("ERROR") >= 0)
logPrint= "
" + logPrint + "
";
return logPrint;
}
private static String getSpaces(int noSpace) {
String pad= "";
for (int i= 0; i < noSpace; i++)
pad+= " ";
return pad;
}
private String formatCode(String field) {
return "" +
escapeCode(field) + "
";
}
private String formatShortLong(String stmtName, String field, String shortPostfix,
String longPostfix, int maxLength) {
if (field.length() > maxLength)
return "" + escapeCode(field.substring(0, maxLength)) + "
" + escapeCode(field) + "
";
return "" + escapeCode(field) +
getSpaces(maxLength-field.length()) + "
";
}
private String formatShortLongRight(String stmtName, String field, String shortPostfix,
String longPostfix, int maxLength) {
if (field.length() > maxLength)
return "" + escapeCode(field.substring(field.length()-maxLength)) + "
" + escapeCode(field) + "
";
return "" + escapeCode(field) +
getSpaces(maxLength-field.length()) + "
";
}
private String escapeCode(String source) {
return source.replaceAll("<", "<").replaceAll(">", ">");
}
//
// Class fields
//
private String classPrefix= "";
private static MathContext precision= new MathContext(42);
private static final String htmlHeader_1=
"\n" +
" \n" +
" \n" +
" " +
" ";
private static final String htmlHeader_2=
"\n" +
" \n" +
" \n" +
" \n" +
" \n" +
" \n" +
" \n" +
" " +
"
";
private static final String htmlTrailer_1=
"
\n" +
" \n" +
" \n" +
"\n";
}