From 991d739bb02b3506da5a0af0edd9a4fd505373a3 Mon Sep 17 00:00:00 2001 From: Leo Tenenbaum Date: Fri, 27 Sep 2019 23:34:29 -0400 Subject: added converter from named arguments to non-named --- arr.c | 61 +++++++++++++++++++++++++++ blockarr.c | 61 +++++++++++++++++++++++++++ err.c | 129 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ location.c | 10 +++++ main.c | 8 +++- parse.c | 41 +++++++++++++----- str.c | 23 ++++++++++ test.toc | 4 +- toc.c | 11 ++--- types.c | 76 +++++++++++++++++++++++++++++++++ util/arr.c | 56 ------------------------ util/blockarr.c | 61 --------------------------- util/err.c | 129 -------------------------------------------------------- util/location.c | 10 ----- util/str.c | 23 ---------- 15 files changed, 405 insertions(+), 298 deletions(-) create mode 100644 arr.c create mode 100644 blockarr.c create mode 100644 err.c create mode 100644 location.c create mode 100644 str.c delete mode 100644 util/arr.c delete mode 100644 util/blockarr.c delete mode 100644 util/err.c delete mode 100644 util/location.c delete mode 100644 util/str.c diff --git a/arr.c b/arr.c new file mode 100644 index 0000000..2555d72 --- /dev/null +++ b/arr.c @@ -0,0 +1,61 @@ +typedef struct { + void *data; + size_t len; + size_t cap; + size_t item_sz; +} Array; + +static void arr_create(Array *arr, size_t item_sz) { + arr->len = arr->cap = 0; + arr->item_sz = item_sz; + arr->data = NULL; +} + +static inline void arr_reserve(Array *arr, size_t n) { + arr->cap = n; + arr->data = err_realloc(arr->data, arr->item_sz * arr->cap); +} + +/* like arr_reserve, but sets the length of the array too */ +static inline void arr_set_len(Array *arr, size_t n) { + arr->len = arr->cap = n; + arr->data = err_realloc(arr->data, arr->item_sz * arr->cap); +} + +static inline void *arr_last(Array *arr) { + if (arr->data) + return (void*)((char*)arr->data + arr->item_sz * (arr->len - 1)); + else + return NULL; +} + +static void *arr_add(Array *arr) { + if (arr->len >= arr->cap) { + arr_reserve(arr, (arr->cap + 1) * 2); + } + arr->len++; + return (void*)((char*)arr->data + arr->item_sz * (arr->len - 1)); +} + +static void arr_clear(Array *arr) { + free(arr->data); + arr->len = arr->cap = 0; + arr->data = NULL; +} + +static void arr_remove_last(Array *arr) { + /* OPTIM (memory): Shorten array. */ + arr->len--; + if (!arr->len) { + arr_clear(arr); + } + +} + +static void arr_free(Array *arr) { + free(arr->data); +} + +/* NOTE: this will not work if type is a pointer! */ +#define arr_foreach(arr, type, var) for (type *var = (arr)->data, *var##_foreach_last = arr_last(arr); var; var == var##_foreach_last ? var = NULL : var++) +#define arr_foreach_reverse(arr, type, var) for (type *var = arr_last(arr); var; var == (arr)->data ? var = NULL : var--) diff --git a/blockarr.c b/blockarr.c new file mode 100644 index 0000000..38bbf1b --- /dev/null +++ b/blockarr.c @@ -0,0 +1,61 @@ +/* +A block array is an array of blocks of T. +They ensure that pointers to values in the array are not invalidated +when something is added to the array. +*/ + +typedef struct { + void *data; + size_t n; /* number of things in this block so far */ + void *last; /* last one of them */ +} ArrBlock; + +typedef struct { + size_t item_sz; + int lg_block_sz; + /* NOTE: dynamic array tends to over-allocate, so we're using our own */ + Array blocks; +} BlockArr; + +/* +Note: the block size must be a power of 2, to use right shifting instead of division +(for optimization)! +*/ +static void block_arr_create(BlockArr *arr, int lg_block_sz, size_t item_sz) { + arr_create(&arr->blocks, sizeof(ArrBlock)); + arr->item_sz = item_sz; + arr->lg_block_sz = lg_block_sz; +} + +static void *block_arr_add(BlockArr *arr) { + ArrBlock *last_block; + last_block = arr_last(&arr->blocks); + if (arr->blocks.data == NULL || + (unsigned long)last_block->n >= (1UL << arr->lg_block_sz)) { + ArrBlock *block; + /* no blocks yet / ran out of blocks*/ + block = arr_add(&arr->blocks); + block->n = 1; + size_t bytes = arr->item_sz << arr->lg_block_sz; + block->data = err_malloc(bytes); + block->last = block->data; + return block->data; + } else { + last_block->last = (char*)last_block->last + arr->item_sz; + last_block->n++; + return last_block->last; + } +} + +static inline void *block_arr_get(BlockArr *arr, size_t index) { + size_t block_index = index >> arr->lg_block_sz; + ArrBlock *block = (ArrBlock*)arr->blocks.data + block_index; + return (char*)block->data + arr->item_sz * index; +} + +static void block_arr_free(BlockArr *arr) { + arr_foreach(&arr->blocks, ArrBlock, block) { + free(block->data); + } + arr_free(&arr->blocks); +} diff --git a/err.c b/err.c new file mode 100644 index 0000000..ac620ec --- /dev/null +++ b/err.c @@ -0,0 +1,129 @@ +#define USE_COLORED_TEXT 1 + +#if USE_COLORED_TEXT +#define TEXT_ERROR(x) "\x1b[91m" x "\x1b[0m" +#define TEXT_INFO(x) "\x1b[94m" x "\x1b[0m" +#define TEXT_WARN(x) "\x1b[93m" x "\x1b[0m" +#define TEXT_IMPORTANT(x) "\x1b[1m" x "\x1b[0m" +#else +#define TEXT_ERROR(x) x +#define TEXT_INFO(x) x +#define TEXT_WARN(x) x +#define TEXT_IMPORTANT(x) x +#endif + +static inline const char *ordinals(size_t x) { + switch (x % 10) { + case 1: return "st"; + case 2: return "nd"; + case 3: return "rd"; + default: return "th"; + } +} + +/* Write directly to the error file */ +static void err_fwrite(const void *data, size_t size, size_t n) { + fwrite(data, size, n, stderr); +} + +static void err_fprint(const char *fmt, ...) { + va_list args; + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); +} + +static void err_vfprint(const char *fmt, va_list args) { + vfprintf(stderr, fmt, args); +} + +static void err_print_header_(Location where) { + err_fprint(TEXT_ERROR("error:") " at line %lu of %s:\n", (unsigned long)where.line, where.filename); +} + +static void info_print_header_(Location where) { + err_fprint(TEXT_INFO("info:") " at line %lu of %s:\n", (unsigned long)where.line, where.filename); +} + +static void warn_print_header_(Location where) { + err_fprint(TEXT_WARN("warning:") " at line %lu of %s:\n", (unsigned long)where.line, where.filename); +} + +static void err_print_footer_(const char *context) { + const char *end = strchr(context, '\n'); + int has_newline = end != NULL; + if (!has_newline) + end = strchr(context, '\0'); + assert(end); + err_fprint("\n\there: --> "); + err_fwrite(context, 1, (size_t)(end - context)); + if (!has_newline) + err_fprint(""); + err_fprint("\n"); +} + +/* Write nicely-formatted errors to the error file */ + + +static void err_vprint(Location where, const char *fmt, va_list args) { + err_print_header_(where); + err_vfprint(fmt, args); + err_print_footer_(where.code); +} + +static void err_print_(int line, const char *file, Location where, const char *fmt, ...) { + va_list args; + if (file) + err_fprint("Generated by line %d of %s:\n", line, file); + va_start(args, fmt); + err_vprint(where, fmt, args); + va_end(args); +} + +#define err_print(...) err_print_(__LINE__, __FILE__, __VA_ARGS__) + +static void info_print(Location where, const char *fmt, ...) { + va_list args; + va_start(args, fmt); + info_print_header_(where); + err_vfprint(fmt, args); + err_print_footer_(where.code); + va_end(args); +} + +static void warn_print(Location where, const char *fmt, ...) { + va_list args; + va_start(args, fmt); + warn_print_header_(where); + err_vfprint(fmt, args); + err_print_footer_(where.code); + va_end(args); +} + +static void *err_malloc(size_t size) { + void *ret = malloc(size); + if (!ret) { + fprintf(stderr, "Error: Out of memory.\n"); + abort(); + } + return ret; +} + +/* static void *err_calloc(size_t n, size_t size) { */ +/* void *ret = calloc(n, size); */ +/* if (!ret) { */ +/* fprintf(stderr, "Error: Out of memory.\n"); */ +/* abort(); */ +/* } */ +/* return ret; */ +/* } */ + +static void *err_realloc(void *data, size_t new_size) { + void *ret = realloc(data, new_size); + if (!ret) { + fprintf(stderr, "Error: Out of memory.\n"); + abort(); + } + return ret; +} + diff --git a/location.c b/location.c new file mode 100644 index 0000000..4b450ce --- /dev/null +++ b/location.c @@ -0,0 +1,10 @@ +typedef uint32_t LineNo; +typedef struct { + LineNo line; + char *code; + const char *filename; +} Location; + +bool location_after(Location a, Location b) { /* a is after b? */ + return a.code > b.code; +} diff --git a/main.c b/main.c index 7375c89..6dc7f4d 100644 --- a/main.c +++ b/main.c @@ -2,8 +2,11 @@ TODO: named args optional params +char type +string constants are []char evaluator (simplify compile time constant expressions) re-do cgen +any odd number of "s for a string */ #include "toc.c" @@ -61,13 +64,16 @@ int main(int argc, char **argv) { return EXIT_FAILURE; } + fprint_parsed_file(stdout, &f); + + printf("\n\n-----\n\n"); block_enter(NULL, &f.stmts); /* enter global scope */ if (!types_file(&f)) { err_fprint(TEXT_IMPORTANT("Errors occured while determining types.\n")); return EXIT_FAILURE; } - + parse_printing_after_types = true; fprint_parsed_file(stdout, &f); tokr_free(&t); diff --git a/parse.c b/parse.c index f7407fd..872c0ae 100644 --- a/parse.c +++ b/parse.c @@ -109,7 +109,7 @@ typedef struct { typedef struct { struct Expression *fn; - Array args; /* of Argument */ + Array args; /* of Argument; after typing, becomes of Expression */ } CallExpr; typedef struct { @@ -168,6 +168,7 @@ typedef struct Expression { } Expression; typedef struct { + Location where; Identifier name; /* NULL = no name */ Expression val; } Argument; @@ -762,6 +763,7 @@ static bool parse_args(Parser *p, Array *args) { return false; } Argument *arg = arr_add(args); + arg->where = t->token->where; /* named arguments */ if (t->token->kind == TOKEN_IDENT && token_is_kw(t->token + 1, KW_EQ)) { arg->name = t->token->ident; @@ -1511,6 +1513,9 @@ static bool parse_file(Parser *p, ParsedFile *f) { #define PARSE_PRINT_LOCATION(l) //fprintf(out, "[l%lu]", (unsigned long)(l).line); +/* in theory, this shouldn't be global, but these functions are mostly for debugging anyways */ +static bool parse_printing_after_types; + static void fprint_expr(FILE *out, Expression *e); static void fprint_stmt(FILE *out, Statement *s); static void fprint_decl(FILE *out, Declaration *d); @@ -1537,6 +1542,8 @@ static void fprint_block(FILE *out, Block *b) { static void fprint_fn_expr(FILE *out, FnExpr *f) { fprintf(out, "fn ("); arr_foreach(&f->params, Declaration, decl) { + if (decl != f->params.data) + fprintf(out, ", "); fprint_decl(out, decl); } fprintf(out, ") "); @@ -1547,13 +1554,22 @@ static void fprint_fn_expr(FILE *out, FnExpr *f) { static void fprint_args(FILE *out, Array *args) { fprintf(out, "("); - arr_foreach(args, Argument, arg) { - if (arg != args->data) fprintf(out, ", "); - if (arg->name) { - fprint_ident(out, arg->name); - fprintf(out, " = "); + if (parse_printing_after_types) { + assert(args->item_sz == sizeof(Expression)); + arr_foreach(args, Expression, arg) { + if (arg != args->data) fprintf(out, ", "); + fprint_expr(out, arg); + } + } else { + assert(args->item_sz == sizeof(Argument)); + arr_foreach(args, Argument, arg) { + if (arg != args->data) fprintf(out, ", "); + if (arg->name) { + fprint_ident(out, arg->name); + fprintf(out, " = "); + } + fprint_expr(out, &arg->val); } - fprint_expr(out, &arg->val); } fprintf(out, ")"); } @@ -1629,8 +1645,10 @@ static void fprint_expr(FILE *out, Expression *e) { fprint_args(out, &e->direct.args); break; } - fprintf(out, ":"); - fprint_type(out, &e->type); + if (parse_printing_after_types) { + fprintf(out, ":"); + fprint_type(out, &e->type); + } } @@ -1641,9 +1659,10 @@ static void fprint_decl(FILE *out, Declaration *d) { fprint_ident(out, *ident); } if (d->flags & DECL_FLAG_CONST) { - fprintf(out, "[const]"); + fprintf(out, "@"); + } else { + fprintf(out, ":"); } - fprintf(out, ":"); if ((d->flags & DECL_FLAG_FOUND_TYPE) || (d->flags & DECL_FLAG_ANNOTATES_TYPE)) { fprint_type(out, &d->type); } diff --git a/str.c b/str.c new file mode 100644 index 0000000..ac4fb26 --- /dev/null +++ b/str.c @@ -0,0 +1,23 @@ +/* +A better alternative to strncpy. dest is guaranteed to be a null-terminated string +after this function is run. +Returns the number of characters copied to dest, not including the null character. +destsz must be greater than 0. +*/ +size_t str_copy(char *dest, size_t destsz, const char *src) { + assert(destsz); + if (!*src) { + *dest = 0; + return 0; + } + for (size_t i = 0; i < destsz-1; i++) { + *dest = *src; + if (!*src) { + *dest = 0; + return i; + } + src++; dest++; + } + dest[destsz-1] = 0; + return destsz-1; +} diff --git a/test.toc b/test.toc index 4646541..a925583 100644 --- a/test.toc +++ b/test.toc @@ -4,7 +4,7 @@ main @= fn() { ret1 = x; }; a,b : i64; - // a, b = test(3,7,2,3); - a, b = test(x = 3, y = 7, z = 30, w = 20); + a, b = test(3,7,2,3); + a, b = test(x = 3, z = 7, w = 30, y = 20); }; diff --git a/toc.c b/toc.c index d20868d..2fd7e86 100644 --- a/toc.c +++ b/toc.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -16,11 +17,11 @@ typedef long double Floating; /* OPTIM: Switch to double */ #define UINTEGER_FMT "%llu" #define INTEGER_FMT "%lld" -#include "util/location.c" -#include "util/err.c" -#include "util/arr.c" -#include "util/blockarr.c" -#include "util/str.c" +#include "location.c" +#include "err.c" +#include "arr.c" +#include "blockarr.c" +#include "str.c" #include "identifiers.c" #include "tokenizer.c" #include "parse.c" diff --git a/types.c b/types.c index 896a480..7cb48e7 100644 --- a/types.c +++ b/types.c @@ -500,7 +500,56 @@ static bool types_expr(Typer *tr, Expression *e) { return false; } bool ret = true; + FnExpr *fn_decl = NULL; + Array new_args_arr; + size_t nargs = c->args.len; + arr_create(&new_args_arr, sizeof(Expression)); + arr_set_len(&new_args_arr, nargs); + Expression *new_args = new_args_arr.data; + bool *params_set = calloc(nargs, sizeof *params_set); + if (f->kind == EXPR_IDENT) { + IdentDecl *decl = ident_decl(f->ident); + assert(decl); + if (decl->decl->flags & DECL_FLAG_HAS_EXPR) { + Expression *expr = &decl->decl->expr; + if (expr->kind == EXPR_FN) + fn_decl = &decl->decl->expr.fn; + } + } + bool had_named_arg = false; for (size_t p = 0; p < nparams; p++) { + if (args[p].name) { + if (!fn_decl) { + err_print(args[p].where, "You must call a function directly by its name to use named arguments."); + return false; + } + long index = 0; + long arg_index = -1; + arr_foreach(&fn_decl->params, Declaration, param) { + arr_foreach(¶m->idents, Identifier, ident) { + if (*ident == args[p].name) { + arg_index = index; + break; + } + index++; + } + if (arg_index != -1) break; + } + if (arg_index == -1) { + char *s = ident_to_str(args[p].name); + err_print(args[p].where, "Argument '%s' does not appear in declaration of function.", s); + free(s); + info_print(ident_decl(f->ident)->decl->where, "Declaration is here."); + return false; + } + new_args[arg_index] = args[p].val; + params_set[arg_index] = true; + continue; + } + if (had_named_arg) { + err_print(args[p].where, "Unnamed argument after named argument."); + return false; + } Expression *val = &args[p].val; Type *expected = ¶m_types[p]; Type *got = &val->type; @@ -510,8 +559,31 @@ static bool types_expr(Typer *tr, Expression *e) { char *gstr = type_to_str(got); err_print(val->where, "Expected type %s as %lu%s argument to function, but got %s.", estr, 1+(unsigned long)p, ordinals(1+p), gstr); } + new_args[p] = args[p].val; + params_set[p] = true; } if (!ret) return false; + for (size_t i = 0; i < nargs; i++) { + if (!params_set[i]) { + size_t index = 0; + assert(fn_decl); /* we can only miss an arg if we're using named args */ + + arr_foreach(&fn_decl->params, Declaration, param) { + arr_foreach(¶m->idents, Identifier, ident) { + if (index == i) { + char *s = ident_to_str(*ident); + err_print(e->where, "Argument %lu (%s) not set in function call.", 1+(unsigned long)i, s); + free(s); + return false; + } + index++; + } + } + } + } + free(params_set); + arr_free(&c->args); + c->args = new_args_arr; *t = *ret_type; break; } @@ -528,6 +600,10 @@ static bool types_expr(Typer *tr, Expression *e) { case EXPR_DIRECT: t->kind = TYPE_UNKNOWN; arr_foreach(&e->direct.args, Argument, arg) { + if (arg->name) { + err_print(arg->where, "Directives should not have named arguments."); + return false; + } if (!types_expr(tr, &arg->val)) return false; } diff --git a/util/arr.c b/util/arr.c deleted file mode 100644 index e3f5b8c..0000000 --- a/util/arr.c +++ /dev/null @@ -1,56 +0,0 @@ -typedef struct { - void *data; - size_t len; - size_t cap; - size_t item_sz; -} Array; - -static void arr_create(Array *arr, size_t item_sz) { - arr->len = arr->cap = 0; - arr->item_sz = item_sz; - arr->data = NULL; -} - -static inline void arr_reserve(Array *arr, size_t n) { - arr->cap = n; - arr->data = err_realloc(arr->data, arr->item_sz * arr->cap); - -} - -static inline void *arr_last(Array *arr) { - if (arr->data) - return (void*)((char*)arr->data + arr->item_sz * (arr->len - 1)); - else - return NULL; -} - -static void *arr_add(Array *arr) { - if (arr->len >= arr->cap) { - arr_reserve(arr, (arr->cap + 1) * 2); - } - arr->len++; - return (void*)((char*)arr->data + arr->item_sz * (arr->len - 1)); -} - -static void arr_clear(Array *arr) { - free(arr->data); - arr->len = arr->cap = 0; - arr->data = NULL; -} - -static void arr_remove_last(Array *arr) { - /* OPTIM (memory): Shorten array. */ - arr->len--; - if (!arr->len) { - arr_clear(arr); - } - -} - -static void arr_free(Array *arr) { - free(arr->data); -} - -/* NOTE: this will not work if type is a pointer! */ -#define arr_foreach(arr, type, var) for (type *var = (arr)->data, *var##_foreach_last = arr_last(arr); var; var == var##_foreach_last ? var = NULL : var++) -#define arr_foreach_reverse(arr, type, var) for (type *var = arr_last(arr); var; var == (arr)->data ? var = NULL : var--) diff --git a/util/blockarr.c b/util/blockarr.c deleted file mode 100644 index 38bbf1b..0000000 --- a/util/blockarr.c +++ /dev/null @@ -1,61 +0,0 @@ -/* -A block array is an array of blocks of T. -They ensure that pointers to values in the array are not invalidated -when something is added to the array. -*/ - -typedef struct { - void *data; - size_t n; /* number of things in this block so far */ - void *last; /* last one of them */ -} ArrBlock; - -typedef struct { - size_t item_sz; - int lg_block_sz; - /* NOTE: dynamic array tends to over-allocate, so we're using our own */ - Array blocks; -} BlockArr; - -/* -Note: the block size must be a power of 2, to use right shifting instead of division -(for optimization)! -*/ -static void block_arr_create(BlockArr *arr, int lg_block_sz, size_t item_sz) { - arr_create(&arr->blocks, sizeof(ArrBlock)); - arr->item_sz = item_sz; - arr->lg_block_sz = lg_block_sz; -} - -static void *block_arr_add(BlockArr *arr) { - ArrBlock *last_block; - last_block = arr_last(&arr->blocks); - if (arr->blocks.data == NULL || - (unsigned long)last_block->n >= (1UL << arr->lg_block_sz)) { - ArrBlock *block; - /* no blocks yet / ran out of blocks*/ - block = arr_add(&arr->blocks); - block->n = 1; - size_t bytes = arr->item_sz << arr->lg_block_sz; - block->data = err_malloc(bytes); - block->last = block->data; - return block->data; - } else { - last_block->last = (char*)last_block->last + arr->item_sz; - last_block->n++; - return last_block->last; - } -} - -static inline void *block_arr_get(BlockArr *arr, size_t index) { - size_t block_index = index >> arr->lg_block_sz; - ArrBlock *block = (ArrBlock*)arr->blocks.data + block_index; - return (char*)block->data + arr->item_sz * index; -} - -static void block_arr_free(BlockArr *arr) { - arr_foreach(&arr->blocks, ArrBlock, block) { - free(block->data); - } - arr_free(&arr->blocks); -} diff --git a/util/err.c b/util/err.c deleted file mode 100644 index ac620ec..0000000 --- a/util/err.c +++ /dev/null @@ -1,129 +0,0 @@ -#define USE_COLORED_TEXT 1 - -#if USE_COLORED_TEXT -#define TEXT_ERROR(x) "\x1b[91m" x "\x1b[0m" -#define TEXT_INFO(x) "\x1b[94m" x "\x1b[0m" -#define TEXT_WARN(x) "\x1b[93m" x "\x1b[0m" -#define TEXT_IMPORTANT(x) "\x1b[1m" x "\x1b[0m" -#else -#define TEXT_ERROR(x) x -#define TEXT_INFO(x) x -#define TEXT_WARN(x) x -#define TEXT_IMPORTANT(x) x -#endif - -static inline const char *ordinals(size_t x) { - switch (x % 10) { - case 1: return "st"; - case 2: return "nd"; - case 3: return "rd"; - default: return "th"; - } -} - -/* Write directly to the error file */ -static void err_fwrite(const void *data, size_t size, size_t n) { - fwrite(data, size, n, stderr); -} - -static void err_fprint(const char *fmt, ...) { - va_list args; - va_start(args, fmt); - vfprintf(stderr, fmt, args); - va_end(args); -} - -static void err_vfprint(const char *fmt, va_list args) { - vfprintf(stderr, fmt, args); -} - -static void err_print_header_(Location where) { - err_fprint(TEXT_ERROR("error:") " at line %lu of %s:\n", (unsigned long)where.line, where.filename); -} - -static void info_print_header_(Location where) { - err_fprint(TEXT_INFO("info:") " at line %lu of %s:\n", (unsigned long)where.line, where.filename); -} - -static void warn_print_header_(Location where) { - err_fprint(TEXT_WARN("warning:") " at line %lu of %s:\n", (unsigned long)where.line, where.filename); -} - -static void err_print_footer_(const char *context) { - const char *end = strchr(context, '\n'); - int has_newline = end != NULL; - if (!has_newline) - end = strchr(context, '\0'); - assert(end); - err_fprint("\n\there: --> "); - err_fwrite(context, 1, (size_t)(end - context)); - if (!has_newline) - err_fprint(""); - err_fprint("\n"); -} - -/* Write nicely-formatted errors to the error file */ - - -static void err_vprint(Location where, const char *fmt, va_list args) { - err_print_header_(where); - err_vfprint(fmt, args); - err_print_footer_(where.code); -} - -static void err_print_(int line, const char *file, Location where, const char *fmt, ...) { - va_list args; - if (file) - err_fprint("Generated by line %d of %s:\n", line, file); - va_start(args, fmt); - err_vprint(where, fmt, args); - va_end(args); -} - -#define err_print(...) err_print_(__LINE__, __FILE__, __VA_ARGS__) - -static void info_print(Location where, const char *fmt, ...) { - va_list args; - va_start(args, fmt); - info_print_header_(where); - err_vfprint(fmt, args); - err_print_footer_(where.code); - va_end(args); -} - -static void warn_print(Location where, const char *fmt, ...) { - va_list args; - va_start(args, fmt); - warn_print_header_(where); - err_vfprint(fmt, args); - err_print_footer_(where.code); - va_end(args); -} - -static void *err_malloc(size_t size) { - void *ret = malloc(size); - if (!ret) { - fprintf(stderr, "Error: Out of memory.\n"); - abort(); - } - return ret; -} - -/* static void *err_calloc(size_t n, size_t size) { */ -/* void *ret = calloc(n, size); */ -/* if (!ret) { */ -/* fprintf(stderr, "Error: Out of memory.\n"); */ -/* abort(); */ -/* } */ -/* return ret; */ -/* } */ - -static void *err_realloc(void *data, size_t new_size) { - void *ret = realloc(data, new_size); - if (!ret) { - fprintf(stderr, "Error: Out of memory.\n"); - abort(); - } - return ret; -} - diff --git a/util/location.c b/util/location.c deleted file mode 100644 index 4b450ce..0000000 --- a/util/location.c +++ /dev/null @@ -1,10 +0,0 @@ -typedef uint32_t LineNo; -typedef struct { - LineNo line; - char *code; - const char *filename; -} Location; - -bool location_after(Location a, Location b) { /* a is after b? */ - return a.code > b.code; -} diff --git a/util/str.c b/util/str.c deleted file mode 100644 index ac4fb26..0000000 --- a/util/str.c +++ /dev/null @@ -1,23 +0,0 @@ -/* -A better alternative to strncpy. dest is guaranteed to be a null-terminated string -after this function is run. -Returns the number of characters copied to dest, not including the null character. -destsz must be greater than 0. -*/ -size_t str_copy(char *dest, size_t destsz, const char *src) { - assert(destsz); - if (!*src) { - *dest = 0; - return 0; - } - for (size_t i = 0; i < destsz-1; i++) { - *dest = *src; - if (!*src) { - *dest = 0; - return i; - } - src++; dest++; - } - dest[destsz-1] = 0; - return destsz-1; -} -- cgit v1.2.3