commit 041c9b4770b933bdc2338cdbf4afe5af4d9a0396
parent 296794bcb62bfc89167f02f23301698be41de294
Author: Virgil Dupras <hsoft@hardcoded.net>
Date: Wed, 14 Sep 2022 14:01:11 -0400
cc/lib: change scanf semantics
Why not take advantage of our powerful pspop() instead of passing pointers
around?
Diffstat:
2 files changed, 28 insertions(+), 15 deletions(-)
diff --git a/fs/cc/lib.fs b/fs/cc/lib.fs
@@ -29,20 +29,30 @@ $100 MemIO :new const _sio
: 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
+
+0 value _pushed
+0 value _res
+
+(S fmt io-hdl -- f ) \ f=1 when scan is successful, preceeded by n args on PS
+: fscanf
+ 0 to _pushed 1 to _res >r c@+ >r begin ( a ) \ V1=hdl V2=loopcnt
c@+ dup '%' = if
- -1 to+ V2 drop c@+ case ( dst a )
+ -1 to+ V2 drop c@+ case ( 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
+ ( a ) V1 IO :getc dup 0< if abort" unexpected EOF" then ( a c )
+ dup 0-9? if ( a c ) 0 swap begin ( a res c )
+ '0' - swap 10 * + V1 IO :getc dup 0-9? not until ( a res c )
+ V1 IO :putback ( a res ) swap ( ... a ) 1 to+ _pushed
+ else ( a c ) drop 0 to _res leave then
+ 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 -- )
+ else ( a c ) V1 IO :getc <> if 0 to _res leave then then next ( a )
+ \ When a scanf doesn't match, we need to un-push all arguments from PS
+ drop rdrop _res not if _pushed ?dup if >r begin drop next then then _res ;
+
+(S fmt -- f )
+: scanf StdOut fscanf ;
+(S fmt str -- f )
+: sscanf
_sio MemIO :rewind c@+ _sio IO :write _sio MemIO :rewind _sio fscanf ;
diff --git a/fs/tests/cc/lib.fs b/fs/tests/cc/lib.fs
@@ -23,11 +23,14 @@ 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;
+ if (sscanf("foo %d bar", s)) {
+ return pspop();
+ } else {
+ return -1;
+ }
}
S" foo 42 bar" foo 42 #eq
+S" foo baz bar" foo -1 #eq
testend