diff --git a/analyser/module_analyser_switch.c2 b/analyser/module_analyser_switch.c2 index 0456876eb..adf20d43d 100644 --- a/analyser/module_analyser_switch.c2 +++ b/analyser/module_analyser_switch.c2 @@ -183,7 +183,7 @@ fn FlowBits Analyser.analyseSwitchStmt(Analyser* ma, Stmt* s) { StringLiteral* lit = (StringLiteral*)e; const char *str = ma.idx2name(lit.getText()); index = 1; // empty string has index 1 - u8 slen = (lit.getSize() - 1) & 0xFF; + u8 slen = lit.getLength() & 0xFF; if (slen) { // encode non emty strings, increment str_index index = str_index++; @@ -405,7 +405,7 @@ fn bool Analyser.analyseCaseExpr(Analyser* ma, } else if (orig.isStringLiteral()) { StringLiteral* lit = (StringLiteral*)orig; - u32 len = lit.getSize() - 1; + u32 len = lit.getLength(); if (len > 255) { ma.error(cond.getLoc(), "string switch case string is loo long (max 255 bytes)"); return false; diff --git a/ast/string_literal.c2 b/ast/string_literal.c2 index c2500a4e0..37043316b 100644 --- a/ast/string_literal.c2 +++ b/ast/string_literal.c2 @@ -27,7 +27,7 @@ type StringLiteralBits struct { public type StringLiteral struct @(opaque) { Expr base; u32 value; - u32 size; // Note: no cost on 64-bit systems because of padding + u32 len; // Note: no cost on 64-bit systems because of padding } public fn StringLiteral* StringLiteral.create(ast_context.Context* c, SrcLoc loc, u32 src_len, u32 value, u32 len) { @@ -35,7 +35,7 @@ public fn StringLiteral* StringLiteral.create(ast_context.Context* c, SrcLoc loc e.base.init(StringLiteral, loc, 0, 1, 0, LValue); e.base.base.stringLiteralBits.src_len = src_len; e.value = value; - e.size = len + 1; // size includes the null terminator + e.len = len; // null terminator is present at the end of the string in the string pool #if AstStatistics Stats.addExpr(StringLiteral, sizeof(StringLiteral)); #endif @@ -47,13 +47,14 @@ public fn u32 StringLiteral.getText(const StringLiteral* e) { return e.value; } -// includes 0-terminator +// get the length of the string literal: includes the null terminator public fn u32 StringLiteral.getSize(const StringLiteral* e) { - return e.size; + return e.len + 1; } -public fn u32 StringLiteral.strlen(const StringLiteral* e) { - return e.size - 1; +// get the length of the string literal: this may include embedded null bytes +public fn u32 StringLiteral.getLength(const StringLiteral* e) { + return e.len; } fn SrcLoc StringLiteral.getEndLoc(const StringLiteral* e) { @@ -62,7 +63,7 @@ fn SrcLoc StringLiteral.getEndLoc(const StringLiteral* e) { public fn void StringLiteral.printLiteral(const StringLiteral* e, string_buffer.Buf* out) { out.add1('"'); - out.encodeBytes(idx2name(e.value), e.size - 1, '"'); + out.encodeBytes(idx2name(e.value), e.len, '"'); out.add1('"'); } diff --git a/generator/c/c_generator_expr.c2 b/generator/c/c_generator_expr.c2 index a31f3cedb..f430c9b9c 100644 --- a/generator/c/c_generator_expr.c2 +++ b/generator/c/c_generator_expr.c2 @@ -168,7 +168,7 @@ fn void Generator.emitExpr2(Generator* gen, string_buffer.Buf* out, Expr* e, C_P fn void Generator.emitStringLiteral(Generator* gen, string_buffer.Buf* out, const StringLiteral* s, bool raw = false) { const char* p = gen.idx2name(s.getText()); - u32 len = s.getSize() - 1; + u32 len = s.getLength(); if (!raw && len > 10) { // break long string with embedded newlines on multiple lines for (;;) { diff --git a/generator/ir/ir_generator.c2 b/generator/ir/ir_generator.c2 index b87395b51..c72ada31f 100644 --- a/generator/ir/ir_generator.c2 +++ b/generator/ir/ir_generator.c2 @@ -289,7 +289,7 @@ fn void Generator.emitInit(Generator* gen, const Expr* e, u32 size) { break; case StringLiteral: const StringLiteral* s = (StringLiteral*)e; - gen.ctx.addInitString(gen.idx2name(s.getText()), s.strlen()); + gen.ctx.addInitString(gen.idx2name(s.getText()), s.getLength()); break; case Nil: assert(0); // should be CTV diff --git a/ir/context.c2 b/ir/context.c2 index a4ecbe2d5..f50240fd1 100644 --- a/ir/context.c2 +++ b/ir/context.c2 @@ -135,6 +135,7 @@ fn void print_function(const void* arg1, const void* arg2, const FunctionInfo* f c.print_function(arg2, fi, label); } +// TODO: handle embedded null bytes public fn SymbolId Context.addStringLiteral(Context* c, const char* name, const char* text, u32 size) { #if DebugIr stdio.printf("addStringLiteral(%s)\n", text); @@ -265,10 +266,11 @@ public fn void Context.addInitSymbol(Context* c, SymbolId id) { v.init(Symbol, id); } -// size = strlen() -public fn void Context.addInitString(Context* c, const char* text, u32 size) { +// size is the length of the string literal +// TODO: handle embedded null bytes +public fn void Context.addInitString(Context* c, const char* text, u32 len) { InitValue* v = c.init_values.add(); - u32 text_idx = c.pool.add(text, size, false); + u32 text_idx = c.pool.add(text, len, false); v.init(Text, text_idx); } diff --git a/ir/print.c2 b/ir/print.c2 index 0a5fd6fe7..93fc4f63a 100644 --- a/ir/print.c2 +++ b/ir/print.c2 @@ -325,6 +325,7 @@ fn void PrintHelper.printInitValue(PrintHelper* ph, const InitValue* v, string_b break; case Text: out.color(col_Data); + // TODO: handle potential embelled null bytes const char* text = ph.c.pool.idx2str(v.value); out.add1('"'); out.encodeBytes(text, (u32)string.strlen(text) + 1, '"'); diff --git a/plugins/git_version_plugin.c2 b/plugins/git_version_plugin.c2 index d4e10d803..039dc3278 100644 --- a/plugins/git_version_plugin.c2 +++ b/plugins/git_version_plugin.c2 @@ -88,8 +88,8 @@ fn void generate_module(void* arg) { ref.setBuiltin(Char, 0); // create variable - u32 version = p.info.astPool.addStr(p.version, false); u32 len = (u32)strlen(p.version); + u32 version = p.info.astPool.add(p.version, len, false); ast.StringLiteral* str = ast.StringLiteral.create(p.info.context, 0, len, version, len); ast.Expr* initExpr = (ast.Expr*)str; ast.VarDecl* vd = ast.VarDecl.create(p.info.context, GlobalVar, var_name, 0, true, &ref, a.getIdx(), 0, false, initExpr);