stage0/stage3/hex2_linker_x86.c

1004 lines
24 KiB
C

## This file was generated by running:
## cat functions/exit.c functions/file.c functions/file_print.c functions/malloc.c functions/calloc.c functions/match.c functions/numerate_number.c functions/stat.c test/test22/hex2_linker.c >| ../stage0/stage3/hex2_linker_x86.c
## inside of M2-Planet's source repo
## Copyright (C) 2016 Jeremiah Orians
## This file is part of stage0.
##
## stage0 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.
##
## stage0 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 stage0. If not, see <http://www.gnu.org/licenses/>.
// CONSTANT EXIT_FAILURE 1
// CONSTANT EXIT_SUCCESS 0
void exit(int value)
{
asm("POP_ebx"
"POP_ebx"
"LOAD_IMMEDIATE_eax %1"
"INT_80");
}
/* Copyright (C) 2016 Jeremiah Orians
* This file is part of stage0.
*
* stage0 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.
*
* stage0 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 stage0. If not, see <http://www.gnu.org/licenses/>.
*/
// CONSTANT stdin 0
// CONSTANT stdout 1
// CONSTANT stderr 2
// CONSTANT EOF 0xFFFFFFFF
int fgetc(FILE* f)
{
asm("LOAD_IMMEDIATE_eax %3"
"LOAD_EFFECTIVE_ADDRESS_ebx %4"
"LOAD_INTEGER_ebx"
"PUSH_ebx"
"COPY_esp_to_ecx"
"LOAD_IMMEDIATE_edx %1"
"INT_80"
"TEST"
"POP_eax"
"JUMP_NE8 !FUNCTION_fgetc_Done"
"LOAD_IMMEDIATE_eax %-1"
":FUNCTION_fgetc_Done");
}
void fputc(char s, FILE* f)
{
asm("LOAD_IMMEDIATE_eax %4"
"LOAD_EFFECTIVE_ADDRESS_ebx %4"
"LOAD_INTEGER_ebx"
"LOAD_EFFECTIVE_ADDRESS_ecx %8"
"LOAD_IMMEDIATE_edx %1"
"INT_80");
}
/* Important values needed for open
* O_RDONLY => 0
* O_WRONLY => 1
* O_RDWR => 2
* O_CREAT => 64
* O_TRUNC => 512
* S_IRWXU => 00700
* S_IXUSR => 00100
* S_IWUSR => 00200
* S_IRUSR => 00400
*/
FILE* open(char* name, int flag, int mode)
{
asm("LOAD_EFFECTIVE_ADDRESS_ebx %12"
"LOAD_INTEGER_ebx"
"LOAD_EFFECTIVE_ADDRESS_ecx %8"
"LOAD_INTEGER_ecx"
"LOAD_EFFECTIVE_ADDRESS_edx %4"
"LOAD_INTEGER_edx"
"LOAD_IMMEDIATE_eax %5"
"INT_80");
}
FILE* fopen(char* filename, char* mode)
{
FILE* f;
if('w' == mode[0])
{ /* 577 is O_WRONLY|O_CREAT|O_TRUNC, 384 is 600 in octal */
f = open(filename, 577 , 384);
}
else
{ /* Everything else is a read */
f = open(filename, 0, 0);
}
/* Negative numbers are error codes */
if(0 > f)
{
return 0;
}
return f;
}
int close(int fd)
{
asm("LOAD_EFFECTIVE_ADDRESS_ebx %4"
"LOAD_IMMEDIATE_eax %6"
"INT_80");
}
int fclose(FILE* stream)
{
int error = close(stream);
return error;
}
/* Copyright (C) 2016 Jeremiah Orians
* This file is part of stage0.
*
* stage0 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.
*
* stage0 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 stage0. If not, see <http://www.gnu.org/licenses/>.
*/
#include<stdio.h>
// void fputc(char s, FILE* f);
void file_print(char* s, FILE* f)
{
while(0 != s[0])
{
fputc(s[0], f);
s = s + 1;
}
}
## Copyright (C) 2016 Jeremiah Orians
## This file is part of stage0.
##
## stage0 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.
##
## stage0 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 stage0. If not, see <http://www.gnu.org/licenses/>.
// CONSTANT NULL 0
void* malloc(int size)
{
asm("STORE_eax_into_ESP_IMMEDIATE8 !4"
"PUSH_eax"
"LOAD_IMMEDIATE_eax %45"
"LOAD_IMMEDIATE_ebx %0"
"INT_80"
"POP_ebx"
"ADD_eax_to_ebx"
"PUSH_eax"
"PUSH_ebx"
"LOAD_IMMEDIATE_eax %45"
"INT_80"
"POP_ebx"
"CMP"
"POP_eax"
"JUMP_EQ8 !FUNCTION_malloc_Done"
"LOAD_IMMEDIATE_eax %-1"
":FUNCTION_malloc_Done");
}
/* Copyright (C) 2016 Jeremiah Orians
* This file is part of stage0.
*
* stage0 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.
*
* stage0 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 stage0. If not, see <http://www.gnu.org/licenses/>.
*/
// void* malloc(int size);
void* memset(void* ptr, int value, int num)
{
char* s;
for(s = ptr; 0 < num; num = num - 1)
{
s[0] = value;
s = s + 1;
}
}
void* calloc(int count, int size)
{
void* ret = malloc(count * size);
memset(ret, 0, (count * size));
return ret;
}
void free(void* l)
{
return;
}
/* Copyright (C) 2016 Jeremiah Orians
* This file is part of stage0.
*
* stage0 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.
*
* stage0 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 stage0. If not, see <http://www.gnu.org/licenses/>.
*/
#define FALSE 0
// CONSTANT FALSE 0
#define TRUE 1
// CONSTANT TRUE 1
int match(char* a, char* b)
{
int i = -1;
do
{
i = i + 1;
if(a[i] != b[i])
{
return FALSE;
}
} while((0 != a[i]) && (0 !=b[i]));
return TRUE;
}
/* Copyright (C) 2016 Jeremiah Orians
* This file is part of stage0.
*
* stage0 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.
*
* stage0 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 stage0. If not, see <http://www.gnu.org/licenses/>.
*/
#include<stdlib.h>
#include<string.h>
// void* calloc(int count, int size);
#define TRUE 1
//CONSTANT TRUE 1
#define FALSE 0
//CONSTANT FALSE 0
char* numerate_number(int a)
{
char* result = calloc(16, sizeof(char));
int i = 0;
/* Deal with Zero case */
if(0 == a)
{
result[0] = '0';
return result;
}
/* Deal with negatives */
if(0 > a)
{
result[0] = '-';
i = 1;
a = a * -1;
}
/* Using the largest 10^n number possible in 32bits */
int divisor = 0x3B9ACA00;
/* Skip leading Zeros */
while(0 == (a / divisor)) divisor = divisor / 10;
/* Now simply collect numbers until divisor is gone */
while(0 < divisor)
{
result[i] = ((a / divisor) + 48);
a = a % divisor;
divisor = divisor / 10;
i = i + 1;
}
return result;
}
int char2hex(int c)
{
if (c >= '0' && c <= '9') return (c - 48);
else if (c >= 'a' && c <= 'f') return (c - 87);
else if (c >= 'A' && c <= 'F') return (c - 55);
else return -1;
}
int hex2char(int c)
{
if((c >= 0) && (c <= 9)) return (c + 48);
else if((c >= 10) && (c <= 15)) return (c + 55);
else return -1;
}
int char2dec(int c)
{
if (c >= '0' && c <= '9') return (c - 48);
else return -1;
}
int dec2char(int c)
{
if((c >= 0) && (c <= 9)) return (c + 48);
else return -1;
}
int numerate_string(char *a)
{
int count = 0;
int index;
int negative;
/* If NULL string */
if(0 == a[0])
{
return 0;
}
/* Deal with hex */
else if (a[0] == '0' && a[1] == 'x')
{
if('-' == a[2])
{
negative = TRUE;
index = 3;
}
else
{
negative = FALSE;
index = 2;
}
while(0 != a[index])
{
if(-1 == char2hex(a[index])) return 0;
count = (16 * count) + char2hex(a[index]);
index = index + 1;
}
}
/* Deal with decimal */
else
{
if('-' == a[0])
{
negative = TRUE;
index = 1;
}
else
{
negative = FALSE;
index = 0;
}
while(0 != a[index])
{
if(-1 == char2dec(a[index])) return 0;
count = (10 * count) + char2dec(a[index]);
index = index + 1;
}
}
if(negative)
{
count = count * -1;
}
return count;
}
## Copyright (C) 2016 Jeremiah Orians
## This file is part of stage0.
##
## stage0 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.
##
## stage0 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 stage0. If not, see <http://www.gnu.org/licenses/>.
/*
* chmod() changes the mode of the file specified whose pathname is given in
* pathname, which is dereferenced if it is a symbolic link.
* fchmod() changes the mode of the file referred to by the open file
* descriptor fd.
* The new file mode is specified in mode, which is a bit mask created by
* ORing together zero or more of the following:
* S_ISUID (04000) set-user-ID (set process effective user ID on execve(2))
* S_ISGID (02000) set-group-ID (set process effective group ID on execve(2)
* mandatory locking, as described in fcntl(2); take a new file's group from
* parent directory, as described in chown(2) and mkdir(2))
* S_ISVTX (01000) sticky bit (restricted deletion flag, as described in
* unlink(2))
* S_IRUSR (00400) read by owner
* S_IWUSR (00200) write by owner
* S_IXUSR (00100) execute/search by owner ("search" applies for directories
* , and means that entries within the directory can be accessed)
* S_IRGRP (00040) read by group
* S_IWGRP (00020) write by group
* S_IXGRP (00010) execute/search by group
* S_IROTH (00004) read by others
* S_IWOTH (00002) write by others
* S_IXOTH (00001) execute/search by others
*/
int chmod(char *pathname, int mode)
{
asm("LOAD_EFFECTIVE_ADDRESS_ebx %8"
"LOAD_INTEGER_ebx"
"LOAD_EFFECTIVE_ADDRESS_ecx %4"
"LOAD_INTEGER_ecx"
"LOAD_IMMEDIATE_eax %15"
"INT_80");
}
/* -*- c-file-style: "linux";indent-tabs-mode:t -*- */
/* Copyright (C) 2017 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 <unistd.h>
#include <sys/stat.h>
#define max_string 4096
//CONSTANT max_string 4096
#define TRUE 1
//CONSTANT TRUE 1
#define FALSE 0
//CONSTANT FALSE 0
void file_print(char* s, FILE* f);
int match(char* a, char* b);
char* numerate_number(int a);
int numerate_string(char *a);
struct input_files
{
struct input_files* next;
char* filename;
};
struct entry
{
struct entry* next;
unsigned target;
char* name;
};
FILE* output;
struct entry* jump_table;
int BigEndian;
int Base_Address;
int Architecture;
int ByteMode;
int exec_enable;
int ip;
char* scratch;
char* scratch2;
int consume_token(FILE* source_file, char* s)
{
int i = 0;
int c = fgetc(source_file);
do
{
if(NULL != s) s[i] = c;
i = i + 1;
c = fgetc(source_file);
} while((' ' != c) && ('\t' != c) && ('\n' != c) && '>' != c);
return c;
}
unsigned GetTarget(char* c)
{
struct entry* i;
for(i = jump_table; NULL != i; i = i->next)
{
if(match(c, i->name))
{
return i->target;
}
}
file_print("Target label ", stderr);
file_print(c, stderr);
file_print(" is not valid\n", stderr);
exit(EXIT_FAILURE);
}
int storeLabel(FILE* source_file, int ip)
{
struct entry* entry = calloc(1, sizeof(struct entry));
/* Prepend to list */
entry->next = jump_table;
jump_table = entry;
/* Store string */
entry->name = calloc(max_string + 1, sizeof(char));
int c = consume_token(source_file, entry->name);
/* Ensure we have target address */
entry->target = ip;
return c;
}
void range_check(int displacement, int number_of_bytes)
{
if(4 == number_of_bytes) return;
else if (3 == number_of_bytes)
{
if((8388607 < displacement) || (displacement < -8388608))
{
file_print("A displacement of ", stderr);
file_print(numerate_number(displacement), stderr);
file_print(" does not fit in 3 bytes\n", stderr);
exit(EXIT_FAILURE);
}
return;
}
else if (2 == number_of_bytes)
{
if((32767 < displacement) || (displacement < -32768))
{
file_print("A displacement of ", stderr);
file_print(numerate_number(displacement), stderr);
file_print(" does not fit in 2 bytes\n", stderr);
exit(EXIT_FAILURE);
}
return;
}
else if (1 == number_of_bytes)
{
if((127 < displacement) || (displacement < -128))
{
file_print("A displacement of ", stderr);
file_print(numerate_number(displacement), stderr);
file_print(" does not fit in 1 byte\n", stderr);
exit(EXIT_FAILURE);
}
return;
}
file_print("Invalid number of bytes given\n", stderr);
exit(EXIT_FAILURE);
}
void outputPointer(int displacement, int number_of_bytes)
{
unsigned value = displacement;
/* HALT HARD if we are going to do something BAD*/
range_check(displacement, number_of_bytes);
if(BigEndian)
{ /* Deal with BigEndian */
if(4 == number_of_bytes) fputc((value >> 24), output);
if(3 <= number_of_bytes) fputc(((value >> 16)%256), output);
if(2 <= number_of_bytes) fputc(((value >> 8)%256), output);
if(1 <= number_of_bytes) fputc((value % 256), output);
}
else
{ /* Deal with LittleEndian */
while(number_of_bytes > 0)
{
unsigned byte = value % 256;
value = value / 256;
fputc(byte, output);
number_of_bytes = number_of_bytes - 1;
}
}
}
int Architectural_displacement(int target, int base)
{
if(0 == Architecture) return (target - base);
else if(1 == Architecture) return (target - base);
else if(2 == Architecture) return (target - base);
else if(40 == Architecture) return (target - base);
file_print("Unknown Architecture, aborting before harm is done\n", stderr);
exit(EXIT_FAILURE);
}
int ConsumePointer(char ch, FILE* source_file, char* s)
{
/* Calculate pointer size*/
if((37 == ch) || (38 == ch)) ip = ip + 4; /* Deal with % and & */
else if((64 == ch) || (36 == ch)) ip = ip + 2; /* Deal with @ and $ */
else if(33 == ch) ip = ip + 1; /* Deal with ! */
else
{
file_print("storePointer given unknown\n", stderr);
exit(EXIT_FAILURE);
}
return consume_token(source_file, s);
}
void storePointer(char ch, FILE* source_file)
{
/* Get string of pointer */
memset (scratch, 0, max_string + 1);
int base_sep_p = (ConsumePointer(ch, source_file, scratch) == 62); /* '>' */
/* Lookup token */
int target = GetTarget(scratch);
int displacement;
int base = ip;
/* Change relative base address to :<base> */
if (base_sep_p)
{
memset (scratch2, 0, max_string + 1);
consume_token (source_file, scratch2);
base = GetTarget (scratch2);
}
displacement = Architectural_displacement(target, base);
/* output calculated difference */
if(33 == ch)
{
if(40 == Architecture) outputPointer(displacement - 7, 1); /* Deal with ! */
else outputPointer(displacement, 1); /* Deal with ! */
}
else if(36 == ch) outputPointer(target, 2); /* Deal with $ */
else if(64 == ch) outputPointer(displacement, 2); /* Deal with @ */
else if(38 == ch) outputPointer(target, 4); /* Deal with & */
else if(37 == ch) outputPointer(displacement, 4); /* Deal with % */
else
{
file_print("storePointer reached impossible case: ch=", stderr);
fputc(ch, stderr);
file_print("\n", stderr);
exit(EXIT_FAILURE);
}
}
void line_Comment(FILE* source_file)
{
int c = fgetc(source_file);
while((10 != c) && (13 != c))
{
c = fgetc(source_file);
}
}
int hex(int c, FILE* source_file)
{
if (c >= '0' && c <= '9') return (c - 48);
else if (c >= 'a' && c <= 'z') return (c - 87);
else if (c >= 'A' && c <= 'Z') return (c - 55);
else if (c == '#' || c == ';') line_Comment(source_file);
return -1;
}
int octal(int c, FILE* source_file)
{
if (c >= '0' && c <= '7') return (c - 48);
else if (c == '#' || c == ';') line_Comment(source_file);
return -1;
}
int binary(int c, FILE* source_file)
{
if (c == '0' || c == '1') return (c - 48);
else if (c == '#' || c == ';') line_Comment(source_file);
return -1;
}
int hold;
int toggle;
void process_byte(char c, FILE* source_file, int write)
{
if(16 == ByteMode)
{
if(0 <= hex(c, source_file))
{
if(toggle)
{
if(write) fputc(((hold * 16)) + hex(c, source_file), output);
ip = ip + 1;
hold = 0;
}
else
{
hold = hex(c, source_file);
}
toggle = !toggle;
}
}
else if(8 ==ByteMode)
{
if(0 <= octal(c, source_file))
{
if(2 == toggle)
{
if(write) fputc(((hold * 8)) + octal(c, source_file), output);
ip = ip + 1;
hold = 0;
toggle = 0;
}
else if(1 == toggle)
{
hold = ((hold * 8) + octal(c, source_file));
toggle = 2;
}
else
{
hold = octal(c, source_file);
toggle = 1;
}
}
}
else if(2 == ByteMode)
{
if(0 <= binary(c, source_file))
{
if(7 == toggle)
{
if(write) fputc((hold * 2) + binary(c, source_file), output);
ip = ip + 1;
hold = 0;
toggle = 0;
}
else
{
hold = ((hold * 2) + binary(c, source_file));
toggle = toggle + 1;
}
}
}
}
void first_pass(struct input_files* input)
{
if(NULL == input) return;
first_pass(input->next);
FILE* source_file = fopen(input->filename, "r");
if(NULL == source_file)
{
file_print("The file: ", stderr);
file_print(input->filename, stderr);
file_print(" can not be opened!\n", stderr);
exit(EXIT_FAILURE);
}
toggle = FALSE;
int c;
for(c = fgetc(source_file); EOF != c; c = fgetc(source_file))
{
/* Check for and deal with label */
if(58 == c)
{
c = storeLabel(source_file, ip);
}
/* check for and deal with relative/absolute pointers to labels */
if((33 == c) || (64 == c) || (36 == c) || (37 == c) || (38 == c))
{ /* deal with 1byte pointer !; 2byte pointers (@ and $); 4byte pointers (% and &) */
c = ConsumePointer(c, source_file, NULL);
if (62 == c)
{ /* deal with label>base */
c = consume_token (source_file, NULL);
}
}
else process_byte(c, source_file, FALSE);
}
fclose(source_file);
}
void second_pass(struct input_files* input)
{
if(NULL == input) return;
second_pass(input->next);
FILE* source_file = fopen(input->filename, "r");
/* Something that should never happen */
if(NULL == source_file)
{
file_print("The file: ", stderr);
file_print(input->filename, stderr);
file_print(" can not be opened!\nWTF-pass2\n", stderr);
exit(EXIT_FAILURE);
}
toggle = FALSE;
hold = 0;
int c;
for(c = fgetc(source_file); EOF != c; c = fgetc(source_file))
{
if(58 == c) c = consume_token(source_file, NULL); /* Deal with : */
else if((33 == c) || (64 == c) || (36 == c) || (37 == c) || (38 == c)) storePointer(c, source_file); /* Deal with !, @, $, % and & */
else process_byte(c, source_file, TRUE);
}
fclose(source_file);
}
/* Standard C main program */
int main(int argc, char **argv)
{
BigEndian = TRUE;
jump_table = NULL;
Architecture = 0;
Base_Address = 0;
struct input_files* input = NULL;
output = stdout;
char* output_file = "";
exec_enable = FALSE;
ByteMode = 16;
scratch = calloc(max_string + 1, sizeof(char));
scratch2 = 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"))
{
BigEndian = TRUE;
option_index = option_index + 1;
}
else if(match(argv[option_index], "--LittleEndian"))
{
BigEndian = FALSE;
option_index = option_index + 1;
}
else if(match(argv[option_index], "--exec_enable"))
{
exec_enable = TRUE;
option_index = option_index + 1;
}
else if(match(argv[option_index], "-A") || match(argv[option_index], "--Architecture"))
{
Architecture = numerate_string(argv[option_index + 1]);
option_index = option_index + 2;
}
else if(match(argv[option_index], "-b") || match(argv[option_index], "--binary"))
{
ByteMode = 2;
option_index = option_index + 1;
}
else if(match(argv[option_index], "-B") || match(argv[option_index], "--BaseAddress"))
{
Base_Address = numerate_string(argv[option_index + 1]);
option_index = option_index + 2;
}
else if(match(argv[option_index], "-h") || match(argv[option_index], "--help"))
{
file_print("Usage: ", stderr);
file_print(argv[0], stderr);
file_print(" -f FILENAME1 {-f FILENAME2} (--BigEndian|--LittleEndian)", stderr);
file_print(" [--BaseAddress 12345] [--Architecture 12345]\nArchitecture", stderr);
file_print(" 0: Knight; 1: x86; 2: AMD64; 40: armv7", stderr);
file_print("\nTo leverage octal or binary", stderr);
file_print(" input: --octal, --binary\n", stderr);
exit(EXIT_SUCCESS);
}
else if(match(argv[option_index], "-f") || match(argv[option_index], "--file"))
{
struct input_files* temp = calloc(1, sizeof(struct input_files));
temp->filename = argv[option_index + 1];
temp->next = input;
input = temp;
option_index = option_index + 2;
}
else if(match(argv[option_index], "-o") || match(argv[option_index], "--output"))
{
output_file = argv[option_index + 1];
output = fopen(output_file, "w");
if(NULL == output)
{
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 = 8;
option_index = option_index + 1;
}
else if(match(argv[option_index], "-V") || match(argv[option_index], "--version"))
{
file_print("hex2 0.3\n", stdout);
exit(EXIT_SUCCESS);
}
else
{
file_print("Unknown option\n", stderr);
exit(EXIT_FAILURE);
}
}
/* Make sure we have a program tape to run */
if (NULL == input)
{
return EXIT_FAILURE;
}
/* Get all of the labels */
ip = Base_Address;
first_pass(input);
/* Fix all the references*/
ip = Base_Address;
second_pass(input);
/* Set file as executable */
if(exec_enable)
{
/* 488 = 750 in octal */
if(0 != chmod(output_file, 488))
{
file_print("Unable to change permissions\n", stderr);
exit(EXIT_FAILURE);
}
}
return EXIT_SUCCESS;
}