commit a0bb03af5745b8366a04492c0c2c601caa2f6bad
parent 1e5ac4fd2262743177ed36dcae5c3642c208db8f
Author: Virgil Dupras <hsoft@hardcoded.net>
Date: Fri, 2 Dec 2022 13:45:45 -0500
comp/c: add ability to create null-terminated string literals
I'm currently looking at porting uxnasm.c which contains a lot of string-related
logic. Changing this for a counted string logic wouldn't be the end of the
world, but it would be more than a "mostly mechanical porting effort" and the
process itself would have significant likelihood of introducing bugs. Because we
can anticipate that other units more complex that uxnasm and that also contain
a lot of string logic will be ported, I thought it wise to add this capability
now.
Diffstat:
4 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/fs/comp/c/pgen.fs b/fs/comp/c/pgen.fs
@@ -279,8 +279,11 @@ MAXLITSZ Stack :new structbind Stack _list
else ( tok ) parseExpression read) parsePostfixOp then
endof
'"' of isChar?^ MAXLITSZ _litarena :[
- here 0 c, ['] ," with-stdin< here over - 1- swap c! ( saddr )
- _litarena :] const>op endof
+ here 0 c, ['] ," with-stdin<
+ ccin dup '0' = if
+ drop 1+ 0 c, \ null terminated
+ else ccputback here over - 1- over c! then ( saddr )
+ _litarena :] drop const>op endof
'{' of isChar?^ \ vmop^ must be set to target for list
vmop^ :hasop# vmop^ type *ariunitsz parseList endof
S" pspop" of s= read( read) vmpspop, parsePostfixOp endof
diff --git a/fs/doc/cc/usage.txt b/fs/doc/cc/usage.txt
@@ -37,7 +37,10 @@ are a few differences:
* Number literals are the same as Dusk OS, so 12345, $1234 and 'X'. No 0x1234
or 0o777.
* string literals are not null-terminated, but "counted strings". The exact same
- format as system strings.
+ format as system strings. You can create a null-terminated string literal by
+ appending a "0" next to the closing quote, for example "hello"0. This 0 shifts
+ the address of the literal by 1 (to skip the count) and adds an extra 0 at the
+ end.
* Added pspop() and pspush() built-in functions. They're tricky to use and are
described in doc/cc/impl.
* No "varargs". pspop() and pspush() replace that functionality.
diff --git a/fs/tests/comp/c/cc.fs b/fs/tests/comp/c/cc.fs
@@ -42,6 +42,8 @@ globalinc 1238 #eq
42 142 sysword 142 #eq
42 142 funcsig 142 #eq
capture helloworld S" Hello World!" #s=
+create expected ," Null terminated\0"
+nullstr expected 16 []= #
5 forsum 10 #eq
1 multret 1 #eq
42 multret 32 #eq
diff --git a/fs/tests/comp/c/test.c b/fs/tests/comp/c/test.c
@@ -169,6 +169,9 @@ static char *msgs[1] = {"Hello World!"};
void helloworld() {
stype(msgs[0]);
}
+void nullstr() {
+ return "Null terminated"0;
+}
int forsum(int n) {
int i;
int r = 0;