From e96fc9dc99b5a5368cc94141527902298928cf19 Mon Sep 17 00:00:00 2001 From: Alexander Demin Date: Sun, 12 Oct 2025 15:37:38 +0100 Subject: [PATCH 1/2] string malloc again, not working --- easyc.ts | 32 +++++-- runtime.c | 159 ++++++++++++++++++++++++++----- tests/string_alloc/test.easy | 14 +++ tests/string_alloc/x/test.c | 23 +++++ tests/string_alloc/x/test.output | 1 + 5 files changed, 198 insertions(+), 31 deletions(-) create mode 100644 tests/string_alloc/test.easy create mode 100644 tests/string_alloc/x/test.c create mode 100644 tests/string_alloc/x/test.output diff --git a/easyc.ts b/easyc.ts index d0e5a20..731a8f1 100644 --- a/easyc.ts +++ b/easyc.ts @@ -6,7 +6,7 @@ import child_process from "node:child_process"; const { execFileSync } = child_process; -function indent(str: string, n: number): string { +function indent(str: string, n: number = 1): string { return str .split(/\r?\n/) .map((line) => " ".repeat(n) + line) @@ -337,13 +337,13 @@ class ArrayType extends Type { } c(): string { const data = this.dynamic ? `*data` : `data[${this.sz()}]`; - return emit(["struct", "{", indent(`${this.type.c()} ${data};`, 1), "}"]); + return emit(["struct", "{", indent(`STR* strings; ${this.type.c()} ${data};`, 1), "}"]); } sz = () => `${this.hi.v([])} - ${this.lo.v([])} + 1`; zero(code: string[]): string { if (!this.dynamic) return "{0}"; const r = this.hi.context().R(); - code.push(`void *${r} AUTOFREE = malloc(sizeof(${this.type.c()}) * (${this.sz()}));`); + code.push(`void *${r} AUTOFREE_ARRAY = malloc(sizeof(${this.type.c()}) * (${this.sz()}));`); return `{ .data = ${r} }`; } typedef = (alias: string) => `typedef ${this.c()} ${alias}`; @@ -370,7 +370,7 @@ class StructType extends Type { this.fields = fields; } c(): string { - const v = ["struct", "{", ...this.fields.map((f) => indent(f.c() + ";", 1)), "}"]; + const v = ["struct", "{", indent("STR* strings;"), ...this.fields.map((f) => indent(f.c() + ";", 1)), "}"]; return emit(v); } init = () => "{0}"; @@ -445,7 +445,11 @@ class DECLARE extends Node { } v(code: string[]): string { function zero(n: string, type: Type): string | undefined { - return `${type.c()} ${n} = ${type.zero(code)};`; + const a_type = type instanceof AliasType ? type.reference_type : type; + let autofree = ""; + if (a_type instanceof ArrayType && type.dynamic) autofree = "AUTOFREE_ARRAY "; + if (a_type instanceof StructType) autofree = "AUTOFREE_STRUCT "; + return `${type.c()} ${autofree}${n} = ${type.zero(code)};`; } return this.names.map((n) => zero(n, this.type)).join("\n"); } @@ -707,15 +711,25 @@ class SET extends Statement { const code: string[] = []; for (const target of this.target) { const variable = find_existing_variable(target); - const { reference, type } = expand_variable_reference(variable, target, code); + const { reference, type, owner } = expand_variable_reference(variable, target, code); if (type.constructor.name !== this.expression.type.constructor.name) { throw new GenerateError( `type mismatch in SET: ${type.constructor.name} !== ${this.expression.type.constructor.name} at ${this.token}` ); } + const value = this.expression.v(code); - code.push(`${reference} = ${value};`); + + if (owner.type instanceof AliasType) owner.type = owner.type.reference_type; + + if (type instanceof StringType) { + code.push(`STR_copy(&${reference}, &${value});`); + } else code.push(`${reference} = ${value};`); + + if (owner.type instanceof StructType || owner.type instanceof ArrayType) { + code.push(`STR_register(&${owner.name}, &${reference});`); + } } return emit(code); } @@ -1291,6 +1305,8 @@ function expand_variable_reference(variable: Variable, variable_reference: Varia let type: Type = variable.type; let reference = variable.name; + const owner = { name: variable.name, type: variable.type }; + for (const part of variable_reference.parts) { if (part instanceof VariableSubscript) { if (type instanceof AliasType) type = type.reference_type; @@ -1329,7 +1345,7 @@ function expand_variable_reference(variable: Variable, variable_reference: Varia throw new GenerateError(`unexpected variable reference part '${part}' at ${variable.token}`); } } - return { type, reference }; + return { type, reference, owner }; } function find_existing_variable(v: VariableReference): Variable { diff --git a/runtime.c b/runtime.c index f00429a..c1881fc 100644 --- a/runtime.c +++ b/runtime.c @@ -15,23 +15,8 @@ void free(void *ptr); #define TRUE 1 #define FALSE 0 -#define AUTOFREE __attribute__((cleanup(free_array))) - -typedef struct -{ - void *data; -} ARRAY; - -void free_array(void *ptr) -{ - ARRAY *array = (ARRAY *)ptr; - void *data = array->data; - if (data) - { - free(data); - array->data = NULL; - } -} +#define AUTOFREE_ARRAY __attribute__((cleanup(free_array))) +#define AUTOFREE_STRUCT __attribute__((cleanup(free_struct))) static inline void $sleep(double seconds) { @@ -49,7 +34,7 @@ typedef struct { int sz; int immutable; - char data[4096]; + char *data; } STR; typedef struct @@ -57,16 +42,126 @@ typedef struct const STR *filename; int line; int character; -} Location; +} L; + +void STR_copy(STR *to, const STR *from) +{ + if (to->data && !to->immutable) + { + free(to->data); + } + to->sz = from->sz; + to->immutable = from->immutable; + if (from->sz > 0) + { + void *ptr = malloc(from->sz); + if (!ptr) + { + fprintf(stderr, "STR_copy(): out of memory\n"); + exit(1); + } + memcpy(ptr, from->data, from->sz); + to->data = ptr; + } + else + { + to->data = NULL; + } +} + +typedef struct STR_REFERENCE +{ + STR *str; + struct STR_REFERENCE *next; +} STR_REFERENCE; + +typedef struct STRINGS_OWNER +{ + STR_REFERENCE *strings; +} STRINGS_OWNER; + +void STR_register(void *owner_, STR *str) +{ + STRINGS_OWNER *owner = (STRINGS_OWNER *)owner_; + + STR_REFERENCE *ref = malloc(sizeof(STR_REFERENCE)); + if (!ref) + { + fprintf(stderr, "STR_register(): out of memory\n"); + exit(1); + } + ref->str = str; + ref->next = owner->strings; + owner->strings = ref; +} -int FIX(double v) { return (int)v; } +void STR_release_strings(STRINGS_OWNER *owner) +{ + printf("STR_release_strings: %p\n", owner); + STR_REFERENCE *ref = owner->strings; + while (ref) + { + STR_REFERENCE *next = ref->next; + if (!ref->str->immutable && ref->str->data) + { + printf("freeing string: %p\n", ref->str); + free(ref->str->data); + ref->str->data = NULL; + } + free(ref); + ref = next; + } + owner->strings = NULL; +} + +typedef struct +{ + void *data; +} ARRAY; + +void free_array(void *ptr) +{ + printf("free_array: %p\n", ptr); + ARRAY *array = (ARRAY *)ptr; + void *data = array->data; + if (data) + { + free(data); + array->data = NULL; + } +} + +void free_struct(void *ptr) +{ + printf("free_struct: %p\n", ptr); + STRINGS_OWNER *owner = (STRINGS_OWNER *)ptr; + STR_release_strings(owner); +} + +int FIX(double v) +{ + return (int)v; +} double FLOAT(int v) { return (double)v; } double FLOOR(double v) { return (double)((int)v); } int LENGTH(STR s) { return s.sz; } STR CHARACTER(int c) { - STR v = {.sz = 1, .data = {c, 0}}; + void *ptr = malloc(1); + if (!ptr) + { + fprintf(stderr, "CHARACTER(): out of memory\n"); + exit(1); + } + STR v = {.sz = 1, .data = ptr}; + v.data[0] = (char)c; + { + char *buf = alloca(2); + buf[0] = (char)c; + buf[1] = '\0'; + printf("CHARACTER: %d -> '%s'\n", c, buf); + } return v; } @@ -99,8 +194,20 @@ STR SUBSTR(STR from, int start, int length) fprintf(stderr, "substr (%s): start + length > size (%d + %d = %d > %d)\n", buf, start, length, start + length, from.sz); exit(1); } - STR v = {.sz = length}; + void *ptr = malloc(length); + if (!ptr) + { + fprintf(stderr, "SUBSTR(): out of memory\n"); + exit(1); + } + STR v = {.sz = length, .data = ptr}; memcpy(v.data, from.data + start, length); + { + char *buf = alloca(length + 1); + memcpy(buf, v.data, length); + buf[length] = '\0'; + printf("SUBSTR: %d,%d -> '%s'\n", start, length, buf); + } return v; } @@ -144,7 +251,13 @@ STR $concat(const char *fmt, ...) sz += n; } va_end(args); - STR v = {.sz = sz}; + void *ptr = malloc(sz); + if (!ptr) + { + fprintf(stderr, "$concat(): out of memory\n"); + exit(1); + } + STR v = {.sz = sz, .data = ptr}; memcpy(v.data, buf, sz); return v; } diff --git a/tests/string_alloc/test.easy b/tests/string_alloc/test.easy new file mode 100644 index 0000000..e1eb742 --- /dev/null +++ b/tests/string_alloc/test.easy @@ -0,0 +1,14 @@ +PROGRAM StringAlloc: + TYPE T IS STRUCTURE + FIELD x IS STRING + END STRUCTURE; + + FUNCTION abc T: + DECLARE a T; + SET a.x := "xyz"; + SET a.x := CHARACTER(100); + RETURN a; + END FUNCTION abc; + +END PROGRAM StringAlloc; + diff --git a/tests/string_alloc/x/test.c b/tests/string_alloc/x/test.c new file mode 100644 index 0000000..80c8ea7 --- /dev/null +++ b/tests/string_alloc/x/test.c @@ -0,0 +1,23 @@ +#include "runtime.c" +typedef int INTEGER; +typedef double REAL; +typedef int BOOLEAN; +typedef STR STRING; +typedef struct +{ + STR x; +} T; +T b = {0}; +STR $0 = { .data = "**", .sz = 2, .immutable = 1 }; +STR $F = { .data = "tests/string3/test.easy", .sz = 23, .immutable = 1 }; +int main_program() +{ + { + T a = {0}; + const STR $r1 = CHARACTER(100); + a.x = $r1; + $output("A", a.x); + b = a; + } + $output("AA", b.x, $0); +} diff --git a/tests/string_alloc/x/test.output b/tests/string_alloc/x/test.output new file mode 100644 index 0000000..3baf447 --- /dev/null +++ b/tests/string_alloc/x/test.output @@ -0,0 +1 @@ +dd** From 35443de459dca55da9b49df617cc9d3d23503e86 Mon Sep 17 00:00:00 2001 From: Alexander Demin Date: Mon, 13 Oct 2025 20:05:47 +0100 Subject: [PATCH 2/2] malloc string working --- .vscode/settings.json | 4 +- easyc.ts | 56 +++++----- life.easy | 2 +- runtime.c | 173 ++++++++++++------------------- tests/array_1000/x/test.c | 4 +- tests/array_dynamic/x/test.c | 2 +- tests/bf/x/test.c | 22 ++-- tests/character/x/test.output | 2 +- tests/input/x/test.c | 7 +- tests/sieve/x/test.c | 2 +- tests/string/test.easy | 8 +- tests/string/x/test.c | 28 ++--- tests/string_alloc/test.easy | 11 ++ tests/string_alloc/x/test.c | 39 +++++-- tests/string_alloc/x/test.output | 2 +- 15 files changed, 181 insertions(+), 181 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index afd1bd7..01b3dba 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -51,5 +51,7 @@ } }, ] - } + }, + "terminal.integrated.fontSize": 16, + "editor.fontSize": 16 } \ No newline at end of file diff --git a/easyc.ts b/easyc.ts index 731a8f1..a533551 100644 --- a/easyc.ts +++ b/easyc.ts @@ -337,7 +337,7 @@ class ArrayType extends Type { } c(): string { const data = this.dynamic ? `*data` : `data[${this.sz()}]`; - return emit(["struct", "{", indent(`STR* strings; ${this.type.c()} ${data};`, 1), "}"]); + return emit(["struct", "{", indent(`${this.type.c()} ${data};`, 1), "}"]); } sz = () => `${this.hi.v([])} - ${this.lo.v([])} + 1`; zero(code: string[]): string { @@ -370,7 +370,7 @@ class StructType extends Type { this.fields = fields; } c(): string { - const v = ["struct", "{", indent("STR* strings;"), ...this.fields.map((f) => indent(f.c() + ";", 1)), "}"]; + const v = ["struct", "{", ...this.fields.map((f) => indent(f.c() + ";", 1)), "}"]; return emit(v); } init = () => "{0}"; @@ -445,11 +445,7 @@ class DECLARE extends Node { } v(code: string[]): string { function zero(n: string, type: Type): string | undefined { - const a_type = type instanceof AliasType ? type.reference_type : type; - let autofree = ""; - if (a_type instanceof ArrayType && type.dynamic) autofree = "AUTOFREE_ARRAY "; - if (a_type instanceof StructType) autofree = "AUTOFREE_STRUCT "; - return `${type.c()} ${autofree}${n} = ${type.zero(code)};`; + return `${type.c()} ${n} = ${type.zero(code)};`; } return this.names.map((n) => zero(n, this.type)).join("\n"); } @@ -711,7 +707,7 @@ class SET extends Statement { const code: string[] = []; for (const target of this.target) { const variable = find_existing_variable(target); - const { reference, type, owner } = expand_variable_reference(variable, target, code); + const { reference, type } = expand_variable_reference(variable, target, code); if (type.constructor.name !== this.expression.type.constructor.name) { throw new GenerateError( @@ -720,16 +716,7 @@ class SET extends Statement { } const value = this.expression.v(code); - - if (owner.type instanceof AliasType) owner.type = owner.type.reference_type; - - if (type instanceof StringType) { - code.push(`STR_copy(&${reference}, &${value});`); - } else code.push(`${reference} = ${value};`); - - if (owner.type instanceof StructType || owner.type instanceof ArrayType) { - code.push(`STR_register(&${owner.name}, &${reference});`); - } + code.push(`${reference} = ${value};`); } return emit(code); } @@ -872,8 +859,11 @@ class INPUT extends Statement { const { type, reference } = expand_variable_reference(variable, variable_reference, code); if (type instanceof StringType) { - code.push(`scanf("%4095s", ${reference}.data);`); - code.push(`${reference}.sz = strlen(${reference}.data);`); + code.push(`{`); + code.push(indent(`char buf[4096];`, 1)); + code.push(indent(`scanf("%4095s", buf);`, 1)); + code.push(indent(`${reference} = make_string(buf, strlen(buf));`, 1)); + code.push(`}`); } else if (type instanceof IntegerType) code.push(`scanf("%d", &${reference});`); else if (type instanceof RealType) code.push(`scanf("%lf", &${reference});`); else throw new GenerateError(`unsupported variable '${variable}' type in INPUT at ${variable.token}`); @@ -1072,10 +1062,18 @@ function string_compare(left: Expression, right: Expression, operation: string, if (operation !== "==" && operation !== "!=") return null; function is_string_type(e: Expression): [boolean, string | null] { - if (!(e instanceof VariableReference)) return [false, null]; - const variable = find_existing_variable(e); - const { type, reference } = expand_variable_reference(variable, e, []); - return [type instanceof StringType, reference]; + if (e instanceof VariableReference) { + const variable = find_existing_variable(e); + const { type, reference } = expand_variable_reference(variable, e, []); + return [type instanceof StringType, reference]; + } + if (e.type instanceof StringType) return [true, e.v(code)]; + if (e instanceof FunctionCall) { + const func = e.context().functions[e.name]; + if (!func) throw new GenerateError(`unknown function '${e.name}' at ${e.token}`); + if (func.type instanceof StringType) return [true, e.v(code)]; + } + return [false, null]; } const [left_string, left_reference] = is_string_type(left); @@ -1084,7 +1082,15 @@ function string_compare(left: Expression, right: Expression, operation: string, if (left_string || right_string) { const cmp = operation === "!=" ? "!=" : "=="; const r = left.context().R(); - code.push(`const int ${r} = strcmp(${left_reference}.data, ${right_reference}.data) ${cmp} 0;`); + const left_sz = `${left_reference}.sz`; + const right_sz = `${right_reference}.sz`; + console.log(right_reference); + code.push( + `const int ${r} = ` + + `${left_sz} == ${right_sz} ` + + `&& ` + + `memcmp(${left_reference}.data, ${right_reference}.data, ${left_sz}) ${cmp} 0;` + ); return r; } return null; diff --git a/life.easy b/life.easy index 3b8bd4e..faf6450 100644 --- a/life.easy +++ b/life.easy @@ -118,7 +118,7 @@ PROGRAM Life: CALL evolution; - CALL rt_pause(0.3); + CALL runtime_pause(0.3); IF i MOD 10 = 0 THEN CALL glider(40, 10); diff --git a/runtime.c b/runtime.c index c1881fc..2119ebb 100644 --- a/runtime.c +++ b/runtime.c @@ -16,7 +16,6 @@ void free(void *ptr); #define FALSE 0 #define AUTOFREE_ARRAY __attribute__((cleanup(free_array))) -#define AUTOFREE_STRUCT __attribute__((cleanup(free_struct))) static inline void $sleep(double seconds) { @@ -44,74 +43,71 @@ typedef struct int character; } L; -void STR_copy(STR *to, const STR *from) -{ - if (to->data && !to->immutable) - { - free(to->data); - } - to->sz = from->sz; - to->immutable = from->immutable; - if (from->sz > 0) - { - void *ptr = malloc(from->sz); - if (!ptr) - { - fprintf(stderr, "STR_copy(): out of memory\n"); - exit(1); - } - memcpy(ptr, from->data, from->sz); - to->data = ptr; - } - else - { - to->data = NULL; - } -} - -typedef struct STR_REFERENCE +typedef struct string_list { + struct string_list *next; STR *str; - struct STR_REFERENCE *next; -} STR_REFERENCE; +} string_list; -typedef struct STRINGS_OWNER +static string_list *strings = NULL; + +void print_string(STR s, const char *prefix) { - STR_REFERENCE *strings; -} STRINGS_OWNER; + char *buf = alloca(s.sz + 1); + memcpy(buf, s.data, s.sz); + buf[s.sz] = '\0'; + printf("%s: '%s'\n", prefix, buf); +} -void STR_register(void *owner_, STR *str) +STR make_string(const char *data, int sz) { - STRINGS_OWNER *owner = (STRINGS_OWNER *)owner_; + void *ptr = malloc(sz); + if (!ptr) + { + fprintf(stderr, "make_string|data: out of memory\n"); + exit(1); + } + STR *str = malloc(sizeof(STR)); + if (!str) + { + fprintf(stderr, "make_string|str: out of memory\n"); + exit(1); + } + *str = (STR){.sz = sz, .data = ptr, .immutable = 0}; + memcpy(str->data, data, sz); - STR_REFERENCE *ref = malloc(sizeof(STR_REFERENCE)); - if (!ref) + string_list *reference = malloc(sizeof(string_list)); + if (!reference) { - fprintf(stderr, "STR_register(): out of memory\n"); + fprintf(stderr, "make_string|list: out of memory\n"); exit(1); } - ref->str = str; - ref->next = owner->strings; - owner->strings = ref; + reference->str = str; + reference->next = strings; + strings = reference; + return *str; } -void STR_release_strings(STRINGS_OWNER *owner) +void free_strings() { - printf("STR_release_strings: %p\n", owner); - STR_REFERENCE *ref = owner->strings; - while (ref) + string_list *list = strings; + while (list) { - STR_REFERENCE *next = ref->next; - if (!ref->str->immutable && ref->str->data) + string_list *next = list->next; + if (list->str->data && !list->str->immutable) { - printf("freeing string: %p\n", ref->str); - free(ref->str->data); - ref->str->data = NULL; + memset(list->str->data, 0, list->str->sz); + free(list->str->data); + list->str->data = NULL; + + memset(list->str, 0, sizeof(STR)); + free(list->str); + list->str = NULL; } - free(ref); - ref = next; + free(list); + list = next; } - owner->strings = NULL; + strings = NULL; } typedef struct @@ -121,23 +117,14 @@ typedef struct void free_array(void *ptr) { - printf("free_array: %p\n", ptr); ARRAY *array = (ARRAY *)ptr; - void *data = array->data; - if (data) + if (array->data) { - free(data); + free(array->data); array->data = NULL; } } -void free_struct(void *ptr) -{ - printf("free_struct: %p\n", ptr); - STRINGS_OWNER *owner = (STRINGS_OWNER *)ptr; - STR_release_strings(owner); -} - int FIX(double v) { return (int)v; @@ -148,21 +135,9 @@ int LENGTH(STR s) { return s.sz; } STR CHARACTER(int c) { - void *ptr = malloc(1); - if (!ptr) - { - fprintf(stderr, "CHARACTER(): out of memory\n"); - exit(1); - } - STR v = {.sz = 1, .data = ptr}; - v.data[0] = (char)c; - { - char *buf = alloca(2); - buf[0] = (char)c; - buf[1] = '\0'; - printf("CHARACTER: %d -> '%s'\n", c, buf); - } - return v; + char cbuf = (char)c; + STR s = make_string(&cbuf, 1); + return s; } STR SUBSTR(STR from, int start, int length) @@ -194,20 +169,7 @@ STR SUBSTR(STR from, int start, int length) fprintf(stderr, "substr (%s): start + length > size (%d + %d = %d > %d)\n", buf, start, length, start + length, from.sz); exit(1); } - void *ptr = malloc(length); - if (!ptr) - { - fprintf(stderr, "SUBSTR(): out of memory\n"); - exit(1); - } - STR v = {.sz = length, .data = ptr}; - memcpy(v.data, from.data + start, length); - { - char *buf = alloca(length + 1); - memcpy(buf, v.data, length); - buf[length] = '\0'; - printf("SUBSTR: %d,%d -> '%s'\n", start, length, buf); - } + STR v = make_string(from.data + start, length); return v; } @@ -239,26 +201,20 @@ STR $concat(const char *fmt, ...) else if (*fmt == 'S') { const STR *arg = va_arg(args, STR *); - n = arg->sz; + n = (int)sizeof(buf) - sz < arg->sz ? (int)sizeof(buf) - sz : arg->sz; memcpy(buf + sz, arg->data, n); } else if (*fmt == 'A') { const STR arg = va_arg(args, STR); - n = arg.sz; + n = (int)sizeof(buf) - sz < arg.sz ? (int)sizeof(buf) - sz : arg.sz; memcpy(buf + sz, arg.data, n); } sz += n; } va_end(args); - void *ptr = malloc(sz); - if (!ptr) - { - fprintf(stderr, "$concat(): out of memory\n"); - exit(1); - } - STR v = {.sz = sz, .data = ptr}; - memcpy(v.data, buf, sz); + + STR v = make_string(buf, sz); return v; } @@ -303,7 +259,7 @@ void $output(const char *fmt, ...) putchar('\n'); } -void rt_pause(double seconds) +void runtime_pause(double seconds) { $sleep(seconds); } @@ -319,15 +275,16 @@ void $index(int index, int lo, int hi, const STR *filename, int line, int charac int main_program(); -int main() +void $exit() { - main_program(); - return 0; + free_strings(); + exit(0); } -void $exit() +int main() { - exit(0); + main_program(); + $exit(); } #pragma clang diagnostic ignored "-Wincompatible-library-redeclaration" diff --git a/tests/array_1000/x/test.c b/tests/array_1000/x/test.c index 814f829..6caad4b 100644 --- a/tests/array_1000/x/test.c +++ b/tests/array_1000/x/test.c @@ -32,12 +32,12 @@ int main_program() $output("i", b.data[(1000) - (1000)]); n = 1000; { - void *$r1 AUTOFREE = malloc(sizeof(double) * (n - n + 1)); + void *$r1 AUTOFREE_ARRAY = malloc(sizeof(double) * (n - n + 1)); struct { double *data; } c = { .data = $r1 }; - void *$r2 AUTOFREE = malloc(sizeof(struct + void *$r2 AUTOFREE_ARRAY = malloc(sizeof(struct { double data[1 - 0 + 1]; }) * (n - n + 1)); diff --git a/tests/array_dynamic/x/test.c b/tests/array_dynamic/x/test.c index e735d5f..a3ff7ad 100644 --- a/tests/array_dynamic/x/test.c +++ b/tests/array_dynamic/x/test.c @@ -13,7 +13,7 @@ int main_program() { sz = 1024; { - void *$r1 AUTOFREE = malloc(sizeof(int) * (sz - 1 + 1)); + void *$r1 AUTOFREE_ARRAY = malloc(sizeof(int) * (sz - 1 + 1)); struct { int *data; diff --git a/tests/bf/x/test.c b/tests/bf/x/test.c index 2e7e7d5..5dc3669 100644 --- a/tests/bf/x/test.c +++ b/tests/bf/x/test.c @@ -38,19 +38,19 @@ STR bf(STR program) if (!(pc <= $r2)) break; const STR $r4 = SUBSTR(program, pc, 1); ch = $r4; - const int $r5 = strcmp(ch.data, $2.data) == 0; + const int $r5 = ch.sz == $2.sz && memcmp(ch.data, $2.data, ch.sz) == 0; if ($r5) { const int $r6 = (ptr + 1); ptr = $r6; } - const int $r7 = strcmp(ch.data, $3.data) == 0; + const int $r7 = ch.sz == $3.sz && memcmp(ch.data, $3.data, ch.sz) == 0; if ($r7) { const int $r8 = (ptr - 1); ptr = $r8; } - const int $r9 = strcmp(ch.data, $4.data) == 0; + const int $r9 = ch.sz == $4.sz && memcmp(ch.data, $4.data, ch.sz) == 0; if ($r9) { $index(ptr, 0, 299, &$F, 26, 33); @@ -58,7 +58,7 @@ STR bf(STR program) const int $r10 = (tape.data[(ptr) - (0)] + 1); tape.data[(ptr) - (0)] = $r10; } - const int $r11 = strcmp(ch.data, $5.data) == 0; + const int $r11 = ch.sz == $5.sz && memcmp(ch.data, $5.data, ch.sz) == 0; if ($r11) { $index(ptr, 0, 299, &$F, 27, 33); @@ -66,7 +66,7 @@ STR bf(STR program) const int $r12 = (tape.data[(ptr) - (0)] - 1); tape.data[(ptr) - (0)] = $r12; } - const int $r13 = strcmp(ch.data, $6.data) == 0; + const int $r13 = ch.sz == $6.sz && memcmp(ch.data, $6.data, ch.sz) == 0; if ($r13) { $index(ptr, 0, 299, &$F, 28, 57); @@ -74,7 +74,7 @@ STR bf(STR program) const STR $r14 = $concat("AA", out, $r15); out = $r14; } - const int $r16 = strcmp(ch.data, $7.data) == 0; + const int $r16 = ch.sz == $7.sz && memcmp(ch.data, $7.data, ch.sz) == 0; if ($r16) { $index(ptr, 0, 299, &$F, 30, 17); @@ -90,13 +90,13 @@ STR bf(STR program) pc = $r19; const STR $r20 = SUBSTR(program, pc, 1); ch = $r20; - const int $r21 = strcmp(ch.data, $7.data) == 0; + const int $r21 = ch.sz == $7.sz && memcmp(ch.data, $7.data, ch.sz) == 0; if ($r21) { const int $r22 = (depth + 1); depth = $r22; } - const int $r23 = strcmp(ch.data, $8.data) == 0; + const int $r23 = ch.sz == $8.sz && memcmp(ch.data, $8.data, ch.sz) == 0; if ($r23) { const int $r24 = (depth - 1); @@ -106,7 +106,7 @@ STR bf(STR program) } } } - const int $r25 = strcmp(ch.data, $8.data) == 0; + const int $r25 = ch.sz == $8.sz && memcmp(ch.data, $8.data, ch.sz) == 0; if ($r25) { $index(ptr, 0, 299, &$F, 40, 17); @@ -122,13 +122,13 @@ STR bf(STR program) pc = $r28; const STR $r29 = SUBSTR(program, pc, 1); ch = $r29; - const int $r30 = strcmp(ch.data, $8.data) == 0; + const int $r30 = ch.sz == $8.sz && memcmp(ch.data, $8.data, ch.sz) == 0; if ($r30) { const int $r31 = (depth + 1); depth = $r31; } - const int $r32 = strcmp(ch.data, $7.data) == 0; + const int $r32 = ch.sz == $7.sz && memcmp(ch.data, $7.data, ch.sz) == 0; if ($r32) { const int $r33 = (depth - 1); diff --git a/tests/character/x/test.output b/tests/character/x/test.output index e8f83fa..15f0979 100644 --- a/tests/character/x/test.output +++ b/tests/character/x/test.output @@ -1,5 +1,5 @@ 02 -1 +1 123! abc diff --git a/tests/input/x/test.c b/tests/input/x/test.c index c662a60..fa846d0 100644 --- a/tests/input/x/test.c +++ b/tests/input/x/test.c @@ -15,8 +15,11 @@ int main_program() { scanf("%d", &i); scanf("%lf", &f); - scanf("%4095s", s.data); - s.sz = strlen(s.data); + { + char buf[4096]; + scanf("%4095s", buf); + s = make_string(buf, strlen(buf)); + } const STR $r1 = $concat("AiA", $0, i, $1); $output("A", $r1); const STR $r2 = $concat("ArA", $2, f, $1); diff --git a/tests/sieve/x/test.c b/tests/sieve/x/test.c index f03a84a..777a046 100644 --- a/tests/sieve/x/test.c +++ b/tests/sieve/x/test.c @@ -84,7 +84,7 @@ int main_program() const int $r1 = (topnum > 0); if ($r1) { - void *$r2 AUTOFREE = malloc(sizeof(int) * (topnum - 1 + 1)); + void *$r2 AUTOFREE_ARRAY = malloc(sizeof(int) * (topnum - 1 + 1)); struct { int *data; diff --git a/tests/string/test.easy b/tests/string/test.easy index 8280bfa..a5af2bf 100644 --- a/tests/string/test.easy +++ b/tests/string/test.easy @@ -4,14 +4,14 @@ PROGRAM String: SET s := "abcXYZ"; SET b := s = "abcXYZ"; SET b := "abcXYZ" = s; - SET b := "abcXYZ" = "abcXYZ"; - SET b := s = s; + SET b := "abcXYZ" = "abcXYZ-*"; + SET b := s = SUBSTR(s, 0, 6); SET s := "abcXYZ"; SET b := s <> "abcXYZ"; SET b := "abcXYZ" <> s; - SET b := "abcXYZ" <> "abcXYZ"; - SET b := s <> s; + SET b := "abcXYZ" <> "abcXYZ-*"; + // SET b := s <> SUBSTR(s, 0, 6); OUTPUT SUBSTR("12345", 1, 2); OUTPUT SUBSTR(s, 1, 2); diff --git a/tests/string/x/test.c b/tests/string/x/test.c index 67c89ab..a4269f2 100644 --- a/tests/string/x/test.c +++ b/tests/string/x/test.c @@ -6,34 +6,34 @@ typedef STR STRING; STR s = {0}; int b = 0; STR $0 = { .data = "abcXYZ", .sz = 6, .immutable = 1 }; -STR $1 = { .data = "12345", .sz = 5, .immutable = 1 }; -STR $2 = { .data = "abc", .sz = 3, .immutable = 1 }; +STR $1 = { .data = "abcXYZ-*", .sz = 8, .immutable = 1 }; +STR $2 = { .data = "12345", .sz = 5, .immutable = 1 }; +STR $3 = { .data = "abc", .sz = 3, .immutable = 1 }; STR $F = { .data = "tests/string/test.easy", .sz = 22, .immutable = 1 }; int main_program() { s = $0; - const int $r1 = strcmp(s.data, $0.data) == 0; + const int $r1 = s.sz == $0.sz && memcmp(s.data, $0.data, s.sz) == 0; b = $r1; - const int $r2 = strcmp($0.data, s.data) == 0; + const int $r2 = $0.sz == s.sz && memcmp($0.data, s.data, $0.sz) == 0; b = $r2; - const int $r3 = strcmp($0.data, $0.data) == 0; + const int $r3 = $0.sz == $1.sz && memcmp($0.data, $1.data, $0.sz) == 0; b = $r3; - const int $r4 = strcmp(s.data, s.data) == 0; - b = $r4; - s = $0; - const int $r5 = strcmp(s.data, $0.data) != 0; + const STR $r4 = SUBSTR(s, 0, 6); + const int $r5 = s.sz == $r4.sz && memcmp(s.data, $r4.data, s.sz) == 0; b = $r5; - const int $r6 = strcmp($0.data, s.data) != 0; + s = $0; + const int $r6 = s.sz == $0.sz && memcmp(s.data, $0.data, s.sz) != 0; b = $r6; - const int $r7 = strcmp($0.data, $0.data) != 0; + const int $r7 = $0.sz == s.sz && memcmp($0.data, s.data, $0.sz) != 0; b = $r7; - const int $r8 = strcmp(s.data, s.data) != 0; + const int $r8 = $0.sz == $1.sz && memcmp($0.data, $1.data, $0.sz) != 0; b = $r8; - const STR $r9 = SUBSTR($1, 1, 2); + const STR $r9 = SUBSTR($2, 1, 2); $output("A", $r9); const STR $r10 = SUBSTR(s, 1, 2); $output("A", $r10); const STR $r12 = SUBSTR(s, 3, 2); - const STR $r11 = $concat("AA", $2, $r12); + const STR $r11 = $concat("AA", $3, $r12); $output("A", $r11); } diff --git a/tests/string_alloc/test.easy b/tests/string_alloc/test.easy index e1eb742..da3c07a 100644 --- a/tests/string_alloc/test.easy +++ b/tests/string_alloc/test.easy @@ -3,6 +3,10 @@ PROGRAM StringAlloc: FIELD x IS STRING END STRUCTURE; + DECLARE t T; + DECLARE huge ARRAY[10485760] OF STRING; // 1024 * 1024 * 1 + DECLARE i INTEGER; + FUNCTION abc T: DECLARE a T; SET a.x := "xyz"; @@ -10,5 +14,12 @@ PROGRAM StringAlloc: RETURN a; END FUNCTION abc; + SET t := abc(); + OUTPUT t.x, CHARACTER(101), " "; + + FOR i := 0 TO 10485759 DO + SET huge[i] := "abcdefghijklm" || "nopqrstuvwxyz"; + END FOR; + END PROGRAM StringAlloc; diff --git a/tests/string_alloc/x/test.c b/tests/string_alloc/x/test.c index 80c8ea7..7e1796e 100644 --- a/tests/string_alloc/x/test.c +++ b/tests/string_alloc/x/test.c @@ -7,17 +7,38 @@ typedef struct { STR x; } T; -T b = {0}; -STR $0 = { .data = "**", .sz = 2, .immutable = 1 }; -STR $F = { .data = "tests/string3/test.easy", .sz = 23, .immutable = 1 }; +T t = {0}; +struct +{ + STR data[10485760 - 0 + 1]; +} huge = {0}; +int i = 0; +STR $0 = { .data = "xyz", .sz = 3, .immutable = 1 }; +STR $1 = { .data = " ", .sz = 2, .immutable = 1 }; +STR $F = { .data = "tests/string_alloc/test.easy", .sz = 28, .immutable = 1 }; +STR $3 = { .data = "abcdefghijklm", .sz = 13, .immutable = 1 }; +STR $4 = { .data = "nopqrstuvwxyz", .sz = 13, .immutable = 1 }; +T abc() +{ + T a = {0}; + a.x = $0; + const STR $r4 = CHARACTER(100); + a.x = $r4; + return a; +} int main_program() { + const T $r1 = abc(); + t = $r1; + const STR $r2 = CHARACTER(101); + $output("AAA", t.x, $r2, $1); + i = 0; + while (1) { - T a = {0}; - const STR $r1 = CHARACTER(100); - a.x = $r1; - $output("A", a.x); - b = a; + if (!(i <= 10485759)) break; + $index(i, 0, 10485760, &$F, 21, 14); + const STR $r3 = $concat("AA", $3, $4); + huge.data[(i) - (0)] = $r3; + i += 1; } - $output("AA", b.x, $0); } diff --git a/tests/string_alloc/x/test.output b/tests/string_alloc/x/test.output index 3baf447..590ad7c 100644 --- a/tests/string_alloc/x/test.output +++ b/tests/string_alloc/x/test.output @@ -1 +1 @@ -dd** +de