Skip to content

Commit 7032942

Browse files
committed
fixes an issue in the logisim hex reader; closes #642
1 parent 8a8f126 commit 7032942

File tree

2 files changed

+41
-32
lines changed

2 files changed

+41
-32
lines changed

src/main/java/de/neemann/digital/core/memory/importer/LogisimReader.java

Lines changed: 40 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
import de.neemann.digital.lang.Lang;
1010

1111
import java.io.*;
12-
import java.util.StringTokenizer;
12+
13+
import static java.io.StreamTokenizer.*;
1314

1415
/**
1516
* Reader to read the original Logisim hex file format
@@ -38,47 +39,55 @@ public LogisimReader(Reader reader) {
3839

3940
@Override
4041
public void read(ValueArray valueArray) throws IOException {
41-
try (BufferedReader br = new BufferedReader(reader)) {
42-
String header = br.readLine();
42+
try (BufferedReader bufferedReader = new BufferedReader(reader)) {
43+
String header = bufferedReader.readLine();
4344
if (header == null || !header.equals("v2.0 raw"))
4445
throw new IOException(Lang.get("err_invalidFileFormat"));
45-
String line;
46-
int pos = 0;
47-
while ((line = br.readLine()) != null) {
48-
try {
49-
int p = line.indexOf('#');
50-
if (p >= 0)
51-
line = line.substring(0, p).trim();
52-
else
53-
line = line.trim();
5446

55-
StringTokenizer tc = new StringTokenizer(line, " \t");
56-
while (tc.hasMoreTokens()) {
57-
String num = tc.nextToken();
58-
int rle = 1;
59-
p = num.indexOf('*');
60-
if (p > 0) {
61-
rle = Integer.parseInt(num.substring(0, p));
62-
num = num.substring(p + 1).trim();
63-
}
64-
65-
if (num.length() > 2 && num.charAt(0) == '0' && (num.charAt(1) == 'x' || num.charAt(1) == 'X'))
66-
num = num.substring(2);
47+
StreamTokenizer t = new StreamTokenizer(bufferedReader);
48+
t.resetSyntax();
49+
t.commentChar('#');
50+
t.wordChars('a', 'f');
51+
t.wordChars('A', 'F');
52+
t.wordChars('x', 'x');
53+
t.wordChars('X', 'X');
54+
t.wordChars('0', '9');
55+
t.whitespaceChars(0, ' ');
6756

68-
if (num.length() > 0) {
69-
long v = Bits.decode(num, 0, 16);
70-
for (int i = 0; i < rle; i++) {
71-
valueArray.set(pos, v);
72-
pos++;
73-
}
57+
int pos = 0;
58+
while (t.nextToken() != TT_EOF) {
59+
try {
60+
String vStr = t.sval;
61+
if (vStr == null)
62+
throw new IOException("invalid token in line " + t.lineno());
63+
if (t.nextToken() == '*') {
64+
t.nextToken();
65+
if (t.sval == null)
66+
throw new IOException("invalid token in line " + t.lineno());
67+
long v = getHexLong(t.sval);
68+
int reps = (int) Bits.decode(vStr, 0, 10);
69+
for (int i = 0; i < reps; i++) {
70+
valueArray.set(pos, v);
71+
pos++;
7472
}
73+
} else {
74+
t.pushBack();
75+
valueArray.set(pos, getHexLong(vStr));
76+
pos++;
7577
}
76-
7778
} catch (Bits.NumberFormatException e) {
7879
throw new IOException(e);
7980
}
8081
}
8182
}
8283
}
8384

85+
private long getHexLong(String vStr) throws Bits.NumberFormatException {
86+
int p = 0;
87+
if (vStr.length() > 2 && vStr.charAt(0) == '0' && (vStr.charAt(1) == 'x' || vStr.charAt(1) == 'X'))
88+
p = 2;
89+
90+
return Bits.decode(vStr, p, 16);
91+
}
92+
8493
}

src/test/java/de/neemann/digital/core/memory/importer/LogisimReaderTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ public void testLoadRLE() throws Exception {
9999
}
100100

101101
public void testLoadRLEMultiline() throws Exception {
102-
String data = "v2.0 raw\n#test1 \n 5*0x0 10*0x10 0xAA 0XFF #test";
102+
String data = "v2.0 raw\n#test1 \n 5*0x0 10 * 0x10 0xAA 0XFF #test";
103103

104104
DataField df = new DataField(1024);
105105
new LogisimReader(new StringReader(data)).read(new DataFieldValueArray(df, 0));

0 commit comments

Comments
 (0)