diff --git a/hawk/lib/dir.c b/hawk/lib/dir.c index 3cba6eb6..5c4407a9 100644 --- a/hawk/lib/dir.c +++ b/hawk/lib/dir.c @@ -492,7 +492,7 @@ static int reset_to_path (hawk_dir_t* dir, const hawk_ooch_t* path) rc = _dos_findfirst(mptr, _A_NORMAL | _A_SUBDIR, &f); if (rc != 0) { - hawk_gem_seterrnum (dir->gem, HAWK_NULL,hawk_syserr_to_errnum(errno)); + hawk_gem_seterrnum (dir->gem, HAWK_NULL, hawk_syserr_to_errnum(errno)); return -1; } diff --git a/hawk/lib/mod-hawk.c b/hawk/lib/mod-hawk.c index 9e71e904..08f1b669 100644 --- a/hawk/lib/mod-hawk.c +++ b/hawk/lib/mod-hawk.c @@ -27,6 +27,40 @@ #include "mod-hawk.h" #include "hawk-prv.h" + +/* ----------------------------------------------------------------- */ +struct mod_ctx_t +{ + hawk_rbt_t* rtxtab; +}; +typedef struct mod_ctx_t mod_ctx_t; + +/* ----------------------------------------------------------------- */ +struct rtx_data_t +{ + struct + { + hawk_uint8_t __static_buf[256]; + hawk_uint8_t* ptr; + hawk_oow_t capa; + hawk_oow_t len; + } pack; +}; +typedef struct rtx_data_t rtx_data_t; + +/* ----------------------------------------------------------------- */ + +static HAWK_INLINE rtx_data_t* rtx_to_data (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi) +{ + mod_ctx_t* mctx = (mod_ctx_t*)fi->mod->ctx; + hawk_rbt_pair_t* pair; + pair = hawk_rbt_search(mctx->rtxtab, &rtx, HAWK_SIZEOF(rtx)); + HAWK_ASSERT (pair != HAWK_NULL); + return (rtx_data_t*)HAWK_RBT_VPTR(pair); +} + +/* ----------------------------------------------------------------- */ + /* * function abc(a, b, c) { return a + b + c; } * BEGIN { print hawk::call("abc", 10, 20, 30); } @@ -390,17 +424,130 @@ static int fnc_typename (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi) } /* -------------------------------------------------------------------------- */ -#if 0 -static int pack_data (hawk_rtx_t* rtx, const hawk_oocs_t* fmt, const hawk_fnc_info_t* fi) + +#define ENDIAN_BIG 1 +#define ENDIAN_LITTLE 2 +#if defined(HAWK_ENDIAN_BIG) +# define ENDIAN_NATIVE ENDIAN_BIG +#else +# define ENDIAN_NATIVE ENDIAN_LITTLE +#endif + +static hawk_oow_t pack_int16_t (hawk_uint8_t* dst, hawk_uint16_t val, int endian) { - hawk_oow_t rep_cnt = 0; + if (endian == ENDIAN_NATIVE) + { + *dst++ = val; + *dst++ = val >> 8; + } + else + { + *dst++ = val >> 8; + *dst++ = val; + } + return 2; +} + +static hawk_oow_t pack_int32_t (hawk_uint8_t* dst, hawk_uint32_t val, int endian) +{ + if (endian == ENDIAN_NATIVE) + { + *dst++ = val; + *dst++ = val >> 8; + *dst++ = val >> 16; + *dst++ = val >> 24; + } + else + { + *dst++ = val >> 24; + *dst++ = val >> 16; + *dst++ = val >> 8; + *dst++ = val; + } + + return 4; +} + +static hawk_oow_t pack_int64_t (hawk_uint8_t* dst, hawk_uint64_t val, int endian) +{ + if (endian == ENDIAN_NATIVE) + { + *dst++ = val; + *dst++ = val >> 8; + *dst++ = val >> 16; + *dst++ = val >> 24; + *dst++ = val >> 32; + *dst++ = val >> 40; + *dst++ = val >> 48; + *dst++ = val >> 56; + } + else + { + *dst++ = val >> 56; + *dst++ = val >> 48; + *dst++ = val >> 40; + *dst++ = val >> 32; + *dst++ = val >> 24; + *dst++ = val >> 16; + *dst++ = val >> 8; + *dst++ = val; + } + + return 8; +} + +static int ensure_pack_buf (hawk_rtx_t* rtx, rtx_data_t* rdp, hawk_oow_t reqsz) +{ + if (rdp->pack.len >= rdp->pack.capa - reqsz) + { + hawk_uint8_t* tmp; + hawk_oow_t newcapa; + + newcapa = HAWK_ALIGN_POW2(rdp->pack.capa + reqsz, 256); + if (rdp->pack.ptr == rdp->pack.__static_buf) + { + tmp = hawk_rtx_allocmem(rtx, newcapa); + if (HAWK_UNLIKELY(!tmp)) return -1; + HAWK_MEMCPY (tmp, rdp->pack.__static_buf, rdp->pack.len); + } + else + { + tmp = hawk_rtx_reallocmem(rtx, rdp->pack.ptr, newcapa); + if (HAWK_UNLIKELY(!tmp)) return -1; + } + + rdp->pack.ptr = tmp; + rdp->pack.capa = newcapa; + } + + return 0; +} + +static int pack_data (hawk_rtx_t* rtx, const hawk_oocs_t* fmt, const hawk_fnc_info_t* fi, rtx_data_t* rdp) +{ + hawk_oow_t rep_cnt, rep_set, rc; const hawk_ooch_t* fmtp, *fmte; - hawk_uint8_t *bp; + hawk_oow_t arg_idx, arg_cnt; int endian = ENDIAN_NATIVE; - char* s; - bp = buf; + +#define PACK_CHECK_ARG_AND_BUF(reqarg, reqsz) do { \ + if (arg_cnt - arg_idx < reqarg) \ + { \ + hawk_rtx_seterrnum (rtx, HAWK_NULL, HAWK_EARGTF); \ + return -1; \ + } \ + if (ensure_pack_buf(rtx, rdp, reqsz) <= -1) return -1; \ +} while(0) + + rdp->pack.len = 0; + + arg_idx = 1; /* set past the format specifier */ + arg_cnt = hawk_rtx_getnargs(rtx); + + rep_cnt = 1; + rep_set = 0; fmte = fmt->ptr + fmt->len; for (fmtp = fmt->ptr; fmtp < fmte; fmtp++) @@ -425,156 +572,195 @@ static int pack_data (hawk_rtx_t* rtx, const hawk_oocs_t* fmt, const hawk_fnc_in case 'b': /* byte, char */ { - signed char v; - BEGIN_REPETITION(); - v = va_arg(args, int); - *bp++ = v; - END_REPETITION(); + hawk_int_t v; + PACK_CHECK_ARG_AND_BUF (rep_cnt, HAWK_SIZEOF(hawk_int8_t) * rep_cnt); + for (rc = 0; rc < rep_cnt; rc++) + { + if (hawk_rtx_valtoint(rtx, hawk_rtx_getarg(rtx, arg_idx++), &v) <= -1) return -1; + rdp->pack.ptr[rdp->pack.len++] = (hawk_int8_t)v; + } break; } case 'B': { - unsigned char v; - BEGIN_REPETITION(); - v = va_arg(args, unsigned int); - *bp++ = v; - END_REPETITION(); + hawk_int_t v; + PACK_CHECK_ARG_AND_BUF (rep_cnt, HAWK_SIZEOF(hawk_uint8_t) * rep_cnt); + for (rc = 0; rc < rep_cnt; rc++) + { + if (hawk_rtx_valtoint(rtx, hawk_rtx_getarg(rtx, arg_idx++), &v) <= -1) return -1; + rdp->pack.ptr[rdp->pack.len++] = (hawk_uint8_t)v; + } break; } case 'h': { - short int v; - BEGIN_REPETITION(); - v = va_arg(args, int); - bp = pack_int16_t(bp, v, endian); - END_REPETITION(); + hawk_int_t v; + PACK_CHECK_ARG_AND_BUF (rep_cnt, HAWK_SIZEOF(hawk_int16_t) * rep_cnt); + for (rc = 0; rc < rep_cnt; rc++) + { + if (hawk_rtx_valtoint(rtx, hawk_rtx_getarg(rtx, arg_idx++), &v) <= -1) return -1; + rdp->pack.len += pack_int16_t(&rdp->pack.ptr[rdp->pack.len], (hawk_int16_t)v, endian); + } break; } case 'H': { - unsigned short int v; - BEGIN_REPETITION(); - v = va_arg(args, int); - bp = pack_int16_t(bp, v, endian); - END_REPETITION(); + hawk_int_t v; + PACK_CHECK_ARG_AND_BUF (rep_cnt, HAWK_SIZEOF(hawk_uint16_t) * rep_cnt); + for (rc = 0; rc < rep_cnt; rc++) + { + if (hawk_rtx_valtoint(rtx, hawk_rtx_getarg(rtx, arg_idx++), &v) <= -1) return -1; + rdp->pack.len += pack_int16_t(&rdp->pack.ptr[rdp->pack.len], (hawk_uint16_t)v, endian); + } break; } case 'i': case 'l': { - hawk_int32_t v; - BEGIN_REPETITION(); - v = va_arg(args, hawk_int32_t); - bp = pack_int32_t(bp, v, endian); - END_REPETITION(); + hawk_int_t v; + PACK_CHECK_ARG_AND_BUF (rep_cnt, HAWK_SIZEOF(hawk_int32_t) * rep_cnt); + for (rc = 0; rc < rep_cnt; rc++) + { + if (hawk_rtx_valtoint(rtx, hawk_rtx_getarg(rtx, arg_idx++), &v) <= -1) return -1; + rdp->pack.len += pack_int32_t(&rdp->pack.ptr[rdp->pack.len], (hawk_int32_t)v, endian); + } break; } case 'I': /* fall through */ case 'L': { - hawk_uint32_t v; - BEGIN_REPETITION(); - v = va_arg(args, hawk_uint32_t); - bp = pack_int32_t(bp, v, endian); - END_REPETITION(); + hawk_int_t v; + PACK_CHECK_ARG_AND_BUF (rep_cnt, HAWK_SIZEOF(hawk_uint32_t) * rep_cnt); + for (rc = 0; rc < rep_cnt; rc++) + { + if (hawk_rtx_valtoint(rtx, hawk_rtx_getarg(rtx, arg_idx++), &v) <= -1) return -1; + rdp->pack.len += pack_int16_t(&rdp->pack.ptr[rdp->pack.len], (hawk_uint32_t)v, endian); + } break; } case 'q': { - hawk_int64_t v; - BEGIN_REPETITION(); - v = va_arg(args, hawk_int64_t); - bp = pack_int64_t(bp, v, endian); - END_REPETITION(); + hawk_int_t v; + PACK_CHECK_ARG_AND_BUF (rep_cnt, HAWK_SIZEOF(hawk_int64_t) * rep_cnt); + for (rc = 0; rc < rep_cnt; rc++) + { + if (hawk_rtx_valtoint(rtx, hawk_rtx_getarg(rtx, arg_idx++), &v) <= -1) return -1; + rdp->pack.len += pack_int64_t(rdp->pack.ptr, (hawk_int64_t)v, endian); + } break; } case 'Q': { - hawk_uint64_t v; - BEGIN_REPETITION(); - v = va_arg(args, hawk_uint64_t); - bp = pack_int64_t(bp, v, endian); - END_REPETITION(); + hawk_int_t v; + PACK_CHECK_ARG_AND_BUF (rep_cnt, HAWK_SIZEOF(hawk_uint64_t) * rep_cnt); + for (rc = 0; rc < rep_cnt; rc++) + { + if (hawk_rtx_valtoint(rtx, hawk_rtx_getarg(rtx, arg_idx++), &v) <= -1) return -1; + rdp->pack.len += pack_int64_t(rdp->pack.ptr, (hawk_uint64_t)v, endian); + } break; } #if 0 case 'f': - BEGIN_REPETITION(); f = va_arg(args, double); pack_float(&bp, f, *ep); - END_REPETITION(); break; case 'd': - BEGIN_REPETITION(); d = va_arg(args, double); pack_double(&bp, d, *ep); - END_REPETITION(); break; #endif + case 's': case 'p': { - int i = 0; - s = va_arg(args, char*); - BEGIN_REPETITION(); - *bp++ = s[i++]; - END_REPETITION(); + hawk_val_t* a; + hawk_bcs_t tmp; + + PACK_CHECK_ARG_AND_BUF (1, HAWK_SIZEOF(hawk_uint8_t) * rep_cnt); + + a = hawk_rtx_getarg(rtx, arg_idx++); + + tmp.ptr = hawk_rtx_getvalbcstr(rtx, a, &tmp.len); + if (HAWK_UNLIKELY(!tmp.ptr)) return -1; + + if (rep_cnt > tmp.len) + { + hawk_rtx_freevalbcstr (rtx, a, tmp.ptr); + hawk_rtx_seterrnum (rtx, HAWK_NULL, HAWK_EINVAL); + return -1; + } + for (rc = 0; rc < rep_cnt; rc++) rdp->pack.ptr[rdp->pack.len++] = tmp.ptr[rc]; + hawk_rtx_freevalbcstr (rtx, a, tmp.ptr); break; } - case 'x': - BEGIN_REPETITION(); - *bp++ = 0; - END_REPETITION(); + case 'x': /* zero-padding */ + PACK_CHECK_ARG_AND_BUF (0, rep_cnt * HAWK_SIZEOF(hawk_uint8_t)); + for (rc = 0; rc < rep_cnt; rc++) rdp->pack.ptr[rdp->pack.len++] = 0; break; default: - if (hawk_is_bch_digit(*fmtp)) + /* handle below outside 'switch' */ + if (hawk_is_ooch_digit(*fmtp)) { - INC_REPETITION(); - } - else + if (!rep_set) + { + rep_cnt = 0; + rep_set = 1; + } + rep_cnt = rep_cnt * 10 + (*fmtp - '0'); + } + else if (!hawk_is_ooch_space(*fmtp)) { + hawk_rtx_seterrnum (rtx, HAWK_NULL, HAWK_EINVAL); return -1; } break; } - if (!hawk_is_bch_digit((int)*fmtp)) CLEAR_REPETITION(); + if (!hawk_is_ooch_digit(*fmtp) && !hawk_is_ooch_space(*fmtp)) + { + rep_cnt = 1; + rep_set = 0; + } } - return (bp - buf); + return 0; } -#endif - static int fnc_pack (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi) { - hawk_val_t* a0, * r; + rtx_data_t* rdp = rtx_to_data(rtx, fi); + hawk_val_t* a0; hawk_oocs_t fmt; + int x; a0 = hawk_rtx_getarg(rtx, 0); fmt.ptr = hawk_rtx_getvaloocstr(rtx, a0, &fmt.len); if (HAWK_UNLIKELY(!fmt.ptr)) return -1; -#if 0 - pack_data (rtx, &fmt, &buf, fi); +/* TODO: how to indicate failure??? */ + x = pack_data(rtx, &fmt, fi, rdp); + hawk_rtx_freevaloocstr (rtx, a0, fmt.ptr); - r = hawk_rtx_makembsvalwithbchars(rtx, buf.ptr, buf.len); - if (HAWK_UNLIKELY(!r)) return -1; - - hawk_rtx_setretval (rtx, r); -#endif + if (x >= 0) + { + hawk_val_t* r; + r = hawk_rtx_makembsvalwithbchars(rtx, rdp->pack.ptr, rdp->pack.len); + if (HAWK_UNLIKELY(!r)) return -1; + hawk_rtx_setretval (rtx, r); + } return 0; } @@ -583,6 +769,7 @@ static int fnc_unpack (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi) /* TODO: */ return 0; } + /* -------------------------------------------------------------------------- */ typedef struct fnctab_t fnctab_t; @@ -673,30 +860,70 @@ static int query (hawk_mod_t* mod, hawk_t* hawk, const hawk_ooch_t* name, hawk_m static int init (hawk_mod_t* mod, hawk_rtx_t* rtx) { + mod_ctx_t* mctx = (mod_ctx_t*)mod->ctx; + rtx_data_t rd, * rdp; + hawk_rbt_pair_t* pair; + + HAWK_MEMSET (&rd, 0, HAWK_SIZEOF(rd)); + pair = hawk_rbt_insert(mctx->rtxtab, &rtx, HAWK_SIZEOF(rtx), &rd, HAWK_SIZEOF(rd)); + if (HAWK_UNLIKELY(!pair)) return -1; + + rdp = (rtx_data_t*)HAWK_RBT_VPTR(pair); + rdp->pack.ptr = rdp->pack.__static_buf; + rdp->pack.capa = HAWK_COUNTOF(rdp->pack.__static_buf); + rdp->pack.len = 0; + return 0; } static void fini (hawk_mod_t* mod, hawk_rtx_t* rtx) { - /* TODO: anything */ + mod_ctx_t* mctx = (mod_ctx_t*)mod->ctx; + hawk_rbt_pair_t* pair; + + pair = hawk_rbt_search(mctx->rtxtab, &rtx, HAWK_SIZEOF(rtx)); + if (pair) + { + rtx_data_t* rdp; + + rdp = (rtx_data_t*)HAWK_RBT_VPTR(pair); + + if (rdp->pack.ptr != rdp->pack.__static_buf) hawk_rtx_freemem(rtx, rdp->pack.ptr); + + hawk_rbt_delete (mctx->rtxtab, &rtx, HAWK_SIZEOF(rtx)); + } } static void unload (hawk_mod_t* mod, hawk_t* hawk) { - /* TODO: anything */ + mod_ctx_t* mctx = (mod_ctx_t*)mod->ctx; + HAWK_ASSERT (HAWK_RBT_SIZE(mctx->rtxtab) == 0); + hawk_rbt_close (mctx->rtxtab); + hawk_freemem (hawk, mctx); } int hawk_mod_hawk (hawk_mod_t* mod, hawk_t* hawk) { + hawk_rbt_t* rbt; + mod->query = query; mod->unload = unload; mod->init = init; mod->fini = fini; - /* - mod->ctx... - */ + mod->ctx = hawk_callocmem(hawk, HAWK_SIZEOF(mod_ctx_t)); + if (HAWK_UNLIKELY(!mod->ctx)) return -1; + + rbt = hawk_rbt_open(hawk_getgem(hawk), 0, 1, 1); + if (HAWK_UNLIKELY(!rbt)) + { + hawk_freemem (hawk, mod->ctx); + return -1; + } + hawk_rbt_setstyle (rbt, hawk_get_rbt_style(HAWK_RBT_STYLE_INLINE_COPIERS)); + + ((mod_ctx_t*)mod->ctx)->rtxtab = rbt; return 0; } diff --git a/hawk/lib/mod-sys.c b/hawk/lib/mod-sys.c index 81c2583c..7003c7ee 100644 --- a/hawk/lib/mod-sys.c +++ b/hawk/lib/mod-sys.c @@ -5385,10 +5385,10 @@ int hawk_mod_sys (hawk_mod_t* mod, hawk_t* hawk) mod->fini = fini; mod->ctx = hawk_callocmem(hawk, HAWK_SIZEOF(mod_ctx_t)); - if (!mod->ctx) return -1; + if (HAWK_UNLIKELY(!mod->ctx)) return -1; rbt = hawk_rbt_open(hawk_getgem(hawk), 0, 1, 1); - if (rbt == HAWK_NULL) + if (HAWK_UNLIKELY(!rbt)) { hawk_freemem (hawk, mod->ctx); return -1; diff --git a/hawk/lib/run.c b/hawk/lib/run.c index a3f428c1..5adf0f6b 100644 --- a/hawk/lib/run.c +++ b/hawk/lib/run.c @@ -8733,7 +8733,7 @@ wp_mod_main: hawk_rtx_refdownval (rtx, v); } - else if (fmt[i] == HAWK_T('s') || fmt[i] == HAWK_T('k') || fmt[i] == HAWK_T('K')) + else if (fmt[i] == 's' || fmt[i] == 'k' || fmt[i] == 'K' || fmt[i] == 'w' || fmt[i] == 'W') { hawk_val_t* v; @@ -8889,7 +8889,7 @@ wp_mod_main: } } - if (fmt[i] == HAWK_T('k')) bytetostr_flagged_radix |= HAWK_BYTE_TO_BCSTR_LOWERCASE; + if (fmt[i] == 'k' || fmt[i] == 'w') bytetostr_flagged_radix |= HAWK_BYTE_TO_BCSTR_LOWERCASE; for (k = 0; k < wp[WP_PRECISION]; k++) { @@ -8903,7 +8903,7 @@ wp_mod_main: else curc = str_ptr[k]; #endif - if (fmt[i] != HAWK_T('s') && !HAWK_BYTE_PRINTABLE(curc)) + if ((fmt[i] != 's' && !HAWK_BYTE_PRINTABLE(curc)) || fmt[i] == 'w' || fmt[i] == 'W') { hawk_ooch_t xbuf[3]; if (curc <= 0xFF) @@ -9617,7 +9617,7 @@ wp_mod_main: hawk_rtx_refdownval (rtx, v); } - else if (fmt[i] == HAWK_BT('s') || fmt[i] == HAWK_BT('k') || fmt[i] == HAWK_BT('K')) + else if (fmt[i] == 's' || fmt[i] == 'k' || fmt[i] == 'K' || fmt[i] == 'w' || fmt[i] == 'W') { hawk_val_t* v; @@ -9773,7 +9773,7 @@ wp_mod_main: } } - if (fmt[i] == HAWK_BT('k')) bytetombs_flagged_radix |= HAWK_BYTE_TO_BCSTR_LOWERCASE; + if (fmt[i] == 'k' || fmt[i] == 'w') bytetombs_flagged_radix |= HAWK_BYTE_TO_BCSTR_LOWERCASE; for (k = 0; k < wp[WP_PRECISION]; k++) { @@ -9781,7 +9781,7 @@ wp_mod_main: curc = str_ptr[k]; - if (fmt[i] != HAWK_BT('s') && !HAWK_BYTE_PRINTABLE(curc)) + if ((fmt[i] != 's' && !HAWK_BYTE_PRINTABLE(curc)) || fmt[i] == 'w' || fmt[i] == 'W') { hawk_bch_t xbuf[3]; if (curc <= 0xFF)