lr/state.c
2024-01-10 20:25:43 -06:00

112 lines
1.8 KiB
C

#include<stdio.h>
#include<stdbool.h>
#include"state.h"
#include"err.h"
// State is global precisely because
// signal() cannot pass user data,
// and we need it to abort/quit
// cleanly.
State state;
inline void cleanquit(int exitval)
{
state_free(&state);
exit(exitval);
}
void sighandle(int sig)
{
if(sig==SIGINT)
cleanquit(0);
}
State state_new(void)
{
State st=(State){
.lexer=lex_new(),
.parser=parser_new(),
.gen=gen_new(),
.input_buffer=str_new(),
.infile=stdin,
.outfile=NULL,
.infilename=NULL,
};
return st;
}
void state_free(State*st)
{
if(!st)
{
err_log("NULL State pointer passed to state_free");
return;
}
lex_free(&st->lexer);
parser_free(&st->parser);
str_free(&st->input_buffer);
gen_free(&st->gen);
}
void state_open_outfile(State*st,char*filename)
{
if(st->outfile!=stdin&&st->outfile!=stdout&&st->outfile!=stderr)
st->outfile=fopen(filename,"w");
if(!st->outfile)
{
err_log("cannot open outfile '%s'",filename);
st->outfile=stdout;
}
}
void state_close_outfile(State*st)
{
if(st->outfile&&st->outfile!=stdout&&
st->outfile!=stderr &&st->outfile!=stdin)
fclose(st->outfile);
}
void state_set_outfile(State*st,char*infile,bool setoutfile,char*setoutfile_name,uint32_t buildarch)
{
/* Str fn=str_new(); */
Str fn={0};
if(!setoutfile)
{
switch(buildarch)
{
case M_I386:
case M_X86_64:
if(infile[0]&&st->infile!=stdin)
{
fn=str_basename(infile);
if(!fn.buffer[0])
str_assign(&fn,"a");
str_append(&fn,".s");
}
else
{
fn=str_new();
str_assign(&fn,"a.s");
}
state_open_outfile(st,fn.buffer);
break;
default:
str_assign(&fn,"");
state.outfile=stdout;
break;
}
}
else
{
str_assign(&fn,setoutfile_name);
state_open_outfile(st,fn.buffer);
}
str_free(&fn);
}