From b5b72c626cc80baf71789ef2bb49836836629af3 Mon Sep 17 00:00:00 2001 From: "hyunghwan.chung" Date: Tue, 29 Oct 2019 14:21:14 +0000 Subject: [PATCH] enhanced the compiler to handle a string as a series of bytes in a byte array literal. added FileAccessor>>seek:whence: --- moo/README.md | 3 ++- moo/kernel/Except.moo | 4 +-- moo/kernel/IO.moo | 9 ++++++- moo/lib/comp.c | 57 ++++++++++++++++++++++++++++-------------- moo/mod/io-file.c | 58 ++++++++++++++++++++++++++++++++++++++++++- moo/mod/io.c | 2 +- 6 files changed, 107 insertions(+), 26 deletions(-) diff --git a/moo/README.md b/moo/README.md index bba62a3..a7ef557 100644 --- a/moo/README.md +++ b/moo/README.md @@ -38,9 +38,10 @@ * #\pB8000000 SmallPointer(smptr) literal * #() Array. Comma as element delimiter is optional -* #[] ByteArray. Comma as element delimiter is optional +* #[] ByteArray. Comma as element delimiter is optional #[ 16r10, 16r20, 16r30 ] #[ "\x10\x20", "\x30" ] * #{} Dictionary - not supported yet + The followings are not literals. The followings forms expressions. * ##() Array expression. Comma required to delimit elements diff --git a/moo/kernel/Except.moo b/moo/kernel/Except.moo index 74ad229..6fb448a 100644 --- a/moo/kernel/Except.moo +++ b/moo/kernel/Except.moo @@ -539,9 +539,7 @@ extend Apex // TODO: implement this properly | class_name ctx | class_name := if (self class == Class) { self name } else { self class name }. - - System backtrace. - +//System backtrace. NoSuchMessageException signal: (message_name & " not understood by " & class_name). } diff --git a/moo/kernel/IO.moo b/moo/kernel/IO.moo index 4f4fbfa..c7fb59c 100644 --- a/moo/kernel/IO.moo +++ b/moo/kernel/IO.moo @@ -3,7 +3,9 @@ class(#limited) InputOutputStud(Object) from "io" var(#get) handle. // you must keep handle as the first field for consitency with the io module. method(#primitive,#lenient) _close. + method(#primitive) _readBytesInto: buffer. method(#primitive) _readBytesInto: buffer startingAt: offset for: count. + method(#primitive) _writeBytesFrom: buffer. method(#primitive) _writeBytesFrom: buffer startingAt: offset for: count. } @@ -21,10 +23,15 @@ class FileAccessor(InputOutputStud) from "io.file" O_RDONLY from "O_RDONLY", O_RDWR from "O_RDWR", O_TRUNC from "O_TRUNC", - O_WRONLY from "O_WRONLY" + O_WRONLY from "O_WRONLY", + + SEEK_CUR from "SEEK_CUR", + SEEK_END from "SEEK_END", + SEEK_SET from "SEEK_SET" } method(#primitive,#lenient) _open: path flags: flags. + method(#primitive) _seek: offset whence: whence. method(#class) on: path for: flags { diff --git a/moo/lib/comp.c b/moo/lib/comp.c index 6f30a4b..8dbfa72 100644 --- a/moo/lib/comp.c +++ b/moo/lib/comp.c @@ -5288,34 +5288,53 @@ static int read_byte_array_literal (moo_t* moo, int rdonly, moo_oop_t* xlit) GET_TOKEN_GOTO (moo, oops); /* skip #[ and read the next token */ - while (TOKEN_TYPE(moo) == MOO_IOTOK_INTLIT || TOKEN_TYPE(moo) == MOO_IOTOK_RADINTLIT || TOKEN_TYPE(moo) == MOO_IOTOK_CHARLIT) + while (TOKEN_TYPE(moo) == MOO_IOTOK_INTLIT || TOKEN_TYPE(moo) == MOO_IOTOK_RADINTLIT || TOKEN_TYPE(moo) == MOO_IOTOK_CHARLIT || TOKEN_TYPE(moo) == MOO_IOTOK_STRLIT) { /* TODO: check if the number is an integer */ - if (TOKEN_TYPE(moo) == MOO_IOTOK_CHARLIT) + if (TOKEN_TYPE(moo) == MOO_IOTOK_STRLIT) { - /* accept a character literal inside a byte array literal */ - tmp = TOKEN_NAME_PTR(moo)[0]; + moo_oow_t i; + for (i = 0; i < TOKEN_NAME_LEN(moo); i++) + { + tmp = TOKEN_NAME_PTR(moo)[i]; + if (tmp < 0 || tmp > 0xFF) + { + moo_setsynerr (moo, MOO_SYNERR_BYTERANGE, TOKEN_LOC(moo), TOKEN_NAME(moo)); + goto oops; + } + if (add_to_byte_array_literal_buffer(moo, tmp) <= -1) goto oops; + } } - else if (string_to_smooi(moo, TOKEN_NAME(moo), TOKEN_TYPE(moo) == MOO_IOTOK_RADINTLIT, &tmp) <= -1) + else { - /* the token reader reads a valid token. no other errors - * than the range error must not occur */ - MOO_ASSERT (moo, moo->errnum == MOO_ERANGE); + if (TOKEN_TYPE(moo) == MOO_IOTOK_CHARLIT) + { + /* accept a character literal inside a byte array literal */ + tmp = TOKEN_NAME_PTR(moo)[0]; + } + + else if (string_to_smooi(moo, TOKEN_NAME(moo), TOKEN_TYPE(moo) == MOO_IOTOK_RADINTLIT, &tmp) <= -1) + { + /* the token reader reads a valid token. no other errors + * than the range error must not occur */ + MOO_ASSERT (moo, moo->errnum == MOO_ERANGE); - /* if the token is out of the SMOOI range, it's too big or - * to small to be a byte */ - moo_setsynerr (moo, MOO_SYNERR_BYTERANGE, TOKEN_LOC(moo), TOKEN_NAME(moo)); - goto oops; + /* if the token is out of the SMOOI range, it's too big or + * to small to be a byte */ + moo_setsynerr (moo, MOO_SYNERR_BYTERANGE, TOKEN_LOC(moo), TOKEN_NAME(moo)); + goto oops; + } + + if (tmp < 0 || tmp > 0xFF) + { + moo_setsynerr (moo, MOO_SYNERR_BYTERANGE, TOKEN_LOC(moo), TOKEN_NAME(moo)); + goto oops; + } + + if (add_to_byte_array_literal_buffer(moo, tmp) <= -1) goto oops; } - if (tmp < 0 || tmp > 0xFF) - { - moo_setsynerr (moo, MOO_SYNERR_BYTERANGE, TOKEN_LOC(moo), TOKEN_NAME(moo)); - goto oops; - } - - if (add_to_byte_array_literal_buffer(moo, tmp) <= -1) goto oops; GET_TOKEN_GOTO (moo, oops); if (comma_used == -1) diff --git a/moo/mod/io-file.c b/moo/mod/io-file.c index b6b77f6..88efb3c 100644 --- a/moo/mod/io-file.c +++ b/moo/mod/io-file.c @@ -111,6 +111,57 @@ oops: } +static moo_pfrc_t pf_seek_file (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs) +{ + oop_io_t io; + moo_oop_t tmp; + moo_oow_t offset, whence; + int fd; + ssize_t n; + + io = (oop_io_t)MOO_STACK_GETRCV(moo, nargs); + MOO_PF_CHECK_RCV (moo, + MOO_OOP_IS_POINTER(io) && + MOO_OBJ_BYTESOF(io) >= (MOO_SIZEOF(*io) - MOO_SIZEOF(moo_obj_t)) && + MOO_OOP_IS_SMOOI(io->handle) + ); + + fd = MOO_OOP_TO_SMOOI(io->handle); + if (fd <= -1) + { + moo_seterrbfmt (moo, MOO_EINVAL, "bad IO handle - %d", fd); + return MOO_PF_FAILURE; + } + + tmp = MOO_STACK_GETARG(moo, nargs, 0); + if (moo_inttooow(moo, tmp, &offset) <= 0) + { + moo_seterrbfmt (moo, MOO_EINVAL, "invalid offset - %O", tmp); + return MOO_PF_FAILURE; + } + + tmp = MOO_STACK_GETARG(moo, nargs, 1); + if (moo_inttooow(moo, tmp, &whence) <= 0) + { + moo_seterrbfmt (moo, MOO_EINVAL, "invalid whence - %O", tmp); + return MOO_PF_FAILURE; + } + + n = lseek(fd, offset, whence); + if (n <= -1) + { + moo_seterrwithsyserr (moo, 0, errno); + return MOO_PF_FAILURE; + } + + /* [NOTE] on EWOULDBLOCK or EGAIN, -1 is returned */ + MOO_ASSERT (moo, MOO_IN_SMOOI_RANGE(n)); + + MOO_STACK_SETRET (moo, nargs, MOO_SMOOI_TO_OOP(n)); + return MOO_PF_SUCCESS; +} + + /* ------------------------------------------------------------------------ */ #define C MOO_METHOD_CLASS @@ -122,6 +173,7 @@ static moo_pfinfo_t pfinfos[] = { { I, "open:flags:", { pf_open_file, 2, 2 } }, { I, "open:flags:mode:", { pf_open_file, 3, 3 } }, + { I, "seek:whence:", { pf_seek_file, 2, 2 } } }; static moo_pvinfo_t pvinfos[] = @@ -134,7 +186,11 @@ static moo_pvinfo_t pvinfos[] = { "O_RDONLY", { MOO_PV_OOI, (const void*)O_RDONLY } }, { "O_RDWR", { MOO_PV_OOI, (const void*)O_RDWR } }, { "O_TRUNC", { MOO_PV_OOI, (const void*)O_TRUNC } }, - { "O_WRONLY", { MOO_PV_OOI, (const void*)O_WRONLY } } + { "O_WRONLY", { MOO_PV_OOI, (const void*)O_WRONLY } }, + + { "SEEK_CUR", { MOO_PV_OOI, (const void*)SEEK_CUR } }, + { "SEEK_END", { MOO_PV_OOI, (const void*)SEEK_SET } }, + { "SEEK_SET", { MOO_PV_OOI, (const void*)SEEK_SET } } }; /* ------------------------------------------------------------------------ */ diff --git a/moo/mod/io.c b/moo/mod/io.c index f5608ed..7613eca 100644 --- a/moo/mod/io.c +++ b/moo/mod/io.c @@ -176,7 +176,7 @@ static moo_pfrc_t pf_write_bytes (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs) moo_oop_t tmp; tmp = MOO_STACK_GETARG(moo, nargs, 1); - if (moo_inttooow (moo, tmp, &offset) <= 0) + if (moo_inttooow(moo, tmp, &offset) <= 0) { moo_seterrbfmt (moo, MOO_EINVAL, "invalid offset - %O", tmp); return MOO_PF_FAILURE;