882 lines
18 KiB
C
882 lines
18 KiB
C
/* -*- c-file-style: "linux";indent-tabs-mode:t -*- */
|
|
/* Copyright (C) 2016 Jeremiah Orians
|
|
* Copyright (C) 2017 Jan Nieuwenhuizen <janneke@gnu.org>
|
|
* This file is part of mescc-tools.
|
|
*
|
|
* mescc-tools is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* mescc-tools is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with mescc-tools. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <getopt.h>
|
|
|
|
//CONSTANT max_string 4096
|
|
#define max_string 4096
|
|
//CONSTANT PROCESSED 1
|
|
#define PROCESSED 1
|
|
//CONSTANT STR 2
|
|
#define STR 2
|
|
//CONSTANT NEWLINE 3
|
|
#define NEWLINE 3
|
|
|
|
//CONSTANT TRUE 1
|
|
#define TRUE 1
|
|
//CONSTANT FALSE 0
|
|
#define FALSE 0
|
|
|
|
// CONSTANT KNIGHT 0
|
|
#define KNIGHT 0
|
|
// CONSTANT X86 1
|
|
#define X86 1
|
|
// CONSTANT AMD64 2
|
|
#define AMD64 2
|
|
// CONSTANT ARMV7L 40
|
|
#define ARMV7L 40
|
|
// CONSTANT AARM64 80
|
|
#define AARM64 80
|
|
|
|
// CONSTANT HEX 16
|
|
#define HEX 16
|
|
// CONSTANT OCTAL 8
|
|
#define OCTAL 8
|
|
// CONSTANT BINARY 2
|
|
#define BINARY 2
|
|
|
|
|
|
/* Imported functions */
|
|
char* numerate_number(int a);
|
|
int hex2char(int c);
|
|
int in_set(int c, char* s);
|
|
int match(char* a, char* b);
|
|
int numerate_string(char *a);
|
|
int string_length(char* a);
|
|
void file_print(char* s, FILE* f);
|
|
void require(int bool, char* error);
|
|
|
|
struct blob
|
|
{
|
|
struct blob* next;
|
|
int type;
|
|
char* Text;
|
|
char* Expression;
|
|
struct blob* hash_next;
|
|
};
|
|
|
|
struct Token
|
|
{
|
|
struct Token* next;
|
|
struct blob* contents;
|
|
char* filename;
|
|
int linenumber;
|
|
};
|
|
|
|
/* Globals */
|
|
FILE* source_file;
|
|
FILE* destination_file;
|
|
int BigEndian;
|
|
int BigBitEndian;
|
|
int ByteMode;
|
|
int Architecture;
|
|
int linenumber;
|
|
struct Token* token_list;
|
|
struct blob* blob_list;
|
|
struct blob* define_blob;
|
|
struct blob* newline_blob;
|
|
int blob_count;
|
|
char* SCRATCH;
|
|
struct blob** hash_table;
|
|
|
|
void line_error(char* filename, int linenumber)
|
|
{
|
|
file_print(filename, stderr);
|
|
file_print(":", stderr);
|
|
file_print(numerate_number(linenumber), stderr);
|
|
file_print(" :", stderr);
|
|
}
|
|
|
|
void ClearScratch()
|
|
{
|
|
int i = 0;
|
|
int c = SCRATCH[i];
|
|
while(0 != c)
|
|
{
|
|
SCRATCH[i] = 0;
|
|
i = i + 1;
|
|
c = SCRATCH[i];
|
|
}
|
|
}
|
|
|
|
int GetHash(char* s)
|
|
{
|
|
int i = 5381;
|
|
while(0 != s[0])
|
|
{
|
|
i = (i << 5) + i + s[0];
|
|
s = s + 1;
|
|
}
|
|
return i & 0xFFFF;
|
|
}
|
|
|
|
struct blob* FindBlob()
|
|
{
|
|
int hash = GetHash(SCRATCH);
|
|
struct blob* i = hash_table[hash];
|
|
while(NULL != i)
|
|
{
|
|
if(match(SCRATCH, i->Text)) return i;
|
|
i = i->hash_next;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void AddHash(struct blob* a, char* s)
|
|
{
|
|
int i = GetHash(s);
|
|
a->hash_next = hash_table[i];
|
|
hash_table[i] = a;
|
|
}
|
|
|
|
void NewBlob(int size)
|
|
{
|
|
blob_count = blob_count + 1;
|
|
struct blob* a = calloc(1, sizeof(struct blob));
|
|
require(NULL != a, "Exhusted available memory\n");
|
|
a->Text = calloc(size + 1, sizeof(char));
|
|
require(NULL != a->Text, "Exhusted available memory\n");
|
|
|
|
int i = 0;
|
|
while(i <= size)
|
|
{
|
|
a->Text[i] = SCRATCH[i];
|
|
i = i + 1;
|
|
}
|
|
a->next = blob_list;
|
|
blob_list = a;
|
|
AddHash(a, SCRATCH);
|
|
}
|
|
|
|
struct Token* newToken(char* filename, int linenumber)
|
|
{
|
|
struct Token* p;
|
|
|
|
p = calloc (1, sizeof (struct Token));
|
|
require(NULL != p, "Exhusted available memory\n");
|
|
|
|
p->filename = filename;
|
|
p->linenumber = linenumber;
|
|
|
|
return p;
|
|
}
|
|
|
|
struct Token* reverse_list(struct Token* head)
|
|
{
|
|
struct Token* root = NULL;
|
|
struct Token* next;
|
|
while(NULL != head)
|
|
{
|
|
next = head->next;
|
|
head->next = root;
|
|
root = head;
|
|
head = next;
|
|
}
|
|
return root;
|
|
}
|
|
|
|
void purge_lineComment()
|
|
{
|
|
int c = fgetc(source_file);
|
|
while(!in_set(c, "\n\r"))
|
|
{
|
|
if(EOF == c) break;
|
|
c = fgetc(source_file);
|
|
}
|
|
}
|
|
|
|
struct Token* append_newline(struct Token* head, char* filename)
|
|
{
|
|
linenumber = linenumber + 1;
|
|
if(NULL == head) return NULL;
|
|
if(NEWLINE == head->contents->type)
|
|
{/* Don't waste whitespace*/
|
|
return head;
|
|
}
|
|
|
|
struct Token* lf = newToken(filename, linenumber);
|
|
lf->contents = newline_blob;
|
|
lf->next = head;
|
|
return lf;
|
|
}
|
|
|
|
|
|
struct Token* store_atom(struct Token* head, char c, char* filename)
|
|
{
|
|
ClearScratch();
|
|
int ch = c;
|
|
int i = 0;
|
|
do
|
|
{
|
|
SCRATCH[i] = ch;
|
|
ch = fgetc(source_file);
|
|
i = i + 1;
|
|
require(i < max_string, "storing atom of size larger than max_string\n");
|
|
if(EOF == ch) break;
|
|
} while (!in_set(ch, "\t\n "));
|
|
|
|
head->contents = FindBlob();
|
|
if(NULL == head->contents)
|
|
{
|
|
NewBlob(i);
|
|
head->contents = blob_list;
|
|
}
|
|
|
|
if('\n' == ch)
|
|
{
|
|
return append_newline(head, filename);
|
|
}
|
|
return head;
|
|
}
|
|
|
|
struct blob* store_string(char c, char* filename)
|
|
{
|
|
ClearScratch();
|
|
|
|
int ch = c;
|
|
int i = 0;
|
|
do
|
|
{
|
|
SCRATCH[i] = ch;
|
|
i = i + 1;
|
|
if('\n' == ch) linenumber = linenumber + 1;
|
|
ch = fgetc(source_file);
|
|
require(EOF != ch, "Unmatched \"!\n");
|
|
|
|
if(max_string == i)
|
|
{
|
|
line_error(filename, linenumber);
|
|
file_print("String: ", stderr);
|
|
file_print(SCRATCH, stderr);
|
|
file_print(" exceeds max string size\n", stderr);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
} while(ch != c);
|
|
|
|
struct blob* a = FindBlob();
|
|
if(NULL == a)
|
|
{
|
|
NewBlob(i);
|
|
a = blob_list;
|
|
a->type = STR;
|
|
}
|
|
|
|
return a;
|
|
}
|
|
|
|
struct Token* Tokenize_Line(struct Token* head, char* filename)
|
|
{
|
|
int c;
|
|
struct Token* p;
|
|
linenumber = 1;
|
|
|
|
do
|
|
{
|
|
restart:
|
|
c = fgetc(source_file);
|
|
|
|
if(in_set(c, ";#"))
|
|
{
|
|
purge_lineComment();
|
|
head = append_newline(head, filename);
|
|
goto restart;
|
|
}
|
|
|
|
if(in_set(c, "\t "))
|
|
{
|
|
goto restart;
|
|
}
|
|
|
|
if('\n' == c)
|
|
{
|
|
head = append_newline(head, filename);
|
|
goto restart;
|
|
}
|
|
|
|
if(EOF == c)
|
|
{
|
|
head = append_newline(head, filename);
|
|
goto done;
|
|
}
|
|
|
|
p = newToken(filename, linenumber);
|
|
p->next = head;
|
|
if(in_set(c, "'\""))
|
|
{
|
|
p->contents = store_string(c, filename);
|
|
}
|
|
else
|
|
{
|
|
p = store_atom(p, c, filename);
|
|
}
|
|
|
|
head = p;
|
|
} while(TRUE);
|
|
done:
|
|
return head;
|
|
}
|
|
|
|
void line_macro(struct Token* p)
|
|
{
|
|
struct Token* i;
|
|
for(i = p; NULL != i; i = i->next)
|
|
{
|
|
if(define_blob == i->contents)
|
|
{
|
|
require(NULL != i->next, "Macro name must exist\n");
|
|
require(NULL != i->next->next, "Macro value must exist\n");
|
|
if(PROCESSED == i->next->contents->type)
|
|
{
|
|
line_error(i->filename, i->linenumber);
|
|
file_print("Multiple definitions for macro ", stderr);
|
|
file_print(i->next->contents->Text, stderr);
|
|
file_print("\n", stderr);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
i->contents = newline_blob;
|
|
|
|
if (STR == i->next->next->contents->type)
|
|
{
|
|
i->contents->Expression = i->next->next->contents->Text + 1;
|
|
}
|
|
else
|
|
{
|
|
i->next->contents->Expression = i->next->next->contents->Text;
|
|
}
|
|
i->next = i->next->next->next;
|
|
}
|
|
}
|
|
}
|
|
|
|
void hexify_string(struct blob* p)
|
|
{
|
|
char* table = "0123456789ABCDEF";
|
|
int i = string_length(p->Text);
|
|
int size;
|
|
|
|
if(HEX == ByteMode) size = (((i << 1) + i) + 12);
|
|
else if(OCTAL == ByteMode) size = (i << 2) + 1;
|
|
else if(BINARY == ByteMode) size = (i << 3) + i + 1;
|
|
else size = 1;
|
|
|
|
require(1 != size, "hexify_string lacked a valid bytemode\n");
|
|
char* d = calloc(size, sizeof(char));
|
|
require(NULL != d, "Exhusted available memory\n");
|
|
p->Expression = d;
|
|
char* S = p->Text;
|
|
|
|
if((KNIGHT == Architecture) && (HEX == ByteMode))
|
|
{
|
|
i = (((((i - 1) >> 2) + 1) << 3) + i);
|
|
while( 0 < i)
|
|
{
|
|
i = i - 1;
|
|
d[i] = '0';
|
|
}
|
|
}
|
|
|
|
if(HEX == ByteMode)
|
|
{
|
|
while(0 != S[0])
|
|
{
|
|
S = S + 1;
|
|
d[0] = table[S[0] >> 4];
|
|
d[1] = table[S[0] & 0xF];
|
|
d[2] = ' ';
|
|
d = d + 3;
|
|
}
|
|
}
|
|
else if(OCTAL == ByteMode)
|
|
{
|
|
while(0 != S[0])
|
|
{
|
|
S = S + 1;
|
|
d[0] = table[S[0] >> 6];
|
|
d[1] = table[(S[0] >> 3) & 0x7];
|
|
d[2] = table[S[0] & 0x7];
|
|
d[3] = ' ';
|
|
d = d + 4;
|
|
}
|
|
}
|
|
else if(BINARY == ByteMode)
|
|
{
|
|
while(0 != S[0])
|
|
{
|
|
S = S + 1;
|
|
d[0] = table[S[0] >> 7];
|
|
d[1] = table[(S[0] >> 6) & 0x1];
|
|
d[2] = table[(S[0] >> 5) & 0x1];
|
|
d[3] = table[(S[0] >> 4) & 0x1];
|
|
d[4] = table[(S[0] >> 3) & 0x1];
|
|
d[5] = table[(S[0] >> 2) & 0x1];
|
|
d[6] = table[(S[0] >> 1) & 0x1];
|
|
d[7] = table[S[0] & 0x1];
|
|
d[8] = ' ';
|
|
d = d + 9;
|
|
}
|
|
}
|
|
}
|
|
|
|
void process_string(struct blob* p)
|
|
{
|
|
struct blob* i;
|
|
for(i = p; NULL != i; i = i->next)
|
|
{
|
|
if(STR == i->type)
|
|
{
|
|
if('\'' == i->Text[0])
|
|
{
|
|
i->Expression = i->Text + 1;
|
|
}
|
|
else if('"' == i->Text[0])
|
|
{
|
|
hexify_string(i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
char* pad_nulls(int size, char* nil)
|
|
{
|
|
if(0 == size) return nil;
|
|
require(size > 0, "negative null padding not possible\n");
|
|
if(HEX == ByteMode) size = size * 2;
|
|
else if (OCTAL == ByteMode) size = size * 3;
|
|
else if (BINARY == ByteMode) size = size * 8;
|
|
|
|
char* s = calloc(size + 1, sizeof(char));
|
|
require(NULL != s, "Exhusted available memory\n");
|
|
|
|
int i = 0;
|
|
while(i < size)
|
|
{
|
|
s[i] = '0';
|
|
i = i + 1;
|
|
}
|
|
|
|
return s;
|
|
}
|
|
|
|
void preserve_other(struct blob* p)
|
|
{
|
|
struct blob* i;
|
|
char c;
|
|
for(i = p; NULL != i; i = i->next)
|
|
{
|
|
if((NULL == i->Expression) && !(i->type & PROCESSED))
|
|
{
|
|
c = i->Text[0];
|
|
|
|
if(in_set(c, "!@$~%&:^"))
|
|
{
|
|
i->Expression = i->Text;
|
|
}
|
|
else if('<' == c)
|
|
{
|
|
i->Expression = pad_nulls(numerate_string(i->Text + 1), i->Text);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void bound_values(int displacement, int number_of_bytes, int low, int high)
|
|
{
|
|
if((high < displacement) || (displacement < low))
|
|
{
|
|
file_print("A displacement of ", stderr);
|
|
file_print(numerate_number(displacement), stderr);
|
|
file_print(" does not fit in ", stderr);
|
|
file_print(numerate_number(number_of_bytes), stderr);
|
|
file_print(" bytes\n", stderr);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
|
|
void range_check(int displacement, int number_of_bytes)
|
|
{
|
|
if(4 == number_of_bytes) return;
|
|
else if(3 == number_of_bytes)
|
|
{
|
|
bound_values(displacement, number_of_bytes, -8388608, 16777216);
|
|
return;
|
|
}
|
|
else if(2 == number_of_bytes)
|
|
{
|
|
bound_values(displacement, number_of_bytes, -32768, 65535);
|
|
return;
|
|
}
|
|
else if(1 == number_of_bytes)
|
|
{
|
|
bound_values(displacement, number_of_bytes, -128, 255);
|
|
return;
|
|
}
|
|
|
|
file_print("Received an invalid number of bytes in range_check\n", stderr);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
void reverseBitOrder(char* c)
|
|
{
|
|
if(NULL == c) return;
|
|
if(0 == c[1]) return;
|
|
int hold = c[0];
|
|
|
|
if(HEX == ByteMode)
|
|
{
|
|
c[0] = c[1];
|
|
c[1] = hold;
|
|
reverseBitOrder(c+2);
|
|
}
|
|
else if(OCTAL == ByteMode)
|
|
{
|
|
c[0] = c[2];
|
|
c[2] = hold;
|
|
reverseBitOrder(c+3);
|
|
}
|
|
else if(BINARY == ByteMode)
|
|
{
|
|
c[0] = c[7];
|
|
c[7] = hold;
|
|
hold = c[1];
|
|
c[1] = c[6];
|
|
c[6] = hold;
|
|
hold = c[2];
|
|
c[2] = c[5];
|
|
c[5] = hold;
|
|
hold = c[3];
|
|
c[3] = c[4];
|
|
c[4] = hold;
|
|
reverseBitOrder(c+8);
|
|
}
|
|
}
|
|
|
|
void LittleEndian(char* start)
|
|
{
|
|
char* end = start;
|
|
char* c = start;
|
|
while(0 != end[0]) end = end + 1;
|
|
int hold;
|
|
for(end = end - 1; start < end; start = start + 1)
|
|
{
|
|
hold = start[0];
|
|
start[0] = end[0];
|
|
end[0] = hold;
|
|
end = end - 1;
|
|
}
|
|
|
|
if(BigBitEndian) reverseBitOrder(c);
|
|
}
|
|
|
|
int stringify(char* s, int digits, int divisor, int value, int shift)
|
|
{
|
|
int i = value;
|
|
if(digits > 1)
|
|
{
|
|
i = stringify(s+1, (digits - 1), divisor, value, shift);
|
|
}
|
|
s[0] = hex2char(i & (divisor - 1));
|
|
return (i >> shift);
|
|
}
|
|
|
|
char* express_number(int value, char c)
|
|
{
|
|
char* ch = calloc(42, sizeof(char));
|
|
require(NULL != ch, "Exhusted available memory\n");
|
|
int size;
|
|
int number_of_bytes;
|
|
int shift;
|
|
if('!' == c)
|
|
{
|
|
number_of_bytes = 1;
|
|
value = value & 0xFF;
|
|
}
|
|
else if('@' == c)
|
|
{
|
|
number_of_bytes = 2;
|
|
value = value & 0xFFFF;
|
|
}
|
|
else if('~' == c)
|
|
{
|
|
number_of_bytes = 3;
|
|
value = value & 0xFFFFFF;
|
|
}
|
|
else if('%' == c)
|
|
{
|
|
number_of_bytes = 4;
|
|
value = value & 0xFFFFFFFF;
|
|
}
|
|
else
|
|
{
|
|
file_print("Given symbol ", stderr);
|
|
fputc(c, stderr);
|
|
file_print(" to express immediate value ", stderr);
|
|
file_print(numerate_number(value), stderr);
|
|
fputc('\n', stderr);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
range_check(value, number_of_bytes);
|
|
|
|
if(HEX == ByteMode)
|
|
{
|
|
size = number_of_bytes * 2;
|
|
shift = 4;
|
|
}
|
|
else if(OCTAL == ByteMode)
|
|
{
|
|
size = number_of_bytes * 3;
|
|
shift = 3;
|
|
}
|
|
else if(BINARY == ByteMode)
|
|
{
|
|
size = number_of_bytes * 8;
|
|
shift = 1;
|
|
}
|
|
else
|
|
{
|
|
file_print("Got invalid ByteMode in express_number\n", stderr);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
stringify(ch, size, ByteMode, value, shift);
|
|
|
|
if(!BigEndian) LittleEndian(ch);
|
|
else if(!BigBitEndian) reverseBitOrder(ch);
|
|
return ch;
|
|
}
|
|
|
|
void eval_immediates(struct blob* p)
|
|
{
|
|
struct blob* i;
|
|
int value;
|
|
for(i = p; NULL != i; i = i->next)
|
|
{
|
|
if(PROCESSED == i->type) continue;
|
|
else if(NEWLINE == i->type) continue;
|
|
else if('<' == i->Text[0]) continue;
|
|
else if(NULL == i->Expression)
|
|
{
|
|
if((X86 == Architecture) || (AMD64 == Architecture) || (ARMV7L == Architecture) || (AARM64 == Architecture))
|
|
{
|
|
if(in_set(i->Text[0], "%~@!"))
|
|
{
|
|
value = numerate_string(i->Text + 1);
|
|
|
|
if(('0' == i->Text[1]) || (0 != value))
|
|
{
|
|
i->Expression = express_number(value, i->Text[0]);
|
|
}
|
|
}
|
|
}
|
|
else if(KNIGHT == Architecture)
|
|
{
|
|
value = numerate_string(i->Text);
|
|
if(('0' == i->Text[0]) || (0 != value))
|
|
{
|
|
i->Expression = express_number(value, '@');
|
|
}
|
|
}
|
|
else
|
|
{
|
|
file_print("Unknown architecture received in eval_immediates\n", stderr);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void print_hex(struct Token* p)
|
|
{
|
|
struct Token* i;
|
|
for(i = p; NULL != i; i = i->next)
|
|
{
|
|
if(NEWLINE == i->contents->type)
|
|
{
|
|
if(NULL == i->next) fputc('\n', destination_file);
|
|
else if(NEWLINE != i->next->contents->type) fputc('\n', destination_file);
|
|
}
|
|
else if(NULL != i->contents->Expression)
|
|
{
|
|
file_print(i->contents->Expression, destination_file);
|
|
if(NEWLINE != i->next->contents->type) fputc(' ', destination_file);
|
|
}
|
|
else
|
|
{
|
|
line_error(i->filename, i->linenumber);
|
|
file_print("Received invalid other; ", stderr);
|
|
file_print(i->contents->Text, stderr);
|
|
file_print("\n", stderr);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Standard C main program */
|
|
int main(int argc, char **argv)
|
|
{
|
|
BigEndian = TRUE;
|
|
Architecture = KNIGHT;
|
|
destination_file = stdout;
|
|
BigBitEndian = TRUE;
|
|
ByteMode = HEX;
|
|
char* filename;
|
|
char* arch;
|
|
blob_count = 2;
|
|
hash_table = calloc(65537, sizeof(struct blob*));
|
|
|
|
/* Create newline blob */
|
|
newline_blob = calloc(1, sizeof(struct blob));
|
|
newline_blob->Text = "\n";
|
|
newline_blob->Expression = "\n";
|
|
newline_blob->type = NEWLINE;
|
|
AddHash(newline_blob, "\n");
|
|
|
|
/* Start the blob list with DEFINE and newline */
|
|
blob_list = calloc(1, sizeof(struct blob));
|
|
blob_list->Text = "DEFINE";
|
|
define_blob = blob_list;
|
|
blob_list->next = newline_blob;
|
|
AddHash(define_blob, "DEFINE");
|
|
|
|
/* Initialize scratch */
|
|
SCRATCH = calloc(max_string + 1, sizeof(char));
|
|
|
|
int option_index = 1;
|
|
while(option_index <= argc)
|
|
{
|
|
if(NULL == argv[option_index])
|
|
{
|
|
option_index = option_index + 1;
|
|
}
|
|
else if(match(argv[option_index], "--BigEndian") || match(argv[option_index], "--big-endian"))
|
|
{
|
|
BigEndian = TRUE;
|
|
option_index = option_index + 1;
|
|
}
|
|
else if(match(argv[option_index], "--LittleEndian") || match(argv[option_index], "--little-endian"))
|
|
{
|
|
BigEndian = FALSE;
|
|
option_index = option_index + 1;
|
|
}
|
|
else if(match(argv[option_index], "-A") || match(argv[option_index], "--architecture"))
|
|
{
|
|
arch = argv[option_index + 1];
|
|
if(match("knight-native", arch) || match("knight-posix", arch)) Architecture = KNIGHT;
|
|
else if(match("x86", arch)) Architecture = X86;
|
|
else if(match("amd64", arch)) Architecture = AMD64;
|
|
else if(match("armv7l", arch)) Architecture = ARMV7L;
|
|
else if(match("aarch64", arch)) Architecture = AARM64;
|
|
else
|
|
{
|
|
file_print("Unknown architecture: ", stderr);
|
|
file_print(arch, stderr);
|
|
file_print(" know values are: knight-native, knight-posix, x86, amd64, armv7l and aarch64", stderr);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
option_index = option_index + 2;
|
|
}
|
|
else if(match(argv[option_index], "-b") || match(argv[option_index], "--binary"))
|
|
{
|
|
ByteMode = BINARY;
|
|
option_index = option_index + 1;
|
|
}
|
|
else if(match(argv[option_index], "-h") || match(argv[option_index], "--help"))
|
|
{
|
|
file_print("Usage: ", stderr);
|
|
file_print(argv[0], stderr);
|
|
file_print(" --file FILENAME1 {-f FILENAME2} (--big-endian|--little-endian) ", stderr);
|
|
file_print("[--architecture name]\nArchitectures: knight-native, knight-posix, x86, amd64 and armv7\n", stderr);
|
|
file_print("To leverage octal or binary output: --octal, --binary\n", stderr);
|
|
exit(EXIT_SUCCESS);
|
|
}
|
|
else if(match(argv[option_index], "-f") || match(argv[option_index], "--file"))
|
|
{
|
|
filename = argv[option_index + 1];
|
|
source_file = fopen(filename, "r");
|
|
|
|
if(NULL == source_file)
|
|
{
|
|
file_print("The file: ", stderr);
|
|
file_print(argv[option_index + 1], stderr);
|
|
file_print(" can not be opened!\n", stderr);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
token_list = Tokenize_Line(token_list, filename);
|
|
|
|
fclose(source_file);
|
|
|
|
option_index = option_index + 2;
|
|
}
|
|
else if(match(argv[option_index], "-o") || match(argv[option_index], "--output"))
|
|
{
|
|
destination_file = fopen(argv[option_index + 1], "w");
|
|
|
|
if(NULL == destination_file)
|
|
{
|
|
file_print("The file: ", stderr);
|
|
file_print(argv[option_index + 1], stderr);
|
|
file_print(" can not be opened!\n", stderr);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
option_index = option_index + 2;
|
|
}
|
|
else if(match(argv[option_index], "-O") || match(argv[option_index], "--octal"))
|
|
{
|
|
ByteMode = OCTAL;
|
|
option_index = option_index + 1;
|
|
}
|
|
else if(match(argv[option_index], "-V") || match(argv[option_index], "--version"))
|
|
{
|
|
file_print("M1 1.0.0\n", stdout);
|
|
exit(EXIT_SUCCESS);
|
|
}
|
|
else
|
|
{
|
|
file_print("Unknown option\n", stderr);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
|
|
if(NULL == token_list)
|
|
{
|
|
file_print("Either no input files were given or they were empty\n", stderr);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
token_list = reverse_list(token_list);
|
|
line_macro(token_list);
|
|
process_string(blob_list);
|
|
eval_immediates(blob_list);
|
|
preserve_other(blob_list);
|
|
print_hex(token_list);
|
|
|
|
if (destination_file != stdout)
|
|
{
|
|
fclose(destination_file);
|
|
}
|
|
|
|
return EXIT_SUCCESS;
|
|
}
|