commit 269aec12f9553fda9a261723fa5cff13f10a8718
parent a13b5d7b2f7af9fcca550f42525a42877299fee0
Author: Virgil Dupras <hsoft@hardcoded.net>
Date: Tue, 13 Sep 2022 14:32:34 -0400
cc/lib: implement fprintf, fputs, puts
Also, implement MemIO in sys/io.
Diffstat:
5 files changed, 68 insertions(+), 22 deletions(-)
diff --git a/fs/app/cos/tools/blkpack.c b/fs/app/cos/tools/blkpack.c
@@ -1,7 +1,5 @@
// This doesn't actually work, I'm just drafting how it would look.
-// TODO: string formatting
// TODO: string scanning
-// TODO: add \n in string literals
// TODO: do multiple "return" paths work?
// TODO: can we "return" early in a void function?
// TODO: signed arithmetics
@@ -35,7 +33,7 @@ unsigned int expectmarker(char *line)
int blkid = getmarker(line);
if (blkid < 0) { // could not scan
fprintf(
- stderr, "Error at line %d: expecting block marker\n", lineno);
+ lineno, "Error at line %d: expecting block marker\n", ConsoleOut());
abort();
}
return blkid;
@@ -51,7 +49,7 @@ extern void blkpack() {
int cnt = strlen(line);
lineno = 1;
if (!cnt) {
- fprintf(stderr, "No input\n");
+ fprintf("No input\n", ConsoleOut());
abort();
}
while (1) {
@@ -59,15 +57,16 @@ extern void blkpack() {
if ((blkid == 0) && (prevblkid >= 0)) {
blkoff = (prevblkid / BUMP_GRANULARITY + 1) * BUMP_GRANULARITY;
fprintf(
- stderr,
- "Block 0 encountered. Bumping current blkid to %d.\n", blkoff);
+ blkoff,
+ "Block 0 encountered. Bumping current blkid to %d.\n",
+ ConsoleOut());
}
blkid += blkoff;
if (blkid <= prevblkid) {
fprintf(
- stderr,
+ blkid, lineno,
"Wrong blkid (%d) at line %d: blocks must be ordered\n",
- blkid, lineno);
+ ConsoleOut());
abort();
}
emptylines((blkid-prevblkid-1)*16);
@@ -77,12 +76,14 @@ extern void blkpack() {
cnt = strlen(line);
if (cnt <= 0) break; // EOF
if (cnt > 65) {
- fprintf(stderr, "Line %d too long (blk %d)\n", lineno, blkid);
+ fprintf(
+ lineno, blkid,
+ "Line %d too long (blk %d)\n", ConsoleOut());
abort();
}
if (getmarker(line) >= 0) break; // we have a marker early
line[cnt-1] = '\0'; // remove newline
- printf("%s", line);
+ puts(line);
// pad line to 64 chars
for (int i=cnt-1; i<64; i++) putchar(' ');
}
diff --git a/fs/cc/lib.fs b/fs/cc/lib.fs
@@ -4,11 +4,19 @@
0 const NULL
: strlen c@ ;
-: printf ( .. n1? n0? fmt )
- c@+ >r begin ( a ) \ V1=loopcnt
+\ 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 )
+ >r c@+ >r begin ( a ) \ V1=hdl V2=loopcnt
c@+ dup '%' = if
- -1 to+ V1 drop c@+ case ( n a )
+ -1 to+ V2 drop c@+ case ( n a )
'd' of = swap . endof
abort" unsupported fmt argument"
endcase
- else stdout then next drop ;
+ else V1 IO :putc then next drop rdrop ;
+
+: printf ( .. n1? n0? fmt ) StdOut fprintf ;
+
+: fputs ( str io-hdl ) IO :puts ;
+: puts ( str ) StdOut fputs ;
diff --git a/fs/doc/io.txt b/fs/doc/io.txt
@@ -59,13 +59,14 @@ convenience words:
:putc ( c hdl -- )
Write 1 byte to hdl. Advance position by 1 byte. Aborts if unable to write.
+:puts ( str hdl -- )
+ Write str to hdl.
+
:putback ( c hdl -- )
Set the putback value to c.
## MemIO
-(TODO: doesn't exist yet)
-
MemIO is a structure that extends IO and provides read/write capabilities to a
memory buffer. It extends IO with those words:
@@ -73,13 +74,19 @@ memory buffer. It extends IO with those words:
Allocate a new buffer of size "sz" and return it.
bufsz ( hdl -- sz )
- Size of the buffer
+ Size of the buffer.
+
+ptr ( hdl -- idx )
+ Index of current position, relative to :buf(.
:buf( ( hdl -- a )
- Address of the buffer
+ Address of the buffer.
:)buf ( hdl -- a )
- Address following the last byte of the buffer
+ Address following the last byte of the buffer.
+
+:ptr ( hdl -- a )
+ Address corresponding to current position.
## SystemIn and SystemOut
diff --git a/fs/sys/io.fs b/fs/sys/io.fs
@@ -5,15 +5,34 @@ here value _)buf
struct+[ IO
: :write ( a n self -- ) >r begin ( a n ) ?dup while
- 2dup r@ :writebuf ?dup not if abort" error during write" then
+ 2dup r@ :writebuf ?dup not if _ioerr then
( a n written-n ) tuck - ( a written-n new-n ) rot> + swap repeat ( a )
drop rdrop ;
: :putback ( c hdl ) to putback ;
- : :putc ( c hdl -- ) swap _buf( c! _buf( 1 rot :writebuf ;
+ : :putc ( c hdl -- ) swap _buf( c! _buf( 1 rot :writebuf not if _ioerr then ;
+ : :puts ( str hdl -- ) swap c@+ rot :write ;
+]struct
+
+extends IO struct[ MemIO
+ sfield bufsz \ size of buffer
+ sfield ptr \ starts at 0, stops at bufsz
+ SZ &+ :buf(
+ : :)buf dup :buf( swap bufsz + ;
+ : :ptr dup :buf( swap 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 ;
+ : _writebuf ( a n hdl -- written-n ) 'X' emit
+ >r V1 _maxn ( a write-n ) dup if ( a write-n )
+ tuck V1 :ptr swap ( write-n a dst n ) move ( write-n ) dup V1 to+ ptr
+ else nip then rdrop ;
+ : :new ( sz -- hdl ) here swap ( hdl sz )
+ 0 ( putback ) , ['] _readbuf , ['] _writebuf , ['] drop , ['] drop ,
+ dup ( bufsz ) , 0 ( ptr ) , ( sz ) allot ;
]struct
: stdin StdIn IO :getc ;
-: stdout StdOut IO :putc not if _ioerr then ;
+: stdout StdOut IO :putc ;
: stdio$ ConsoleIn to StdIn ConsoleOut to StdOut ;
\ TODO: move to IO struct
diff --git a/fs/tests/cc/lib.fs b/fs/tests/cc/lib.fs
@@ -8,4 +8,15 @@ foo 12 #eq
:cfunc void foo(int n) { printf(n, "foo %d bar"); }
42 capture foo S" foo 42 bar" #s=
+
+:cfunc void foo() { puts("Hello World!"); }
+capture foo S" Hello World!" #s=
+
+$20 MemIO :new const memio
+S" What about this?" const s
+\ TODO: allow memio() to be called inside fputs() parens.
+:cfunc void foo() { int x; memio(); x = pspop(); fputs("What about this?", x); }
+foo
+memio MemIO ptr s strlen #eq
+memio MemIO :buf( s c@+ []= #
testend