commit aba729fb99abadc1f34cc47d13f9a8c5d1caac10
parent e110728166b2ee1bba827fb55f0abc43232c1de0
Author: Virgil Dupras <hsoft@hardcoded.net>
Date: Fri, 9 Sep 2022 15:56:14 -0400
Add \n \r and \0 escapes in string literals
See doc/usage.
Diffstat:
8 files changed, 83 insertions(+), 21 deletions(-)
diff --git a/fs/cc/tok.fs b/fs/cc/tok.fs
@@ -24,7 +24,7 @@
\ with a symbol that is also a 1 char symbol and all 3 chars symbols begin with
\ 2 chars that are also a 2 chars symbol.
\ list of 1 char symbols
-create symbols1 ," +-*/~&<>=[](){}.%^?:;,|^#" '"' c,
+create symbols1 ," +-*/~&<>=[](){}.%^?:;,|^#\""
: isSym1? ( c -- f ) symbols1 26 [c]? 0>= ;
diff --git a/fs/doc/dict.txt b/fs/doc/dict.txt
@@ -308,11 +308,14 @@ rebind 'data 'bind --
key -- c Read next character from system interactive input source.
in< -- c Read next character from system input source.
+"< -- c Read from in< and apply literal escapes. c=-1 when " is
+ read (end of string).
emit c -- Emit character to system output destination.
nl> -- Emit CR then LF.
spc> -- Emit SPC.
rtype a u -- Emit characters in range [a, a+u].
stype s -- Emit all characters in s.
+," x" -- Read from in< until " is reached and write it to here.
." x" -- *IC* Emit string x.
abort" x" -- *IC* Emit string x then abort.
maybeword -- s-or-0 Try to read word from system input source and yield it as
diff --git a/fs/doc/usage.txt b/fs/doc/usage.txt
@@ -3,6 +3,22 @@
NOTE: this document isn't complete. I'm only writing a few notes that will end
up being in the usage guide once it's done.
+# String literals
+
+When a string literal word such as S" ." or ," is used, the following content
+is parsed in an almost verbatim manner until the closing " is reached. We say
+almost verbatim because we can write special characters with the '\' escape
+character:
+
+\n: newline ($0a)
+\r: carriage return ($0d)
+\0: 0
+\\: '\' character
+\": '"' character
+
+Any other character following the '\' results in that character being parsed as-
+is, the preceding '\' being ignored.
+
# "to" semantics
Values and aliases are very similar to cells: they're a piece of memory attached
diff --git a/fs/sys/rdln.fs b/fs/sys/rdln.fs
@@ -13,7 +13,7 @@ in) value in>
dup emitv dup rot c!+ ( c ptr+1 ) dup in) = rot SPC < or ( ptr+1 f )
then ;
: rdln
- in( LNSZ SPC fill S" ok" stype nl>
+ in( LNSZ SPC fill S" ok\n" stype
in( begin key lntype until drop nl> ;
: rdln<? ( -- c-or-0 )
in> in) < if in> c@+ swap to in> else 0 then ;
diff --git a/fs/xcomp/bootlo.fs b/fs/xcomp/bootlo.fs
@@ -161,7 +161,7 @@ $20 const SPC $0d const CR $0a const LF $08 const BS
here 1 allot here ," here -^ ( 'len len ) swap c! ; immediate
: ."
compiling if [compile] S" compile stype else
- begin in< dup '"' = not while emit repeat drop then ; immediate
+ begin "< dup 0>= while emit repeat drop then ; immediate
: abort" [compile] ." compile abort ; immediate
\ Return whether strings s1 and s2 are equal
diff --git a/fs/xcomp/i386.fs b/fs/xcomp/i386.fs
@@ -864,11 +864,34 @@ xcode parse ( str -- n? f )
bp CELLSZ d) neg,
ret,
-xcode ,"
+pc 7 nc, 'n' LF 'r' CR '0' 0 0
+xcode "<
lblin< m) call,
- AX pspop,
- al '"' i) cmp,
+ [ebp] '"' i) cmp,
+ forward jnz,
+ [ebp] -1 i) mov,
+ ret,
+ forward!
+ [ebp] '\' i) cmp,
+ lblret abs>rel jnz,
+ ps-,
+ lblin< m) call,
+ si ( pc ) i) mov,
+pc
+ lodsb,
+ al al test,
lblret abs>rel jz,
+ [ebp] al cmp,
+ lodsb,
+ ( pc ) abs>rel jnz,
+ [ebp] al mov,
+ ret,
+
+xcode ,"
+ wcall, "<
+ AX pspop,
+ ax ax test,
+ lblret abs>rel js,
xwordlbl ," i) push,
lblcwrite abs>rel jmp,
diff --git a/fs/xcomp/init.fs b/fs/xcomp/init.fs
@@ -6,5 +6,5 @@ f<< lib/diag.fs
f<< sys/xhere.fs
f<< sys/rdln.fs
f<< lib/btrace.fs
-: init S" Dusk OS" stype nl> .free rdln$ btrace$ ( unwind the boot RS ) quit ;
+: init S" Dusk OS\n" stype .free rdln$ btrace$ ( unwind the boot RS ) quit ;
init
diff --git a/posix/vm.c b/posix/vm.c
@@ -419,6 +419,36 @@ static void WRITE() { // op: 30
ISTOREADD();
}
+#define ESCAPECNT 3
+static char escapes[ESCAPECNT][2] = {{'n', '\n'}, {'r', '\r'}, {'0', 0}};
+static void SRD() { // op: 31
+ dword c;
+ callword(gd(INRD));
+ c = ppop();
+ if (c == '"') {
+ c = 0xffffffff;
+ } else if (c == '\\') {
+ callword(gd(INRD));
+ c = ppop();
+ for (int i=0; i<ESCAPECNT; i++) {
+ if ((dword)escapes[i][0] == c) {
+ c = escapes[i][1];
+ }
+ }
+ }
+ ppush(c);
+}
+
+static void SWR() { // op: 32
+ dword c;
+ while (1) {
+ SRD();
+ c = ppop();
+ if (c==0xffffffff) return;
+ cwrite(c);
+ }
+}
+
static void SETBW() { // op: 34
vm.bwidth = ppop();
}
@@ -668,16 +698,6 @@ static void COMPILING() { // op: 57
ppush(vm.compiling);
}
-static void SWR() { // op: 58
- dword c;
- while (1) {
- callword(gd(INRD));
- c = ppop();
- if (c == '"') return;
- cwrite(c);
- }
-}
-
static void STARTCOMP() { // op: 59
vm.compiling = 1;
}
@@ -948,12 +968,12 @@ static void (*ops[OPCNT])() = {
DUP, CDUP, SWAP, OVER, ROT, ROTR, NIP, TUCK,
RSADD, RSADDWR, RSADDR, RSADDRWR, SCNT, RCNT, SET16B, SET8B,
FETCH, STORE, ADDSTORE, FETCHSTORE, FETCHADD, STOREADD, IFETCHADD, ISTOREADD,
- WRITE, NULL, NULL, NULL, SETBW, NULL, NULL, NULL,
+ WRITE, SRD, SWR, NULL, SETBW, NULL, NULL, NULL,
INC, DEC, ADD, SUB, MUL, DIVMOD, AND, NULL,
OR, XOR, BOOL, NOT, LT, SHLC, SHRC, LSHIFT,
RSHIFT, LITN, EXECUTEWR, EXITWR, MOVE, MOVEWR, RTYPE, WNF,
STACKCHK, MAYBEWORD, WORD, PARSE, REQ, FIND, APOS, COMPILING,
- SWR, STARTCOMP, STOPCOMP, COMPWORD, RUNWORD, NULL, NULL, NULL,
+ NULL, STARTCOMP, STOPCOMP, COMPWORD, RUNWORD, NULL, NULL, NULL,
FCHILD, FOPEN, FREADBUF, FCLOSE, FINFO, FITER, NULL, NULL,
MOUNTDRV, DRVRD, DRVWR};
@@ -964,12 +984,12 @@ static char *opnames[OPCNT] = {
"dup", "?dup", "swap", "over", "rot", "rot>", "nip", "tuck",
NULL, "r+,", NULL, "r',", "scnt", "rcnt", "16b", "8b",
"@", "!", "+!", "@!", "@+", "!+", "@@+", "@!+",
- ",", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ ",", "\"<", ",\"", NULL, NULL, NULL, NULL, NULL,
"1+", "1-", "+", "-", "*", "/mod", "and", NULL,
"or", "xor", "bool", "not", "<", "<<c", ">>c", "lshift",
"rshift", "litn", "execute,", "exit,", "move", "move,", "rtype", "(wnf)",
"stack?", "maybeword", "word", "parse", "[]=", "find", "'", "compiling",
- ",\"", "]", "[", "compword", "runword", NULL, NULL, NULL,
+ NULL, "]", "[", "compword", "runword", NULL, NULL, NULL,
"_fchild", "_fopen", "_freadbuf", "_fclose", "_finfo", "_fiter", NULL, NULL,
"_mountdrv", "_drv@", "_drv!"};