[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
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [SCM] gawk branch, stable/printf-rework, updated. gawk-4.1.0-5517-g7731d9fd,
Arnold Robbins <=