diff --git a/include/ir.h b/include/acir.h similarity index 66% rename from include/ir.h rename to include/acir.h index a0a3b28..61772c2 100644 --- a/include/ir.h +++ b/include/acir.h @@ -6,16 +6,21 @@ enum { IR_ADD, IR_SUB, IR_MUL, IR_DIV, IR_EQ, IR_NE, IR_LT, IR_GT, IR_LE, IR_GE, IR_NEG, - IR_LIT, + IR_LIT32, IR_LIT64, }; +struct IRblock { + +} + struct IRinstruction { int op; union { - struct { IRinstruction *left, *right; }; - int val; + struct { int left, right; }; + int val_i32; + int val_i64; }; }; -#endif \ No newline at end of file +#endif diff --git a/include/ast.h b/include/ast.h index fbd3c59..2d08fe0 100644 --- a/include/ast.h +++ b/include/ast.h @@ -19,28 +19,32 @@ enum { extern const char *ast_opname[31]; +#ifndef ACC_ASTnode_SHARED_FIELDS + // AST structure field shared by all types -// llist_node *n : for linklist +// llist_node *n : linklist header // int op : node operation -#define ASTnode_SHARED_FIELDS \ +#define ACC_ASTnode_SHARED_FIELDS \ struct llist_node n; \ int op; +#endif + // AST structure (common) struct ASTnode { - ASTnode_SHARED_FIELDS + ACC_ASTnode_SHARED_FIELDS }; // AST binary operation node struct ASTbinnode { - ASTnode_SHARED_FIELDS + ACC_ASTnode_SHARED_FIELDS struct ASTnode *left; struct ASTnode *right; }; // AST if statement node struct ASTifnode { - ASTnode_SHARED_FIELDS + ACC_ASTnode_SHARED_FIELDS struct ASTnode *left; // condition true branch struct ASTnode *right; // condition false branch struct ASTnode *cond; @@ -48,41 +52,51 @@ struct ASTifnode { // AST unary operation node struct ASTunnode { - ASTnode_SHARED_FIELDS + ACC_ASTnode_SHARED_FIELDS struct ASTnode *left; }; // AST block node struct ASTblocknode { - ASTnode_SHARED_FIELDS + ACC_ASTnode_SHARED_FIELDS struct linklist st; // statements linklist }; // AST integer literal (32bit) node struct ASTi32node { - ASTnode_SHARED_FIELDS + ACC_ASTnode_SHARED_FIELDS int32_t val; }; // AST integer literal (64bit) node struct ASTi64node { - ASTnode_SHARED_FIELDS + ACC_ASTnode_SHARED_FIELDS int64_t val; }; // AST assign literal node struct ASTassignnode { - ASTnode_SHARED_FIELDS + ACC_ASTnode_SHARED_FIELDS struct ASTnode* left; struct ASTnode* right; }; // AST variable value node struct ASTvarnode { - ASTnode_SHARED_FIELDS + ACC_ASTnode_SHARED_FIELDS int id; }; +// A function with its AST root. +// TODO: parameters +struct Afunction { + struct llist_node n; // linklist header + char *name; // function name + struct ASTnode *rt; // AST root +}; + +struct Afunction* afunc_make(); + struct ASTnode* ast_make_binary(int op, struct ASTnode *left, struct ASTnode *right); struct ASTnode* ast_make_lit_i32(int32_t x); struct ASTnode* ast_make_lit_i64(int64_t x); @@ -91,6 +105,11 @@ struct ASTnode* ast_make_block(); struct ASTnode* ast_make_var(int id); struct ASTnode* ast_make_assign(int op, struct ASTnode *left, struct ASTnode *right); struct ASTnode* ast_make_if(struct ASTnode *left, struct ASTnode *right, struct ASTnode *cond); + +void ast_debug_print(FILE *Outfile, struct ASTnode *rt); +void afunc_debug_print(FILE *Outfile, struct Afunction *f); + +void afunc_free(struct Afunction *f); void ast_free(struct ASTnode *x); #endif diff --git a/include/fatals.h b/include/fatals.h index 3730927..6021950 100644 --- a/include/fatals.h +++ b/include/fatals.h @@ -7,6 +7,7 @@ void* malloc_or_fail(size_t s, const char *func_name); noreturn void fail_target(const char *target_name); noreturn void fail_malloc(const char *func_name); +noreturn void fail_quad_op(int op, const char *func_name); noreturn void fail_ast_op(int op, const char *func_name); noreturn void fail_ce_expect(int line, const char *expected, const char *got); noreturn void fail_ce(int line, const char *reason); diff --git a/include/parse.h b/include/parse.h index 5515f10..b83ad25 100644 --- a/include/parse.h +++ b/include/parse.h @@ -1,6 +1,6 @@ #ifndef ACC_PARSE_H #define ACC_PARSE_H -struct ASTnode* parse(const char *name); +struct Afunction* parse_source(const char *filename); #endif diff --git a/include/print_ast.h b/include/print_ast.h deleted file mode 100644 index 02b0382..0000000 --- a/include/print_ast.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef ACC_DEBUG_PRINT_AST -#define ACC_DEBUG_PRINT_AST - -void debug_ast_print(FILE *Outfile, struct ASTnode *rt); - -#endif - diff --git a/include/quad.h b/include/quad.h new file mode 100644 index 0000000..6c4d675 --- /dev/null +++ b/include/quad.h @@ -0,0 +1,96 @@ +#ifndef ACC_QUAD_H +#define ACC_QUAD_H + +#include +#include +#include "ast.h" +#include "util/linklist.h" + +// Operation code definations +enum { + // Loading immediates + Q_IMM_I32, // integer (32bits) + + // Terminates + Q_RET, // return + Q_BR_ALWAYS, // conditional goto: always goto true branch. + + // Guard + Q_NULL, +}; + +// Local(in function) variable. +struct Qvar { + struct llist_node n; // linklist header + int id; // variable id +}; + +// Quad instruction. +struct Quad { + struct llist_node n; // linklist header + int op; // operation code + struct Qvar *dest; // operation destination + union { + struct { struct Qvar *left, *right; }; // left/right operands for calculations + struct { struct Qblock *bt, *bf; }; // true branch & false branch for conditional goto + int32_t val_i32; // immediate: integer (32bits) + }; +}; + +// Basic block consist of Quad instructions. +struct Qblock { + struct llist_node n; // linklist header + int id; // block id + struct linklist ins; // instruction Quads + bool is_complete; // whether the block is properly ended with a terminate +}; + +// Function containing Quad instructions. +// TODO: paramaters +struct Qfunction { + struct llist_node n; // linklist header + char *name; // function name + struct linklist bs; // basic blocks + struct linklist vars; // local variables +}; + +// Constructs a Quad with an operator, a destination and two operands. +struct Quad* quad_make(int op, struct Qvar *dest, struct Qvar *left, struct Qvar *right); + +// Constructs a Quad with a loads an integer immediate (32bits). +struct Quad* quad_make_i32(struct Qvar *dest, int32_t v); + +// Constructs a Quad with instruction Q_BR_XXX (conditional goto). +struct Quad* quad_make_br(int op, struct Qblock *bt, struct Qblock *bf); + +// Returns whether the given opcode is a opcode from a terminate. +bool quad_is_terminate(int op); + +// Constructs a Qblock. +struct Qblock* qblock_make(); + +// Allocates a new basic block in the give function. +struct Qblock* qfunc_new_block(struct Qfunction *f); + +// Appends an instruction to a block. +void qblock_add_ins(struct Qblock *b, struct Quad *x); + +// Constructs a new Qvar. +struct Qvar* qvar_make(int id); + +// Allocates a new variable in the given function. +struct Qvar* qfunc_new_var(struct Qfunction *f); + +// Generates Quad Repersentation from an AST +struct Qfunction* qfunc_cgenerate(struct Afunction *afunc); + +// Frees a Qblock and all its components. +void qblock_free(struct Qblock *b); + +// Frees a Qfunction and all its components. +void qfunc_free(struct Qfunction *f); + +// Prints the contents of a Qfunction for debugging. +void qfunc_debug_print(struct Qfunction *self, FILE *Outfile); + +#endif diff --git a/include/scan.h b/include/scan.h index 4d01cb6..99a962e 100644 --- a/include/scan.h +++ b/include/scan.h @@ -3,6 +3,6 @@ #include "util/linklist.h" -struct linklist scan_tokens(const char *name); +struct linklist scan_tokens(const char *filename); #endif diff --git a/include/target.h b/include/target.h index 660f1e8..4fc2761 100644 --- a/include/target.h +++ b/include/target.h @@ -3,7 +3,9 @@ // Target types enum { - TARGET_AST + TARGET_AST, + TARGET_QUAD, + TARGET_NULL, }; int target_parse(const char *target_string); diff --git a/include/util/misc.h b/include/util/misc.h index 008fabf..6987f4e 100644 --- a/include/util/misc.h +++ b/include/util/misc.h @@ -3,7 +3,9 @@ #include +#define ACC_ARRAY_LENGTH(a) (sizeof((a))/sizeof(*(a))) + bool strequal(const char *s1, const char *s2); -char *strclone(const char *s); +char* strclone(const char *s); #endif diff --git a/main.c b/main.c index 19d4998..fcee80f 100644 --- a/main.c +++ b/main.c @@ -5,7 +5,7 @@ #include "parse.h" #include "ast.h" #include "target.h" -#include "print_ast.h" +#include "quad.h" // Print out a usage if started incorrectly static void usage(char *prog) { @@ -14,8 +14,13 @@ static void usage(char *prog) { exit(1); } +static FILE *Outfile; + // Do clean up job void unload(void) { + if (Outfile && Outfile != stdout) { + fclose(Outfile); + } } int main(int argc, char *argv[]) { @@ -24,19 +29,21 @@ int main(int argc, char *argv[]) { usage(argv[0]); } - FILE *Outfile; if (argc >= 4) { Outfile = fopen(argv[3], "w"); } else { - Outfile = fopen("out.txt", "w"); + Outfile = stdout; } int target = target_parse(argv[1]); - struct ASTnode *rt = parse(argv[2]); + struct Afunction *afunc = parse_source(argv[2]); if (target == TARGET_AST) { - debug_ast_print(Outfile, rt); + afunc_debug_print(Outfile, afunc); + } else if (target == TARGET_QUAD) { + struct Qfunction *qfunc = qfunc_cgenerate(afunc); + qfunc_debug_print(qfunc, Outfile); + qfunc_free(qfunc); } - ast_free(rt); - fclose(Outfile); + afunc_free(afunc); return (0); } diff --git a/src/ast.c b/src/ast.c index 97eacde..5bd45cd 100644 --- a/src/ast.c +++ b/src/ast.c @@ -16,7 +16,7 @@ const char *ast_opname[] = { NULL }; -// Build and return a binary AST node +// Constructs a binary AST node struct ASTnode* ast_make_binary(int op, struct ASTnode *left, struct ASTnode *right) { struct ASTbinnode *x = malloc_or_fail(sizeof(struct ASTbinnode), __FUNCTION__); @@ -26,7 +26,7 @@ struct ASTnode* ast_make_binary(int op, struct ASTnode *left, struct ASTnode *ri return ((struct ASTnode*)x); } -// Make an AST integer literal (32bit) node +// Make an AST integer literal (32bits) node struct ASTnode* ast_make_lit_i32(int32_t v) { struct ASTi32node *x = malloc_or_fail(sizeof(struct ASTi32node), __FUNCTION__); @@ -35,7 +35,7 @@ struct ASTnode* ast_make_lit_i32(int32_t v) { return ((struct ASTnode*)x); } -// Make an AST integer literal (64bit) node +// Make an AST integer literal (64bits) node struct ASTnode* ast_make_lit_i64(int64_t v) { struct ASTi64node *x = malloc_or_fail(sizeof(struct ASTi64node), __FUNCTION__); @@ -92,7 +92,83 @@ struct ASTnode* ast_make_if(struct ASTnode *left, struct ASTnode *right, struct return ((struct ASTnode*)x); } -// free an AST's memory +static void ast_print_dfs(FILE* Outfile, struct ASTnode *x, int tabs) { + for (int i = 0; i < tabs; ++i) { + fprintf(Outfile, "\t"); + } + + if (x == NULL) { + fprintf(Outfile, "--->NULL.\n"); + return; + } + + switch(x->op) { + case A_RETURN: case A_PRINT: { + struct ASTunnode *t = (struct ASTunnode*)x; + fprintf(Outfile, "--->UNOP(%s)\n", ast_opname[x->op]); + ast_print_dfs(Outfile, t->left, tabs + 1); + } break; + + case A_LIT_I32: { + struct ASTi32node *t = (struct ASTi32node*)x; + fprintf(Outfile, "--->INT32(%d)\n", t->val); + } break; + + case A_LIT_I64: { + struct ASTi64node *t = (struct ASTi64node*)x; + fprintf(Outfile, "--->INT64(%lld)\n", t->val); + } break; + + case A_BLOCK: { + struct ASTblocknode *t = (struct ASTblocknode*)x; + fprintf(Outfile, "--->BLOCK(%d statements)\n", t->st.length); + struct llist_node *p = t->st.head; + while (p) { + ast_print_dfs(Outfile, (struct ASTnode*)p, tabs + 1); + p = p->nxt; + } + } break; + + default: { + fail_ast_op(x->op, __FUNCTION__); + } break; + } +} + +// Prints the structure of a AST into Outfile. +void ast_debug_print(FILE *Outfile, struct ASTnode *rt) { + ast_print_dfs(Outfile, rt, 0); +} + +// Prints the structure of a Afunction into Outfile. +void afunc_debug_print(FILE *Outfile, struct Afunction *f) { + fprintf(Outfile, "FUNCTION %s: \n", f->name); + ast_print_dfs(Outfile, f->rt, 0); +} + +// Constructs a Afunction. +struct Afunction* afunc_make() { + struct Afunction *res = (struct Afunction*)malloc_or_fail(sizeof(struct Afunction), __FUNCTION__); + + res->rt = NULL; + res->name = NULL; + return res; +} + +// Frees a Afunction and all its components. +void afunc_free(struct Afunction *f) { + if (f->name) { + free(f->name); + } + + if (f->rt) { + ast_free(f->rt); + } + + free(f); +} + +// Frees an AST's memory, including its childs. void ast_free(struct ASTnode *x) { if (x == NULL) { return; @@ -125,10 +201,13 @@ void ast_free(struct ASTnode *x) { ast_free((struct ASTnode*)p); p = nxt; } - llist_free(&t->st); + } break; + + case A_LIT_I32: case A_LIT_I64: { } break; default: { + fail_ast_op(x->op, __FUNCTION__); } break; } free(x); diff --git a/src/fatals.c b/src/fatals.c index d479f4a..d9e1177 100644 --- a/src/fatals.c +++ b/src/fatals.c @@ -1,6 +1,8 @@ #include #include #include "scan.h" +#include "ast.h" +#include "quad.h" void fail_target(const char *target_name) { fprintf(stderr, "unknown target: %s.\n", target_name); @@ -20,9 +22,24 @@ void* malloc_or_fail(size_t s, const char *func_name) { return (res); } +void fail_quad_op(int op, const char *func_name) { + if (op < Q_NULL) { + fprintf(stderr, "%s: unsupported Quad operator %s.\n", func_name, ast_opname[op]); + exit(1); + } else { + fprintf(stderr, "%s: unknown Quad operator %d.\n", func_name, op); + exit(1); + } +} + void fail_ast_op(int op, const char *func_name) { - fprintf(stderr, "%s: unknown ast operator %d.\n", func_name, op); - exit(1); + if (op < A_SOUL) { + fprintf(stderr, "%s: unsupported AST operator %s.\n", func_name, ast_opname[op]); + exit(1); + } else { + fprintf(stderr, "%s: unknown AST operator %d.\n", func_name, op); + exit(1); + } } void fail_ce_expect(int line, const char *expected, const char *got) { diff --git a/src/parse.c b/src/parse.c index f90862a..d4ec163 100644 --- a/src/parse.c +++ b/src/parse.c @@ -347,11 +347,13 @@ static struct ASTnode* statement(void) { // Parse one top-level function // Sets the func_name param. -static struct ASTnode* function(char **func_name) { +static struct Afunction* function() { + struct Afunction *res = afunc_make(); + match(T_INT); expect(T_ID); - *func_name = current()->val_s; // transfer ownership of the identifier string to caller - current()->val_s = NULL; // prevent it from being freed in token_free() called by next. + res->name = current()->val_s; // transfer ownership of the identifier string to caller + current()->val_s = NULL; // prevent it from being freed in token_free() called by next(). next(); match(T_LP); @@ -359,20 +361,19 @@ static struct ASTnode* function(char **func_name) { next(); goto END_PARAM_LIST; } - // TODO: param list + // TODO: parameter list END_PARAM_LIST: match(T_RP); - return (block()); + res->rt = block(); + return (res); } // Parse ans return the full ast -struct ASTnode* parse(const char *name) { - Tokens = scan_tokens(name); - char *func_name; - struct ASTnode* res = function(&func_name); +struct Afunction* parse_source(const char *filename) { + Tokens = scan_tokens(filename); + struct Afunction* res = function(); - free(func_name); while (Tokens.length > 0) { token_free(llist_popfront(&Tokens)); } diff --git a/src/print_ast.c b/src/print_ast.c deleted file mode 100644 index 0fb0552..0000000 --- a/src/print_ast.c +++ /dev/null @@ -1,65 +0,0 @@ -#include -#include -#include "ast.h" -#include "print_ast.h" -#include "symbol.h" -#include "fatals.h" -#include "util/array.h" - -static int tabs; - -static void print_tabs(FILE* Outfile) { - for (int i = 0; i < tabs; ++i) { - fprintf(Outfile, "\t"); - } -} - -static void ast_dfs(FILE* Outfile, struct ASTnode *x) { - print_tabs(Outfile); - if (x == NULL) { - fprintf(Outfile, "--->NULL.\n"); - return; - } - - switch(x->op) { - case A_RETURN: case A_PRINT: { - struct ASTunnode *t = (struct ASTunnode*)x; - fprintf(Outfile, "--->UNOP(%s)\n", ast_opname[x->op]); - tabs += 1; - ast_dfs(Outfile, t->left); - tabs -= 1; - } break; - - case A_LIT_I32: { - struct ASTi32node *t = (struct ASTi32node*)x; - fprintf(Outfile, "--->INT32(%d)\n", t->val); - } break; - - case A_LIT_I64: { - struct ASTi64node *t = (struct ASTi64node*)x; - fprintf(Outfile, "--->INT64(%lld)\n", t->val); - } break; - - case A_BLOCK: { - struct ASTblocknode *t = (struct ASTblocknode*)x; - fprintf(Outfile, "--->BLOCK(%d statements)\n", t->st.length); - tabs += 1; - struct llist_node *p = t->st.head; - while (p) { - ast_dfs(Outfile, (struct ASTnode*)p); - p = p->nxt; - } - tabs -= 1; - } break; - - default: { - fprintf(Outfile, "--->%s...\n", ast_opname[x->op]); - } break; - } -} - -void debug_ast_print(FILE *Outfile, struct ASTnode *rt) { - tabs = 0; - ast_dfs(Outfile, rt); -} - diff --git a/src/quad.c b/src/quad.c new file mode 100644 index 0000000..147cafe --- /dev/null +++ b/src/quad.c @@ -0,0 +1,193 @@ +#include +#include +#include "quad.h" +#include "fatals.h" + +// Constructs a Quad with an operator, a destination and two operands. +struct Quad* quad_make(int op, struct Qvar *dest, struct Qvar *left, struct Qvar *right) { + struct Quad *x = malloc_or_fail(sizeof(struct Quad), __FUNCTION__); + + x->op = op; + x->dest = dest; + x->left = left; + x->right = right; + return (x); +} + +// Constructs a Quad with a loads an integer immediate (32bits). +struct Quad* quad_make_i32(struct Qvar *dest, int32_t v) { + struct Quad *x = malloc_or_fail(sizeof(struct Quad), __FUNCTION__); + + x->op = Q_IMM_I32; + x->dest = dest; + x->val_i32 = v; + return (x); +} + +// Constructs a Quad with instruction Q_BR_XXX (conditional goto). +struct Quad* quad_make_br(int op, struct Qblock *bt, struct Qblock *bf) { + struct Quad *x = malloc_or_fail(sizeof(struct Quad), __FUNCTION__); + + x->op = op; + x->bt = bt; + x->bf = bf; + return (x); +} + +// Returns whether the given opcode is a opcode from a terminate. +bool quad_is_terminate(int op) { + switch (op) { + case Q_RET: + case Q_BR_ALWAYS: + return (true); + + default: + return (false); + } +} + +// Constructs a Qblock. +struct Qblock* qblock_make(int id) { + struct Qblock *x = malloc_or_fail(sizeof(struct Qblock), __FUNCTION__); + llist_init(&x->ins); + x->id = id; + x->is_complete = false; + return (x); +} + +// Allocates a new basic block in the give function. +struct Qblock* qfunc_new_block(struct Qfunction *f) { + struct Qblock *x = qblock_make(f->bs.length); + llist_pushback(&f->bs, x); + return (x); +} + +// Appends an instruction to a block. +void qblock_add_ins(struct Qblock *b, struct Quad *x) { + if (b->is_complete) { + return; + } + llist_pushback(&b->ins, x); +} + +// Constructs a new Qvar. +struct Qvar* qvar_make(int id) { + struct Qvar *res = malloc_or_fail(sizeof(struct Qvar), __FUNCTION__); + res->id = id; + return (res); +} + +// Allocates a new variable in the given function. +struct Qvar* qfunc_new_var(struct Qfunction *f) { + struct Qvar *res = qvar_make(f->vars.length); + llist_pushback(&f->vars, res); + return (res); +} + +static struct Qvar* qcg_dfs(struct ASTnode *x, struct Qfunction *f, struct Qblock *b) { + switch (x->op) { + case A_RETURN: { + struct ASTunnode *t = (void*)x; + struct Qvar *value = qcg_dfs(t->left, f, b); + qblock_add_ins(b, quad_make(Q_RET, NULL, value, NULL)); + b->is_complete = true; + return (NULL); + } + + case A_LIT_I32: { + struct ASTi32node *t = (void*)x; + struct Qvar *res = qfunc_new_var(f); + qblock_add_ins(b, quad_make_i32(res, t->val)); + return (res); + } + + case A_BLOCK: { + struct ASTblocknode *t = (void*)x; + struct llist_node *p = t->st.head; + while (p) { + qcg_dfs((struct ASTnode*)p, f, b); + p = p->nxt; + } + return (NULL); + } + + default: { + fail_ast_op(x->op, __FUNCTION__); + } + } +} + +// Generates Quad Repersentation from an AST +struct Qfunction* qfunc_cgenerate(struct Afunction *afunc) { + struct Qfunction *self = malloc_or_fail(sizeof(struct Qfunction), __FUNCTION__); + + self->name = afunc->name; // transfer ownership of function name string + afunc->name = NULL; // prevents the pointer being freed when freeing the Afunction + + llist_init(&self->bs); + llist_init(&self->vars); + + struct Qblock *entry = qfunc_new_block(self); + qcg_dfs(afunc->rt, self, entry); + return (self); +} + +// Frees a Qblock and all its components. +void qblock_free(struct Qblock *b) { + llist_free(&b->ins); + free(b); +} + +// Frees a Qfunction and all its components. +void qfunc_free(struct Qfunction *f) { + if (f->name) { + free(f->name); + } + + struct llist_node *p = f->bs.head, *nxt; + while (p) { + nxt = p->nxt; + qblock_free((struct Qblock*)p); + p = nxt; + } + + llist_free(&f->vars); + free(f); +} + +// Prints the given instruction for debugging. +static void quad_debug_print(struct Quad *self, FILE *Outfile) { + switch(self->op) { + case Q_IMM_I32: { + fprintf(Outfile, "\t$%d = i32 %d;\n", self->dest->id, self->val_i32); + } break; + + case Q_RET: { + fprintf(Outfile, "\tret $%d.\n", self->left->id); + } break; + + default: { + fail_quad_op(self->op, __FUNCTION__); + } + } +} + +// Prints the contents of a Qblock for debugging. +static void qblock_debug_print(struct Qblock *self, FILE *Outfile) { + fprintf(Outfile, "L%d:\n", self->id); + struct llist_node *p = self->ins.head; + while (p) { + quad_debug_print((struct Quad*)p, Outfile); + p = p->nxt; + } +} + +// Prints the contents of a Qfunction for debugging. +void qfunc_debug_print(struct Qfunction *self, FILE *Outfile) { + fprintf(Outfile, "%s:\n", self->name); + struct llist_node *p = self->bs.head; + while (p) { + qblock_debug_print((struct Qblock*)p, Outfile); + p = p->nxt; + } +} diff --git a/src/target.c b/src/target.c index c089567..3e13b59 100644 --- a/src/target.c +++ b/src/target.c @@ -1,19 +1,23 @@ #include +#include "util/misc.h" #include "fatals.h" #include "target.h" +// Parse the target string int target_parse(const char *target_string) { static const char *target_map_k[] = { "ast", + "quad", NULL }; static const int target_map_v[] = { TARGET_AST, + TARGET_QUAD, }; for (int i = 0; target_map_k[i]; ++i) { - if (strcmp(target_map_k[i], target_string) == 0) { + if (strequal(target_map_k[i], target_string)) { return (target_map_v[i]); } } diff --git a/src/util/misc.c b/src/util/misc.c index 85c03ea..991211a 100644 --- a/src/util/misc.c +++ b/src/util/misc.c @@ -2,13 +2,14 @@ #include #include "util/misc.h" -// check if two string are the same +// This function does what you think it does :) +// Returns whether the given strings are the same. bool strequal(const char *s1, const char *s2) { return (strcmp(s1, s2) == 0); } -// A impl of C23 strdup() -// Clones the given string +// A impl of C23 strdup(). +// Clones the given string and returns a pointer. char* strclone(const char *s) { int n = strlen(s); char *res = malloc(n + 1); @@ -16,4 +17,3 @@ char* strclone(const char *s) { res[n] = '\0'; return res; } -