mirror of
https://github.com/dmolony/DiskBrowser.git
synced 2025-02-18 05:30:29 +00:00
created XrefFormatter
This commit is contained in:
parent
a4aa18330c
commit
34c8c16aba
@ -1,12 +1,7 @@
|
|||||||
package com.bytezone.diskbrowser.applefile;
|
package com.bytezone.diskbrowser.applefile;
|
||||||
|
|
||||||
import static com.bytezone.diskbrowser.utilities.Utility.isPossibleNumber;
|
|
||||||
import static com.bytezone.diskbrowser.utilities.Utility.unsignedShort;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.TreeMap;
|
|
||||||
|
|
||||||
import com.bytezone.diskbrowser.utilities.Utility;
|
import com.bytezone.diskbrowser.utilities.Utility;
|
||||||
|
|
||||||
@ -14,40 +9,13 @@ import com.bytezone.diskbrowser.utilities.Utility;
|
|||||||
public class ApplesoftBasicProgram extends BasicProgram implements ApplesoftConstants
|
public class ApplesoftBasicProgram extends BasicProgram implements ApplesoftConstants
|
||||||
// -----------------------------------------------------------------------------------//
|
// -----------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
private static final String underline =
|
|
||||||
"----------------------------------------------------"
|
|
||||||
+ "----------------------------------------------";
|
|
||||||
private static final String NEWLINE = "\n";
|
|
||||||
|
|
||||||
private final List<SourceLine> sourceLines = new ArrayList<> ();
|
private final List<SourceLine> sourceLines = new ArrayList<> ();
|
||||||
private final int endPtr;
|
private final int endPtr;
|
||||||
private final int longestVarName;
|
|
||||||
|
|
||||||
private final Map<Integer, List<Integer>> gotoLines = new TreeMap<> ();
|
|
||||||
private final Map<Integer, List<Integer>> gosubLines = new TreeMap<> ();
|
|
||||||
private final Map<Integer, List<Integer>> constantsInt = new TreeMap<> ();
|
|
||||||
private final Map<Float, List<Integer>> constantsFloat = new TreeMap<> ();
|
|
||||||
|
|
||||||
private final Map<String, List<Integer>> callLines = new TreeMap<> ();
|
|
||||||
private final Map<String, List<Integer>> symbolLines = new TreeMap<> ();
|
|
||||||
private final Map<String, List<Integer>> functionLines = new TreeMap<> ();
|
|
||||||
private final Map<String, List<Integer>> arrayLines = new TreeMap<> ();
|
|
||||||
|
|
||||||
private final Map<String, List<String>> uniqueSymbols = new TreeMap<> ();
|
|
||||||
private final Map<String, List<String>> uniqueArrays = new TreeMap<> ();
|
|
||||||
|
|
||||||
private final List<Integer> stringsLine = new ArrayList<> ();
|
|
||||||
private final List<String> stringsText = new ArrayList<> ();
|
|
||||||
|
|
||||||
private final String formatLeft;
|
|
||||||
private final String formatLineNumber;
|
|
||||||
private final String formatRight;
|
|
||||||
|
|
||||||
private final int maxDigits;
|
|
||||||
|
|
||||||
private UserBasicFormatter userBasicFormatter;
|
private UserBasicFormatter userBasicFormatter;
|
||||||
private AppleBasicFormatter appleBasicFormatter;
|
private AppleBasicFormatter appleBasicFormatter;
|
||||||
private DebugBasicFormatter debugBasicFormatter;
|
private DebugBasicFormatter debugBasicFormatter;
|
||||||
|
private XrefFormatter xrefFormatter;
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
public ApplesoftBasicProgram (String name, byte[] buffer)
|
public ApplesoftBasicProgram (String name, byte[] buffer)
|
||||||
@ -61,24 +29,15 @@ public class ApplesoftBasicProgram extends BasicProgram implements ApplesoftCons
|
|||||||
{
|
{
|
||||||
SourceLine line = new SourceLine (this, buffer, ptr);
|
SourceLine line = new SourceLine (this, buffer, ptr);
|
||||||
sourceLines.add (line);
|
sourceLines.add (line);
|
||||||
checkXref (line);
|
|
||||||
ptr += line.length; // assumes lines are contiguous
|
ptr += line.length; // assumes lines are contiguous
|
||||||
}
|
}
|
||||||
|
|
||||||
endPtr = ptr; // record where the end-of-program marker is
|
endPtr = ptr; // record where the end-of-program marker is
|
||||||
|
|
||||||
longestVarName = getLongestName ();
|
|
||||||
maxDigits = getMaxDigits ();
|
|
||||||
|
|
||||||
// build format strings based on existing line numbers and variable names
|
|
||||||
formatLeft = longestVarName > 7 ? "%-" + longestVarName + "." + longestVarName + "s "
|
|
||||||
: "%-7.7s ";
|
|
||||||
formatRight = formatLeft.replace ("-", "");
|
|
||||||
formatLineNumber = "%" + maxDigits + "d ";
|
|
||||||
|
|
||||||
userBasicFormatter = new UserBasicFormatter (this, basicPreferences);
|
userBasicFormatter = new UserBasicFormatter (this, basicPreferences);
|
||||||
appleBasicFormatter = new AppleBasicFormatter (this, basicPreferences);
|
appleBasicFormatter = new AppleBasicFormatter (this, basicPreferences);
|
||||||
debugBasicFormatter = new DebugBasicFormatter (this, basicPreferences);
|
debugBasicFormatter = new DebugBasicFormatter (this, basicPreferences);
|
||||||
|
xrefFormatter = new XrefFormatter (this, basicPreferences);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
@ -109,66 +68,11 @@ public class ApplesoftBasicProgram extends BasicProgram implements ApplesoftCons
|
|||||||
appleBasicFormatter.format (text);
|
appleBasicFormatter.format (text);
|
||||||
|
|
||||||
if (basicPreferences.showAllXref)
|
if (basicPreferences.showAllXref)
|
||||||
addXref (text);
|
xrefFormatter.format (text);
|
||||||
|
|
||||||
return Utility.rtrim (text);
|
return Utility.rtrim (text);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
private void addXref (StringBuilder fullText)
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
{
|
|
||||||
if (basicPreferences.showSymbols)
|
|
||||||
{
|
|
||||||
if (!symbolLines.isEmpty ())
|
|
||||||
showSymbolsLeft (fullText, symbolLines, "Var");
|
|
||||||
|
|
||||||
if (!arrayLines.isEmpty ())
|
|
||||||
showSymbolsLeft (fullText, arrayLines, "Array");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (basicPreferences.showDuplicateSymbols)
|
|
||||||
{
|
|
||||||
if (!uniqueSymbols.isEmpty ())
|
|
||||||
showDuplicates (fullText, uniqueSymbols, "Var");
|
|
||||||
|
|
||||||
if (!uniqueArrays.isEmpty ())
|
|
||||||
showDuplicates (fullText, uniqueArrays, "Array");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (basicPreferences.showFunctions && !functionLines.isEmpty ())
|
|
||||||
showSymbolsLeft (fullText, functionLines, "Fnction");
|
|
||||||
|
|
||||||
if (basicPreferences.showConstants)
|
|
||||||
{
|
|
||||||
if (!constantsInt.isEmpty ())
|
|
||||||
showSymbolsRightInt (fullText, constantsInt, "Integer");
|
|
||||||
|
|
||||||
if (!constantsFloat.isEmpty ())
|
|
||||||
showSymbolsRightFloat (fullText, constantsFloat, "Float");
|
|
||||||
|
|
||||||
if (stringsLine.size () > 0)
|
|
||||||
{
|
|
||||||
heading (fullText, formatRight, "Line", "String");
|
|
||||||
for (int i = 0; i < stringsLine.size (); i++)
|
|
||||||
fullText.append (String.format (formatRight + "%s%n", stringsLine.get (i),
|
|
||||||
stringsText.get (i)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (basicPreferences.showXref)
|
|
||||||
{
|
|
||||||
if (!gosubLines.isEmpty ())
|
|
||||||
showSymbolsRight (fullText, gosubLines, "GOSUB");
|
|
||||||
|
|
||||||
if (!gotoLines.isEmpty ())
|
|
||||||
showSymbolsRight (fullText, gotoLines, "GOTO");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (basicPreferences.showCalls && !callLines.isEmpty ())
|
|
||||||
showSymbolsLeftRight (fullText, callLines, " CALL");
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
List<SourceLine> getSourceLines ()
|
List<SourceLine> getSourceLines ()
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
@ -190,378 +94,13 @@ public class ApplesoftBasicProgram extends BasicProgram implements ApplesoftCons
|
|||||||
return endPtr;
|
return endPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
private int getMaxDigits ()
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
{
|
|
||||||
if (sourceLines.size () == 0)
|
|
||||||
return 4; // anything non-zero
|
|
||||||
|
|
||||||
SourceLine lastLine = sourceLines.get (sourceLines.size () - 1);
|
|
||||||
return (lastLine.lineNumber + "").length ();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
private int getLongestName ()
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
{
|
|
||||||
int longestName = getLongestName (symbolLines, 0);
|
|
||||||
longestName = getLongestName (arrayLines, longestName);
|
|
||||||
longestName = getLongestName (functionLines, longestName);
|
|
||||||
|
|
||||||
return longestName;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
private void heading (StringBuilder fullText, String format, String... heading)
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
{
|
|
||||||
if (fullText.charAt (fullText.length () - 2) != '\n')
|
|
||||||
fullText.append (NEWLINE);
|
|
||||||
|
|
||||||
fullText.append (String.format (format, underline));
|
|
||||||
fullText.append (underline);
|
|
||||||
fullText.append (NEWLINE);
|
|
||||||
|
|
||||||
fullText.append (String.format (format, heading[0]));
|
|
||||||
if (heading.length == 1)
|
|
||||||
fullText.append ("Line numbers");
|
|
||||||
else
|
|
||||||
fullText.append (heading[1]);
|
|
||||||
|
|
||||||
fullText.append (NEWLINE);
|
|
||||||
fullText.append (String.format (format, underline));
|
|
||||||
fullText.append (underline);
|
|
||||||
fullText.append (NEWLINE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
private void showDuplicates (StringBuilder fullText, Map<String, List<String>> map,
|
|
||||||
String heading)
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
{
|
|
||||||
boolean headingShown = false;
|
|
||||||
for (String key : map.keySet ())
|
|
||||||
{
|
|
||||||
List<String> usage = map.get (key);
|
|
||||||
if (usage.size () > 1)
|
|
||||||
{
|
|
||||||
if (!headingShown)
|
|
||||||
{
|
|
||||||
headingShown = true;
|
|
||||||
heading (fullText, formatLeft, heading, "Duplicate Names");
|
|
||||||
}
|
|
||||||
|
|
||||||
String line = usage.toString ();
|
|
||||||
line = line.substring (1, line.length () - 1);
|
|
||||||
fullText.append (String.format ("%-6s %s%n", key, line));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
private void showSymbolsLeft (StringBuilder fullText, Map<String, List<Integer>> map,
|
|
||||||
String heading)
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
{
|
|
||||||
heading (fullText, formatLeft, heading);
|
|
||||||
|
|
||||||
for (String symbol : map.keySet ()) // left-justify strings
|
|
||||||
{
|
|
||||||
if (symbol.length () <= 7)
|
|
||||||
appendLineNumbers (fullText, String.format (formatLeft, symbol),
|
|
||||||
map.get (symbol));
|
|
||||||
else
|
|
||||||
appendLineNumbers (fullText, symbol + " ", map.get (symbol));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
private void showSymbolsLeftRight (StringBuilder fullText,
|
|
||||||
Map<String, List<Integer>> map, String heading)
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
{
|
|
||||||
heading (fullText, formatLeft, heading);
|
|
||||||
|
|
||||||
for (String symbol : map.keySet ()) // left-justify strings
|
|
||||||
{
|
|
||||||
if (isNumeric (symbol))
|
|
||||||
appendLineNumbers (fullText, String.format (formatRight, symbol),
|
|
||||||
map.get (symbol));
|
|
||||||
else if (symbol.length () <= 7)
|
|
||||||
appendLineNumbers (fullText, String.format (formatLeft, symbol),
|
|
||||||
map.get (symbol));
|
|
||||||
else
|
|
||||||
appendLineNumbers (fullText, symbol + " ", map.get (symbol));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
private boolean isNumeric (String value)
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
{
|
|
||||||
byte[] bytes = value.getBytes ();
|
|
||||||
int start = value.charAt (0) == Utility.ASCII_MINUS ? 1 : 0;
|
|
||||||
for (int i = start; i < bytes.length; i++)
|
|
||||||
if (!isPossibleNumber (bytes[i]))
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
private void showSymbolsRight (StringBuilder fullText, Map<Integer, List<Integer>> map,
|
|
||||||
String heading)
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
{
|
|
||||||
heading (fullText, formatRight, heading);
|
|
||||||
|
|
||||||
for (Integer symbol : map.keySet ()) // right-justify integers
|
|
||||||
appendLineNumbers (fullText, String.format (formatRight, symbol), map.get (symbol));
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
private void showSymbolsRightInt (StringBuilder fullText,
|
|
||||||
Map<Integer, List<Integer>> map, String heading)
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
{
|
|
||||||
heading (fullText, formatRight, heading);
|
|
||||||
|
|
||||||
for (int symbol : map.keySet ()) // right-justify integers
|
|
||||||
appendLineNumbers (fullText, String.format (formatRight, symbol), map.get (symbol));
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
private void showSymbolsRightFloat (StringBuilder fullText,
|
|
||||||
Map<Float, List<Integer>> map, String heading)
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
{
|
|
||||||
heading (fullText, formatRight, heading);
|
|
||||||
|
|
||||||
for (float symbol : map.keySet ()) // right-justify integers
|
|
||||||
appendLineNumbers (fullText, String.format (formatRight, symbol), map.get (symbol));
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
private void appendLineNumbers (StringBuilder fullText, String symbol,
|
|
||||||
List<Integer> lineNumbers)
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
{
|
|
||||||
StringBuilder text = new StringBuilder ();
|
|
||||||
text.append (symbol);
|
|
||||||
|
|
||||||
for (int lineNo : lineNumbers)
|
|
||||||
{
|
|
||||||
if (text.length () > underline.length () - maxDigits + longestVarName)
|
|
||||||
{
|
|
||||||
fullText.append (text);
|
|
||||||
fullText.append (NEWLINE);
|
|
||||||
text.setLength (0);
|
|
||||||
text.append (String.format (formatRight, ""));
|
|
||||||
}
|
|
||||||
text.append (String.format (formatLineNumber, lineNo));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (text.length () > longestVarName + 3)
|
|
||||||
fullText.append (text + "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
private int getLongestName (Map<String, List<Integer>> map, int longestName)
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
{
|
|
||||||
for (String symbol : map.keySet ())
|
|
||||||
if (symbol.length () > longestName)
|
|
||||||
longestName = symbol.length ();
|
|
||||||
|
|
||||||
return longestName;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
private void addHeader (StringBuilder pgm)
|
private void addHeader (StringBuilder pgm)
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
pgm.append ("Name : " + name + "\n");
|
pgm.append ("Name : " + name + "\n");
|
||||||
pgm.append (String.format ("Length : $%04X (%<,d)%n", buffer.length));
|
pgm.append (String.format ("Length : $%04X (%<,d)%n", buffer.length));
|
||||||
pgm.append (String.format ("Load at : $%04X (%<,d)%n%n", getLoadAddress ()));
|
pgm.append (String.format ("Load at : $%04X (%<,d)%n%n",
|
||||||
}
|
BasicFormatter.getLoadAddress (buffer)));
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
int getLoadAddress ()
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
{
|
|
||||||
return (buffer.length > 1) ? unsignedShort (buffer, 0) - getLineLength (0) : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
private int getLineLength (int ptr)
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
{
|
|
||||||
int linkField = unsignedShort (buffer, ptr);
|
|
||||||
if (linkField == 0)
|
|
||||||
return 2;
|
|
||||||
|
|
||||||
ptr += 4; // skip link field and line number
|
|
||||||
int length = 5;
|
|
||||||
|
|
||||||
while (ptr < buffer.length && buffer[ptr++] != 0)
|
|
||||||
length++;
|
|
||||||
|
|
||||||
assert length == ptr;
|
|
||||||
return length;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
private void checkXref (SourceLine line)
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
{
|
|
||||||
for (SubLine subline : line.sublines)
|
|
||||||
{
|
|
||||||
for (String symbol : subline.getVariables ())
|
|
||||||
checkVar (symbol, line.lineNumber, symbolLines, uniqueSymbols);
|
|
||||||
for (String symbol : subline.getArrays ())
|
|
||||||
checkVar (symbol, line.lineNumber, arrayLines, uniqueArrays);
|
|
||||||
for (String symbol : subline.getFunctions ())
|
|
||||||
checkFunction (line.lineNumber, symbol);
|
|
||||||
for (int targetLine : subline.getGosubLines ())
|
|
||||||
addNumberInt (line.lineNumber, targetLine, gosubLines);
|
|
||||||
for (int targetLine : subline.getGotoLines ())
|
|
||||||
addNumberInt (line.lineNumber, targetLine, gotoLines);
|
|
||||||
for (int num : subline.getConstantsInt ())
|
|
||||||
addNumberInt (line.lineNumber, num, constantsInt);
|
|
||||||
for (float num : subline.getConstantsFloat ())
|
|
||||||
addNumberFloat (line.lineNumber, num, constantsFloat);
|
|
||||||
if (subline.callTarget != null)
|
|
||||||
addString (line.lineNumber, subline.callTarget, callLines);
|
|
||||||
for (String s : subline.getStringsText ())
|
|
||||||
{
|
|
||||||
stringsText.add (s);
|
|
||||||
stringsLine.add (line.lineNumber);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
private void checkVar (String var, int lineNumber, Map<String, List<Integer>> map,
|
|
||||||
Map<String, List<String>> unique)
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
{
|
|
||||||
List<Integer> lines = map.get (var);
|
|
||||||
if (lines == null)
|
|
||||||
{
|
|
||||||
lines = new ArrayList<> ();
|
|
||||||
map.put (var, lines);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lines.size () == 0)
|
|
||||||
lines.add (lineNumber);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int lastLine = lines.get (lines.size () - 1);
|
|
||||||
if (lastLine != lineNumber)
|
|
||||||
lines.add (lineNumber);
|
|
||||||
}
|
|
||||||
|
|
||||||
checkUniqueName (var, unique);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
private void checkFunction (int sourceLine, String var)
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
{
|
|
||||||
List<Integer> lines = functionLines.get (var);
|
|
||||||
if (lines == null)
|
|
||||||
{
|
|
||||||
lines = new ArrayList<> ();
|
|
||||||
functionLines.put (var, lines);
|
|
||||||
}
|
|
||||||
|
|
||||||
addLine (lines, sourceLine);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
private void addNumberInt (int sourceLine, Integer key, Map<Integer, List<Integer>> map)
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
{
|
|
||||||
List<Integer> lines = map.get (key);
|
|
||||||
if (lines == null)
|
|
||||||
{
|
|
||||||
lines = new ArrayList<> ();
|
|
||||||
map.put (key, lines);
|
|
||||||
}
|
|
||||||
|
|
||||||
addLine (lines, sourceLine);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
private void addNumberFloat (int sourceLine, Float key, Map<Float, List<Integer>> map)
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
{
|
|
||||||
List<Integer> lines = map.get (key);
|
|
||||||
if (lines == null)
|
|
||||||
{
|
|
||||||
lines = new ArrayList<> ();
|
|
||||||
map.put (key, lines);
|
|
||||||
}
|
|
||||||
|
|
||||||
addLine (lines, sourceLine);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
private void addString (int sourceLine, String key, Map<String, List<Integer>> map)
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
{
|
|
||||||
List<Integer> lines = map.get (key);
|
|
||||||
if (lines == null)
|
|
||||||
{
|
|
||||||
lines = new ArrayList<> ();
|
|
||||||
map.put (key, lines);
|
|
||||||
}
|
|
||||||
|
|
||||||
addLine (lines, sourceLine);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
private void addLine (List<Integer> lines, int lineNumber)
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
{
|
|
||||||
if (lines.size () == 0)
|
|
||||||
lines.add (lineNumber);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int lastLine = lines.get (lines.size () - 1);
|
|
||||||
if (lastLine != lineNumber)
|
|
||||||
lines.add (lineNumber);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
private void checkUniqueName (String symbol, Map<String, List<String>> map)
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
{
|
|
||||||
String uniqueName = getUniqueName (symbol);
|
|
||||||
|
|
||||||
List<String> usage = map.get (uniqueName);
|
|
||||||
if (usage == null)
|
|
||||||
{
|
|
||||||
usage = new ArrayList<> ();
|
|
||||||
map.put (uniqueName, usage);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!usage.contains (symbol))
|
|
||||||
usage.add (symbol);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
private String getUniqueName (String symbolName)
|
|
||||||
// ---------------------------------------------------------------------------------//
|
|
||||||
{
|
|
||||||
int ptr = symbolName.length () - 1;
|
|
||||||
|
|
||||||
if (symbolName.charAt (ptr) == Utility.ASCII_DOLLAR // string
|
|
||||||
|| symbolName.charAt (ptr) == Utility.ASCII_PERCENT) // integer
|
|
||||||
ptr--;
|
|
||||||
|
|
||||||
return (ptr <= 1) ? symbolName
|
|
||||||
: symbolName.substring (0, 2) + symbolName.substring (ptr + 1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,5 +1,7 @@
|
|||||||
package com.bytezone.diskbrowser.applefile;
|
package com.bytezone.diskbrowser.applefile;
|
||||||
|
|
||||||
|
import static com.bytezone.diskbrowser.utilities.Utility.unsignedShort;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.bytezone.diskbrowser.gui.BasicPreferences;
|
import com.bytezone.diskbrowser.gui.BasicPreferences;
|
||||||
@ -35,6 +37,33 @@ public abstract class BasicFormatter implements ApplesoftConstants
|
|||||||
int getLoadAddress ()
|
int getLoadAddress ()
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
return program.getLoadAddress ();
|
// return program.getLoadAddress ();
|
||||||
|
return getLoadAddress (buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
static int getLoadAddress (byte[] buffer)
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
return (buffer.length > 1) ? unsignedShort (buffer, 0) - getLineLength (buffer, 0)
|
||||||
|
: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
private static int getLineLength (byte[] buffer, int ptr)
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
int linkField = unsignedShort (buffer, ptr);
|
||||||
|
if (linkField == 0)
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
ptr += 4; // skip link field and line number
|
||||||
|
int length = 5;
|
||||||
|
|
||||||
|
while (ptr < buffer.length && buffer[ptr++] != 0)
|
||||||
|
length++;
|
||||||
|
|
||||||
|
assert length == ptr;
|
||||||
|
return length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
460
src/com/bytezone/diskbrowser/applefile/XrefFormatter.java
Normal file
460
src/com/bytezone/diskbrowser/applefile/XrefFormatter.java
Normal file
@ -0,0 +1,460 @@
|
|||||||
|
package com.bytezone.diskbrowser.applefile;
|
||||||
|
|
||||||
|
import static com.bytezone.diskbrowser.utilities.Utility.isPossibleNumber;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
|
import com.bytezone.diskbrowser.gui.BasicPreferences;
|
||||||
|
import com.bytezone.diskbrowser.utilities.Utility;
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------------//
|
||||||
|
public class XrefFormatter extends BasicFormatter
|
||||||
|
// -----------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
private static final String underline =
|
||||||
|
"----------------------------------------------------"
|
||||||
|
+ "----------------------------------------------";
|
||||||
|
|
||||||
|
private final Map<Integer, List<Integer>> gotoLines = new TreeMap<> ();
|
||||||
|
private final Map<Integer, List<Integer>> gosubLines = new TreeMap<> ();
|
||||||
|
private final Map<Integer, List<Integer>> constantsInt = new TreeMap<> ();
|
||||||
|
private final Map<Float, List<Integer>> constantsFloat = new TreeMap<> ();
|
||||||
|
|
||||||
|
private final Map<String, List<Integer>> callLines = new TreeMap<> ();
|
||||||
|
private final Map<String, List<Integer>> symbolLines = new TreeMap<> ();
|
||||||
|
private final Map<String, List<Integer>> functionLines = new TreeMap<> ();
|
||||||
|
private final Map<String, List<Integer>> arrayLines = new TreeMap<> ();
|
||||||
|
|
||||||
|
private final Map<String, List<String>> uniqueSymbols = new TreeMap<> ();
|
||||||
|
private final Map<String, List<String>> uniqueArrays = new TreeMap<> ();
|
||||||
|
|
||||||
|
private final List<Integer> stringsLine = new ArrayList<> ();
|
||||||
|
private final List<String> stringsText = new ArrayList<> ();
|
||||||
|
|
||||||
|
private final String formatLeft;
|
||||||
|
private final String formatLineNumber;
|
||||||
|
private final String formatRight;
|
||||||
|
|
||||||
|
private final int longestVarName;
|
||||||
|
|
||||||
|
private final int maxDigits;
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
public XrefFormatter (ApplesoftBasicProgram program, BasicPreferences basicPreferences)
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
super (program, basicPreferences);
|
||||||
|
|
||||||
|
for (SourceLine sourceLine : program.getSourceLines ())
|
||||||
|
checkXref (sourceLine);
|
||||||
|
|
||||||
|
longestVarName = getLongestName ();
|
||||||
|
maxDigits = getMaxDigits ();
|
||||||
|
|
||||||
|
// build format strings based on existing line numbers and variable names
|
||||||
|
formatLeft = longestVarName > 7 ? "%-" + longestVarName + "." + longestVarName + "s "
|
||||||
|
: "%-7.7s ";
|
||||||
|
formatRight = formatLeft.replace ("-", "");
|
||||||
|
formatLineNumber = "%" + maxDigits + "d ";
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
void checkXref (SourceLine line)
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
for (SubLine subline : line.sublines)
|
||||||
|
{
|
||||||
|
for (String symbol : subline.getVariables ())
|
||||||
|
checkVar (symbol, line.lineNumber, symbolLines, uniqueSymbols);
|
||||||
|
for (String symbol : subline.getArrays ())
|
||||||
|
checkVar (symbol, line.lineNumber, arrayLines, uniqueArrays);
|
||||||
|
for (String symbol : subline.getFunctions ())
|
||||||
|
checkFunction (line.lineNumber, symbol);
|
||||||
|
for (int targetLine : subline.getGosubLines ())
|
||||||
|
addNumberInt (line.lineNumber, targetLine, gosubLines);
|
||||||
|
for (int targetLine : subline.getGotoLines ())
|
||||||
|
addNumberInt (line.lineNumber, targetLine, gotoLines);
|
||||||
|
for (int num : subline.getConstantsInt ())
|
||||||
|
addNumberInt (line.lineNumber, num, constantsInt);
|
||||||
|
for (float num : subline.getConstantsFloat ())
|
||||||
|
addNumberFloat (line.lineNumber, num, constantsFloat);
|
||||||
|
if (subline.callTarget != null)
|
||||||
|
addString (line.lineNumber, subline.callTarget, callLines);
|
||||||
|
for (String s : subline.getStringsText ())
|
||||||
|
{
|
||||||
|
stringsText.add (s);
|
||||||
|
stringsLine.add (line.lineNumber);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
@Override
|
||||||
|
public void format (StringBuilder fullText)
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
if (basicPreferences.showSymbols)
|
||||||
|
{
|
||||||
|
if (!symbolLines.isEmpty ())
|
||||||
|
showSymbolsLeft (fullText, symbolLines, "Var");
|
||||||
|
|
||||||
|
if (!arrayLines.isEmpty ())
|
||||||
|
showSymbolsLeft (fullText, arrayLines, "Array");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (basicPreferences.showDuplicateSymbols)
|
||||||
|
{
|
||||||
|
if (!uniqueSymbols.isEmpty ())
|
||||||
|
showDuplicates (fullText, uniqueSymbols, "Var");
|
||||||
|
|
||||||
|
if (!uniqueArrays.isEmpty ())
|
||||||
|
showDuplicates (fullText, uniqueArrays, "Array");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (basicPreferences.showFunctions && !functionLines.isEmpty ())
|
||||||
|
showSymbolsLeft (fullText, functionLines, "Fnction");
|
||||||
|
|
||||||
|
if (basicPreferences.showConstants)
|
||||||
|
{
|
||||||
|
if (!constantsInt.isEmpty ())
|
||||||
|
showSymbolsRightInt (fullText, constantsInt, "Integer");
|
||||||
|
|
||||||
|
if (!constantsFloat.isEmpty ())
|
||||||
|
showSymbolsRightFloat (fullText, constantsFloat, "Float");
|
||||||
|
|
||||||
|
if (stringsLine.size () > 0)
|
||||||
|
{
|
||||||
|
heading (fullText, formatRight, "Line", "String");
|
||||||
|
for (int i = 0; i < stringsLine.size (); i++)
|
||||||
|
fullText.append (String.format (formatRight + "%s%n", stringsLine.get (i),
|
||||||
|
stringsText.get (i)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (basicPreferences.showXref)
|
||||||
|
{
|
||||||
|
if (!gosubLines.isEmpty ())
|
||||||
|
showSymbolsRight (fullText, gosubLines, "GOSUB");
|
||||||
|
|
||||||
|
if (!gotoLines.isEmpty ())
|
||||||
|
showSymbolsRight (fullText, gotoLines, "GOTO");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (basicPreferences.showCalls && !callLines.isEmpty ())
|
||||||
|
showSymbolsLeftRight (fullText, callLines, " CALL");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
private int getMaxDigits ()
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
if (sourceLines.size () == 0)
|
||||||
|
return 4; // anything non-zero
|
||||||
|
|
||||||
|
SourceLine lastLine = sourceLines.get (sourceLines.size () - 1);
|
||||||
|
return (lastLine.lineNumber + "").length ();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
private int getLongestName ()
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
int longestName = getLongestName (symbolLines, 0);
|
||||||
|
longestName = getLongestName (arrayLines, longestName);
|
||||||
|
longestName = getLongestName (functionLines, longestName);
|
||||||
|
|
||||||
|
return longestName;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
private int getLongestName (Map<String, List<Integer>> map, int longestName)
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
for (String symbol : map.keySet ())
|
||||||
|
if (symbol.length () > longestName)
|
||||||
|
longestName = symbol.length ();
|
||||||
|
|
||||||
|
return longestName;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
private void heading (StringBuilder fullText, String format, String... heading)
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
if (fullText.charAt (fullText.length () - 2) != '\n')
|
||||||
|
fullText.append (NEWLINE);
|
||||||
|
|
||||||
|
fullText.append (String.format (format, underline));
|
||||||
|
fullText.append (underline);
|
||||||
|
fullText.append (NEWLINE);
|
||||||
|
|
||||||
|
fullText.append (String.format (format, heading[0]));
|
||||||
|
if (heading.length == 1)
|
||||||
|
fullText.append ("Line numbers");
|
||||||
|
else
|
||||||
|
fullText.append (heading[1]);
|
||||||
|
|
||||||
|
fullText.append (NEWLINE);
|
||||||
|
fullText.append (String.format (format, underline));
|
||||||
|
fullText.append (underline);
|
||||||
|
fullText.append (NEWLINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
private void showDuplicates (StringBuilder fullText, Map<String, List<String>> map,
|
||||||
|
String heading)
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
boolean headingShown = false;
|
||||||
|
for (String key : map.keySet ())
|
||||||
|
{
|
||||||
|
List<String> usage = map.get (key);
|
||||||
|
if (usage.size () > 1)
|
||||||
|
{
|
||||||
|
if (!headingShown)
|
||||||
|
{
|
||||||
|
headingShown = true;
|
||||||
|
heading (fullText, formatLeft, heading, "Duplicate Names");
|
||||||
|
}
|
||||||
|
|
||||||
|
String line = usage.toString ();
|
||||||
|
line = line.substring (1, line.length () - 1);
|
||||||
|
fullText.append (String.format ("%-6s %s%n", key, line));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
private void showSymbolsLeft (StringBuilder fullText, Map<String, List<Integer>> map,
|
||||||
|
String heading)
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
heading (fullText, formatLeft, heading);
|
||||||
|
|
||||||
|
for (String symbol : map.keySet ()) // left-justify strings
|
||||||
|
{
|
||||||
|
if (symbol.length () <= 7)
|
||||||
|
appendLineNumbers (fullText, String.format (formatLeft, symbol),
|
||||||
|
map.get (symbol));
|
||||||
|
else
|
||||||
|
appendLineNumbers (fullText, symbol + " ", map.get (symbol));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
private void showSymbolsLeftRight (StringBuilder fullText,
|
||||||
|
Map<String, List<Integer>> map, String heading)
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
heading (fullText, formatLeft, heading);
|
||||||
|
|
||||||
|
for (String symbol : map.keySet ()) // left-justify strings
|
||||||
|
{
|
||||||
|
if (isNumeric (symbol))
|
||||||
|
appendLineNumbers (fullText, String.format (formatRight, symbol),
|
||||||
|
map.get (symbol));
|
||||||
|
else if (symbol.length () <= 7)
|
||||||
|
appendLineNumbers (fullText, String.format (formatLeft, symbol),
|
||||||
|
map.get (symbol));
|
||||||
|
else
|
||||||
|
appendLineNumbers (fullText, symbol + " ", map.get (symbol));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
private void showSymbolsRight (StringBuilder fullText, Map<Integer, List<Integer>> map,
|
||||||
|
String heading)
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
heading (fullText, formatRight, heading);
|
||||||
|
|
||||||
|
for (Integer symbol : map.keySet ()) // right-justify integers
|
||||||
|
appendLineNumbers (fullText, String.format (formatRight, symbol), map.get (symbol));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
private void showSymbolsRightInt (StringBuilder fullText,
|
||||||
|
Map<Integer, List<Integer>> map, String heading)
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
heading (fullText, formatRight, heading);
|
||||||
|
|
||||||
|
for (int symbol : map.keySet ()) // right-justify integers
|
||||||
|
appendLineNumbers (fullText, String.format (formatRight, symbol), map.get (symbol));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
private void showSymbolsRightFloat (StringBuilder fullText,
|
||||||
|
Map<Float, List<Integer>> map, String heading)
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
heading (fullText, formatRight, heading);
|
||||||
|
|
||||||
|
for (float symbol : map.keySet ()) // right-justify integers
|
||||||
|
appendLineNumbers (fullText, String.format (formatRight, symbol), map.get (symbol));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
private boolean isNumeric (String value)
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
byte[] bytes = value.getBytes ();
|
||||||
|
int start = value.charAt (0) == Utility.ASCII_MINUS ? 1 : 0;
|
||||||
|
for (int i = start; i < bytes.length; i++)
|
||||||
|
if (!isPossibleNumber (bytes[i]))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
private void appendLineNumbers (StringBuilder fullText, String symbol,
|
||||||
|
List<Integer> lineNumbers)
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
StringBuilder text = new StringBuilder ();
|
||||||
|
text.append (symbol);
|
||||||
|
|
||||||
|
for (int lineNo : lineNumbers)
|
||||||
|
{
|
||||||
|
if (text.length () > underline.length () - maxDigits + longestVarName)
|
||||||
|
{
|
||||||
|
fullText.append (text);
|
||||||
|
fullText.append (NEWLINE);
|
||||||
|
text.setLength (0);
|
||||||
|
text.append (String.format (formatRight, ""));
|
||||||
|
}
|
||||||
|
text.append (String.format (formatLineNumber, lineNo));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (text.length () > longestVarName + 3)
|
||||||
|
fullText.append (text + "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
private void checkVar (String var, int lineNumber, Map<String, List<Integer>> map,
|
||||||
|
Map<String, List<String>> unique)
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
List<Integer> lines = map.get (var);
|
||||||
|
if (lines == null)
|
||||||
|
{
|
||||||
|
lines = new ArrayList<> ();
|
||||||
|
map.put (var, lines);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lines.size () == 0)
|
||||||
|
lines.add (lineNumber);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int lastLine = lines.get (lines.size () - 1);
|
||||||
|
if (lastLine != lineNumber)
|
||||||
|
lines.add (lineNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
checkUniqueName (var, unique);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
private void checkFunction (int sourceLine, String var)
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
List<Integer> lines = functionLines.get (var);
|
||||||
|
if (lines == null)
|
||||||
|
{
|
||||||
|
lines = new ArrayList<> ();
|
||||||
|
functionLines.put (var, lines);
|
||||||
|
}
|
||||||
|
|
||||||
|
addLine (lines, sourceLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
private void addNumberInt (int sourceLine, Integer key, Map<Integer, List<Integer>> map)
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
List<Integer> lines = map.get (key);
|
||||||
|
if (lines == null)
|
||||||
|
{
|
||||||
|
lines = new ArrayList<> ();
|
||||||
|
map.put (key, lines);
|
||||||
|
}
|
||||||
|
|
||||||
|
addLine (lines, sourceLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
private void addNumberFloat (int sourceLine, Float key, Map<Float, List<Integer>> map)
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
List<Integer> lines = map.get (key);
|
||||||
|
if (lines == null)
|
||||||
|
{
|
||||||
|
lines = new ArrayList<> ();
|
||||||
|
map.put (key, lines);
|
||||||
|
}
|
||||||
|
|
||||||
|
addLine (lines, sourceLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
private void addString (int sourceLine, String key, Map<String, List<Integer>> map)
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
List<Integer> lines = map.get (key);
|
||||||
|
if (lines == null)
|
||||||
|
{
|
||||||
|
lines = new ArrayList<> ();
|
||||||
|
map.put (key, lines);
|
||||||
|
}
|
||||||
|
|
||||||
|
addLine (lines, sourceLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
private void addLine (List<Integer> lines, int lineNumber)
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
if (lines.size () == 0)
|
||||||
|
lines.add (lineNumber);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int lastLine = lines.get (lines.size () - 1);
|
||||||
|
if (lastLine != lineNumber)
|
||||||
|
lines.add (lineNumber);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
private void checkUniqueName (String symbol, Map<String, List<String>> map)
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
String uniqueName = getUniqueName (symbol);
|
||||||
|
|
||||||
|
List<String> usage = map.get (uniqueName);
|
||||||
|
if (usage == null)
|
||||||
|
{
|
||||||
|
usage = new ArrayList<> ();
|
||||||
|
map.put (uniqueName, usage);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!usage.contains (symbol))
|
||||||
|
usage.add (symbol);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
private String getUniqueName (String symbolName)
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
int ptr = symbolName.length () - 1;
|
||||||
|
|
||||||
|
if (symbolName.charAt (ptr) == Utility.ASCII_DOLLAR // string
|
||||||
|
|| symbolName.charAt (ptr) == Utility.ASCII_PERCENT) // integer
|
||||||
|
ptr--;
|
||||||
|
|
||||||
|
return (ptr <= 1) ? symbolName
|
||||||
|
: symbolName.substring (0, 2) + symbolName.substring (ptr + 1);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user