aboutsummaryrefslogtreecommitdiff
path: root/warn.c
diff options
context:
space:
mode:
authorXavier Del Campo Romero <xavi92@disroot.org>2026-05-09 02:56:07 +0200
committerXavier Del Campo Romero <xavi92@disroot.org>2026-06-21 01:15:38 +0200
commitb25ff71bb198c227b3202ee32a8067cda413bc16 (patch)
tree41d665a87d948c10b17a853220cbcdbaeebf3672 /warn.c
downloadprc-master.tar.gz
Add project skeletonHEADmaster
Diffstat (limited to 'warn.c')
-rw-r--r--warn.c146
1 files changed, 146 insertions, 0 deletions
diff --git a/warn.c b/warn.c
new file mode 100644
index 0000000..456ce79
--- /dev/null
+++ b/warn.c
@@ -0,0 +1,146 @@
+#include "warn.h"
+#include "cgen.h"
+#include "parse.h"
+#include "prv.h"
+#include "stmt.h"
+#include "storage.h"
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+static int finalize(const struct lex *l, const struct prv *p,
+ const struct print *pr)
+{
+ const struct ast *ast = p->ast;
+ struct fn *fn = &ast->fns[ast->nfns - 1];
+ size_t n = fn->nstmts + 1;
+ struct stmt *stmts = realloc(fn->stmts, n * sizeof *stmts);
+
+ if (!stmts)
+ {
+ perror("realloc(3)");
+ return -1;
+ }
+
+ fn->stmts = stmts;
+ fn->stmts[fn->nstmts++] = (struct stmt)
+ {
+ .type = WARN,
+ .u.warn.p = *pr
+ };
+
+ fprintf(stderr, "\t\tadding warn statement with %zu entries%s\n",
+ pr->nentries, pr->println ? "" : ", no lf");
+ return 0;
+}
+
+static int cg_val(const struct tk *tk)
+{
+ const char *num = tk->s;
+ int neg = *num == '-';
+ unsigned long long uv;
+ char *end;
+
+ fputs("call $printf(l $____fmt", stdout);
+ errno = 0;
+ uv = strtoull(num, &end, 16);
+
+ if (!neg && !errno && !*end)
+ printf("lx, ..., l %llu )\n", uv);
+ else
+ {
+ errno = 0;
+ uv = strtoull(num, &end, 0);
+
+ if (neg || errno || *end)
+ {
+ long long v = strtoll(num, NULL, 0);
+ printf("l, ..., l %lld )\n", v);
+ }
+ else
+ printf("l, ..., l %llu )\n", uv);
+ }
+
+ return 0;
+}
+
+static int cg_lit(const struct prientry *e)
+{
+ const struct lit *l = e->lit;
+ const char *tmp;
+
+ if (!l)
+ {
+ fprintf(stderr, "%s: unexpected null literal\n", __func__);
+ return -1;
+ }
+
+ printf("%%%s =l loadl $stderr\n", (tmp = cgen_tmp(sizeof (void *))));
+ printf("call $fputs(l $%s, w %%%s)\n", l->name, tmp);
+ return 0;
+}
+
+static int cg_id(const struct prientry *de, const struct fn *fn)
+{
+ const struct stentry *e = de->entry;
+ const struct type *t = e->t;
+ const char *id = e->tk->s;
+ int global = cgen_global(fn, e);
+ size_t sz = t->sz;
+ const char *asz = cgen_sz(sz < 4 ? 4 : sz), *tmp = cgen_tmp(sz);
+
+ if (global)
+ printf("%%%s =%s load%s $%s\n", tmp, asz, cgen_load(t), id);
+ else
+ printf("%%%s =%s load%s %%%s_\n", tmp, asz, cgen_load(t), id);
+
+ puts("%z =l loadl $stderr");
+ fputs("call $fprintf(w %z, l $____fmt", stdout);
+
+ if (t->type == PTR)
+ fputs("lx, ..., l ", stdout);
+ else
+ printf("%s, ..., %s ", cgen_type(t), asz);
+
+ printf("%%%s)\n", tmp);
+
+ return 0;
+}
+
+int warn_cgen(const struct warn *w, struct cgen *c)
+{
+ const struct print *p = &w->p;
+
+ for (size_t i = 0; i < p->nentries; i++)
+ {
+ const struct prientry *e = &p->entries[i];
+ const struct tk *tk = e->tk;
+
+ if (tk->type == LIT && cg_lit(e))
+ return -1;
+ else if (tk->type == NUM && cg_val(tk))
+ return -1;
+ else if (tk->type == ID && e->entry && cg_id(e, c->fn))
+ return -1;
+ else if (tk->type == ID && e->lit && cg_lit(e))
+ return -1;
+ }
+
+ if (p->println)
+ {
+ puts("%v =l loadl $stderr");
+ puts("call $fputc(l 10 , w %v)");
+ }
+
+ return 0;
+}
+
+void warn_free(struct warn *w)
+{
+ print_free(&w->p);
+}
+
+int warn(const struct lex *l, struct prv *p)
+{
+ return print(l, p, finalize);
+}