gawk-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[SCM] gawk branch, stable/printf-rework, updated. gawk-4.1.0-5492-g7b9e9


From: Arnold Robbins
Subject: [SCM] gawk branch, stable/printf-rework, updated. gawk-4.1.0-5492-g7b9e9bca
Date: Sun, 7 Jul 2024 15:21:55 -0400 (EDT)

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "gawk".

The branch, stable/printf-rework has been updated
       via  7b9e9bca203c92acaa6b3cd107764be319994038 (commit)
      from  dde70cc78f2cfc69439c35713575158d14366567 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://git.sv.gnu.org/cgit/gawk.git/commit/?id=7b9e9bca203c92acaa6b3cd107764be319994038

commit 7b9e9bca203c92acaa6b3cd107764be319994038
Author: Arnold D. Robbins <arnold@skeeve.com>
Date:   Sun Jul 7 22:21:31 2024 +0300

    Continuing to refactor printf.

diff --git a/ChangeLog b/ChangeLog
index 0f07fbab..226ec04e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2024-07-07         Arnold D. Robbins     <arnold@skeeve.com>
+
+       * printf.c: Signed and unsigned integer printing mostly working now.
+       Still to go: Finish that up, get GMP/MPFR integer printing working.
+
 2024-07-05         Arnold D. Robbins     <arnold@skeeve.com>
 
        * printf.c: Lots of cleanup. Floating point format pretty
diff --git a/printf.c b/printf.c
index 3cb5450c..939741b7 100644
--- a/printf.c
+++ b/printf.c
@@ -1139,7 +1139,7 @@ NODE *
 format_tree_new(
        const char *fmt_string,
        size_t n0,
-       NODE **the_args,
+       NODE *the_args[],
        long num_args)
 {
 /* copy 'l' bytes from 's' to 'obufout' checking for space in the process */
@@ -1824,6 +1824,18 @@ out0:
 
                        set_flags();
                        adjust_flags(& flags);
+                       {
+                       const char *formatted = format_unsigned_integer(arg, & 
flags);
+                       len = strlen(formatted);
+                       chksize(len)
+                       strcpy(obufout, formatted);
+                       free((void *) formatted);
+
+                       ofre -= len;
+                       obufout += len;
+                       s0 = s1;
+                       break;
+                       }
 
 
                        if (out_of_range(arg))
@@ -2358,8 +2370,9 @@ format_integer_digits(NODE *arg, struct flags *flags)
        const char *chbuf;
        char *cp;
        bool quote_flag = false;
-       bool negative = false;
        uintmax_t uval;
+       int i;
+       double tmpval;
 
 #define growbuffer(buf, buflen, cp) { \
                erealloc(buf, char *, buflen * 2, "format_integer_xxx"); \
@@ -2370,34 +2383,47 @@ format_integer_digits(NODE *arg, struct flags *flags)
 #if defined(HAVE_LOCALE_H)
        quote_flag = (flags->quote && loc.thousands_sep[0] != '\0');
 #endif
-
-       chbuf = (flags->format == 'X' ? Uchbuf : lchbuf);
        emalloc(buf, char *, VALUE_SIZE, "format_integer_digits");
        buflen = VALUE_SIZE;
        cp = buf;
 
-       // C 2023 says negative zeros get a minus sign
-       // for floating conversions.
-       if (flags->base == 10 && arg->numbr < 0) {
-               negative = true;
-               arg->numbr = -arg->numbr;
-       }
-       uval = get_number_uj(arg);
+       if (flags->base == 10 && flags->format != 'u') {
+               // signed decimal
+               tmpval = double_to_int(arg->numbr);
+               if (tmpval == -0)
+                       tmpval = 0;
+
+               /*
+                * Use snprintf return value to tell if there
+                * is enough room in the buffer or not.
+                */
+               while ((i = snprintf(buf, buflen, "%.0f", tmpval)) >= buflen) {
+                       if (i > 0)
+                               buflen += (i > buflen) ?  i : buflen;
+                       else
+                               buflen *= 2;
+                       assert(buflen > 0);
+                       erealloc(buf, char *, buflen, "format_tree");
+               }
+       } else {
+               // octal or hex
+               chbuf = (flags->format == 'X' ? Uchbuf : lchbuf);
 
-       // generate the digits backwards.
-       do {
-               if (cp >= buf + buflen)
-                       growbuffer(buf, buflen, cp);
+               uval = get_number_uj(arg);
 
-               *cp++ = chbuf[uval % flags->base];
-               uval /= flags->base;
-       } while (uval > 0);
-       if (negative)
-               *cp++ = '-';
-       *cp = '\0';
+               // generate the digits backwards.
+               do {
+                       if (cp >= buf + buflen)
+                               growbuffer(buf, buflen, cp);
 
-       // turn it back around
-       reverse(buf);
+                       *cp++ = chbuf[uval % flags->base];
+                       uval /= flags->base;
+               } while (uval > 0);
+               *cp = '\0';
+
+               // turn it back around
+               reverse(buf);
+       }
 
        if (flags->base == 10 && quote_flag) {
                const char *with_commas = add_thousands(buf);
@@ -2508,13 +2534,11 @@ format_signed_integer(NODE *arg, struct flags *flags)
 static const char *
 format_unsigned_integer(NODE *arg, struct flags *flags)
 {
-       // FIXME: still needs work
        const char *number_value;
-       double tmpval;
        char *buf1 = NULL;
-       size_t buflen;
        char *buf2 = NULL;
        char fill[] = " ";
+       size_t val_len;
 
        if (out_of_range(arg))
                return format_out_of_range(arg, flags);
@@ -2522,187 +2546,85 @@ format_unsigned_integer(NODE *arg, struct flags *flags)
        if (is_mpg_integer(arg) || is_mpg_float(arg))
                return format_mpg_integer(arg, flags);
 
-       number_value = format_integer_digits(arg, flags);       // just digits, 
possible leading '-'
-       tmpval = arg->numbr;
-
+       number_value = format_integer_digits(arg, flags);       // just digits
+       val_len = strlen(number_value);
 
        // We now have the initial *integer* decimal, octal, or hex value in 
hand.
-       // If it's decimal, we've added commas if appropriate. If it's negative
-       // and decimal, it has a minus sign.
+       // If it's decimal, we've added commas if appropriate.
        
        // The next step is deal with the rest of the printf flags.
 
-       if (tmpval == 0 && flags->field_width == 0
-           && ! flags->have_prec) {
-               // relatively simple case
-               if (flags->base == 16 && flags->alt) {
-                       size_t len = strlen(number_value) + 2 + 1;
-
-                       emalloc(buf1, char *, len, "format_integer");
-                       sprintf(buf1, "0%c%s", flags->format, number_value);
-                       free((void *) number_value);
-
-                       return buf1;
-               } else if (flags->base == 10 && (flags->plus || flags->space)
-                       && number_value[0] != '-') {
-                       size_t len = strlen(number_value) + 1 + 1;
-
-                       emalloc(buf1, char *, len, "format_integer");
-                       if (flags->plus)
-                               sprintf(buf1, "+%s", number_value);
-                       else
-                               sprintf(buf1, " %s", number_value);
-                       free((void *) number_value);
-
-                       return buf1;
-               } else
-                       return number_value;
-       }
-
-       // Now it gets messy...
-
+       // Add more output digits to match the precision
+       if (flags->have_prec && val_len < flags->precision) {
+               char *cp;
+               const char *src;
+               int prec = flags->precision;
 
-       /*
-        * ``The result of converting a zero value with a
-        * precision of zero is no characters.''
-        *
-        * If I remember the ANSI C standard, though,
-        * it says that for octal conversions
-        * the precision is artificially increased
-        * to add an extra 0 if # is supplied.
-        * Indeed, in C,
-        *      printf("%#.0o\n", 0);
-        * prints a single 0.
-        */
-       if (! flags->alt && flags->have_prec && flags->precision == 0 && tmpval 
== 0) {
-               if (flags->base == 8)
-                       flags->precision = 1;
-               else {
-                       buf1 = (char *) number_value;
-                       goto pr_tail;
+               // plus and space flags are only for signed conversions
+               emalloc(buf1, char *, flags->precision + 1,
+                               "format_unsigned_integer");
+               cp = buf1;
+               src = number_value;
+               if (number_value[0] == '-') {
+                       *cp++ = '-';
+                       src++;
+                       val_len--;
                }
-       }
-
-       if (compute_zero_flag(flags))
-               fill[0] = '0';  // fill with zeros
-
-       /* add more output digits to match the precision */
-       if (flags->have_prec && flags->precision > 0) {
-               bool negative = (number_value[0] == '-');
-               size_t len = strlen(number_value);
-               char *cp1;
 
-               len += flags->precision + 1;
-               emalloc(buf1, char *, len, "format_integer");
-               strcpy(buf1, number_value);
-
-               reverse(buf1);
-               cp1 = buf1 + len;
-               if (negative)
-                       cp1--;  // overwrite the '-', we'll add it back in a 
minute
-               while (cp1 - buf1 < flags->precision) {
-                       if (cp1 - buf1 >= len)
-                               growbuffer(buf1, len, cp1);
+               for (; prec > val_len; prec--)
+                       *cp++ = '0';
 
-                       *cp1++ = '0';
-               }
-               if (negative)
-                       *cp1++ = '-';
-               *cp1 = '\0';
-               reverse(buf1);
+               strcpy(cp, src);
+               free((void *) number_value);
+               val_len = strlen(buf1);
        } else
                buf1 = (char *) number_value;
 
+       // handle the alt flag
        if (flags->alt) {
-               if (flags->base == 16 && tmpval != 0) {
-                       if (fill[0] == '0') {
-                               emalloc(buf2, char *, strlen(buf1) + 3, 
"format_integer");
-                               sprintf(buf2, "0%c%s", flags->format, buf1);
-                               flags->field_width -= 2;
-                               free((void *) buf1);
-                               buf1 = buf2;
-                       }
-               } else if (flags->base == 8 && tmpval == 0) {
-                       assert(number_value[0] == '\0');
-                       emalloc(buf2, char *, 2, "format_integer");
-                       strcpy(buf2, "0");
-                       flags->field_width--;
-                       free((void *) buf1);
-                       buf1 = buf2;
+               emalloc(buf2, char *, val_len + 3, "format_unsigned_integer");
+
+               if (flags->base == 16) {
+                       sprintf(buf2, "0%c%s", flags->format, buf1);
+               } else if (flags->base == 8) {
+                       if (number_value[0] != '0')
+                               sprintf(buf2, "0%s", buf1);
+                       else
+                               strcpy(buf2, buf1);
                }
+               free((void *) buf1);
+               buf1 = buf2;
+               val_len = strlen(buf1);
        }
-       // deal with space or plus flags
-
-       if (flags->precision > flags->field_width)
-               flags->field_width = flags->precision;
-       flags->precision = strlen(buf1);
-pr_tail:
-       int st_len = strlen(buf1);
-       buflen = flags->field_width;
-       if (buflen < st_len)
-               buflen = st_len;
-       if (flags->plus || flags->space)
-               buflen++;
-       buflen++;       // for '\0'
-
-       emalloc(buf2, char *, buflen, "format_integer");
-       char *cp = buf2;
 
-       /*
-        * Order:
-        * 1. Create the number. This is what's in buf1.
-        * 2. If zero flag, pad number to field width.
-        * 3. If plus flag, first leading zero converts to +.
-        * 4. Else if space flag, first leading zero converts to space.
-        * 5. If not padded, just, insert plus or space if need be.
-        * 
-        * If we have not padded, and the field width is > length of
-        * number, two cases:
-        * 1. Left justified, stick plus or space in front of number,
-        *    then the number, then the spaces.
-        * 2. Right justified, do spaces, then plus, then number.
-        *
-        * Plus sign is only added if not a negative number and if signed;
-        * in practice this means base == 10.
-        */
-       bool padded = false;
-       int padlen = buflen - st_len;
+       // pad the field if necessary
+       if (flags->field_width > val_len) {
+               char *cp;
+               const char *src;
+               int fw = flags->field_width;
 
-       if (flags->zero) {
-               for (; padlen > 0; padlen--)
-                       *cp++ = '0';
-               strcpy(cp, buf1);
-               padded = true;
-       }
+               emalloc(buf2, char *, flags->field_width + 1, 
"format_unsigned_integer");
 
-       if (padded) {
-               buf2[0] = (flags->plus ? '+' :
-                               flags->space ? ' ' : '0');
-       } else if (flags->plus || flags->space) {
-               sprintf(buf2, "%c%s",
-                       flags->plus ? '+' :  ' ', buf1);
-       }
+               cp = buf2;
+               src = buf1;
 
+               if (compute_zero_flag(flags) && ! flags->alt)
+                       fill[0] = '0';
 
-       if (flags->left_just) {
-       } else {
-               // normal - spaces or zeros first.
-               if (flags->plus && fill[0] == '0') {
-                       *cp++ = '+';
-                       flags->field_width--;
-               }
-               while (flags->field_width > flags->precision) {
-                       *cp++ = fill[0];
-                       flags->field_width--;
+               if (flags->left_just) {
+                       strcpy(cp, src);
+                       cp += val_len;
+                       for (; fw > val_len; fw--)
+                               *cp++ = fill[0];
+               } else {
+                       for (; fw > val_len; fw--)
+                               *cp++ = fill[0];
+                       strcpy(cp, src);
                }
-               if (flags->plus && fill[0] == ' ')
-                       *--cp = '+';
-       }
-       // bchunk(cp, buf1);
-       free((void *) buf1);
-       while (flags->field_width > flags->precision) {
-               // bchunk_one(fill);
-               flags->field_width--;
+
+               free((void *) buf1);
+               buf1 = buf2;
+               val_len = strlen(buf1);
        }
 
        return buf1;
@@ -2792,7 +2714,79 @@ compute_zero_flag(struct flags *flags)
 static const char *
 format_mpg_integer(NODE *arg, struct flags *flags)
 {
-       return strdup("mpg_int");
+#if 0
+#ifdef HAVE_MPFR
+       mpz_ptr zi;
+       mpfr_ptr mf;
+       bool zero_flags = compute_zero_flag(flags);
+
+       if (is_mpg_integer(arg)) {
+               zi = arg->mpg_i;
+
+               if (flags->format != 'd' && flags->format != 'i') {
+                       if (mpz_sgn(zi) <= 0) {
+                               /*
+                                * Negative value or 0 requires special 
handling.
+                                * Unlike MPFR, GMP does not allow conversion
+                                * to (u)intmax_t. So we first convert GMP type 
to
+                                * a MPFR type.
+                                */
+                               mf = mpz2mpfr(zi);
+                               goto mpf1;
+                       }
+                       signchar = '\0';        /* Don't print '+' */
+               }
+
+               zero_flags = compute_zero_flag(flags);
+
+               fmt_type = have_prec ? MP_INT_WITH_PREC : MP_INT_WITHOUT_PREC;
+               goto fmt0;
+
+       } else if (is_mpg_float(arg)) {
+mpf0:
+               mf = arg->mpg_numbr;
+               if (! mpfr_number_p(mf)) {
+                       cant_happen("%s", "format_mpg_integer called on nan or 
inf");
+               }
+
+               if (cs1 != 'd' && cs1 != 'i') {
+mpf1:
+                       /*
+                        * The output of printf("%#.0x", 0) is 0 instead of 0x, 
hence <= in
+                        * the comparison below.
+                        */
+                       if (mpfr_sgn(mf) <= 0) {
+                               if (! mpfr_fits_intmax_p(mf, ROUND_MODE)) {
+                                       return format_float(arg, flags);
+                               }
+
+                               tmpval = uval = (uintmax_t) mpfr_get_sj(mf, 
ROUND_MODE);
+                               if (! alt && have_prec && prec == 0 && tmpval 
== 0) {
+                                       if (flags->base == 8)
+                                               return strdup("0");
+                                       else
+                                               return strdup("");      /* 
printf("%.0x", 0) is no characters */
+                               }
+                               goto int0;
+                       }
+               }
+
+               /* See comments above about when to fill with zeros */
+               zero_flag = (! lj
+                                   && ((zero_flag && ! have_prec)
+                                        || (fw == 0 && have_prec)));
+
+               (void) mpfr_get_z(mpzval, mf, MPFR_RNDZ);       /* convert to 
GMP integer */
+               fmt_type = have_prec ? MP_INT_WITH_PREC : MP_INT_WITHOUT_PREC;
+               zi = mpzval;
+               goto fmt0;
+       }
+#else
+       cant_happen("%s", "trying to format GMP integer");
+#endif
+#else
+       return strdup("mpgint");
+#endif
 }
 
 
@@ -2838,6 +2832,9 @@ format_mpg_integer(NODE *arg, struct flags *flags)
 static void
 adjust_flags(struct flags *flags)
 {
+       if (flags->base == 0)
+               cant_happen("%s", "flags->base == 0");
+
        if (flags->base == 10 || strchr("cdisu", flags->format) != NULL)
                flags->alt = false;
 
@@ -2849,13 +2846,16 @@ adjust_flags(struct flags *flags)
        if (flags->base != 10) {
                flags->quote = false;
                flags->plus = false;
+               flags->space = false;
        }
 
        if (flags->plus)
                flags->space = false;
 
-       if (flags->format == 'u')
+       if (flags->format == 'u') {
                flags->plus = false;
+               flags->space = false;
+       }
 
        if (flags->left_just)
                flags->zero = false;

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog |   5 +
 printf.c  | 376 +++++++++++++++++++++++++++++++-------------------------------
 2 files changed, 193 insertions(+), 188 deletions(-)


hooks/post-receive
-- 
gawk



reply via email to

[Prev in Thread] Current Thread [Next in Thread]