lr/main.c

246 lines
4.8 KiB
C

#include<fcntl.h>
#include<signal.h>
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include"state.h"
#include"version.h"
#define HELPMSG "lr v"VERSION"\n"\
"usage: lr [-behprt] [-o OUTFILE] [-m ARCH] [--help] [--list-arches] [FILES]"
#define ARCHESMSG "i386\nir\nrun\nx86_64"
int main(int argc,char**argv)
{
const bool generate=true;
bool setoutfile=false;
bool showparsetree=false;
bool showparsetreebrief=false;
bool showtokens=false;
bool showrpn=false;
bool showeval=false;
char*setoutfile_name=NULL;
int skip_arg=0;
uint32_t buildarch=M_X86_64;
Vec args=vec_new(sizeof(char*));
// Ensure cleanup is called
signal(SIGINT,sighandle);
// Parse arguments
for(int i=1;i<argc;i+=1+skip_arg)
{
if(!argv[i][0])continue;
skip_arg=0;
if(argv[i][0]=='-')
{
if(argv[i][1]=='-')
{
// LONG OPTIONS
if(strcmp("--help",argv[i])==0)
{
puts(HELPMSG);
cleanquit(0);
}
else if(strcmp("--list-arches",argv[i])==0)
{
puts(ARCHESMSG);
cleanquit(0);
}
else
{
err_log("unrecognized long option '%s'",argv[i]);
cleanquit(1);
}
}
// SHORT OPTIONS
else
{
for(size_t j=1;argv[i][j];++j)
{
switch(argv[i][j])
{
// Select build architecture
case 'm':
if(argc-1>i)
{
++skip_arg;
if(strcmp(argv[i+skip_arg],"ir")==0)
buildarch=M_IR;
else if(strcmp(argv[i+skip_arg],"run")==0)
buildarch=M_RUN;
else if(strcmp(argv[i+skip_arg],"x86_64")==0)
buildarch=M_X86_64;
else if(strcmp(argv[i+skip_arg],"i386")==0)
buildarch=M_I386;
else
{
err_log("unrecognized build architecture '%s'",argv[i+skip_arg]);
cleanquit(1);
}
}
else
{
err_log("no argument to option '-m'");
cleanquit(1);
}
break;
case 'o':
setoutfile=true;
if(argc-1>i)
{
++skip_arg;
setoutfile_name=argv[i+skip_arg];
}
else
{
err_log("no argument to option '-o'");
cleanquit(1);
}
break;
case 'p':
showparsetree=true;
break;
case 'b':
showparsetree=true;
showparsetreebrief=true;
break;
case 't':
showtokens=true;
break;
case 'r':
showrpn=true;
break;
case 'e':
showeval=true;
break;
case 'h':
puts(HELPMSG);
cleanquit(0);
break;
default:
err_log("unrecognized short option '%c'",argv[i][j]);
cleanquit(1);
break;
}
}
}
continue;
}
// All arguments otherwise treated as filenames
vec_push(&args,argv+i);
}
// Iterate over input files
for(size_t i=0;i<args.size;++i)
{
state=state_new();
state.gen.rootnode=&state.parser.root;
state.gen.buildarch=buildarch;
state.gen.showrpn=showrpn;
state.gen.showeval=showeval;
state.infile=fopen(*vec_at(&args,i,const char**),"r");
if(!state.infile)
{
err_log("failed to open infile '%s'",*vec_at(&args,i,const char**));
cleanquit(1);
}
// Read input file into buffer
if(state.infile)
{
state.infilename=(char*)*vec_at(&args,i,const char**);
char file_buffer[1024]={0};
size_t count=0;
while((count=fread(file_buffer,1,1000,state.infile)))
{
file_buffer[count]=0;
str_append(&state.input_buffer,file_buffer);
}
fclose(state.infile);
}
// Lex, Parse
if(state.input_buffer.buffer)
{
lex_string(&state.lexer,state.input_buffer.buffer);
str_free(&state.input_buffer);
if(showtokens||showparsetree)
printf("%s:\n",state.infilename);
if(showtokens)lex_print(&state.lexer);
parser_parse(&state.parser,&state.lexer.tokens);
lex_free(&state.lexer);
if(showparsetree)
{
if(showparsetreebrief)
pnode_print_brief(&state.parser.root,0);
else
pnode_print(&state.parser.root,0);
}
}
// Generate code
if(generate)
{
state_set_outfile(&state,(char*)*vec_at(&args,i,const char**),setoutfile,setoutfile_name,state.gen.buildarch);
// Set gen LangDef
switch(state.gen.buildarch)
{
case M_X86_64:state.gen.ld=(LangDef)gen_x86_64_langdef();break;
case M_I386:state.gen.ld=(LangDef)gen_i386_langdef();break;
case M_IR:case M_RUN:break;
default:err_log("Undefined generator language");break;
}
// Generate code based on buildarch
switch(state.gen.buildarch)
{
case M_IR:
gen_ir(&state.gen,&state.parser.root,state.outfile);
break;
case M_RUN:
gen_run(&state.gen,&state.parser.root,state.outfile);
break;
case M_X86_64:
case M_I386:
gen_code(&state.gen,&state.parser.root,state.outfile);
break;
}
state_close_outfile(&state);
}
state_free(&state);
}
// Free memory and leave
/* state_free(&state); */
vec_free(&args);
cleanquit(0);
}