1
0
mirror of https://github.com/pfusik/xasm.git synced 2024-06-15 18:29:31 +00:00

Upgraded to DMD 2.051.

This commit is contained in:
Adrian Matoga 2010-12-28 13:44:00 +01:00 committed by Piotr Fusik
parent 034b95ea83
commit 6992795f55

326
xasm.d
View File

@ -1,6 +1,6 @@
// xasm 3.0.2 by Piotr Fusik <fox@scene.pl> // xasm 3.0.2 by Piotr Fusik <fox@scene.pl>
// http://xasm.atari.org // http://xasm.atari.org
// Can be compiled with DMD v1.030. // Can be compiled with DMD v2.051.
// Poetic License: // Poetic License:
// //
@ -16,10 +16,11 @@
// free or for profit. // free or for profit.
// These rights, on this notice, rely. // These rights, on this notice, rely.
import std.stdio;
import std.math; import std.math;
import std.stream; import std.stream;
import std.cstream;
import std.string; import std.string;
import std.conv;
version (Windows) { version (Windows) {
import std.c.windows.windows; import std.c.windows.windows;
@ -52,31 +53,31 @@ const char[] TITLE = "xasm 3.0.2";
char[] sourceFilename = null; char[] sourceFilename = null;
bit[26] options; bool[26] options;
char[][26] optionParameters; char[][26] optionParameters;
char[][] commandLineDefinitions = null; char[][] commandLineDefinitions = null;
char[] makeTarget = null; char[] makeTarget;
char[] makeSources = ""; char[] makeSources;
int exitCode = 0; int exitCode;
int totalLines; int totalLines;
bit pass2 = false; bool pass2;
bit optionFill; // opt f bool optionFill; // opt f
bit option5200; // opt g bool option5200; // opt g
bit optionHeaders; // opt h bool optionHeaders; // opt h
bit optionListing; // opt l bool optionListing; // opt l
bit optionObject; // opt o bool optionObject; // opt o
char[] line; char[] line;
@ -84,11 +85,11 @@ int column;
class Location { class Location {
char[] filename; string filename;
int lineNo = 0; int lineNo = 0;
this(char[] filename) { this(string filename) {
this.filename = filename; this.filename = filename;
} }
} }
@ -97,11 +98,15 @@ Location[] locations;
Location currentLocation; Location currentLocation;
bit foundEnd; bool foundEnd;
class AssemblyError : Exception { class AssemblyError : Exception {
this(char[] msg) { this(in char[] msg) {
super(msg.idup);
}
this(string msg) {
super(msg); super(msg);
} }
} }
@ -110,24 +115,24 @@ class Label {
int value; int value;
bit unused = true; bool unused = true;
bit unknownInPass1 = false; bool unknownInPass1 = false;
bit passed = false; bool passed = false;
this(int value) { this(int value) {
this.value = value; this.value = value;
} }
} }
Label[char[]] labelTable; Label[string] labelTable;
Label currentLabel; Label currentLabel;
typedef int function(int a, int b) OperatorFunction; typedef int function(int a, int b) OperatorFunction;
bit inOpcode = false; bool inOpcode = false;
struct ValOp { struct ValOp {
@ -142,7 +147,7 @@ ValOp[] valOpStack;
int value; int value;
bit unknownInPass1; bool unknownInPass1;
enum AddrMode { enum AddrMode {
ACCUMULATOR = 0, ACCUMULATOR = 0,
@ -175,17 +180,17 @@ ushort[] blockEnds;
int blockIndex; int blockIndex;
bit repeating; // line bool repeating; // line
int repeatCounter; // line int repeatCounter; // line
bit instructionBegin; bool instructionBegin;
bit pairing; bool pairing;
bit willSkip; bool willSkip;
bit skipping; bool skipping;
ushort[] skipOffsets; ushort[] skipOffsets;
@ -193,7 +198,7 @@ int skipOffsetsIndex = 0;
int repeatOffset; // instruction repeat int repeatOffset; // instruction repeat
bit wereManyInstructions; bool wereManyInstructions;
typedef void function(int move) MoveFunction; typedef void function(int move) MoveFunction;
@ -207,11 +212,11 @@ AddrMode addrMode2;
struct IfContext { struct IfContext {
bit condition; bool condition;
bit wasElse; bool wasElse;
bit aConditionMatched; bool aConditionMatched;
} }
IfContext[] ifContexts; IfContext[] ifContexts;
@ -222,37 +227,35 @@ char[32] listingLine;
int listingColumn; int listingColumn;
char[] lastListedFilename = null; string lastListedFilename;
Stream objectStream = null; Stream objectStream;
int objectBytes = 0; int objectBytes = 0;
bit getOption(char letter) { bool getOption(char letter) {
assert(letter >= 'a' && letter <= 'z'); assert(letter >= 'a' && letter <= 'z');
return options[letter - 'a']; return options[letter - 'a'];
} }
void warning(char[] msg, bool error = false) { void warning(in char[] msg, bool error = false) {
dout.flush(); stdout.flush();
version (Windows) { version (Windows) {
HANDLE h = GetStdHandle(STD_ERROR_HANDLE); HANDLE h = GetStdHandle(STD_ERROR_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO csbi; CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(h, &csbi); GetConsoleScreenBufferInfo(h, &csbi);
SetConsoleTextAttribute(h, (csbi.wAttributes & ~0xf) | (error ? 12 : 14)); SetConsoleTextAttribute(h, (csbi.wAttributes & ~0xf) | (error ? 12 : 14));
scope (exit) SetConsoleTextAttribute(h, csbi.wAttributes);
} }
if (line !is null) { if (line !is null) {
derr.printf("%.*s\n", line); stderr.writeln(line);
} }
derr.printf("%.*s (%d) %.*s: %.*s\n", stderr.writefln("%s (%d) %s: %s",
currentLocation.filename, currentLocation.filename,
currentLocation.lineNo, currentLocation.lineNo,
error ? "ERROR" : "WARNING", error ? "ERROR" : "WARNING",
msg msg
); );
version (Windows) {
SetConsoleTextAttribute(h, csbi.wAttributes);
}
exitCode = 1; exitCode = 1;
} }
@ -260,7 +263,7 @@ void illegalCharacter() {
throw new AssemblyError("Illegal character"); throw new AssemblyError("Illegal character");
} }
bit eol() { bool eol() {
return column >= line.length; return column >= line.length;
} }
@ -327,7 +330,7 @@ void readSpaces() {
} }
char[] readLabel() { char[] readLabel() {
char[] label = ""; char[] label;
while (!eol()) { while (!eol()) {
char c = line[column++]; char c = line[column++];
if (c >= '0' && c <= '9' || c == '_') { if (c >= '0' && c <= '9' || c == '_') {
@ -352,7 +355,7 @@ void readComma() {
} }
char[] readInstruction() { char[] readInstruction() {
char[] r = ""; char[] r;
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
char c = readChar() & 0xdf; char c = readChar() & 0xdf;
if (c < 'A' || c > 'Z') { if (c < 'A' || c > 'Z') {
@ -364,12 +367,12 @@ char[] readInstruction() {
} }
char[] readFunction() { char[] readFunction() {
if (column + 5 >= line.length) return ""; if (column + 5 >= line.length) return null;
if (line[column + 3] != '(') return ""; if (line[column + 3] != '(') return null;
char[] r = ""; char[] r;
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
char c = line[column + i] & 0xdf; char c = line[column + i] & 0xdf;
if (c < 'A' || c > 'Z') return ""; if (c < 'A' || c > 'Z') return null;
r ~= c; r ~= c;
} }
column += 4; column += 4;
@ -377,7 +380,7 @@ char[] readFunction() {
} }
char[] readFilename() { char[] readFilename() {
char[] filename = ""; char[] filename;
readSpaces(); readSpaces();
char delimiter = readChar(); char delimiter = readChar();
switch (delimiter) { switch (delimiter) {
@ -391,6 +394,7 @@ char[] readFilename() {
default: default:
illegalCharacter(); illegalCharacter();
} }
assert(0);
} }
void readStringChar(char c) { void readStringChar(char c) {
@ -413,7 +417,7 @@ ubyte[] readString() {
if (line[column] != delimiter) { if (line[column] != delimiter) {
if (line[column] == '*') { if (line[column] == '*') {
column++; column++;
foreach (inout ubyte b; r) { foreach (ref b; r) {
b ^= 0x80; b ^= 0x80;
} }
} }
@ -548,7 +552,7 @@ int operatorShiftLeft(int a, int b) {
if (b < 0) { if (b < 0) {
return operatorShiftRight(a, -b); return operatorShiftRight(a, -b);
} }
if (a != 0 & b >= 32) { if (a != 0 && b >= 32) {
throw new AssemblyError("Arithmetic overflow"); throw new AssemblyError("Arithmetic overflow");
} }
long r = cast(long) a << b; long r = cast(long) a << b;
@ -672,8 +676,8 @@ void readValue() {
} }
ValOp[] savedValOpStack = valOpStack; ValOp[] savedValOpStack = valOpStack;
AddrMode savedAddrMode = addrMode; AddrMode savedAddrMode = addrMode;
bit savedUnknownInPass1 = unknownInPass1; bool savedUnknownInPass1 = unknownInPass1;
bit savedInstructionBegin = instructionBegin; bool savedInstructionBegin = instructionBegin;
valOpStack.length = 0; valOpStack.length = 0;
inOpcode = true; inOpcode = true;
assemblyInstruction(readInstruction()); assemblyInstruction(readInstruction());
@ -863,11 +867,11 @@ void readValue() {
valOpStack.length = 0; valOpStack.length = 0;
} }
debug int testValue(char[] l) { debug int testValue(in char[] l) {
line = l; line = l.dup;
column = 0; column = 0;
readValue(); readValue();
dout.printf("Value of %.*s is %x\n", line, value); writefln("Value of %s is %x", line, value);
return value; return value;
} }
@ -1139,11 +1143,11 @@ void readAbsoluteAddrMode() {
addrMode = AddrMode.ABSOLUTE; addrMode = AddrMode.ABSOLUTE;
} }
debug AddrMode testAddrMode(char[] l) { debug AddrMode testAddrMode(in char[] l) {
line = l; line = l.dup;
column = 0; column = 0;
readAddrMode(); readAddrMode();
dout.printf("Addressing mode of \"%.*s\" is %x\n", line, addrMode); writefln("Addressing mode of \"%s\" is %x", line, addrMode);
return addrMode; return addrMode;
} }
@ -1166,14 +1170,14 @@ unittest {
inOpcode = false; inOpcode = false;
} }
bit inFalseCondition() { bool inFalseCondition() {
foreach (IfContext ic; ifContexts) { foreach (IfContext ic; ifContexts) {
if (!ic.condition) return true; if (!ic.condition) return true;
} }
return false; return false;
} }
int filenameExt(char[] filename) { int filenameExt(in char[] filename) {
int i = filename.length; int i = filename.length;
while (--i >= 0) { while (--i >= 0) {
switch (filename[i]) { switch (filename[i]) {
@ -1197,19 +1201,19 @@ unittest {
} }
char[] makeEscape(char[] s) { char[] makeEscape(char[] s) {
return replace(s, "$", "$$"); return replace(s.idup, "$", "$$").dup;
} }
Stream openInputFile(char[] filename) { Stream openInputFile(char[] filename) {
makeSources ~= ' ' ~ makeEscape(filename); makeSources ~= ' ' ~ makeEscape(filename);
try { try {
return new BufferedFile(filename, FileMode.In); return new BufferedFile(filename.idup, FileMode.In);
} catch (OpenException e) { } catch (OpenException e) {
throw new AssemblyError(e.toString()); throw new AssemblyError(e.toString());
} }
} }
Stream openOutputFile(char letter, char[] defaultExt) { Stream openOutputFile(char letter, string defaultExt) {
char[] filename; char[] filename;
if (optionParameters[letter - 'a'] is null) { if (optionParameters[letter - 'a'] is null) {
filename = sourceFilename; filename = sourceFilename;
@ -1225,24 +1229,24 @@ Stream openOutputFile(char letter, char[] defaultExt) {
makeTarget = makeEscape(filename); makeTarget = makeEscape(filename);
} }
try { try {
return new BufferedFile(filename, FileMode.OutNew); return new BufferedFile(filename.idup, FileMode.OutNew);
} catch (OpenException e) { } catch (OpenException e) {
throw new AssemblyError(e.toString()); throw new AssemblyError(e.toString());
} }
} }
void ensureListingFileOpen(char letter, char[] msg) { void ensureListingFileOpen(char letter, in char[] msg) {
if (listingStream is null) { if (listingStream is null) {
listingStream = openOutputFile(letter, ".lst"); listingStream = openOutputFile(letter, ".lst");
if (!getOption('q')) { if (!getOption('q')) {
dout.printf(msg); write(msg);
} }
listingStream.printf(TITLE ~ "\r\n"); listingStream.writeLine(TITLE);
} }
} }
void listNibble(int x) { void listNibble(int x) {
listingLine[listingColumn++] = x <= 9 ? x + '0' : x + ('A' - 10); listingLine[listingColumn++] = cast(char) (x <= 9 ? x + '0' : x + ('A' - 10));
} }
void listByte(ubyte x) { void listByte(ubyte x) {
@ -1268,13 +1272,13 @@ void listLine() {
} }
ensureListingFileOpen('l', "Writing listing file...\n"); ensureListingFileOpen('l', "Writing listing file...\n");
if (currentLocation.filename != lastListedFilename) { if (currentLocation.filename != lastListedFilename) {
listingStream.printf("Source: %.*s\n", currentLocation.filename); listingStream.writefln("Source: %s", currentLocation.filename);
lastListedFilename = currentLocation.filename; lastListedFilename = currentLocation.filename;
} }
int i = 4; int i = 4;
int x = currentLocation.lineNo; int x = currentLocation.lineNo;
while (x > 0 && i >= 0) { while (x > 0 && i >= 0) {
listingLine[i--] = '0' + x % 10; listingLine[i--] = cast(char) ('0' + x % 10);
x /= 10; x /= 10;
} }
while (i >= 0) { while (i >= 0) {
@ -1284,7 +1288,7 @@ void listLine() {
while (listingColumn < 32) { while (listingColumn < 32) {
listingLine[listingColumn++] = ' '; listingLine[listingColumn++] = ' ';
} }
listingStream.printf("%.32s%.*s\r\n", cast(char*) listingLine, line); listingStream.writefln("%.32s%s", listingLine, line);
} }
void listCommentLine() { void listCommentLine() {
@ -1303,8 +1307,8 @@ void listLabelTable() {
listingStream = null; listingStream = null;
} }
ensureListingFileOpen('t', "Writing label table...\n"); ensureListingFileOpen('t', "Writing label table...\n");
listingStream.printf("Label table:\r\n"); listingStream.writefln("Label table:");
foreach (char[] name; labelTable.keys.sort) { foreach (name; labelTable.keys.sort) {
Label l = labelTable[name]; Label l = labelTable[name];
listingStream.write(l.unused ? 'n' : ' '); listingStream.write(l.unused ? 'n' : ' ');
listingStream.write(l.unknownInPass1 ? '2' : ' '); listingStream.write(l.unknownInPass1 ? '2' : ' ');
@ -1314,8 +1318,8 @@ void listLabelTable() {
sign = '-'; sign = '-';
value = -value; value = -value;
} }
listingStream.printf( listingStream.writefln(
(l.value & 0xffff0000) != 0 ? " %c%08X %.*s\r\n" : " %c%04X %.*s\r\n", (l.value & 0xffff0000) != 0 ? " %s%08X %s" : " %s%04X %s",
sign, value, name sign, value, name
); );
} }
@ -1332,7 +1336,7 @@ void objectByte(ubyte b) {
if (objectStream is null) { if (objectStream is null) {
objectStream = openOutputFile('o', ".obx"); objectStream = openOutputFile('o', ".obx");
if (!getOption('q')) { if (!getOption('q')) {
dout.printf("Writing object file...\n"); writeln("Writing object file...");
} }
} }
try { try {
@ -1438,7 +1442,7 @@ void putCommand(ubyte b) {
case AddrMode.ABSOLUTE_X: case AddrMode.ABSOLUTE_X:
case AddrMode.ABSOLUTE_Y: case AddrMode.ABSOLUTE_Y:
case AddrMode.INDIRECT: case AddrMode.INDIRECT:
putWord(value); putWord(cast(ushort) value);
break; break;
} }
switch (addrMode) { switch (addrMode) {
@ -1525,37 +1529,37 @@ void assemblyAccumulator(ubyte b, ubyte prefix, int move) {
// STA # // STA #
illegalAddrMode(); illegalAddrMode();
} }
putCommand(b + 9); putCommand(cast(ubyte) (b + 9));
break; break;
case AddrMode.ABSOLUTE: case AddrMode.ABSOLUTE:
putCommand(b + 0xd); putCommand(cast(ubyte) (b + 0xd));
break; break;
case AddrMode.ZEROPAGE: case AddrMode.ZEROPAGE:
putCommand(b + 5); putCommand(cast(ubyte) (b + 5));
break; break;
case AddrMode.ABSOLUTE_X: case AddrMode.ABSOLUTE_X:
putCommand(b + 0x1d); putCommand(cast(ubyte) (b + 0x1d));
break; break;
case AddrMode.ZEROPAGE_X: case AddrMode.ZEROPAGE_X:
putCommand(b + 0x15); putCommand(cast(ubyte) (b + 0x15));
break; break;
case AddrMode.ZEROPAGE_Y: case AddrMode.ZEROPAGE_Y:
addrMode -= 1; addrMode -= 1;
goto case AddrMode.ABSOLUTE_Y; goto case AddrMode.ABSOLUTE_Y;
case AddrMode.ABSOLUTE_Y: case AddrMode.ABSOLUTE_Y:
putCommand(b + 0x19); putCommand(cast(ubyte) (b + 0x19));
break; break;
case AddrMode.INDIRECT_X: case AddrMode.INDIRECT_X:
if ((addrMode & AddrMode.ZERO) != 0) { if ((addrMode & AddrMode.ZERO) != 0) {
putWord(0x00a2); putWord(0x00a2);
} }
putCommand(b + 1); putCommand(cast(ubyte) (b + 1));
break; break;
case AddrMode.INDIRECT_Y: case AddrMode.INDIRECT_Y:
if ((addrMode & AddrMode.ZERO) != 0) { if ((addrMode & AddrMode.ZERO) != 0) {
putWord(0x00a0); putWord(0x00a0);
} }
putCommand(b + 0x11); putCommand(cast(ubyte) (b + 0x11));
break; break;
} }
} }
@ -1568,19 +1572,19 @@ void assemblyShift(ubyte b) {
// INC @, DEC @ // INC @, DEC @
illegalAddrMode(); illegalAddrMode();
} }
putByte(b + 0xa); putByte(cast(ubyte) (b + 0xa));
break; break;
case AddrMode.ABSOLUTE: case AddrMode.ABSOLUTE:
putCommand(b + 0xe); putCommand(cast(ubyte) (b + 0xe));
break; break;
case AddrMode.ZEROPAGE: case AddrMode.ZEROPAGE:
putCommand(b + 6); putCommand(cast(ubyte) (b + 6));
break; break;
case AddrMode.ABSOLUTE_X: case AddrMode.ABSOLUTE_X:
putCommand(b + 0x1e); putCommand(cast(ubyte) (b + 0x1e));
break; break;
case AddrMode.ZEROPAGE_X: case AddrMode.ZEROPAGE_X:
putCommand(b + 0x16); putCommand(cast(ubyte) (b + 0x16));
break; break;
default: default:
illegalAddrMode(); illegalAddrMode();
@ -1594,10 +1598,10 @@ void assemblyCompareIndex(ubyte b) {
putCommand(b); putCommand(b);
break; break;
case AddrMode.ABSOLUTE: case AddrMode.ABSOLUTE:
putCommand(b + 0xc); putCommand(cast(ubyte) (b + 0xc));
break; break;
case AddrMode.ZEROPAGE: case AddrMode.ZEROPAGE:
putCommand(b + 4); putCommand(cast(ubyte) (b + 4));
break; break;
default: default:
illegalAddrMode(); illegalAddrMode();
@ -1761,7 +1765,7 @@ ubyte calculateBranch(int offset) {
} else { } else {
dist = offset - 0x7f; dist = offset - 0x7f;
} }
throw new AssemblyError("Branch out of range by " ~ toString(dist) ~ " bytes"); throw new AssemblyError("Branch out of range by " ~ to!string(dist) ~ " bytes");
} }
return cast(ubyte) offset; return cast(ubyte) offset;
} }
@ -1844,7 +1848,7 @@ void assemblyMove() {
readAddrMode(); readAddrMode();
value1 = value; value1 = value;
addrMode1 = addrMode; addrMode1 = addrMode;
bit unknown1 = unknownInPass1; bool unknown1 = unknownInPass1;
readAddrMode(); readAddrMode();
value2 = value; value2 = value;
addrMode2 = addrMode; addrMode2 = addrMode;
@ -1971,7 +1975,7 @@ void assemblyDtaInteger(char letter) {
storeDtaNumber(value, letter); storeDtaNumber(value, letter);
} }
bit realSign; bool realSign;
int realExponent; int realExponent;
@ -2009,7 +2013,7 @@ void putReal() {
putByte(cast(ubyte) realMantissa); putByte(cast(ubyte) realMantissa);
} }
bit readSign() { bool readSign() {
switch (readChar()) { switch (readChar()) {
case '+': case '+':
return false; return false;
@ -2022,7 +2026,7 @@ bit readSign() {
} }
void readExponent() { void readExponent() {
bit sign = readSign(); bool sign = readSign();
char c = readChar(); char c = readChar();
if (c < '0' || c > '9') { if (c < '0' || c > '9') {
illegalCharacter(); illegalCharacter();
@ -2165,11 +2169,11 @@ void assemblyDta() {
foreach (ubyte b; s) { foreach (ubyte b; s) {
switch (b & 0x60) { switch (b & 0x60) {
case 0x00: case 0x00:
putByte(b + 0x40); putByte(cast(ubyte) (b + 0x40));
break; break;
case 0x20: case 0x20:
case 0x40: case 0x40:
putByte(b - 0x20); putByte(cast(ubyte) (b - 0x20));
break; break;
case 0x60: case 0x60:
putByte(b); putByte(b);
@ -2307,7 +2311,7 @@ void assemblyErt() {
} }
} }
bit readOption() { bool readOption() {
switch (readChar()) { switch (readChar()) {
case '-': case '-':
return false; return false;
@ -2316,6 +2320,7 @@ bit readOption() {
default: default:
illegalCharacter(); illegalCharacter();
} }
assert(0);
} }
void assemblyOpt() { void assemblyOpt() {
@ -2356,7 +2361,7 @@ void originWord(ushort value, char listingChar) {
listingLine[listingColumn++] = listingChar; listingLine[listingColumn++] = listingChar;
} }
void setOrigin(int addr, bit requestedHeader, bit requestedFFFF) { void setOrigin(int addr, bool requestedHeader, bool requestedFFFF) {
origin = loadOrigin = addr; origin = loadOrigin = addr;
if (requestedHeader || loadingOrigin < 0 || (addr != loadingOrigin && !optionFill)) { if (requestedHeader || loadingOrigin < 0 || (addr != loadingOrigin && !optionFill)) {
blockIndex++; blockIndex++;
@ -2395,8 +2400,8 @@ void checkHeadersOn() {
void assemblyOrg() { void assemblyOrg() {
noRepeatSkipDirective(); noRepeatSkipDirective();
readSpaces(); readSpaces();
bit requestedFFFF = false; bool requestedFFFF = false;
bit requestedHeader = false; bool requestedHeader = false;
if (column + 2 < line.length && line[column + 1] == ':') { if (column + 2 < line.length && line[column + 1] == ':') {
switch (line[column]) { switch (line[column]) {
case 'F': case 'F':
@ -2433,7 +2438,7 @@ void assemblyRunIni(ushort addr) {
setOrigin(addr, false, false); setOrigin(addr, false, false);
readSpaces(); readSpaces();
readUnsignedWord(); readUnsignedWord();
putWord(value); putWord(cast(ushort) (value));
loadingOrigin = -1; // don't fill loadingOrigin = -1; // don't fill
} }
@ -2463,6 +2468,7 @@ void assemblyIns() {
} }
} }
Stream stream = openInputFile(filename); Stream stream = openInputFile(filename);
scope (exit) stream.close();
try { try {
stream.seek(offset, offset >= 0 ? SeekPos.Set : SeekPos.End); stream.seek(offset, offset >= 0 ? SeekPos.Set : SeekPos.End);
} catch (SeekException e) { } catch (SeekException e) {
@ -2481,7 +2487,6 @@ void assemblyIns() {
putByte(b); putByte(b);
if (length > 0) length--; if (length > 0) length--;
} }
// stream.close(); bug in Phobos
} }
void assemblyInstruction(char[] instruction) { void assemblyInstruction(char[] instruction) {
@ -2805,16 +2810,16 @@ void assemblyInstruction(char[] instruction) {
skipping = false; skipping = false;
} }
debug ubyte[] testInstruction(char[] l) { debug ubyte[] testInstruction(in char[] l) {
objectBuffer.length = 0; objectBuffer.length = 0;
line = l; line = l.dup;
column = 0; column = 0;
assemblyInstruction(readInstruction()); assemblyInstruction(readInstruction());
dout.printf("%.*s assembles to", line); write(line, " assembles to");
foreach (ubyte b; objectBuffer) { foreach (ubyte b; objectBuffer) {
dout.printf(" %02x", b); writef(" %02x", b);
} }
dout.printf("\n"); writeln();
return objectBuffer; return objectBuffer;
} }
@ -2853,14 +2858,14 @@ void assemblyPair() {
void assemblyLine() { void assemblyLine() {
debug { debug {
dout.printf("%.*s\n", line); writeln(line);
} }
currentLocation.lineNo++; currentLocation.lineNo++;
totalLines++; totalLines++;
column = 0; column = 0;
listingColumn = 6; listingColumn = 6;
if (origin >= 0) { if (origin >= 0) {
listWord(origin); listWord(cast(ushort) origin);
listingLine[listingColumn++] = ' '; listingLine[listingColumn++] = ' ';
} }
char[] label = readLabel(); char[] label = readLabel();
@ -2872,7 +2877,7 @@ void assemblyLine() {
throw new AssemblyError("Label declared twice"); throw new AssemblyError("Label declared twice");
} }
currentLabel = new Label(origin); currentLabel = new Label(origin);
labelTable[label] = currentLabel; labelTable[label.idup] = currentLabel;
} else { } else {
assert(label in labelTable); assert(label in labelTable);
currentLabel = labelTable[label]; currentLabel = labelTable[label];
@ -2978,48 +2983,45 @@ void assemblyFile(char[] filename) {
if (getOption('p')) { if (getOption('p')) {
filename = getFullPath(filename); filename = getFullPath(filename);
} }
currentLocation = new Location(filename); currentLocation = new Location(filename.idup);
foundEnd = false; foundEnd = false;
Stream stream = openInputFile(filename); Stream stream = openInputFile(filename);
line = ""; scope (exit) stream.close();
try { line = null;
readChar: while (!foundEnd) { readChar: while (!foundEnd) {
ubyte c; ubyte c;
try {
stream.read(c);
} catch (ReadException e) {
break;
}
switch (c) {
case '\r':
assemblyLine();
line = null;
try { try {
stream.read(c); stream.read(c);
} catch (ReadException e) { } catch (ReadException e) {
break; break readChar;
} }
switch (c) { if (c != '\n') {
case '\r':
assemblyLine();
line = "";
try {
stream.read(c);
} catch (ReadException e) {
break readChar;
}
if (c != '\n') {
line ~= cast(char) c;
}
break;
case '\n':
case '\x9b':
assemblyLine();
line = "";
break;
default:
line ~= cast(char) c; line ~= cast(char) c;
break;
} }
} break;
if (!foundEnd) { case '\n':
case '\x9b':
assemblyLine(); assemblyLine();
line = null;
break;
default:
line ~= cast(char) c;
break;
} }
foundEnd = false;
} finally {
// stream.close(); // bug in Phobos
} }
if (!foundEnd) {
assemblyLine();
}
foundEnd = false;
if (locations.length > 0) { if (locations.length > 0) {
currentLocation = locations[locations.length - 1]; currentLocation = locations[locations.length - 1];
locations.length = locations.length - 1; locations.length = locations.length - 1;
@ -3042,8 +3044,8 @@ void assemblyPass() {
wereManyInstructions = false; wereManyInstructions = false;
if (commandLineDefinitions.length > 0) { if (commandLineDefinitions.length > 0) {
currentLocation = new Location("command line"); currentLocation = new Location("command line");
foreach (char[] definition; commandLineDefinitions) { foreach (definition; commandLineDefinitions) {
int i = find(definition, '='); int i = indexOf(definition, '=');
assert(i >= 0); assert(i >= 0);
line = definition[0 .. i] ~ " equ " ~ definition[i + 1 .. definition.length]; line = definition[0 .. i] ~ " equ " ~ definition[i + 1 .. definition.length];
assemblyLine(); assemblyLine();
@ -3061,7 +3063,7 @@ void assemblyPass() {
} }
} }
bit isOption(char[] arg) { bool isOption(char[] arg) {
if (arg.length < 2) return false; if (arg.length < 2) return false;
if (arg[0] == '-') return true; if (arg[0] == '-') return true;
if (arg[0] != '/') return false; if (arg[0] != '/') return false;
@ -3102,12 +3104,12 @@ int main(char[][] args) {
char[] definition = null; char[] definition = null;
if (arg[0] == '/') { if (arg[0] == '/') {
if (arg.length >= 3 && arg[2] == ':') { if (arg.length >= 3 && arg[2] == ':') {
definition = arg[3..arg.length]; definition = arg[3 .. arg.length];
} }
} else if (i + 1 < args.length && !isOption(args[i + 1])) { } else if (i + 1 < args.length && !isOption(args[i + 1])) {
definition = args[++i]; definition = args[++i];
} }
if (definition is null || find(definition, '=') < 0) { if (definition is null || indexOf(definition, '=') < 0) {
exitCode = 3; exitCode = 3;
} }
commandLineDefinitions ~= definition; commandLineDefinitions ~= definition;
@ -3119,7 +3121,7 @@ int main(char[][] args) {
char[] filename = null; char[] filename = null;
if (arg[0] == '/') { if (arg[0] == '/') {
if (arg.length >= 3 && arg[2] == ':') { if (arg.length >= 3 && arg[2] == ':') {
filename = arg[3..arg.length]; filename = arg[3 .. arg.length];
} }
} else if (i + 1 < args.length && !isOption(args[i + 1])) { } else if (i + 1 < args.length && !isOption(args[i + 1])) {
filename = args[++i]; filename = args[++i];
@ -3144,10 +3146,10 @@ int main(char[][] args) {
exitCode = 3; exitCode = 3;
} }
if (!getOption('q')) { if (!getOption('q')) {
dout.printf(TITLE ~ "\n"); writeln(TITLE);
} }
if (exitCode != 0) { if (exitCode != 0) {
dout.printf( write(
"Syntax: xasm source [options]\n" "Syntax: xasm source [options]\n"
"/c Include false conditionals in listing\n" "/c Include false conditionals in listing\n"
"/d:label=value Define a label\n" "/d:label=value Define a label\n"
@ -3181,13 +3183,13 @@ int main(char[][] args) {
} }
if (exitCode <= 1) { if (exitCode <= 1) {
if (!getOption('q')) { if (!getOption('q')) {
dout.printf("%d lines of source assembled\n", totalLines); writefln("%d lines of source assembled", totalLines);
if (objectBytes > 0) { if (objectBytes > 0) {
dout.printf("%d bytes written to the object file\n", objectBytes); writefln("%d bytes written to the object file", objectBytes);
} }
} }
if (getOption('m')) { if (getOption('m')) {
dout.printf("%.*s:%.*s\n\txasm", makeTarget, makeSources); writef("%s:%s\n\txasm", makeTarget, makeSources);
for (int i = 1; i < args.length; i++) { for (int i = 1; i < args.length; i++) {
char[] arg = args[i]; char[] arg = args[i];
if (isOption(arg)) { if (isOption(arg)) {
@ -3199,9 +3201,9 @@ int main(char[][] args) {
break; break;
case 'o': case 'o':
if (arg[0] == '/') { if (arg[0] == '/') {
dout.printf(" /%c:$@", arg[1]); writef(" /%c:$@", arg[1]);
} else { } else {
dout.printf(" -%c $@", arg[1]); writef(" -%c $@", arg[1]);
++i; ++i;
} }
break; break;
@ -3209,18 +3211,18 @@ int main(char[][] args) {
if (arg[0] == '-' if (arg[0] == '-'
&& (letter == 'd' || letter == 'l' || letter == 't') && (letter == 'd' || letter == 'l' || letter == 't')
&& i + 1 < args.length && !isOption(args[i + 1])) { && i + 1 < args.length && !isOption(args[i + 1])) {
dout.printf(" %.*s %.*s", arg, makeEscape(args[++i])); writef(" %s %s", arg, makeEscape(args[++i]));
} }
else { else {
dout.printf(" %.*s", makeEscape(arg)); writef(" %s", makeEscape(arg));
} }
break; break;
} }
continue; continue;
} }
dout.printf(" $<"); writef(" $<");
} }
dout.printf("\n"); writeln();
} }
} }
return exitCode; return exitCode;