2021-01-18 01:47:42 +00:00
|
|
|
/*************/
|
|
|
|
/*GEMWIRE */
|
|
|
|
/* ERYTHRO*/
|
|
|
|
/*************/
|
|
|
|
|
|
|
|
#include <Defs.h>
|
|
|
|
#include <Data.h>
|
2021-01-18 01:49:46 +00:00
|
|
|
#include <errno.h>
|
2021-01-18 01:47:42 +00:00
|
|
|
|
2021-01-21 01:53:00 +00:00
|
|
|
/********************************************************************************
|
|
|
|
* The Delegate is what allows the compiler backend to be abstracted. *
|
|
|
|
* *
|
|
|
|
* It delegates the operation of compiling, assembling and linking *
|
|
|
|
* to the proper subsystems. *
|
|
|
|
* *
|
|
|
|
* As of right now (20/01/2021) it uses the GCC backend. *
|
|
|
|
* *
|
|
|
|
* Compile parses files to their AST and generates mingw PECOFF32+ assembly, *
|
|
|
|
* Assemble uses GCC-as to compile the assembly to an object file. *
|
|
|
|
* Link links the object files into an executable. *
|
|
|
|
* *
|
|
|
|
********************************************************************************/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Files inputted must have a suffix/extension (because we're on Windows right now)
|
|
|
|
* This is the way to change the suffix for when a file is converted to another.
|
|
|
|
*
|
|
|
|
* @param String: The full, current file name
|
|
|
|
* @param Suffix: The new, desired extension.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2021-01-18 01:47:42 +00:00
|
|
|
char* Suffixate(char* String, char Suffix) {
|
|
|
|
char* Pos, *NewStr;
|
|
|
|
|
|
|
|
if((NewStr = strdup(String)) == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if((Pos = strrchr(NewStr, '.')) == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
Pos++;
|
|
|
|
|
|
|
|
if(*Pos == '\0')
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
*Pos++ = Suffix;
|
|
|
|
*Pos = '\0';
|
|
|
|
return NewStr;
|
|
|
|
}
|
|
|
|
|
2021-01-21 01:53:00 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Starts most of the work to do with the Erythro compiler.
|
|
|
|
* It:
|
|
|
|
* Opens the input and output files,
|
|
|
|
* Parses the global symbols of the file, including function blocks.
|
|
|
|
* Generates the assembly representation of the source code
|
|
|
|
*/
|
2021-01-18 01:47:42 +00:00
|
|
|
char* Compile(char* InputFile) {
|
|
|
|
char* OutputName;
|
|
|
|
OutputName = Suffixate(InputFile, 's');
|
|
|
|
if(OutputName == NULL) {
|
|
|
|
fprintf(stderr, "%s must have a suffix.\r\n", InputFile);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if((SourceFile = fopen(InputFile, "r")) == NULL) {
|
|
|
|
fprintf(stderr, "Unable to open %s: %s\n", InputFile, strerror(errno));
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if((OutputFile = fopen(OutputName, "w")) == NULL) {
|
|
|
|
fprintf(stderr, "Unable to open %s: %s\n", OutputName, strerror(errno));
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
Line = 1;
|
|
|
|
Overread = '\n';
|
|
|
|
CurrentGlobal = 0;
|
|
|
|
CurrentLocal = SYMBOLS - 1;
|
|
|
|
|
|
|
|
if(OptVerboseOutput)
|
|
|
|
printf("Compiling %s\r\n", InputFile);
|
|
|
|
|
2021-01-20 19:22:15 +00:00
|
|
|
Tokenise();
|
2021-01-18 01:47:42 +00:00
|
|
|
|
|
|
|
AssemblerPreamble();
|
|
|
|
|
|
|
|
ParseGlobals();
|
|
|
|
|
|
|
|
fclose(OutputFile);
|
|
|
|
return OutputName;
|
|
|
|
}
|
|
|
|
|
|
|
|
char* Assemble(char* InputFile) {
|
|
|
|
char Command[TEXTLEN];
|
|
|
|
int Error;
|
|
|
|
char* OutputName;
|
|
|
|
OutputName = Suffixate(InputFile, 'o');
|
|
|
|
if(OutputName == NULL) {
|
|
|
|
fprintf(stderr, "%s must have a suffix.\r\n", InputFile);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
snprintf(Command, TEXTLEN, "%s %s %s", "as -o ", OutputName, InputFile);
|
|
|
|
if(OptVerboseOutput)
|
|
|
|
printf("%s\n", Command);
|
|
|
|
|
|
|
|
Error = system(Command);
|
|
|
|
|
|
|
|
if(Error != 0) {
|
|
|
|
fprintf(stderr, "Assembling of %s failed with code %d\n", InputFile, Error);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
return OutputName;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Link(char* Output, char* Objects[]) {
|
|
|
|
int Count, Size = TEXTLEN, Error;
|
|
|
|
char Command[TEXTLEN], *CommandPtr;
|
|
|
|
|
|
|
|
CommandPtr = Command;
|
|
|
|
Count = snprintf(CommandPtr, Size, "%s %s ", "gcc -o ", OutputFileName);
|
|
|
|
CommandPtr += Count;
|
|
|
|
Size -= Count;
|
|
|
|
|
|
|
|
while(*Objects != NULL) {
|
|
|
|
Count = snprintf(CommandPtr, Size, "%s ", *Objects);
|
|
|
|
CommandPtr += Count;
|
|
|
|
Size -= Count;
|
|
|
|
Objects++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(OptVerboseOutput)
|
|
|
|
printf("%s\n", Command);
|
|
|
|
|
|
|
|
Error = system(Command);
|
|
|
|
|
|
|
|
if(Error != 0) {
|
|
|
|
fprintf(stderr, "Link failure\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DisplayUsage(char* ProgName) {
|
|
|
|
fprintf(stderr, "Usage: %s -[vcST] {-o output} file [file ...]\n", ProgName);
|
|
|
|
fprintf(stderr, " -v: Verbose Output Level\n");
|
|
|
|
fprintf(stderr, " -c: Compile without Linking\n");
|
|
|
|
fprintf(stderr, " -S: Assemble without Linking\n");
|
|
|
|
fprintf(stderr, " -T: Dump AST\n");
|
|
|
|
fprintf(stderr, " -o: Name of the destination [executable/object/assembly] file.\n");
|
|
|
|
exit(1);
|
|
|
|
}
|