237 lines
4.6 KiB
C
237 lines
4.6 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 "par v"VERSION"\n"\
|
|
"usage: par [-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);
|
|
|
|
// 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);
|
|
}
|