|
@@ -1,4 +1,5 @@
|
|
|
/*
|
|
|
+ * Copyright (c) 2021 Noah Vogt <noah@noahvogt.com>
|
|
|
* Copyright (c) 2011 Matthew Iselin
|
|
|
*
|
|
|
* Permission to use, copy, modify, and distribute this software for any
|
|
@@ -18,35 +19,31 @@
|
|
|
#include <fstream>
|
|
|
#include <vector>
|
|
|
#include <string>
|
|
|
-
|
|
|
#include <stdio.h>
|
|
|
#include <string.h>
|
|
|
|
|
|
#include "tibasic.h"
|
|
|
+#include "compiler.h"
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
/* \todo More error handling. */
|
|
|
|
|
|
-unsigned short Compiler::doChecksum(size_t sum)
|
|
|
-{
|
|
|
+unsigned short Compiler::doChecksum(size_t sum) {
|
|
|
/* Bottom 16 bits of the sum. */
|
|
|
return (unsigned short) (sum & 0xFFFF);
|
|
|
}
|
|
|
|
|
|
-size_t Compiler::sumBytes(const char *data, size_t len)
|
|
|
-{
|
|
|
+size_t Compiler::sumBytes(const char *data, size_t len) {
|
|
|
size_t ret = 0;
|
|
|
for(size_t i = 0; i < len; i++)
|
|
|
ret += data[i];
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-string trim(const string& str)
|
|
|
-{
|
|
|
+string trim(const string& str) {
|
|
|
size_t first = str.find_first_not_of(' ');
|
|
|
- if (string::npos == first)
|
|
|
- {
|
|
|
+ if (string::npos == first) {
|
|
|
return str;
|
|
|
}
|
|
|
size_t last = str.find_last_not_of(' ');
|
|
@@ -55,8 +52,7 @@ string trim(const string& str)
|
|
|
|
|
|
extern bool verbose;
|
|
|
|
|
|
-bool Compiler::compile(string inFile, string outFile)
|
|
|
-{
|
|
|
+bool Compiler::compile(string inFile, string outFile) {
|
|
|
ifstream f(inFile.c_str(), ifstream::in);
|
|
|
|
|
|
string tmpLine;
|
|
@@ -65,13 +61,11 @@ bool Compiler::compile(string inFile, string outFile)
|
|
|
vector<token_t> output;
|
|
|
unsigned short outputSize = 0;
|
|
|
|
|
|
- while(!f.eof())
|
|
|
- {
|
|
|
+ while(!f.eof()) {
|
|
|
getline(f, tmpLine, '\n');
|
|
|
|
|
|
/* ignore empty lines */
|
|
|
- if(!tmpLine.length())
|
|
|
- {
|
|
|
+ if(!tmpLine.length()) {
|
|
|
if(verbose)
|
|
|
log(Debug, "Empty line detected!");
|
|
|
continue;
|
|
@@ -86,8 +80,7 @@ bool Compiler::compile(string inFile, string outFile)
|
|
|
|
|
|
/* ignore lines with now only whitespaces */
|
|
|
bool containsSpaces = tmpLine.find_first_not_of(' ') != std::string::npos;
|
|
|
- if(!containsSpaces)
|
|
|
- {
|
|
|
+ if(!containsSpaces) {
|
|
|
if(verbose)
|
|
|
log(Debug, "Line with only whitespaces / comments detected!");
|
|
|
continue;
|
|
@@ -97,37 +90,31 @@ bool Compiler::compile(string inFile, string outFile)
|
|
|
/* Parse. */
|
|
|
token_t token;
|
|
|
|
|
|
- while(tmpLine.length())
|
|
|
- {
|
|
|
+ while(tmpLine.length()) {
|
|
|
/* Grab the longest possible token we can from the input. */
|
|
|
string s = tmpLine.substr(0, getLongestToken());
|
|
|
|
|
|
bool validToken = false;
|
|
|
- while(!validToken && s.length())
|
|
|
- {
|
|
|
+ while(!validToken && s.length()) {
|
|
|
validToken = lookupToken(s, token);
|
|
|
if(!validToken)
|
|
|
s = s.substr(0, s.length() - 1);
|
|
|
}
|
|
|
|
|
|
/* Special case for alphabet characters */
|
|
|
- if(!s.length() && isalpha(tmpLine[0]))
|
|
|
- {
|
|
|
+ if(!s.length() && isalpha(tmpLine[0])) {
|
|
|
token.token = toupper(tmpLine[0]);
|
|
|
token.sz = 1;
|
|
|
|
|
|
s = tmpLine.substr(0, 1);
|
|
|
}
|
|
|
|
|
|
- if(!s.length())
|
|
|
- {
|
|
|
+ if(!s.length()) {
|
|
|
/* Error, asplode! */
|
|
|
log(Error, "Invalid token.");
|
|
|
f.close();
|
|
|
return false;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
+ } else {
|
|
|
outputSize += token.sz;
|
|
|
output.push_back(token);
|
|
|
if(verbose)
|
|
@@ -138,8 +125,7 @@ bool Compiler::compile(string inFile, string outFile)
|
|
|
|
|
|
/* Output a newline. */
|
|
|
bool gotNewline = lookupToken("\n", token);
|
|
|
- if(gotNewline)
|
|
|
- {
|
|
|
+ if(gotNewline) {
|
|
|
outputSize += token.sz;
|
|
|
output.push_back(token);
|
|
|
}
|
|
@@ -151,7 +137,7 @@ bool Compiler::compile(string inFile, string outFile)
|
|
|
memset(&ventry, 0, sizeof(VariableEntry));
|
|
|
|
|
|
phdr.datalen = sizeof(VariableEntry) + outputSize + sizeof(outputSize);
|
|
|
- strcpy(phdr.sig, "**TI83F*");
|
|
|
+ strcpy(phdr.sig, "**TI83F*x");
|
|
|
phdr.extsig[0] = 0x1A; phdr.extsig[1] = 0x0A; phdr.extsig[2] = 0;
|
|
|
strcpy(phdr.comment, "Generated by the TI-BASIC Compiler.");
|
|
|
|
|
@@ -165,8 +151,7 @@ bool Compiler::compile(string inFile, string outFile)
|
|
|
size_t n = outFile.find_last_of('/');
|
|
|
if(n == inFile.npos) n = outFile.find_last_of('\\');
|
|
|
if(n == inFile.npos) n = 0; else n++;
|
|
|
- for(; (i < 8) && (n < inFile.length() - 4); n++)
|
|
|
- {
|
|
|
+ for(; (i < 8) && (n < inFile.length() - 4); n++) {
|
|
|
if(outFile[n] == '.')
|
|
|
break;
|
|
|
ventry.name[i++] = toupper(outFile[n]);
|
|
@@ -183,10 +168,9 @@ bool Compiler::compile(string inFile, string outFile)
|
|
|
|
|
|
for(vector<token_t>::iterator it = output.begin();
|
|
|
it != output.end();
|
|
|
- ++it)
|
|
|
- {
|
|
|
- fwrite(&(it->token), it->sz, 1, out);
|
|
|
- sum += it->token;
|
|
|
+ ++it) {
|
|
|
+ fwrite(&(it->token), it->sz, 1, out);
|
|
|
+ sum += it->token;
|
|
|
}
|
|
|
|
|
|
/* Perform a checksum and write to file. */
|
|
@@ -200,12 +184,10 @@ bool Compiler::compile(string inFile, string outFile)
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
-bool Compiler::decompile(string inFile, string outFile)
|
|
|
-{
|
|
|
+bool Compiler::decompile(string inFile, string outFile) {
|
|
|
/* Parse the file. */
|
|
|
FILE *fp = fopen(inFile.c_str(), "rb");
|
|
|
- if(!fp)
|
|
|
- {
|
|
|
+ if(!fp) {
|
|
|
log(Error, "Couldn't open input file.");
|
|
|
return false;
|
|
|
}
|
|
@@ -230,13 +212,11 @@ bool Compiler::decompile(string inFile, string outFile)
|
|
|
|
|
|
bool bAsmProgram = false;
|
|
|
|
|
|
- while((!feof(fp)) && (nBytesRead < tokenLength))
|
|
|
- {
|
|
|
+ while((!feof(fp)) && (nBytesRead < tokenLength)) {
|
|
|
fread(&temp, 1, 2, fp);
|
|
|
|
|
|
/* If we're in assembly mode, just copy the bytes straight in a numbers. */
|
|
|
- if(bAsmProgram)
|
|
|
- {
|
|
|
+ if(bAsmProgram) {
|
|
|
if(((temp & 0xFF) == 0x3F))
|
|
|
sOutput += "\n";
|
|
|
sOutput += temp & 0xFF;
|
|
@@ -253,26 +233,21 @@ bool Compiler::decompile(string inFile, string outFile)
|
|
|
if(!bIsFound)
|
|
|
bIsFound = lookupToken(temp & 0xFF, conv);
|
|
|
|
|
|
- if(!bIsFound)
|
|
|
- {
|
|
|
+ if(!bIsFound) {
|
|
|
sOutput += static_cast<char>(temp);
|
|
|
|
|
|
fseek(fp, -1, SEEK_CUR);
|
|
|
nBytesRead++;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
+ } else {
|
|
|
sOutput += conv;
|
|
|
|
|
|
token_t tokenInfo;
|
|
|
lookupToken(conv, tokenInfo);
|
|
|
|
|
|
- if(tokenInfo.sz < sizeof(unsigned short))
|
|
|
- {
|
|
|
+ if(tokenInfo.sz < sizeof(unsigned short)) {
|
|
|
fseek(fp, -1, SEEK_CUR);
|
|
|
nBytesRead++;
|
|
|
- }
|
|
|
- else
|
|
|
+ } else
|
|
|
nBytesRead += 2;
|
|
|
|
|
|
if(conv == "AsmPrgm")
|