harec

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 1e39643dc342926d80fedd5ce6bc6aae7e075060
parent 084a4e9d986baf52f29235dba2bebe6b041d012b
Author: Drew DeVault <sir@cmpwn.com>
Date:   Thu, 31 Dec 2020 15:55:07 -0500

gen, emit: escape string constants

Diffstat:
Minclude/qbe.h | 5++++-
Msrc/emit.c | 30+++++++++++++++++++++++++++++-
Msrc/gen.c | 2+-
3 files changed, 34 insertions(+), 3 deletions(-)

diff --git a/include/qbe.h b/include/qbe.h @@ -228,7 +228,10 @@ struct qbe_data_item { union { struct qbe_value value; size_t zeroed; - char *str; + struct { + char *str; + size_t sz; + }; }; struct qbe_data_item *next; }; diff --git a/src/emit.c b/src/emit.c @@ -1,4 +1,5 @@ #include <assert.h> +#include <ctype.h> #include <stdio.h> #include "emit.h" #include "qbe.h" @@ -192,6 +193,33 @@ emit_func(struct qbe_def *def, FILE *out) } static void +emit_data_string(const char *str, size_t sz, FILE *out) +{ + bool q = false; + for (size_t i = 0; i < sz; ++i) { + /* XXX: We could stand to emit less conservatively */ + if (!isprint(str[i]) || str[i] == '"' || str[i] == '\\') { + if (q) { + q = false; + fprintf(out, "\", "); + } + fprintf(out, "b %d, ", str[i]); + } else { + if (!q) { + q = true; + fprintf(out, "b \""); + } + fprintf(out, "%c", str[i]); + } + } + if (q) { + fprintf(out, "\", b 0, "); + } else { + fprintf(out, "b 0, "); + } +} + +static void emit_data(struct qbe_def *def, FILE *out) { assert(def->kind == Q_DATA); @@ -207,7 +235,7 @@ emit_data(struct qbe_def *def, FILE *out) case QD_ZEROED: assert(0); // TODO case QD_STRING: - fprintf(out, " b \"%s\", b 0", item->str); + emit_data_string(item->str, item->sz, out); break; } diff --git a/src/gen.c b/src/gen.c @@ -686,8 +686,8 @@ gen_string(struct gen_context *ctx, def->name = temp.name; def->kind = Q_DATA; def->data.items.type = QD_STRING; - // TODO: Escape special characters def->data.items.str = strdup(expr->constant.string.value); + def->data.items.sz = expr->constant.string.len; qbe_append_def(ctx->out, def); struct qbe_value str = {0};