diff --git a/lib/hcl-cmn.h b/lib/hcl-cmn.h index fbda1da..9bb8868 100644 --- a/lib/hcl-cmn.h +++ b/lib/hcl-cmn.h @@ -331,14 +331,18 @@ typedef struct hcl_bcs_t hcl_bcs_t; #if defined(HCL_ENABLE_UNICODE) typedef hcl_uch_t hcl_ooch_t; + typedef hcl_uchu_t hcl_oochu_t; typedef hcl_uci_t hcl_ooci_t; typedef hcl_ucs_t hcl_oocs_t; # define HCL_OOCH_IS_UCH +# define HCL_SIZEOF_OOCH_T HCL_SIZEOF_UCH_T #else typedef hcl_bch_t hcl_ooch_t; + typedef hcl_bchu_t hcl_oochu_t; typedef hcl_bci_t hcl_ooci_t; typedef hcl_bcs_t hcl_oocs_t; # define HCL_OOCH_IS_BCH +# define HCL_SIZEOF_OOCH_T HCL_SIZEOF_BCH_T #endif /* ========================================================================= diff --git a/lib/hcl.h b/lib/hcl.h index c93900b..3cc24d9 100644 --- a/lib/hcl.h +++ b/lib/hcl.h @@ -1720,6 +1720,18 @@ HCL_EXPORT hcl_oop_t hcl_oowtoint ( hcl_oow_t w ); + +HCL_EXPORT int hcl_inttoooi ( + hcl_t* hcl, + hcl_oop_t x, + hcl_ooi_t* i +); + +HCL_EXPORT hcl_oop_t hcl_ooitoint ( + hcl_t* hcl, + hcl_ooi_t i +); + /* ========================================================================= * CONS OBJECT UTILITIES * ========================================================================= */ diff --git a/lib/logfmt.c b/lib/logfmt.c index e1be75b..2c4fa29 100644 --- a/lib/logfmt.c +++ b/lib/logfmt.c @@ -723,7 +723,7 @@ void hcl_seterrufmtv (hcl_t* hcl, hcl_errnum_t errnum, const hcl_uch_t* fmt, va_ * SUPPORT FOR THE BUILTIN PRINTF PRIMITIVE FUNCTION * -------------------------------------------------------------------------- */ -#if 0 +#if 1 static int put_formatted_chars (hcl_t* hcl, int mask, const hcl_ooch_t ch, hcl_oow_t len) { /* TODO: better error handling, buffering. @@ -791,23 +791,21 @@ static HCL_INLINE int print_formatted (hcl_t* hcl, hcl_ooi_t nargs, hcl_fmtout_t hcl_oop_char_t fmtoop; hcl_ooi_t i; - const fmtchar_t* percent; - const fmtchar_t* checkpoint; - hcl_bch_t nbuf[MAXNBUF], bch; - const hcl_bch_t* nbufp; + //hcl_bch_t nbuf[MAXNBUF], bch; int n, base, neg, sign; hcl_ooi_t tmp, width, precision; - hcl_ooch_t ch, padc; - fmtchar_t fch; - int lm_flag, lm_dflag, flagc, numlen; + hcl_ooch_t ch, padc, ooch; + int lm_flag, lm_dflag, flagc; hcl_uintmax_t num = 0; int stop = 0; hcl_ooch_t* fmt, * fmtend; + const hcl_ooch_t* checkpoint, * percent; - hcl_bch_t* (*sprintn) (hcl_bch_t* nbuf, hcl_uintmax_t num, int base, hcl_ooi_t* lenp); + hcl_oop_t arg; + hcl_ooi_t argidx = 0; - fmtoop = (hcl_oop_char_t)HCL_STACK_GETARG(hcl, nargs, 0); + fmtoop = (hcl_oop_char_t)HCL_STACK_GETARG(hcl, nargs, argidx); argidx++; HCL_ASSERT (hcl, HCL_IS_STRING(hcl, fmtoop)); fmt = HCL_OBJ_GET_CHAR_SLOT(fmtoop); @@ -835,14 +833,14 @@ static HCL_INLINE int print_formatted (hcl_t* hcl, hcl_ooi_t nargs, hcl_fmtout_t neg = 0; sign = 0; lm_flag = 0; lm_dflag = 0; flagc = 0; - sprintn = sprintn_lower; + //sprintn = sprintn_lower; reswitch: switch (ch = *fmt++) { case '%': /* %% */ - bch = ch; - goto print_lowercase_c; + ooch = ch; + goto print_char; /* flag characters */ case '.': @@ -889,7 +887,8 @@ reswitch: if (flagc & (FLAGC_STAR2 | FLAGC_PRECISION)) goto invalid_format; flagc |= FLAGC_STAR2; - precision = va_arg(ap, hcl_ooi_t); /* this deviates from the standard printf that accepts 'int' */ + arg = HCL_STACK_GETARG(hcl, nargs, argidx); argidx++; + if (hcl_inttoooi(hcl, arg, &precision) <= -1) goto oops; if (precision < 0) { /* if precision is less than 0, @@ -903,7 +902,8 @@ reswitch: if (flagc & (FLAGC_STAR1 | FLAGC_WIDTH)) goto invalid_format; flagc |= FLAGC_STAR1; - width = va_arg(ap, hcl_ooi_t); /* it deviates from the standard printf that accepts 'int' */ + arg = HCL_STACK_GETARG(hcl, nargs, argidx); argidx++; + if (hcl_inttoooi(hcl, arg, &width) <= -1) goto oops; if (width < 0) { /* @@ -973,79 +973,43 @@ reswitch: break; #endif - /* signed integer conversions */ + /* integer conversions */ case 'd': case 'i': /* signed conversion */ base = 10; sign = 1; - goto handle_sign; - /* end of signed integer conversions */ - - /* unsigned integer conversions */ + goto number; case 'o': base = 8; - goto handle_nosign; + goto number; case 'u': base = 10; - goto handle_nosign; + goto number; case 'X': - sprintn = sprintn_upper; + //sprintn = sprintn_upper; case 'x': base = 16; - goto handle_nosign; + goto number; case 'b': base = 2; - goto handle_nosign; - /* end of unsigned integer conversions */ - -#if 0 - case 'p': /* pointer */ - base = 16; - - if (width == 0) flagc |= FLAGC_SHARP; - else flagc &= ~FLAGC_SHARP; - - num = (hcl_uintptr_t)va_arg(ap, void*); goto number; -#endif + /* end of integer conversions */ case 'c': - { + case 'C': + print_char: + /* zeropad must not take effect for 'c' */ if (flagc & FLAGC_ZEROPAD) padc = ' '; - if (lm_flag & LF_L) goto uppercase_c; - #if defined(HCL_OOCH_IS_UCH) - if (lm_flag & LF_J) goto uppercase_c; - #endif - lowercase_c: //bch = HCL_SIZEOF(hcl_bch_t) < HCL_SIZEOF(int)? va_arg(ap, int): va_arg(ap, hcl_bch_t); - arg = HCL_STACK_GETARG(hcl, nargs, cur_arg); - if (HCL_OOP_IS_CHAR(arg)) + arg = HCL_STACK_GETARG(hcl, nargs, argidx); argidx++; + if (!HCL_OOP_IS_CHAR(arg)) { + /* TODO: error code ... */ + goto oops; } - - print_lowercase_c: - /* precision 0 doesn't kill the letter */ - width--; - if (!(flagc & FLAGC_LEFTADJ) && width > 0) PRINT_OOCH (padc, width); - PRINT_OOCH (bch, 1); - if ((flagc & FLAGC_LEFTADJ) && width > 0) PRINT_OOCH (padc, width); - break; - } - - case 'C': - { - hcl_uch_t ooch; - - /* zeropad must not take effect for 'C' */ - if (flagc & FLAGC_ZEROPAD) padc = ' '; - if (lm_flag & LF_H) goto lowercase_c; - #if defined(HCL_OOCH_IS_BCH) - if (lm_flag & LF_J) goto lowercase_c; - #endif - uppercase_c: - ooch = HCL_SIZEOF(hcl_uch_t) < HCL_SIZEOF(int)? va_arg(ap, int): va_arg(ap, hcl_uch_t); + ooch = HCL_OOP_TO_CHAR(arg); /* precision 0 doesn't kill the letter */ width--; @@ -1053,239 +1017,62 @@ reswitch: PRINT_OOCH (ooch, 1); if ((flagc & FLAGC_LEFTADJ) && width > 0) PRINT_OOCH (padc, width); break; - } case 's': + case 'S': { - const hcl_bch_t* bsp; - hcl_oow_t bslen, slen; + const hcl_ooch_t* oosp; + hcl_oow_t oosl; /* zeropad must not take effect for 'S' */ if (flagc & FLAGC_ZEROPAD) padc = ' '; - if (lm_flag & LF_L) goto uppercase_s; - #if defined(HCL_OOCH_IS_UCH) - if (lm_flag & LF_J) goto uppercase_s; - #endif - lowercase_s: - - bsp = va_arg (ap, hcl_bch_t*); - if (bsp == HCL_NULL) bsp = bch_nullstr; - - #if defined(HCL_OOCH_IS_UCH) - /* get the length */ - for (bslen = 0; bsp[bslen]; bslen++); - - if (hcl_convbtooochars(hcl, bsp, &bslen, HCL_NULL, &slen) <= -1) goto oops; - - /* slen holds the length after conversion */ - n = slen; - if ((flagc & FLAGC_DOT) && precision < slen) n = precision; - width -= n; - - if (!(flagc & FLAGC_LEFTADJ) && width > 0) PRINT_OOCH (padc, width); + arg = HCL_STACK_GETARG(hcl, nargs, argidx); argidx++; + if (!HCL_OOP_IS_POINTER(arg) || HCL_OBJ_GET_FLAGS_TYPE(arg) != HCL_OBJ_TYPE_CHAR) { - hcl_ooch_t conv_buf[32]; - hcl_oow_t conv_len, src_len, tot_len = 0; - while (n > 0) - { - HCL_ASSERT (hcl, bslen > tot_len); - - src_len = bslen - tot_len; - conv_len = HCL_COUNTOF(conv_buf); - - /* this must not fail since the dry-run above was successful */ - hcl_convbtooochars (hcl, &bsp[tot_len], &src_len, conv_buf, &conv_len); - tot_len += src_len; - - if (conv_len > n) conv_len = n; - PRINT_OOCS (conv_buf, conv_len); - - n -= conv_len; - } + goto oops; } - - if ((flagc & FLAGC_LEFTADJ) && width > 0) PRINT_OOCH (padc, width); - #else + + oosp = HCL_OBJ_GET_CHAR_SLOT(arg); + oosl = HCL_OBJ_GET_SIZE(arg); + if (flagc & FLAGC_DOT) { - for (n = 0; n < precision && bsp[n]; n++); + if (oosl > precision) oosl = precision; } - else - { - for (n = 0; bsp[n]; n++); - } - - width -= n; + width -= oosl; if (!(flagc & FLAGC_LEFTADJ) && width > 0) PRINT_OOCH (padc, width); - PRINT_OOCS (bsp, n); + PRINT_OOCS (oosp, oosl); if ((flagc & FLAGC_LEFTADJ) && width > 0) PRINT_OOCH (padc, width); - #endif break; } - case 'S': - { - const hcl_uch_t* usp; - hcl_oow_t uslen, slen; - - /* zeropad must not take effect for 's' */ - if (flagc & FLAGC_ZEROPAD) padc = ' '; - if (lm_flag & LF_H) goto lowercase_s; - #if defined(HCL_OOCH_IS_UCH) - if (lm_flag & LF_J) goto lowercase_s; - #endif - uppercase_s: - usp = va_arg (ap, hcl_uch_t*); - if (usp == HCL_NULL) usp = uch_nullstr; - - #if defined(HCL_OOCH_IS_BCH) - /* get the length */ - for (uslen = 0; usp[uslen]; uslen++); - - if (hcl_convutooochars(hcl, usp, &uslen, HCL_NULL, &slen) <= -1) goto oops; - - /* slen holds the length after conversion */ - n = slen; - if ((flagc & FLAGC_DOT) && precision < slen) n = precision; - width -= n; - - if (!(flagc & FLAGC_LEFTADJ) && width > 0) PRINT_OOCH (padc, width); - { - hcl_ooch_t conv_buf[32]; - hcl_oow_t conv_len, src_len, tot_len = 0; - while (n > 0) - { - HCL_ASSERT (hcl, uslen > tot_len); - - src_len = uslen - tot_len; - conv_len = HCL_COUNTOF(conv_buf); - - /* this must not fail since the dry-run above was successful */ - hcl_convutooochars (hcl, &usp[tot_len], &src_len, conv_buf, &conv_len); - tot_len += src_len; - - if (conv_len > n) conv_len = n; - PRINT_OOCS (conv_buf, conv_len); - - n -= conv_len; - } - } - if ((flagc & FLAGC_LEFTADJ) && width > 0) PRINT_OOCH (padc, width); - #else - if (flagc & FLAGC_DOT) - { - for (n = 0; n < precision && usp[n]; n++); - } - else - { - for (n = 0; usp[n]; n++); - } - - width -= n; - - if (!(flagc & FLAGC_LEFTADJ) && width > 0) PRINT_OOCH (padc, width); - PRINT_OOCS (usp, n); - if ((flagc & FLAGC_LEFTADJ) && width > 0) PRINT_OOCH (padc, width); - #endif - break; - } case 'O': /* object - ignore precision, width, adjustment */ - if (hcl_outfmtobj(hcl, data->mask, va_arg(ap, hcl_oop_t), outbfmt) <= -1) goto oops; + arg = HCL_STACK_GETARG(hcl, nargs, argidx); argidx++; + if (hcl_outfmtobj(hcl, 0, arg, hcl_proutbfmt) <= -1) goto oops; break; -handle_nosign: - sign = 0; - if (lm_flag & LF_J) - { - #if defined(__GNUC__) && \ - (HCL_SIZEOF_UINTMAX_T > HCL_SIZEOF_OOW_T) && \ - (HCL_SIZEOF_UINTMAX_T != HCL_SIZEOF_LONG_LONG) && \ - (HCL_SIZEOF_UINTMAX_T != HCL_SIZEOF_LONG) - /* GCC-compiled binaries crashed when getting hcl_uintmax_t with va_arg. - * This is just a work-around for it */ - int i; - for (i = 0, num = 0; i < HCL_SIZEOF(hcl_uintmax_t) / HCL_SIZEOF(hcl_oow_t); i++) - { - #if defined(HCL_ENDIAN_BIG) - num = num << (8 * HCL_SIZEOF(hcl_oow_t)) | (va_arg (ap, hcl_oow_t)); - #else - register int shift = i * HCL_SIZEOF(hcl_oow_t); - hcl_oow_t x = va_arg (ap, hcl_oow_t); - num |= (hcl_uintmax_t)x << (shift * 8); - #endif - } - #else - num = va_arg (ap, hcl_uintmax_t); - #endif - } -#if 0 - else if (lm_flag & LF_T) - num = va_arg (ap, hcl_ptrdiff_t); -#endif - else if (lm_flag & LF_Z) - num = va_arg (ap, hcl_oow_t); - #if (HCL_SIZEOF_LONG_LONG > 0) - else if (lm_flag & LF_Q) - num = va_arg (ap, unsigned long long int); - #endif - else if (lm_flag & (LF_L | LF_LD)) - num = va_arg (ap, unsigned long int); - else if (lm_flag & LF_H) - num = (unsigned short int)va_arg (ap, int); - else if (lm_flag & LF_C) - num = (unsigned char)va_arg (ap, int); - else - num = va_arg (ap, unsigned int); - goto number; + number: + { + const hcl_ooch_t* nsptr; + hcl_oow_t nslen; + arg = HCL_STACK_GETARG(hcl, nargs, argidx); argidx++; -handle_sign: - if (lm_flag & LF_J) + if (HCL_OOP_IS_CHAR(arg)) arg = HCL_SMOOI_TO_OOP(HCL_OOP_TO_CHAR(arg)); + + if (!hcl_inttostr(hcl, arg, base, -1)) { - #if defined(__GNUC__) && \ - (HCL_SIZEOF_INTMAX_T > HCL_SIZEOF_OOI_T) && \ - (HCL_SIZEOF_UINTMAX_T != HCL_SIZEOF_LONG_LONG) && \ - (HCL_SIZEOF_UINTMAX_T != HCL_SIZEOF_LONG) - /* GCC-compiled binraries crashed when getting hcl_uintmax_t with va_arg. - * This is just a work-around for it */ - int i; - for (i = 0, num = 0; i < HCL_SIZEOF(hcl_intmax_t) / HCL_SIZEOF(hcl_oow_t); i++) - { - #if defined(HCL_ENDIAN_BIG) - num = num << (8 * HCL_SIZEOF(hcl_oow_t)) | (va_arg (ap, hcl_oow_t)); - #else - register int shift = i * HCL_SIZEOF(hcl_oow_t); - hcl_oow_t x = va_arg (ap, hcl_oow_t); - num |= (hcl_uintmax_t)x << (shift * 8); - #endif - } - #else - num = va_arg (ap, hcl_intmax_t); - #endif + hcl_seterrbfmt (hcl, HCL_EINVAL, "not a valid number - %O", arg); + goto oops; } -#if 0 - else if (lm_flag & LF_T) - num = va_arg(ap, hcl_ptrdiff_t); -#endif - else if (lm_flag & LF_Z) - num = va_arg (ap, hcl_ooi_t); - #if (HCL_SIZEOF_LONG_LONG > 0) - else if (lm_flag & LF_Q) - num = va_arg (ap, long long int); - #endif - else if (lm_flag & (LF_L | LF_LD)) - num = va_arg (ap, long int); - else if (lm_flag & LF_H) - num = (short int)va_arg (ap, int); - else if (lm_flag & LF_C) - num = (char)va_arg (ap, int); - else - num = va_arg (ap, int); + nsptr = hcl->inttostr.xbuf.ptr; + nslen = hcl->inttostr.xbuf.len; -number: + tmp = nslen; +/* if (sign && (hcl_intmax_t)num < 0) { neg = 1; @@ -1293,6 +1080,8 @@ number: } nbufp = sprintn (nbuf, num, base, &tmp); +*/ + if ((flagc & FLAGC_SHARP) && num != 0) { if (base == 8) tmp++; @@ -1302,11 +1091,13 @@ number: else if (flagc & FLAGC_SIGN) tmp++; else if (flagc & FLAGC_SPACE) tmp++; +/* numlen = (int)((const hcl_bch_t*)nbufp - (const hcl_bch_t*)nbuf); - if ((flagc & FLAGC_DOT) && precision > numlen) +*/ + if ((flagc & FLAGC_DOT) && precision > nslen) { /* extra zeros for precision specified */ - tmp += (precision - numlen); + tmp += (precision - nslen); } if (!(flagc & FLAGC_LEFTADJ) && !(flagc & FLAGC_ZEROPAD) && width > 0 && (width -= tmp) > 0) @@ -1337,10 +1128,10 @@ number: } } - if ((flagc & FLAGC_DOT) && precision > numlen) + if ((flagc & FLAGC_DOT) && precision > nslen) { /* extra zeros for precision specified */ - PRINT_OOCH ('0', precision - numlen); + PRINT_OOCH ('0', precision - nslen); } if (!(flagc & FLAGC_LEFTADJ) && width > 0 && (width -= tmp) > 0) @@ -1348,13 +1139,15 @@ number: PRINT_OOCH (padc, width); } - while (*nbufp) PRINT_OOCH (*nbufp--, 1); /* output actual digits */ + //while (*nbufp) PRINT_OOCH (*nbufp--, 1); /* output actual digits */ + PRINT_OOCS (nsptr, nslen); if ((flagc & FLAGC_LEFTADJ) && width > 0 && (width -= tmp) > 0) { PRINT_OOCH (padc, width); } break; + } invalid_format: #if defined(FMTCHAR_IS_OOCH) @@ -1387,4 +1180,11 @@ done: oops: return -1; } + +int hcl_print_formatted (hcl_t* hcl, hcl_ooi_t nargs) +{ + hcl_fmtout_t fo; + HCL_MEMSET (&fo, 0, HCL_SIZEOF(fo)); + return print_formatted (hcl, nargs, &fo); +} #endif diff --git a/lib/prim.c b/lib/prim.c index 8ae1e5e..5228350 100644 --- a/lib/prim.c +++ b/lib/prim.c @@ -394,9 +394,16 @@ static hcl_pfrc_t pf_printf (hcl_t* hcl, hcl_mod_t* mod, hcl_ooi_t nargs) return HCL_PF_SUCCESS; } -// print_formatted (hcl, nargs); + if (hcl_print_formatted(hcl, nargs) <= -1) + { + HCL_STACK_SETRETTOERRNUM (hcl, nargs); + } + else + { +/* TODO: better return code? */ + HCL_STACK_SETRET (hcl, nargs, hcl->_nil); + } - HCL_STACK_SETRET (hcl, nargs, hcl->_nil); return HCL_PF_SUCCESS; } diff --git a/lib/print.c b/lib/print.c index c1bc9d5..c2ffefd 100644 --- a/lib/print.c +++ b/lib/print.c @@ -113,14 +113,18 @@ static struct { 12, { '#','<','S','E','M','A','P','H','O','R','E','>' } } }; - static HCL_INLINE int print_single_char (hcl_t* hcl, int mask, hcl_ooch_t ch, hcl_outbfmt_t outbfmt) { - if (ch < ' ') + hcl_oochu_t chu = (hcl_oochu_t)ch; +#if defined(HCL_OOCH_IS_UCH) + if (chu < ' ') +#else + if (chu < ' ' || chu >= 0x80) +#endif { hcl_ooch_t escaped; - switch (ch) + switch (chu) { case '\0': escaped = '0'; @@ -153,7 +157,7 @@ static HCL_INLINE int print_single_char (hcl_t* hcl, int mask, hcl_ooch_t ch, hc if (escaped == ch) { - if (outbfmt(hcl, mask, "\\x%X", ch) <= -1) return -1; + if (outbfmt(hcl, mask, "\\x%X", chu) <= -1) return -1; } else { diff --git a/lib/read.c b/lib/read.c index 73826dd..ee61c1d 100644 --- a/lib/read.c +++ b/lib/read.c @@ -803,6 +803,7 @@ static int get_sharp_token (hcl_t* hcl) "invalid hexadecimal character in %.*js", TOKEN_NAME_LEN(hcl), TOKEN_NAME_PTR(hcl)); return -1; } +/* TODO: check for the max charcter value and raise an error... */ c = c * 16 + CHAR_TO_NUM(hcl->c->tok.name.ptr[i], 16); /* don't care if it is for 'p' */ } }