better error handling + segfault safe frees

This commit is contained in:
Aaro Koivukangas
2024-08-16 18:39:33 +02:00
parent dc37278588
commit 90b629b806
12 changed files with 163 additions and 97 deletions
+12
View File
@@ -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
+1 -1
View File
@@ -81,7 +81,7 @@ extern int yydebug;
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
union YYSTYPE union YYSTYPE
{ {
#line 47 "src/parser.bison" #line 48 "src/parser.bison"
struct expr *expr; struct expr *expr;
struct oper *oper; struct oper *oper;
+3 -3
View File
@@ -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(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_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_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_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(char* addr_mode, struct pure_value *p_v);
struct value * value_create_direct_register(struct ttk_register *ttk_reg); 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_label(struct label *l);
struct pure_value * pure_value_create(value_t kind, struct ttk_register *ttk_reg, int num, 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); int value_print(struct value *v);
+2 -1
View File
@@ -1,6 +1,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "error.h"
#include "comment.h" #include "comment.h"
struct comment * comment_create(char *text) struct comment * comment_create(char *text)
@@ -17,7 +18,7 @@ int comment_print(struct comment *c)
if (!c || !c->text) if (!c || !c->text)
{ {
printf("\nERROR: Comment does not exist\n"); printf("\nERROR: Comment does not exist\n");
return 1; return VARIABLE_NULL;
} }
printf("%s", c->text); printf("%s", c->text);
+55 -39
View File
@@ -1,5 +1,6 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include "error.h"
#include "expr.h" #include "expr.h"
#define PRINT_COMMENTS 1 #define PRINT_COMMENTS 1
@@ -63,69 +64,86 @@ struct expr *expr_create_comment(struct comment *c)
int expr_print(struct expr *e) int expr_print(struct expr *e)
{ {
if (!e) if (!e)
return 1; return VARIABLE_NULL;
switch (e->kind) switch (e->kind)
{ {
case INSTRUCTION: case INSTRUCTION:
{
if (e->label) if (e->label)
{ {
if (label_print(e->label)!=0) int err = label_print(e->label);
return 1;; if (err)
return err;
printf(" "); printf(" ");
} }
if (oper_print(e->oper)!=0) int err = oper_print(e->oper);
return 1; if (err)
return err;
printf(" "); printf(" ");
if (ttk_register_print(e->first_arg)!=0) err = ttk_register_print(e->first_arg);
return 1; if (err)
return err;
printf(","); printf(",");
printf(" "); printf(" ");
if (value_print(e->second_arg)!=0) err = value_print(e->second_arg);
return 1; if (err)
return err;
printf("\n"); printf("\n");
return 0; return 0;
}
case INSTRUCTION_ONE_ARG: case INSTRUCTION_ONE_ARG:
{
if (e->label) if (e->label)
{ {
if (label_print(e->label)!=0) int err = label_print(e->label);
return 1; if (err)
return err;
printf(" "); printf(" ");
} }
if (oper_print(e->oper)!=0) int err = oper_print(e->oper);
return 1; if (err)
return err;
printf(" "); printf(" ");
if (value_print(e->second_arg)!=0) err = value_print(e->second_arg);
return 1; if (err)
return err;
printf("\n"); printf("\n");
return 0; return 0;
}
case LABEL_DEF: case LABEL_DEF:
if (label_print(e->label)!=0) {
return 1; int err = label_print(e->label);
if (err)
return err;
printf(" "); printf(" ");
if (oper_print(e->oper)!=0) err = oper_print(e->oper);
return 1; if (err)
return err;
printf(" "); printf(" ");
if (value_print(e->second_arg)!=0) err = value_print(e->second_arg);
return 1; if (err)
return err;
printf("\n"); printf("\n");
return 0; return 0;
}
case COMMENT: case COMMENT:
if (PRINT_COMMENTS == 1) if (PRINT_COMMENTS)
return 0; return 0;
if (comment_print(e->comment)!=0) int err = comment_print(e->comment);
return 1; if (err)
return err;
printf("\n"); printf("\n");
return 0; return 0;
default: default:
return 1; return SWITCH_NOT_MATCHED;
} }
} }
@@ -146,33 +164,31 @@ int expr_free(struct expr *e)
switch (e->kind) switch (e->kind)
{ {
case INSTRUCTION: case INSTRUCTION:
if (e->label != NULL) if (e->label) label_free(e->label);
label_free(e->label); if (e->oper) oper_free(e->oper);
oper_free(e->oper); if (e->first_arg) ttk_register_free(e->first_arg);
ttk_register_free(e->first_arg); if (e->second_arg) value_free(e->second_arg);
value_free(e->second_arg);
break; break;
case INSTRUCTION_ONE_ARG: case INSTRUCTION_ONE_ARG:
if (e->label != NULL) if (e->label) label_free(e->label);
label_free(e->label); if (e->oper) oper_free(e->oper);
oper_free(e->oper); if (e->second_arg) value_free(e->second_arg);
value_free(e->second_arg);
break; break;
case LABEL_DEF: case LABEL_DEF:
label_free(e->label); if (e->label) label_free(e->label);
oper_free(e->oper); if (e->oper) oper_free(e->oper);
value_free(e->second_arg); if (e->second_arg) value_free(e->second_arg);
break; break;
case COMMENT: case COMMENT:
comment_free(e->comment); if (e->comment) comment_free(e->comment);
break; break;
default: default:
printf("ERROR: Expr kind not matched while freeing\n"); printf("ERROR: Expr kind not matched while freeing\n");
return 1; return SWITCH_NOT_MATCHED;
} }
return 0; return 0;
+3 -2
View File
@@ -1,6 +1,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include "error.h"
#include "label.h" #include "label.h"
@@ -27,7 +28,7 @@ int label_print(struct label *l)
if (!l->name) if (!l->name)
{ {
printf("ERROR: Label name doesn't exist.\n"); printf("ERROR: Label name doesn't exist.\n");
return 1; return VARIABLE_NULL;
} }
printf("%s", l->name); printf("%s", l->name);
@@ -36,6 +37,6 @@ int label_print(struct label *l)
void label_free(struct label *l) void label_free(struct label *l)
{ {
free(l->name); if (l->name) free(l->name);
free(l); free(l);
} }
+9 -8
View File
@@ -1,11 +1,12 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include "error.h"
#include "token.h" #include "token.h"
#include "program.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.k91"
//#define FILENAME "../docs/example-file-simple.k91" #define FILENAME "../docs/example-file-simple.k91"
// scanner // scanner
extern FILE *yyin; extern FILE *yyin;
@@ -23,27 +24,27 @@ int main()
if (!yyin) { if (!yyin) {
printf("Couldn't open file\n"); printf("Couldn't open file\n");
return 1; return FILE_ERROR;
} }
struct expr *parse_result = malloc(sizeof(*parse_result)); struct expr *parse_result = malloc(sizeof(*parse_result));
if (!parse_result) if (!parse_result)
{ {
printf("ERROR: Failed to allocate memory for parse_result.\n"); printf("ERROR: Failed to allocate memory for parse_result.\n");
return 1; return ALLOC_FAILED;
} }
if (yyparse(parse_result) == 0) { if (yyparse(parse_result) == 0) {
printf("Parse succesful :)\n"); printf("Parse succesful :)\n");
} else { } else {
printf("Parse failed\n");
program_free(parse_result); program_free(parse_result);
return 1; return PARSE_ERROR;
} }
if (program_print(parse_result)!=0) int err = program_print(parse_result);
return 1; if (err!=0)
return err;
program_free(parse_result); program_free(parse_result);
// TODO handle errors with assertions // TODO handle errors with assertions
+4 -3
View File
@@ -1,6 +1,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include "error.h"
#include "oper.h" #include "oper.h"
@@ -9,7 +10,7 @@ struct oper * oper_create(oper_t kind, char* oper_name)
struct oper *o = malloc(sizeof(*o)); struct oper *o = malloc(sizeof(*o));
o->kind = kind; 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; return o;
} }
@@ -28,7 +29,7 @@ int oper_print(struct oper *o)
if (!o) if (!o)
{ {
printf("\nERROR: Null oper given.\n"); printf("\nERROR: Null oper given.\n");
return 1; return VARIABLE_NULL;
} }
printf("%s", o->oper_name); printf("%s", o->oper_name);
@@ -37,6 +38,6 @@ int oper_print(struct oper *o)
void oper_free(struct oper *o) void oper_free(struct oper *o)
{ {
free(o->oper_name); if (o->oper_name) free(o->oper_name);
free(o); free(o);
} }
+7 -6
View File
@@ -1,6 +1,7 @@
/* TODO support tags to jump to different sections */ /* TODO support tags to jump to different sections */
%{ %{
#include <stdio.h> #include <stdio.h>
#include "error.h"
#include "program.h" #include "program.h"
#include "comment.h" #include "comment.h"
#include "expr.h" #include "expr.h"
@@ -67,8 +68,8 @@ int yyerror(struct expr *e, const char*);
%type <name> TOKEN_REGISTER TOKEN_STACK_REGISTER %type <name> TOKEN_REGISTER TOKEN_STACK_REGISTER
%type <name> TOKEN_OPER_DATA TOKEN_OPER_AR TOKEN_OPER_LOGIC TOKEN_OPER_BRANCH TOKEN_OPER_STACK TOKEN_OPER_SYS TOKEN_COMP_OPER %type <name> TOKEN_OPER_DATA TOKEN_OPER_AR TOKEN_OPER_LOGIC TOKEN_OPER_BRANCH TOKEN_OPER_STACK TOKEN_OPER_SYS TOKEN_COMP_OPER
%type <name> TOKEN_LABEL TOKEN_SYS_NUM %type <name> TOKEN_LABEL TOKEN_SYS_NUM TOKEN_ADDR_M
%type <character> TOKEN_PAREN_L TOKEN_PAREN_R TOKEN_ADDR_M TOKEN_SIGN %type <character> TOKEN_PAREN_L TOKEN_PAREN_R TOKEN_SIGN
%type <num> TOKEN_NUMBER %type <num> TOKEN_NUMBER
%type <name> TOKEN_COMMENT %type <name> TOKEN_COMMENT
@@ -97,8 +98,8 @@ oper : TOKEN_OPER_DATA { $$ = oper_create_data($1); }
| TOKEN_OPER_SYS { $$ = oper_create_sys($1); } | TOKEN_OPER_SYS { $$ = oper_create_sys($1); }
; ;
ttk_register: TOKEN_REGISTER { $$ = ttk_register_create_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); } | 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 ) int yyerror ( struct expr *e, const char *s )
{ {
printf("ERROR: Parser error: %s at line %d\n", s, yylineno); printf("Parser error: %s at line %d\n", s, yylineno);
return 1; return PARSE_ERROR;
} }
+3 -2
View File
@@ -8,8 +8,9 @@ int program_print(struct expr *program)
while (current != NULL) while (current != NULL)
{ {
if (expr_print(current)!=0) int err = expr_print(current);
return 1; if (err!=0)
return err;
current = current->next; current = current->next;
} }
+17 -3
View File
@@ -1,14 +1,24 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "error.h"
#include "ttk_register.h" #include "ttk_register.h"
struct ttk_register * ttk_register_create(ttk_register_t kind, char* name, int value) 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)); struct ttk_register * r = malloc(sizeof(*r));
r->kind = kind; r->kind = kind;
r->id = parse_register_num(name, kind); r->id = id;
r->value = value; r->value = value;
return r; 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) int parse_register_num(char* name, ttk_register_t kind)
{ {
if (!name) { if (!name) {
printf("Name null while parsing register name.\n");
return -1; return -1;
} }
@@ -49,6 +60,7 @@ int parse_register_num(char* name, ttk_register_t kind)
default: default:
free(name); free(name);
printf("Register type not matched while parsing register name.\n");
return -1; return -1;
} }
@@ -60,8 +72,8 @@ int ttk_register_print(struct ttk_register *ttk_reg)
{ {
if (!ttk_reg || !ttk_reg->id) if (!ttk_reg || !ttk_reg->id)
{ {
printf("ERROR: No ttk_register exists.\n"); printf("ttk_register missing while trying to print it.\n");
return 1; return VARIABLE_NULL;
} }
switch (ttk_reg->id) switch (ttk_reg->id)
{ {
@@ -71,6 +83,8 @@ int ttk_register_print(struct ttk_register *ttk_reg)
case 7: case 7:
printf("FP"); printf("FP");
return 0; return 0;
default:
break;
} }
printf("R%d", ttk_reg->id); printf("R%d", ttk_reg->id);
+47 -29
View File
@@ -1,5 +1,6 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include "error.h"
#include "value.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); 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); 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); 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); } 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 '=': case '=':
return IMMEDIATE; return IMMEDIATE;
@@ -79,23 +82,25 @@ int pure_value_print(struct pure_value *p_v)
if (!p_v) if (!p_v)
{ {
printf("\nERROR: Pure_value does not exist\n"); printf("\nERROR: Pure_value does not exist\n");
return 1; return VARIABLE_NULL;
} }
switch (p_v->kind) switch (p_v->kind)
{ {
case REGISTER: case REGISTER:
ttk_register_print(p_v->ttk_register); ttk_register_print(p_v->ttk_register);
return 0; break;
case NUMBER: case NUMBER:
printf("%d", p_v->number); printf("%d", p_v->number);
return 0; break;
case LABEL: case LABEL:
label_print(p_v->label); label_print(p_v->label);
return 0; break;
default:
return SWITCH_NOT_MATCHED;
} }
return 1; return 0;
} }
int value_print(struct value *v) int value_print(struct value *v)
@@ -104,7 +109,7 @@ int value_print(struct value *v)
if (!v) if (!v)
{ {
printf("ERROR: Value not defined.\n"); printf("ERROR: Value not defined.\n");
return 1; return VARIABLE_NULL;
} }
// add = or @ to the beginnig of value // add = or @ to the beginnig of value
@@ -123,26 +128,39 @@ int value_print(struct value *v)
switch (v->indexing_mode) switch (v->indexing_mode)
{ {
case NONE: case NONE:
if (pure_value_print(v->value)!=0) {
return 1; int err = pure_value_print(v->value);
return 0; if (err)
return err;
break;
}
case INDEXED: case INDEXED:
if (pure_value_print(v->value)!=0) {
return 1; int err = pure_value_print(v->value);
if (err)
return err;
printf("("); printf("(");
if (ttk_register_print(v->index_register)!=0) err = ttk_register_print(v->index_register); // is already defined
return 1; if (err)
return err;
printf(")"); printf(")");
return 0; break;
}
case INDEXED_ONLY_IREG: case INDEXED_ONLY_IREG:
{
printf("("); printf("(");
if (ttk_register_print(v->index_register)!=0) int err = ttk_register_print(v->index_register);
return 1; if (err)
return err;
printf(")"); printf(")");
return 0; break;
}
default:
return SWITCH_NOT_MATCHED;
} }
return 1; return 0;
} }
void pure_value_free(struct pure_value *p_v) 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) switch (p_v->kind)
{ {
case REGISTER: case REGISTER:
ttk_register_free(p_v->ttk_register); if (p_v->ttk_register) ttk_register_free(p_v->ttk_register);
break; break;
case NUMBER: case NUMBER:
break; break;
case LABEL: case LABEL:
label_free(p_v->label); if (p_v->label) label_free(p_v->label);
break; break;
} }
free(p_v); free(p_v);
@@ -166,15 +184,15 @@ void value_free(struct value *v)
switch (v->indexing_mode) switch (v->indexing_mode)
{ {
case NONE: case NONE:
pure_value_free(v->value); if (v->value) pure_value_free(v->value);
break; break;
case INDEXED: case INDEXED:
pure_value_free(v->value); if (v->value) pure_value_free(v->value);
ttk_register_free(v->index_register); if (v->index_register) ttk_register_free(v->index_register);
break; break;
default: default:
printf("ERROR: Value indexing mode not matched while freeing\n"); printf("ERROR: Indexing mode not matched while freeing value\n");
break;; break;
} }
free(v); free(v);
} }