#include "lit.h" #include "fn.h" #include "lex.h" #include "parse.h" #include "prv.h" #include #include #include #include void lit_free(struct lit *l) { free(l->name); } static char *gen(struct ast *ast, struct fn *fn) { static const char fmt[] = "__str_%zu"; int n = snprintf(NULL, 0, fmt, ast->litcnt); char *ret = NULL; size_t sz; if (n < 0) { fprintf(stderr, "%s: snprintf(3) failed\n", __func__); goto failure; } else if (!(ret = malloc((sz = n + 1)))) { perror("malloc(3)"); goto failure; } n = snprintf(ret, sz, fmt, ast->litcnt); if (n < 0 || n >= sz) { fprintf(stderr, "%s: snprintf(3) failed with %d\n", __func__, n); goto failure; } ast->litcnt++; return ret; failure: free(ret); return NULL; } static const struct lit *find(const struct tk *tk, const struct ast *ast) { for (const struct lit *l = ast->lits; l; l = l->next) if (!strcmp(l->tk->s, tk->s)) return l; return NULL; } int lit_cgen(const struct lit *l) { printf("data $%s = { b \"%s\", b 0 }\n", l->name, l->tk->s); return 0; } const struct lit *lit_push(const struct tk *tk, struct prv *p) { char *name = NULL; struct fn *fn = fn_cur(p); struct ast *ast = p->ast; const struct lit *prev = find(tk, ast); struct lit *l; if (prev) return prev; else if (!(name = gen(ast, fn))) goto failure; else if (!(l = malloc(sizeof *l))) { perror("malloc(3)"); goto failure; } *l = (struct lit) { .name = name, .fn = fn, .tk = tk }; if (!ast->lits) ast->lits = l; else if (ast->lastlit) ast->lastlit->next = l; ast->lastlit = l; fprintf(stderr, "adding literal \"%s\"\n", name); return l; failure: free(name); return NULL; }