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-5517-g7731d


From: Arnold Robbins
Subject: [SCM] gawk branch, stable/printf-rework, updated. gawk-4.1.0-5517-g7731d9fd
Date: Sun, 21 Jul 2024 14:37:43 -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  7731d9fd9fa4d0a27e15c8da5cbd1e4d3a515b0f (commit)
      from  35f3fd8439e6a7d168c3221a4326e0eaef594c70 (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=7731d9fd9fa4d0a27e15c8da5cbd1e4d3a515b0f

commit 7731d9fd9fa4d0a27e15c8da5cbd1e4d3a515b0f
Author: Arnold D. Robbins <arnold@skeeve.com>
Date:   Sun Jul 21 21:37:21 2024 +0300

    Start on simplifying the code.

diff --git a/ChangeLog b/ChangeLog
index 802bb097..915fe065 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2024-07-21         Arnold D. Robbins     <arnold@skeeve.com>
+
+       * printf.c: Simplify printing of signed integers; move several
+       common tasks out into separate routines, and use char * instead
+       of const char * to avoid a lot of casting.
+
 2024-07-20         Tim Rice              <trice@posteo.net>
 
        * io.c (csvscan): Set the sentinel if we found CR-LF.
diff --git a/printf.c b/printf.c
index 13c05d26..262edaab 100644
--- a/printf.c
+++ b/printf.c
@@ -40,6 +40,7 @@ struct flags {
        int base;
        int field_width;
        int precision;
+       bool negative;
 };
 
 extern int max_args;
@@ -53,14 +54,16 @@ static size_t mbc_char_count(const char *ptr, size_t 
numbytes);
 static void reverse(char *str);
 static bool compute_zero_flag(struct flags *flags);
 static void adjust_flags(struct flags *flags);
-static const char *add_thousands(const char *original);
-static const char *format_integer_digits(NODE *arg, struct flags *flags, bool 
*used_float);
-static const char *format_mpg_integer_digits(NODE *arg, struct flags *flags, 
bool *used_float);
-static const char *format_signed_integer(NODE *arg, struct flags *flags);
-static const char *format_unsigned_integer(NODE *arg, struct flags *flags);
-static const char *format_float(NODE *arg, struct flags *flags);
-static const char *format_out_of_range(NODE *arg, struct flags *flags);
+static char *add_thousands(const char *original);
+static char *format_integer_digits(NODE *arg, struct flags *flags, bool 
*used_float);
+static char *format_mpg_integer_digits(NODE *arg, struct flags *flags, bool 
*used_float);
+static char *format_signed_integer(NODE *arg, struct flags *flags);
+static char *format_unsigned_integer(NODE *arg, struct flags *flags);
+static char *format_float(NODE *arg, struct flags *flags);
+static char *format_out_of_range(NODE *arg, struct flags *flags);
 static char *fill_to_field_width(char *startval, struct flags *flags, int 
fill);
+static char *add_plus_or_space_and_fill(char *number_value, struct flags 
*flags);
+static char *zero_fill_to_precision(char *number_value, struct flags *flags);
 
 #ifdef HAVE_MPFR
 
@@ -638,7 +641,8 @@ out0:
        flags.format = cs1; \
        flags.base = base; \
        flags.field_width = fw; \
-       flags.precision = prec
+       flags.precision = prec; \
+       flags.negative = false
 
                        set_flags();
                        adjust_flags(& flags);
@@ -880,7 +884,7 @@ do_printf(int nargs, int redirtype)
 
 /* format_integer_digits --- format just the actual value of an integer. 
caller frees return value */
 
-static const char *
+static char *
 format_integer_digits(NODE *arg, struct flags *flags, bool *used_float)
 {
 #define VALUE_SIZE 40
@@ -966,10 +970,10 @@ format_integer_digits(NODE *arg, struct flags *flags, 
bool *used_float)
        }
 
        if (flags->base == 10 && quote_flag) {
-               const char *with_commas = add_thousands(buf);
+               char *with_commas = add_thousands(buf);
 
                free((void *) buf);
-               buf = (char *) with_commas;
+               buf = with_commas;
        }
 
        return buf;
@@ -977,8 +981,112 @@ format_integer_digits(NODE *arg, struct flags *flags, 
bool *used_float)
 
 /* format_signed_integer --- format a signed integer (decimal) value. caller 
frees return value */
 
-static const char *
+static char *
 format_signed_integer(NODE *arg, struct flags *flags)
+{
+       char *number_value;
+       size_t val_len;
+       char *buf1 = NULL;
+       char fill = ' ';
+       bool used_float = false;
+
+       if (out_of_range(arg))
+               return format_out_of_range(arg, flags);
+
+       if (is_mpg_integer(arg) || is_mpg_float(arg))
+               number_value = format_mpg_integer_digits(arg, flags, & 
used_float);
+       else
+               number_value = format_integer_digits(arg, flags, & used_float); 
// just digits, possible leading '-'
+
+       if (used_float)
+               return number_value;
+
+       val_len = strlen(number_value);
+
+       // We now have the initial *integer* decimal value in hand.
+       // If it's decimal, we've added commas if appropriate. If it's negative
+       // and decimal, it has a minus sign.
+
+       // check if negative
+       flags->negative = (number_value[0] == '-');
+       
+       // The next step is deal with the rest of the printf flags.
+
+       // add more output digits to match the precision
+       if (flags->have_prec && flags->precision == 0 && is_zero(arg)) {
+               /*
+                * No actual value. But if there is plus or space or wide
+                * field width or left just, we have to handle those.
+                */
+               number_value[0] = '\0';         // value is empty
+
+               return add_plus_or_space_and_fill(number_value, flags);
+       } else if (flags->have_prec && val_len < flags->precision) {
+               buf1 = zero_fill_to_precision(number_value, flags);
+               val_len = strlen(buf1);
+
+               if (val_len < flags->field_width)
+                       buf1 = fill_to_field_width(buf1, flags, ' ');
+
+               return buf1;
+       } else if (flags->field_width > val_len) {
+               int fw = flags->field_width;
+               size_t buflen = flags->field_width +
+                       (flags->negative || flags->plus || flags->space) + 1;
+               char *cp;
+
+               if (compute_zero_flag(flags))
+                       fill = '0';
+
+               reverse(number_value);
+               if (flags->negative) {
+                       number_value[val_len - 1] = '\0';       // will restore 
later.
+                       val_len--;
+               }
+               
+               fw -= (flags->negative || flags->space || flags->plus);
+
+               emalloc(buf1, char *, buflen, "format_signed_integer");
+               strcpy(buf1, number_value);
+               free((void *) number_value);
+               cp = buf1 + val_len;
+
+               if (fill == '0')
+                       for (; fw > val_len; fw--)
+                               *cp++ = fill;
+
+               if (flags->negative)
+                       *cp++ = '-';
+               else if (flags->plus)
+                       *cp++ = '+';
+               else if (flags->space)
+                       *cp++ = ' ';
+
+               *cp = '\0';
+
+               reverse(buf1);
+
+               return fill_to_field_width(buf1, flags, ' ');
+       } else if ((flags->plus || flags->space) && ! flags->negative) {
+               emalloc(buf1, char *, val_len + 2, "format_signed_integer");
+               if (flags->plus) {
+                       sprintf(buf1, "+%s", number_value);
+               } else {
+                       sprintf(buf1, " %s", number_value);
+               }
+
+               free((void *) number_value);
+       } else
+               buf1 = number_value;
+
+       return buf1;
+}
+
+#if 0
+/* format_signed_integer --- format a signed integer (decimal) value. caller 
frees return value */
+
+static const char *
+format_signed_integer0(NODE *arg, struct flags *flags)
 {
        const char *number_value;
        size_t val_len;
@@ -1165,17 +1273,167 @@ format_signed_integer(NODE *arg, struct flags *flags)
 
                free((void *) number_value);
        } else
-               buf1 = (char *) number_value;
+               buf1 = number_value;
 
        return buf1;
 }
+#endif
 
 /* format_unsigned_integer --- format an unsigned integer value. caller frees 
return value */
 
-static const char *
+static char *
 format_unsigned_integer(NODE *arg, struct flags *flags)
 {
-       const char *number_value;
+       char *number_value;
+       char *buf1 = NULL;
+       char *buf2 = NULL;
+       char fill = ' ';
+       size_t val_len;
+       bool used_float = false;
+
+       if (out_of_range(arg))
+               return format_out_of_range(arg, flags);
+
+       if (is_mpg_integer(arg) || is_mpg_float(arg))
+               number_value = format_mpg_integer_digits(arg, flags, & 
used_float);
+       else
+               number_value = format_integer_digits(arg, flags, & used_float); 
// just digits
+
+       if (used_float)
+               return number_value;
+
+       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.
+       
+       // The next step is deal with the rest of the printf flags.
+
+       // Add more output digits to match the precision
+       if (flags->have_prec) {
+               if (flags->precision == 0 && is_zero(arg) && flags->field_width 
== 0 && ! flags->alt) {
+                       free((void *) number_value);
+                       return estrdup("", 1);
+               }
+
+               if (val_len < flags->precision) {
+                       char *cp;
+                       const char *src;
+                       int prec = flags->precision;
+
+                       // plus and space flags are only for signed conversions
+                       emalloc(buf1, char *, flags->precision + 1,
+                                       "format_unsigned_integer");
+                       cp = buf1;
+                       src = number_value;
+
+                       for (; prec > val_len; prec--)
+                               *cp++ = '0';
+
+                       strcpy(cp, src);
+                       free((void *) number_value);
+               } else if (flags->have_prec) {
+                       if (flags->base == 8) {
+                               if (number_value[0] != '0') {
+                                       emalloc(buf1, char *, val_len + 2, 
"format_unsigned_integer");
+                                       sprintf(buf1, "0%s", number_value);
+                                       free((void *) number_value);
+                               } else
+                                       buf1 = number_value;
+                       } else {
+                               free((void *) number_value);
+                               if (flags->plus)
+                                       buf1 = estrdup("+", 1);
+                               else if (flags->space)
+                                       buf1 = estrdup(" ", 1);
+                               else
+                                       buf1 = estrdup("", 1);
+                       }
+               } else
+                       buf1 = number_value;
+
+               val_len = strlen(buf1);
+       } else if (flags->field_width > val_len) { // pad the field if necessary
+               // when there's a precision, field width padding with zeros is 
not done.
+               char *cp;
+               const char *src;
+               int fw = flags->field_width;
+
+               emalloc(buf1, char *, flags->field_width + 3, 
"format_unsigned_integer");
+
+               cp = buf1;
+               src = number_value;
+
+               if (compute_zero_flag(flags))
+                       fill = '0';
+
+               if (flags->alt) {
+                       if (flags->base == 16 && ! is_zero(arg)) {
+                               if (fill == '0') {
+                                       *cp++ = '0';
+                                       *cp++ = flags->format;
+                                       fw -= 2;
+                                       for (; fw > val_len; fw--)
+                                               *cp++ = fill;
+                               } else {
+                                       fw -= 2;
+                                       *cp++ = '0';
+                                       *cp++ = flags->format;
+                               }
+                       } else if (flags->base == 8 && src[0] != '0') {
+                               *cp++ = '0';
+                       }
+
+                       strcpy(cp, src);
+                       free((void *) number_value);
+                       flags->alt = false;
+               } else
+                       buf1 = number_value;
+
+               val_len = strlen(buf1);
+
+               if (val_len < flags->field_width) {
+                       buf1 = fill_to_field_width(buf1, flags, fill);
+                       val_len = strlen(buf1);
+               }
+       } else
+               buf1 = number_value;
+
+       if (flags->alt && ! is_zero(arg)) {
+               // handle the alt flag
+               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 (buf1[0] != '0')
+                               sprintf(buf2, "0%s", buf1);
+                       else
+                               strcpy(buf2, buf1);
+               }
+               free((void *) buf1);
+               buf1 = buf2;
+               val_len = strlen(buf1);
+       }
+
+       if (is_zero(arg) && (flags->plus || flags->space)) {
+               emalloc(buf2, char *, val_len + 3, "format_unsigned_integer");
+               strcpy(buf2, " ");
+               free((void *) buf1);
+               buf1 = buf2;
+               val_len = strlen(buf1);
+       }
+
+       return buf1;
+}
+
+#if 0
+/* format_unsigned_integer --- format an unsigned integer value. caller frees 
return value */
+
+static char *
+format_unsigned_integer0(NODE *arg, struct flags *flags)
+{
+       char *number_value;
        char *buf1 = NULL;
        char *buf2 = NULL;
        char fill = ' ';
@@ -1279,7 +1537,7 @@ format_unsigned_integer(NODE *arg, struct flags *flags)
                        free((void *) number_value);
                        flags->alt = false;
                } else
-                       buf1 = (char *) number_value;
+                       buf1 = number_value;
 
                val_len = strlen(buf1);
 
@@ -1288,7 +1546,7 @@ format_unsigned_integer(NODE *arg, struct flags *flags)
                        val_len = strlen(buf1);
                }
        } else
-               buf1 = (char *) number_value;
+               buf1 = number_value;
 
        if (flags->alt && ! is_zero(arg)) {
                // handle the alt flag
@@ -1317,10 +1575,11 @@ format_unsigned_integer(NODE *arg, struct flags *flags)
 
        return buf1;
 }
+#endif
 
 /* format_out_of_range --- format an out of range value as %g. caller frees 
return value */
 
-static const char *
+static char *
 format_out_of_range(NODE *arg, struct flags *flags)
 {
        /*
@@ -1390,7 +1649,7 @@ compute_zero_flag(struct flags *flags)
  * the digits and let the higher level code handle padding and so on.
  */
 
-static const char *
+static char *
 format_mpg_integer_digits(NODE *arg, struct flags *flags, bool *used_float)
 {
 #ifdef HAVE_MPFR
@@ -1476,10 +1735,10 @@ fmt0:
 #endif
 
        if (quote_flag && flags->base == 10) {
-               const char *new_text = add_thousands(buf);
+               char *new_text = add_thousands(buf);
 
                free((void *) buf);
-               buf = (char *) new_text;
+               buf = new_text;
        }
 
        return buf;
@@ -1562,7 +1821,7 @@ adjust_flags(struct flags *flags)
  * struct locale loc.
  */
 
-static const char *
+static char *
 format_float(NODE *arg, struct flags *flags)
 {
        char *buf;
@@ -1811,7 +2070,7 @@ reverse(char *str)
  * to work through the string backwards. (We tried it, it was yucky.)
  */
 
-static const char *
+static char *
 add_thousands(const char *original)
 {
        size_t orig_len = strlen(original);
@@ -1883,7 +2142,7 @@ fill_to_field_width(char *startval, struct flags *flags, 
int fill)
        char *cp;
        int fw = flags->field_width;
 
-       if (l > fw)     // nothing to do
+       if (l >= fw)    // nothing to do
                return startval;
 
        emalloc(buf, char *, l + 1, "fill_to_field_width");
@@ -1905,3 +2164,91 @@ fill_to_field_width(char *startval, struct flags *flags, 
int fill)
 
        return buf;
 }
+
+/* add_plus_or_space_and_fill --- what it says */
+
+static char *
+add_plus_or_space_and_fill(char *number_value, struct flags *flags)
+{
+       char *buf1;
+       char *cp;
+       size_t buflen;
+       int fw = flags->field_width;
+
+       buflen = flags->field_width + strlen(number_value) +
+               (flags->space || flags->plus || flags->negative) + 1;
+
+       emalloc(buf1, char *, buflen, "add_plus_or_space_and_fill");
+       cp = buf1;
+
+       if (flags->left_just) {
+               if (flags->negative) {
+                       *cp++ = '-';
+                       fw--;
+               } else if (flags->plus) {
+                       *cp++ = '+';
+                       fw--;
+               } else if (flags->space) {
+                       *cp++ = ' ';
+                       fw--;
+               }
+               for (; fw > 0; fw--)
+                       *cp++ = ' ';
+               *cp = '\0';
+       } else if (fw > 0 || flags->plus || flags->space) {
+               char final = ' ';
+               if (flags->negative)
+                       final = '-';
+               else if (flags->plus)
+                       final = '+';
+
+               for (fw--; fw > 0; fw--)
+                       *cp++ = ' ';
+               *cp++ = final;
+               *cp = '\0';
+       } else
+               buf1[0] = '\0';
+
+       strcat(buf1, number_value);
+
+       free((void *) number_value);
+
+       return buf1;
+
+}
+
+/* zero_fill_to_precision --- what it says */
+
+static char *
+zero_fill_to_precision(char *number_value, struct flags *flags)
+{
+       char *buf1;
+       char *cp, *src;
+       size_t buflen;
+       int prec = flags->precision;
+       size_t val_len = strlen(number_value);
+
+       buflen = flags->precision + 1;  // we know val_len < precision
+
+       emalloc(buf1, char *, buflen, "zero_fill_to_precision");
+       cp = buf1;
+       src = number_value;
+
+       if (flags->negative) {
+               *cp++ = '-';
+               src++;
+               val_len--;
+       } else if (flags->plus) {
+               *cp++ = '+';
+       } else if (flags->space) {
+               *cp++ = ' ';
+       }
+
+       for (; prec > val_len; prec--)
+               *cp++ = '0';
+
+       strcpy(cp, src);
+       free((void *) number_value);
+
+       return buf1;
+}

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

Summary of changes:
 ChangeLog |   6 +
 printf.c  | 395 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 377 insertions(+), 24 deletions(-)


hooks/post-receive
-- 
gawk



reply via email to

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