#ifndef PROGRAM_C
#define PROGRAM_C
#include<program.h>
struct Source* extract_source(char *src_name)
{
FILE *file;
struct Source *ret;
file=fopen(src_name,"r");
if(file==NULL)
{
fprintf(stderr,"Could not open source file. ");
exit(1);
}
if(fseek(file,0L,SEEK_END)!=0)
{
fprintf(stderr,"Could not open source file. ");
exit(1);
}
ret=malloc(sizeof(struct Source));
ret->src_size=ftell(file);
ret->where_in_src=0;
ret->src_name=src_name;
ret->src=malloc(ret->src_size);
ret->current_column=0;
ret->current_row=0;
fseek(file,0L,SEEK_SET);
fread(ret->src,sizeof(char),ret->src_size,file);
fclose(file);
return ret;
}
struct Options* parse_command_line(int argc,char **argv)
{
struct Options *ret;
int i;
assert(argv!=NULL && argc>0);
ret=malloc(sizeof(struct Options));
ret->target=OPTION_DEFAULT;
ret->src_name=NULL;
ret->output_name=NULL;
ret->is_quiet=0;
ret->providing_own_queue_implementation=0;
ret->providing_own_buffer_implementation=0;
ret->has_mutex=0;
ret->has_context=0; /*inline is the default*/
for(i=0;i<argc;++i)
{
if(!strncmp(argv[i],"--print-tokens",sizeof("--print-tokens")))
ret->target=OPTION_TARGET_TOKENS;
else if(!strncmp(argv[i],"--print-ast",sizeof("--print-ast")))
ret->target=OPTION_TARGET_AST;
else if(!strncmp(argv[i],"--print-c",sizeof("--print-c")))
ret->target=OPTION_TARGET_C;
else if(!strncmp(argv[i],"--extern-queue",sizeof("--extern-queue")))
ret->providing_own_queue_implementation=1;
else if(!strncmp(argv[i],"--extern-buffer",sizeof("--extern-buffer")))
ret->providing_own_buffer_implementation=1;
else if(!strncmp(argv[i],"--extern-mutex",sizeof("--extern-mutex")))
ret->has_mutex=1;
else if(!strncmp(argv[i],"--with-context",sizeof("--extern-mutex")))
ret->has_context=1;
else if(!strncmp(argv[i],"--help",sizeof("--help")) || !strncmp(argv[i],"-h",sizeof("-h")))
{
printf("Wonky automata options:\n"
"--print-tokens Prints the tokens of the programs, used for debugging\n"
"--print-ast Prints the ast of the program, used for debugging\n"
"--print-c Transpiles to C and outputs the result to stdout ( default )\n"
"--extern-queue delegates the queue implementation to user\n"
"--extern-buffer delegates the buffer implementation to the user\n"
"--extern-mutex delegates the mutex implementation to the user and generates mutex guards\n"
"--with-context have a context struct, so you can have multiple instances of the automata\n"
"\n");
exit(0);
}
else if(!strncmp(argv[i],"-o",sizeof("-o")) || !strncmp(argv[i],"--output",sizeof("--output")))
{
if(++i<argc)
{
if(strnlen(argv[i],101)<100)
ret->output_name=argv[i];
else if(!ret->is_quiet)
{
fprintf(stderr,"Error: Output filename is too long\n");
exit(1);
}else
{
exit(1);
}
}
}else if(argv[i][0]=='-')
{
fprintf(stderr,"Error: Invalid command line option %s\n",argv[i]);
exit(1);
}else if(strnlen(argv[i],101)<100)
{
ret->src_name=argv[i];
}else if(!ret->is_quiet)
{
fprintf(stderr,"Error: Input filename is too long\n");
exit(1);
}else
{
exit(1);
}
}
if(ret->target==OPTION_DEFAULT)
ret->target=OPTION_TARGET_C;
return ret;
}
struct Translation_Data* get_translation_data()
{
struct Translation_Data *ret;
ret=malloc(sizeof(struct Translation_Data));
ret->errors=malloc(sizeof(struct Queue));
ret->tokens=malloc(sizeof(struct Queue));
Queue_Init(ret->errors);
Queue_Init(ret->tokens);
ret->hold_number_of_errors=0;
return ret;
}
struct Error* get_error(char *message,size_t row,size_t column)
{
struct Error *ret;
ret=malloc(sizeof(struct Error));
ret->message=message;
ret->row=row+1;
ret->column=column+1;
}
void push_lexing_error(char *error_message,struct Source *src,struct Translation_Data *translation_data)
{
Queue_Push(translation_data->errors,get_error(error_message,src->current_row,src->current_column));
}
void push_parsing_error(char *error_message,struct Translation_Data *translation_data)
{
struct token *error_token;
error_token=Queue_Pop(translation_data->tokens);
Queue_Push(translation_data->errors,get_error(error_message,error_token->row,error_token->column));
}
char has_new_errors(struct Translation_Data *translation_data)
{
if(translation_data->hold_number_of_errors!=translation_data->errors->size)
{
translation_data->hold_number_of_errors=translation_data->errors->size;
return 1;
}else
{
return 0;
}
}
void delete_translation_data(struct Translation_Data *data)
{
struct Error *hold_error;
struct token *hold_token;
while(data->tokens->size>0)
delete_token(Queue_Pop(data->tokens));
free(data->tokens);
while(data->errors->size>0)
delete_error(Queue_Pop(data->errors));
free(data->errors);
free(data);
}
void delete_source(struct Source *src)
{
free(src->src_name);
free(src->src);
free(src);
}
void delete_options(struct Options *options)
{
free(options);
}
void delete_error(struct Error *error)
{
free(error->message);
free(error);
}
char get_and_check(struct Translation_Data *translation_data,enum Keyword kw)
{
if( ( (struct token *)translation_data->tokens->first->data)->type==kw)
{
delete_token(Queue_Pop(translation_data->tokens));
return 1;
}else
{
return 0;
}
}
enum Keyword get_kw(struct Translation_Data *translation_data)
{
return ( (struct token*)translation_data->tokens->first->data)->type;
}
void chomp(struct Translation_Data *translation_data)
{
assert(translation_data->tokens->size>0);
delete_token(Queue_Pop(translation_data->tokens));
}
void touch_errors(struct Translation_Data *translation_data)
{
assert(translation_data->hold_number_of_errors>0);
--translation_data->hold_number_of_errors;
}
void push_error_with_token(char *error_message,struct token *token,struct Translation_Data *translation_data)
{
Queue_Push(translation_data->errors,get_error(error_message,token->row,token->column));
}
#endif