Command line argument parsing
This commit is contained in:
183
src/main.c
183
src/main.c
@@ -2,10 +2,88 @@
|
||||
#include "lexer/lexer.h"
|
||||
#include "parser/parser.h"
|
||||
#include "codegen/codegen.h"
|
||||
#include "include/error.h"
|
||||
#include "include/estr.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#ifdef _WIN32
|
||||
#include <direct.h>
|
||||
#else
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#include <groundvm.h>
|
||||
|
||||
typedef enum SolsAction {
|
||||
SA_PRINT, SA_EXEC, SA_BYTECODE, SA_COMPILE
|
||||
} SolsAction;
|
||||
|
||||
typedef struct Args {
|
||||
SolsAction action;
|
||||
char* inputFile;
|
||||
char* outputFile;
|
||||
} Args;
|
||||
|
||||
Args parseArgs(int argc, char** argv) {
|
||||
Args args = {
|
||||
.action = SA_EXEC,
|
||||
.inputFile = NULL,
|
||||
.outputFile = NULL
|
||||
};
|
||||
for (int i = 0; i < argc; i++) {
|
||||
if (strcmp("-h", argv[i]) == 0 || strcmp("--help", argv[i]) == 0) {
|
||||
printf("Solstice programming language\n");
|
||||
printf("Usage: %s <file> [-h] [--help] [-p] [--print] [-b <file>] [--bytecode <file>] [-c <file>] [--compile <file>]\n", argv[0]);
|
||||
printf("Args:\n");
|
||||
printf(" <file>: Solstice source file\n");
|
||||
printf(" -h or --help: Prints this help message and exits\n");
|
||||
printf(" -p or --print: Prints textual version of Ground bytecode to console\n");
|
||||
printf(" -b <file> or --bytecode <file>: Generates Ground bytecode (.grbc) and saves it to the provided filename\n");
|
||||
printf(" -c <file> or --compile <file>: Compiles Ground to Linux x86_64 assembly, outputs a binary to the provided filename (experimental)\n");
|
||||
printf(" If no extra arguments are provided, the generated Ground bytecode will be executed.\n");
|
||||
exit(0);
|
||||
}
|
||||
else if (strcmp("-p", argv[i]) == 0 || strcmp("--print", argv[i]) == 0) {
|
||||
args.action = SA_PRINT;
|
||||
}
|
||||
else if (strcmp("-b", argv[i]) == 0 || strcmp("--bytecode", argv[i]) == 0) {
|
||||
if (args.action != SA_EXEC) {
|
||||
printf("Expecting only one action\n");
|
||||
exit(1);
|
||||
}
|
||||
args.action = SA_BYTECODE;
|
||||
if (i + 1 >= argc) {
|
||||
printf("Expecting file name after %s\n", argv[i]);
|
||||
exit(1);
|
||||
}
|
||||
i++;
|
||||
args.outputFile = argv[i];
|
||||
}
|
||||
else if (strcmp("-c", argv[i]) == 0 || strcmp("--compile", argv[i]) == 0) {
|
||||
if (args.action != SA_EXEC) {
|
||||
printf("Expecting only one action\n");
|
||||
exit(1);
|
||||
}
|
||||
args.action = SA_COMPILE;
|
||||
if (i + 1 >= argc) {
|
||||
printf("Expecting file name after %s\n", argv[i]);
|
||||
exit(1);
|
||||
}
|
||||
i++;
|
||||
args.outputFile = argv[i];
|
||||
}
|
||||
else {
|
||||
args.inputFile = argv[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (args.inputFile == NULL) {
|
||||
printf("Usage: %s <file> [-h] [--help] [-p] [--print] [-b <file>] [--bytecode <file>] [-c <file>] [--compile <file>]\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
char* getFileContents(const char* filename) {
|
||||
// https://stackoverflow.com/questions/3747086/reading-the-whole-text-file-into-a-char-array-in-c
|
||||
FILE* fp;
|
||||
@@ -41,24 +119,8 @@ char* getFileContents(const char* filename) {
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if (argc < 2) {
|
||||
printf("Usage: %s [file]\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char* fileContents = NULL;
|
||||
bool printProgram = false;
|
||||
|
||||
if (strcmp(argv[1], "-p") == 0) {
|
||||
if (argc < 3) {
|
||||
printf("Usage: %s -p [file]\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
printProgram = true;
|
||||
fileContents = getFileContents(argv[2]);
|
||||
} else {
|
||||
fileContents = getFileContents(argv[1]);
|
||||
}
|
||||
Args args = parseArgs(argc, argv);
|
||||
char* fileContents = getFileContents(args.inputFile);
|
||||
|
||||
if (fileContents == NULL) {
|
||||
printf("Couldn't read that file :(\n");
|
||||
@@ -102,16 +164,81 @@ int main(int argc, char** argv) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (printProgram) {
|
||||
groundPrintProgram(&codegen.as.success);
|
||||
exit(0);
|
||||
switch (args.action) {
|
||||
case SA_PRINT: {
|
||||
groundPrintProgram(&codegen.as.success);
|
||||
break;
|
||||
}
|
||||
case SA_EXEC: {
|
||||
GroundValue retval = groundRunProgram(&codegen.as.success);
|
||||
if (retval.type == INT) {
|
||||
return retval.data.intVal;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SA_BYTECODE: {
|
||||
serializeProgramToFile(args.outputFile, &codegen.as.success);
|
||||
break;
|
||||
}
|
||||
case SA_COMPILE: {
|
||||
char* compiled = groundCompileProgram(&codegen.as.success);
|
||||
|
||||
// Make work directory
|
||||
Estr dir = CREATE_ESTR(".solsbuild_");
|
||||
APPEND_ESTR(dir, args.outputFile);
|
||||
|
||||
#ifdef _WIN32
|
||||
int dirstatus = _mkdir(estr.str);
|
||||
#else
|
||||
int dirstatus = mkdir(dir.str, 0755);
|
||||
#endif
|
||||
if (dirstatus != 0) {
|
||||
printf("Couldn't create temporary work directory\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Write generated asm to .s
|
||||
Estr tmpasm = CREATE_ESTR(dir.str);
|
||||
APPEND_ESTR(tmpasm, "/generated.s");
|
||||
|
||||
FILE* file = fopen(tmpasm.str, "w");
|
||||
if (file == NULL) {
|
||||
printf("Couldn't write to temporary assembly file");
|
||||
}
|
||||
fprintf(file, "%s", compiled);
|
||||
fclose(file);
|
||||
|
||||
// Assemble with nasm
|
||||
Estr nasmcmd = CREATE_ESTR("nasm -f elf64 -o ");
|
||||
APPEND_ESTR(nasmcmd, dir.str);
|
||||
APPEND_ESTR(nasmcmd, "/generated.o ");
|
||||
APPEND_ESTR(nasmcmd, tmpasm.str);
|
||||
|
||||
int nasmstatus = system(nasmcmd.str);
|
||||
if (nasmstatus != 0) {
|
||||
printf("command \"%s\" exited with code %d\n", nasmcmd.str, nasmstatus);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Link with ld
|
||||
Estr ldcmd = CREATE_ESTR("ld -o ");
|
||||
APPEND_ESTR(ldcmd, args.outputFile);
|
||||
APPEND_ESTR(ldcmd, " ");
|
||||
APPEND_ESTR(ldcmd, dir.str);
|
||||
APPEND_ESTR(ldcmd, "/generated.o");
|
||||
|
||||
int ldstatus = system(ldcmd.str);
|
||||
if (ldstatus != 0) {
|
||||
printf("command \"%s\" exited with code %d\n", ldcmd.str, ldstatus);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Yay we compiled it
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Run program on GroundVM
|
||||
GroundValue retval = groundRunProgram(&codegen.as.success);
|
||||
if (retval.type == INT) {
|
||||
return retval.data.intVal;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user