commit 296794bcb62bfc89167f02f23301698be41de294
parent dceccf2ca00c8133c7c60e3cd508bd203dc100ed
Author: Virgil Dupras <hsoft@hardcoded.net>
Date: Wed, 14 Sep 2022 12:53:11 -0400
cc/lib: implement sprintf fscanf scanf sscanf
Also, make lib/nfmt use stdout instead of emit and fix fprintf when io-hdl is
not ConsoleOut.
Diffstat:
5 files changed, 47 insertions(+), 9 deletions(-)
diff --git a/fs/app/cos/tools/blkpack.c b/fs/app/cos/tools/blkpack.c
@@ -1,5 +1,4 @@
// This doesn't actually work, I'm just drafting how it would look.
-// TODO: string scanning
#[ 10 const BUMP_GRANULARITY ]#
diff --git a/fs/cc/lib.fs b/fs/cc/lib.fs
@@ -1,5 +1,6 @@
\ C library
\ Isn't needed by the compiler, so it can have C code.
+?f<< /lib/str.fs
0 const NULL
: strlen c@ ;
@@ -7,16 +8,41 @@
\ TODO: write this in C. but for this, we need to have 8-bit operations on char
\ arrays. As CC works now, we can't iterate through a "char*".
-: fprintf ( .. n1? n0? fmt io-hdl )
+$100 MemIO :new const _sio
+
+: fprintf ( .. n1? n0? fmt io-hdl -- )
>r c@+ >r begin ( a ) \ V1=hdl V2=loopcnt
c@+ dup '%' = if
-1 to+ V2 drop c@+ case ( n a )
- 'd' of = swap . endof
+ 'd' of = swap V1 to@! StdOut swap . to StdOut endof
abort" unsupported fmt argument"
endcase
else V1 IO :putc then next drop rdrop ;
-: printf ( .. n1? n0? fmt ) StdOut fprintf ;
+: printf ( .. n1? n0? fmt -- ) StdOut fprintf ;
+
+(S ... fmt -- str )
+: sprintf
+ 1 to _sio MemIO ptr _sio fprintf
+ _sio MemIO ptr 1- ( len ) _sio MemIO :buf( tuck c! ;
: fputs ( str io-hdl ) IO :puts ;
: puts ( str ) StdOut fputs ;
+
+: _err abort" scanf not matching" ;
+: fscanf ( .. n1? n0? fmt io-hdl -- )
+ >r c@+ >r begin ( a ) \ V1=hdl V2=loopcnt
+ c@+ dup '%' = if
+ -1 to+ V2 drop c@+ case ( dst a )
+ 'd' of =
+ swap 0 ( a dst res ) V1 IO :getc dup 0< if _err then
+ ( a dst res c ) dup 0-9? not if _err then begin ( a dst res c )
+ '0' - swap 10 * + V1 IO :getc dup 0-9? not until ( a dst res c )
+ V1 IO :putback ( a dst res ) swap ! ( a ) endof
+ abort" unsupported fmt argument"
+ endcase
+ else ( a c ) V1 IO :getc <> if _err then then next drop rdrop ;
+
+: scanf ( .. n1? n0? fmt -- ) StdOut fscanf ;
+: sscanf ( .. n1? n0? fmt str -- )
+ _sio MemIO :rewind c@+ _sio IO :write _sio MemIO :rewind _sio fscanf ;
diff --git a/fs/lib/nfmt.fs b/fs/lib/nfmt.fs
@@ -1,7 +1,7 @@
\ Number formatting
\ hexadecimal
create _ ," 0123456789abcdef"
-: .xh $f and _ + c@ emit ;
+: .xh $f and _ + c@ stdout ;
: .x1 dup 4 rshift .xh .xh ;
: .x2 dup 8 rshift .x1 .x1 ;
\\ print top of stack in hexadecimal
@@ -10,11 +10,11 @@ create _ ," 0123456789abcdef"
: .x? dup $ffff > if .x else dup $ff > if .x2 else .x1 then then ;
\ decimal
-: _ 10 /mod ( r q ) ?dup if _ then '0' + emit ;
+: _ 10 /mod ( r q ) ?dup if _ then '0' + stdout ;
: . ( n -- )
?dup not if
- '0' emit else
- dup 0< if '-' emit 0 -^ _ else _ then
+ '0' stdout else
+ dup 0< if '-' stdout 0 -^ _ else _ then
then ;
\ size
create _ ," KMG"
@@ -22,5 +22,5 @@ create _ ," KMG"
0 begin ( sz lvl )
swap 1024 /mod ( lvl r q ) ?dup while
nip swap 1+ repeat ( lvl sz )
- . ?dup if 1- _ + c@ emit then 'B' emit ;
+ . ?dup if 1- _ + c@ stdout then 'B' stdout ;
diff --git a/fs/sys/io.fs b/fs/sys/io.fs
@@ -19,6 +19,7 @@ extends IO struct[ MemIO
SZ &+ :buf(
: :)buf dup :buf( swap bufsz + ;
: :ptr dup :buf( swap ptr + ;
+ : :rewind 0 swap to ptr ;
: _maxn ( n hdl -- real-n ) >r V1 ptr + V1 bufsz min r> ptr - ;
: _readbuf ( n hdl -- a? read-n )
>r V1 _maxn ( read-n ) dup if V1 :ptr swap dup V1 to+ ptr then rdrop ;
diff --git a/fs/tests/cc/lib.fs b/fs/tests/cc/lib.fs
@@ -9,6 +9,9 @@ foo 12 #eq
:cfunc void foo(int n) { printf(n, "foo %d bar"); }
42 capture foo S" foo 42 bar" #s=
+:cfunc char* foo(int n) { return sprintf(n, "foo %d bar"); }
+54 foo S" foo 54 bar" #s=
+
:cfunc void foo() { puts("Hello World!"); }
capture foo S" Hello World!" #s=
@@ -18,4 +21,13 @@ S" What about this?" const s
foo
memio MemIO ptr s strlen #eq
memio MemIO :buf( s c@+ []= #
+
+:cfunc int foo(char *s) {
+ int x;
+ sscanf(&x, "foo %d bar", s);
+ return x;
+}
+
+S" foo 42 bar" foo 42 #eq
+
testend