#ifndef PROGRAM_C #define PROGRAM_C #include 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;itarget=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(++ioutput_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