From 90b629b806e09f1fda661e1915e45faa3e3fee5b Mon Sep 17 00:00:00 2001 From: Aaro Koivukangas Date: Fri, 16 Aug 2024 18:39:33 +0200 Subject: [PATCH] better error handling + segfault safe frees --- c/include/error.h | 12 ++++++ c/include/token.h | 2 +- c/include/value.h | 6 +-- c/src/comment.c | 3 +- c/src/expr.c | 94 ++++++++++++++++++++++++++------------------ c/src/label.c | 5 ++- c/src/main.c | 17 ++++---- c/src/oper.c | 7 ++-- c/src/parser.bison | 13 +++--- c/src/program.c | 5 ++- c/src/ttk_register.c | 20 ++++++++-- c/src/value.c | 76 +++++++++++++++++++++-------------- 12 files changed, 163 insertions(+), 97 deletions(-) create mode 100644 c/include/error.h diff --git a/c/include/error.h b/c/include/error.h new file mode 100644 index 0000000..515ee8b --- /dev/null +++ b/c/include/error.h @@ -0,0 +1,12 @@ +#ifndef ERROR_H +#define ERROR_H + +typedef enum { + VARIABLE_NULL=1, + SWITCH_NOT_MATCHED, + PARSE_ERROR, + FILE_ERROR, + ALLOC_FAILED +} error_t; + +#endif diff --git a/c/include/token.h b/c/include/token.h index acdac24..a353b95 100644 --- a/c/include/token.h +++ b/c/include/token.h @@ -81,7 +81,7 @@ extern int yydebug; #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED union YYSTYPE { -#line 47 "src/parser.bison" +#line 48 "src/parser.bison" struct expr *expr; struct oper *oper; diff --git a/c/include/value.h b/c/include/value.h index 0d9499e..6052a7c 100644 --- a/c/include/value.h +++ b/c/include/value.h @@ -39,8 +39,8 @@ struct pure_value { struct value * value_create(addr_mode_t addr_m, index_t i_m, struct pure_value *value, struct ttk_register *i_reg); struct value * value_create_direct_value(struct pure_value *p_v); struct value * value_create_direct_indexed(struct pure_value *p_v, struct ttk_register *ttk_reg); -struct value * value_create_address_mode_indexed(char addr_mode, struct pure_value *p_v, struct ttk_register *ttk_reg); -struct value * value_create_address_mode(char addr_mode, struct pure_value *p_v); +struct value * value_create_address_mode_indexed(char* addr_mode, struct pure_value *p_v, struct ttk_register *ttk_reg); +struct value * value_create_address_mode(char* addr_mode, struct pure_value *p_v); struct value * value_create_direct_register(struct ttk_register *ttk_reg); @@ -49,7 +49,7 @@ struct pure_value * pure_value_create_value(int value); struct pure_value * pure_value_create_label(struct label *l); struct pure_value * pure_value_create(value_t kind, struct ttk_register *ttk_reg, int num, struct label *l); -addr_mode_t parse_addr_mode(char addr_mode); +addr_mode_t parse_addr_mode(char* addr_mode); int value_print(struct value *v); diff --git a/c/src/comment.c b/c/src/comment.c index 7d05e5d..db1b9b5 100644 --- a/c/src/comment.c +++ b/c/src/comment.c @@ -1,6 +1,7 @@ #include #include #include +#include "error.h" #include "comment.h" struct comment * comment_create(char *text) @@ -17,7 +18,7 @@ int comment_print(struct comment *c) if (!c || !c->text) { printf("\nERROR: Comment does not exist\n"); - return 1; + return VARIABLE_NULL; } printf("%s", c->text); diff --git a/c/src/expr.c b/c/src/expr.c index ed12054..f20a1eb 100644 --- a/c/src/expr.c +++ b/c/src/expr.c @@ -1,5 +1,6 @@ #include #include +#include "error.h" #include "expr.h" #define PRINT_COMMENTS 1 @@ -63,69 +64,86 @@ struct expr *expr_create_comment(struct comment *c) int expr_print(struct expr *e) { if (!e) - return 1; + return VARIABLE_NULL; switch (e->kind) { case INSTRUCTION: + { if (e->label) { - if (label_print(e->label)!=0) - return 1;; + int err = label_print(e->label); + if (err) + return err; printf(" "); } - if (oper_print(e->oper)!=0) - return 1; + int err = oper_print(e->oper); + if (err) + return err; printf(" "); - if (ttk_register_print(e->first_arg)!=0) - return 1; + err = ttk_register_print(e->first_arg); + if (err) + return err; printf(","); printf(" "); - if (value_print(e->second_arg)!=0) - return 1; + err = value_print(e->second_arg); + if (err) + return err; printf("\n"); return 0; + } case INSTRUCTION_ONE_ARG: + { if (e->label) { - if (label_print(e->label)!=0) - return 1; + int err = label_print(e->label); + if (err) + return err; printf(" "); } - if (oper_print(e->oper)!=0) - return 1; + int err = oper_print(e->oper); + if (err) + return err; printf(" "); - if (value_print(e->second_arg)!=0) - return 1; + err = value_print(e->second_arg); + if (err) + return err; printf("\n"); return 0; + } case LABEL_DEF: - if (label_print(e->label)!=0) - return 1; + { + int err = label_print(e->label); + if (err) + return err; printf(" "); - if (oper_print(e->oper)!=0) - return 1; + err = oper_print(e->oper); + if (err) + return err; printf(" "); - if (value_print(e->second_arg)!=0) - return 1; + err = value_print(e->second_arg); + if (err) + return err; printf("\n"); return 0; + } case COMMENT: - if (PRINT_COMMENTS == 1) + if (PRINT_COMMENTS) return 0; - if (comment_print(e->comment)!=0) - return 1; + int err = comment_print(e->comment); + if (err) + return err; printf("\n"); return 0; default: - return 1; + return SWITCH_NOT_MATCHED; } } @@ -146,33 +164,31 @@ int expr_free(struct expr *e) switch (e->kind) { case INSTRUCTION: - if (e->label != NULL) - label_free(e->label); - oper_free(e->oper); - ttk_register_free(e->first_arg); - value_free(e->second_arg); + if (e->label) label_free(e->label); + if (e->oper) oper_free(e->oper); + if (e->first_arg) ttk_register_free(e->first_arg); + if (e->second_arg) value_free(e->second_arg); break; case INSTRUCTION_ONE_ARG: - if (e->label != NULL) - label_free(e->label); - oper_free(e->oper); - value_free(e->second_arg); + if (e->label) label_free(e->label); + if (e->oper) oper_free(e->oper); + if (e->second_arg) value_free(e->second_arg); break; case LABEL_DEF: - label_free(e->label); - oper_free(e->oper); - value_free(e->second_arg); + if (e->label) label_free(e->label); + if (e->oper) oper_free(e->oper); + if (e->second_arg) value_free(e->second_arg); break; case COMMENT: - comment_free(e->comment); + if (e->comment) comment_free(e->comment); break; default: printf("ERROR: Expr kind not matched while freeing\n"); - return 1; + return SWITCH_NOT_MATCHED; } return 0; diff --git a/c/src/label.c b/c/src/label.c index b8b80c0..421c0fc 100644 --- a/c/src/label.c +++ b/c/src/label.c @@ -1,6 +1,7 @@ #include #include #include +#include "error.h" #include "label.h" @@ -27,7 +28,7 @@ int label_print(struct label *l) if (!l->name) { printf("ERROR: Label name doesn't exist.\n"); - return 1; + return VARIABLE_NULL; } printf("%s", l->name); @@ -36,6 +37,6 @@ int label_print(struct label *l) void label_free(struct label *l) { - free(l->name); + if (l->name) free(l->name); free(l); } diff --git a/c/src/main.c b/c/src/main.c index 6506038..a4dfbb6 100644 --- a/c/src/main.c +++ b/c/src/main.c @@ -1,11 +1,12 @@ #include #include +#include "error.h" #include "token.h" #include "program.h" -#define FILENAME "../docs/example-file-harder.k91" +//#define FILENAME "../docs/example-file-harder.k91" //#define FILENAME "../docs/example-file.k91" -//#define FILENAME "../docs/example-file-simple.k91" +#define FILENAME "../docs/example-file-simple.k91" // scanner extern FILE *yyin; @@ -23,27 +24,27 @@ int main() if (!yyin) { printf("Couldn't open file\n"); - return 1; + return FILE_ERROR; } struct expr *parse_result = malloc(sizeof(*parse_result)); if (!parse_result) { printf("ERROR: Failed to allocate memory for parse_result.\n"); - return 1; + return ALLOC_FAILED; } if (yyparse(parse_result) == 0) { printf("Parse succesful :)\n"); } else { - printf("Parse failed\n"); program_free(parse_result); - return 1; + return PARSE_ERROR; } - if (program_print(parse_result)!=0) - return 1; + int err = program_print(parse_result); + if (err!=0) + return err; program_free(parse_result); // TODO handle errors with assertions diff --git a/c/src/oper.c b/c/src/oper.c index 372fb83..316cdf3 100644 --- a/c/src/oper.c +++ b/c/src/oper.c @@ -1,6 +1,7 @@ #include #include #include +#include "error.h" #include "oper.h" @@ -9,7 +10,7 @@ struct oper * oper_create(oper_t kind, char* oper_name) struct oper *o = malloc(sizeof(*o)); o->kind = kind; - o->oper_name = oper_name; + o->oper_name = oper_name; // TODO rename to just name just like everyone else xd return o; } @@ -28,7 +29,7 @@ int oper_print(struct oper *o) if (!o) { printf("\nERROR: Null oper given.\n"); - return 1; + return VARIABLE_NULL; } printf("%s", o->oper_name); @@ -37,6 +38,6 @@ int oper_print(struct oper *o) void oper_free(struct oper *o) { - free(o->oper_name); + if (o->oper_name) free(o->oper_name); free(o); } diff --git a/c/src/parser.bison b/c/src/parser.bison index 45e2f2c..81c6085 100644 --- a/c/src/parser.bison +++ b/c/src/parser.bison @@ -1,6 +1,7 @@ /* TODO support tags to jump to different sections */ %{ #include +#include "error.h" #include "program.h" #include "comment.h" #include "expr.h" @@ -67,8 +68,8 @@ int yyerror(struct expr *e, const char*); %type TOKEN_REGISTER TOKEN_STACK_REGISTER %type TOKEN_OPER_DATA TOKEN_OPER_AR TOKEN_OPER_LOGIC TOKEN_OPER_BRANCH TOKEN_OPER_STACK TOKEN_OPER_SYS TOKEN_COMP_OPER -%type TOKEN_LABEL TOKEN_SYS_NUM -%type TOKEN_PAREN_L TOKEN_PAREN_R TOKEN_ADDR_M TOKEN_SIGN +%type TOKEN_LABEL TOKEN_SYS_NUM TOKEN_ADDR_M +%type TOKEN_PAREN_L TOKEN_PAREN_R TOKEN_SIGN %type TOKEN_NUMBER %type TOKEN_COMMENT @@ -97,8 +98,8 @@ oper : TOKEN_OPER_DATA { $$ = oper_create_data($1); } | TOKEN_OPER_SYS { $$ = oper_create_sys($1); } ; -ttk_register: TOKEN_REGISTER { $$ = ttk_register_create_register($1); } - | TOKEN_STACK_REGISTER { $$ = ttk_register_create_stack_register($1); } +ttk_register: TOKEN_REGISTER { $$ = ttk_register_create_register($1); if (!$$) { yyerror(parse_result, "Token empty"); YYERROR;} } + | TOKEN_STACK_REGISTER { $$ = ttk_register_create_stack_register($1); if (!$$) { yyerror(parse_result, "Token empty"); YYERROR;} } ; @@ -127,6 +128,6 @@ num_value : TOKEN_SIGN TOKEN_NUMBER { $$ = -$2; } int yyerror ( struct expr *e, const char *s ) { - printf("ERROR: Parser error: %s at line %d\n", s, yylineno); - return 1; + printf("Parser error: %s at line %d\n", s, yylineno); + return PARSE_ERROR; } diff --git a/c/src/program.c b/c/src/program.c index c206a20..2928cac 100644 --- a/c/src/program.c +++ b/c/src/program.c @@ -8,8 +8,9 @@ int program_print(struct expr *program) while (current != NULL) { - if (expr_print(current)!=0) - return 1; + int err = expr_print(current); + if (err!=0) + return err; current = current->next; } diff --git a/c/src/ttk_register.c b/c/src/ttk_register.c index ebe04c3..907fcec 100644 --- a/c/src/ttk_register.c +++ b/c/src/ttk_register.c @@ -1,14 +1,24 @@ #include #include #include +#include "error.h" #include "ttk_register.h" struct ttk_register * ttk_register_create(ttk_register_t kind, char* name, int value) { + + int id = parse_register_num(name, kind); + + if (id == -1) + { + printf("Register creation failed.\n"); + return NULL; + } + struct ttk_register * r = malloc(sizeof(*r)); r->kind = kind; - r->id = parse_register_num(name, kind); + r->id = id; r->value = value; return r; @@ -28,6 +38,7 @@ struct ttk_register * ttk_register_create_stack_register(char* name) int parse_register_num(char* name, ttk_register_t kind) { if (!name) { + printf("Name null while parsing register name.\n"); return -1; } @@ -49,6 +60,7 @@ int parse_register_num(char* name, ttk_register_t kind) default: free(name); + printf("Register type not matched while parsing register name.\n"); return -1; } @@ -60,8 +72,8 @@ int ttk_register_print(struct ttk_register *ttk_reg) { if (!ttk_reg || !ttk_reg->id) { - printf("ERROR: No ttk_register exists.\n"); - return 1; + printf("ttk_register missing while trying to print it.\n"); + return VARIABLE_NULL; } switch (ttk_reg->id) { @@ -71,6 +83,8 @@ int ttk_register_print(struct ttk_register *ttk_reg) case 7: printf("FP"); return 0; + default: + break; } printf("R%d", ttk_reg->id); diff --git a/c/src/value.c b/c/src/value.c index a107328..bf45d7a 100644 --- a/c/src/value.c +++ b/c/src/value.c @@ -1,5 +1,6 @@ #include #include +#include "error.h" #include "value.h" @@ -31,12 +32,12 @@ struct value * value_create_direct_indexed(struct pure_value *p_v, struct ttk_re return value_create(DIRECT, INDEXED, p_v, ttk_reg); } -struct value * value_create_address_mode_indexed(char addr_mode, struct pure_value *p_v, struct ttk_register *ttk_reg) +struct value * value_create_address_mode_indexed(char* addr_mode, struct pure_value *p_v, struct ttk_register *ttk_reg) { return value_create(parse_addr_mode(addr_mode), INDEXED, p_v, ttk_reg); } -struct value * value_create_address_mode(char addr_mode, struct pure_value *p_v) +struct value * value_create_address_mode(char* addr_mode, struct pure_value *p_v) { return value_create(parse_addr_mode(addr_mode), NONE, p_v, NULL); } @@ -60,9 +61,11 @@ struct pure_value * pure_value_create_value(int value) struct pure_value * pure_value_create_label(struct label *l) { return pure_value_create(LABEL, NULL, 0, l); } -addr_mode_t parse_addr_mode(char addr_mode) +addr_mode_t parse_addr_mode(char* addr_mode) { - switch (addr_mode) + if (!addr_mode) + return -1; + switch (addr_mode[0]) { case '=': return IMMEDIATE; @@ -79,23 +82,25 @@ int pure_value_print(struct pure_value *p_v) if (!p_v) { printf("\nERROR: Pure_value does not exist\n"); - return 1; + return VARIABLE_NULL; } switch (p_v->kind) { case REGISTER: ttk_register_print(p_v->ttk_register); - return 0; + break; case NUMBER: printf("%d", p_v->number); - return 0; + break; case LABEL: label_print(p_v->label); - return 0; + break; + default: + return SWITCH_NOT_MATCHED; } - return 1; + return 0; } int value_print(struct value *v) @@ -104,7 +109,7 @@ int value_print(struct value *v) if (!v) { printf("ERROR: Value not defined.\n"); - return 1; + return VARIABLE_NULL; } // add = or @ to the beginnig of value @@ -123,26 +128,39 @@ int value_print(struct value *v) switch (v->indexing_mode) { case NONE: - if (pure_value_print(v->value)!=0) - return 1; - return 0; + { + int err = pure_value_print(v->value); + if (err) + return err; + break; + } case INDEXED: - if (pure_value_print(v->value)!=0) - return 1; + { + int err = pure_value_print(v->value); + if (err) + return err; printf("("); - if (ttk_register_print(v->index_register)!=0) - return 1; + err = ttk_register_print(v->index_register); // is already defined + if (err) + return err; printf(")"); - return 0; + break; + + } case INDEXED_ONLY_IREG: + { printf("("); - if (ttk_register_print(v->index_register)!=0) - return 1; + int err = ttk_register_print(v->index_register); + if (err) + return err; printf(")"); - return 0; + break; + } + default: + return SWITCH_NOT_MATCHED; } - return 1; + return 0; } void pure_value_free(struct pure_value *p_v) @@ -150,12 +168,12 @@ void pure_value_free(struct pure_value *p_v) switch (p_v->kind) { case REGISTER: - ttk_register_free(p_v->ttk_register); + if (p_v->ttk_register) ttk_register_free(p_v->ttk_register); break; case NUMBER: break; case LABEL: - label_free(p_v->label); + if (p_v->label) label_free(p_v->label); break; } free(p_v); @@ -166,15 +184,15 @@ void value_free(struct value *v) switch (v->indexing_mode) { case NONE: - pure_value_free(v->value); + if (v->value) pure_value_free(v->value); break; case INDEXED: - pure_value_free(v->value); - ttk_register_free(v->index_register); + if (v->value) pure_value_free(v->value); + if (v->index_register) ttk_register_free(v->index_register); break; default: - printf("ERROR: Value indexing mode not matched while freeing\n"); - break;; + printf("ERROR: Indexing mode not matched while freeing value\n"); + break; } free(v); }