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-5510-g74f3b


From: Arnold Robbins
Subject: [SCM] gawk branch, stable/printf-rework, updated. gawk-4.1.0-5510-g74f3b305
Date: Tue, 16 Jul 2024 01:09:00 -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  74f3b30538985e5d66cf2932cec33ff044170127 (commit)
      from  057d4307ed06d0247c8756e1d18312f37e22fe90 (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=74f3b30538985e5d66cf2932cec33ff044170127

commit 74f3b30538985e5d66cf2932cec33ff044170127
Author: Arnold D. Robbins <arnold@skeeve.com>
Date:   Tue Jul 16 08:08:41 2024 +0300

    Considerable code cleanup.

diff --git a/ChangeLog b/ChangeLog
index 63863a53..db90f750 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2024-07-16         Arnold D. Robbins     <arnold@skeeve.com>
+
+       * awk.h (format_args): Renamed from format_tree. Remove
+       format_tree_old.
+       * debug.c, main.c, mpfr.c, node.c: Adjusted.
+       * printf.c (format_args): Renamed. Removed all old, factored-out
+       code.
+       (format_tree_old): Removed.
+
 2024-07-16         Arnold D. Robbins     <arnold@skeeve.com>
 
        * printf.c: Use mpfr_sprintf() just to generate digits.
diff --git a/awk.h b/awk.h
index fb1a74a7..9997534d 100644
--- a/awk.h
+++ b/awk.h
@@ -1516,9 +1516,7 @@ extern NODE *do_sub(int nargs, unsigned int flags);
 extern NODE *call_sub(const char *name, int nargs);
 extern NODE *call_match(int nargs);
 extern NODE *call_split_func(const char *name, int nargs);
-extern NODE *format_tree_old(const char *, size_t, NODE **, long);
-extern NODE *format_tree_new(const char *, size_t, NODE **, long);
-extern NODE *(*format_tree)(const char *, size_t, NODE **, long);
+extern NODE *format_args(const char *, size_t, NODE **, long);
 extern NODE *do_lshift(int nargs);
 extern NODE *do_rshift(int nargs);
 extern NODE *do_and(int nargs);
diff --git a/debug.c b/debug.c
index 8c5bee6c..40c785f8 100644
--- a/debug.c
+++ b/debug.c
@@ -5227,7 +5227,7 @@ do_print_f(CMDARG *arg, int cmd ATTRIBUTE_UNUSED)
 
        PUSH_BINDING(fatal_tag_stack, fatal_tag, fatal_tag_valid);
        if (setjmp(fatal_tag) == 0)
-               r = format_tree(tmp[0]->stptr, tmp[0]->stlen, tmp, i);
+               r = format_args(tmp[0]->stptr, tmp[0]->stlen, tmp, i);
        else {
                /* fatal error, restore exit_val of program */
                exit_val = EXIT_SUCCESS;
diff --git a/main.c b/main.c
index f71d3584..4ef0208d 100644
--- a/main.c
+++ b/main.c
@@ -161,8 +161,6 @@ GETGROUPS_T *groupset;              /* current group set */
 int ngroups;                   /* size of said set */
 #endif
 
-NODE *(*format_tree)(const char *, size_t, NODE **, long);
-
 void (*lintfunc)(const char *mesg, ...) = r_warning;
 
 /* Sorted by long option name! */
@@ -220,11 +218,6 @@ main(int argc, char **argv)
        const char *initial_locale;
 #endif
 
-       if (getenv("PRINTF_NEW") != NULL)
-               format_tree = format_tree_new;
-       else
-               format_tree = format_tree_old;
-
        myname = gawk_name(argv[0]);
 
        check_pma_security(persist_file);
diff --git a/mpfr.c b/mpfr.c
index 1cb02c11..370f4088 100644
--- a/mpfr.c
+++ b/mpfr.c
@@ -422,16 +422,16 @@ mpg_format_val(const char *format, int index, NODE *s)
                return make_string(result, strlen(result));
        }
 
-       /* create dummy node for a sole use of format_tree */
+       /* create dummy node for a sole use of format_args */
        dummy[1] = s;
        oflags = s->flags;
 
        if (is_mpg_integer(s) || mpfr_integer_p(s->mpg_numbr)) {
                /* integral value, use %d */
-               r = format_tree("%d", 2, dummy, 2);
+               r = format_args("%d", 2, dummy, 2);
                s->stfmt = STFMT_UNUSED;
        } else {
-               r = format_tree(format, fmt_list[index]->stlen, dummy, 2);
+               r = format_args(format, fmt_list[index]->stlen, dummy, 2);
                assert(r != NULL);
                s->stfmt = index;
        }
diff --git a/node.c b/node.c
index 0d8fea72..181152dd 100644
--- a/node.c
+++ b/node.c
@@ -246,16 +246,16 @@ r_format_val(const char *format, int index, NODE *s)
                NODE *dummy[2], *r;
                unsigned int oflags;
 
-               /* create dummy node for a sole use of format_tree */
+               /* create dummy node for a sole use of format_args */
                dummy[1] = s;
                oflags = s->flags;
 
                if (val == s->numbr) {
                        /* integral value, but outside range of %ld, use %.0f */
-                       r = format_tree("%.0f", 4, dummy, 2);
+                       r = format_args("%.0f", 4, dummy, 2);
                        s->stfmt = STFMT_UNUSED;
                } else {
-                       r = format_tree(format, fmt_list[index]->stlen, dummy, 
2);
+                       r = format_args(format, fmt_list[index]->stlen, dummy, 
2);
                        assert(r != NULL);
                        s->stfmt = index;
                }
diff --git a/printf.c b/printf.c
index be58a500..820d4cb2 100644
--- a/printf.c
+++ b/printf.c
@@ -98,1046 +98,19 @@ mpz2mpfr(mpz_ptr zi)
 #endif
 
 /*
- * format_tree() formats arguments of sprintf,
+ * format_args() formats arguments of sprintf,
  * and accordingly to a fmt_string providing a format like in
  * printf family from C library.  Returns a string node which value
  * is a formatted string.  Called by  sprintf function.
  *
  * It is one of the uglier parts of gawk.  Thanks to Michal Jaegermann
  * for taming this beast and making it compatible with ANSI C.
- */
-
-NODE *
-format_tree_old(
-       const char *fmt_string,
-       size_t n0,
-       NODE **the_args,
-       long num_args)
-{
-/* copy 'l' bytes from 's' to 'obufout' checking for space in the process */
-/* difference of pointers should be of ptrdiff_t type, but let us be kind */
-#define bchunk(s, l) if (l) { \
-       while ((l) > ofre) { \
-               size_t olen = obufout - obuf; \
-               erealloc(obuf, char *, osiz * 2, "format_tree"); \
-               ofre += osiz; \
-               osiz *= 2; \
-               obufout = obuf + olen; \
-       } \
-       memcpy(obufout, s, (size_t) (l)); \
-       obufout += (l); \
-       ofre -= (l); \
-}
-
-/* copy one byte from 's' to 'obufout' checking for space in the process */
-#define bchunk_one(s) { \
-       if (ofre < 1) { \
-               size_t olen = obufout - obuf; \
-               erealloc(obuf, char *, osiz * 2, "format_tree"); \
-               ofre += osiz; \
-               osiz *= 2; \
-               obufout = obuf + olen; \
-       } \
-       *obufout++ = *s; \
-       --ofre; \
-}
-
-/* Is there space for something L big in the buffer? */
-#define chksize(l)  if ((l) >= ofre) { \
-       size_t olen = obufout - obuf; \
-       size_t delta = osiz+l-ofre; \
-       erealloc(obuf, char *, osiz + delta, "format_tree"); \
-       obufout = obuf + olen; \
-       ofre += delta; \
-       osiz += delta; \
-}
-
-       size_t cur_arg = 0;
-       NODE *r = NULL;
-       int i, nc;
-       bool toofew = false;
-       char *obuf, *obufout;
-       size_t osiz, ofre, olen_final;
-       const char *chbuf;
-       const char *s0, *s1;
-       int cs1;
-       NODE *arg;
-       long fw, prec, argnum;
-       bool used_dollar;
-       bool lj, alt, have_prec, need_format;
-       long *cur = NULL;
-       uintmax_t uval;
-       bool sgn;
-       int base;
-       /*
-        * Although this is an array, the elements serve two different
-        * purposes. The first element is the general buffer meant
-        * to hold the entire result string.  The second one is a
-        * temporary buffer for large floating point values. They
-        * could just as easily be separate variables, and the
-        * code might arguably be clearer.
-        */
-       struct {
-               char *buf;
-               size_t bufsize;
-               char stackbuf[30];
-       } cpbufs[2];
-#define cpbuf  cpbufs[0].buf
-       char *cend = &cpbufs[0].stackbuf[sizeof(cpbufs[0].stackbuf)];
-       char *cp;
-       const char *fill;
-       AWKNUM tmpval = 0.0;
-       char signchar = '\0';
-       size_t len;
-       bool zero_flag = false;
-       bool quote_flag = false;
-       int ii, jj;
-       char *chp;
-       size_t copy_count, char_count;
-       char *nan_inf_val;
-       bool magic_posix_flag;
-#ifdef HAVE_MPFR
-       mpz_ptr zi;
-       mpfr_ptr mf;
-#endif
-       enum { MP_NONE = 0, MP_INT_WITH_PREC = 1, MP_INT_WITHOUT_PREC, MP_FLOAT 
} fmt_type;
-
-       static const char sp[] = " ";
-       static const char zero_string[] = "0";
-       static const char lchbuf[] = "0123456789abcdef";
-       static const char Uchbuf[] = "0123456789ABCDEF";
-       static const char bad_modifiers[] = "hjlLtz";
-       static bool warned[sizeof(bad_modifiers)-1];    // auto-init to zero
-
-       bool modifier_seen[sizeof(bad_modifiers)-1];
-#define modifier_index(c)  (strchr(bad_modifiers, c) - bad_modifiers)
-
-#define INITIAL_OUT_SIZE       64
-       emalloc(obuf, char *, INITIAL_OUT_SIZE, "format_tree");
-       obufout = obuf;
-       osiz = INITIAL_OUT_SIZE;
-       ofre = osiz - 1;
-
-       cur_arg = 1;
-
-       {
-               size_t k;
-               for (k = 0; k < sizeof(cpbufs)/sizeof(cpbufs[0]); k++) {
-                       cpbufs[k].bufsize = sizeof(cpbufs[k].stackbuf);
-                       cpbufs[k].buf = cpbufs[k].stackbuf;
-               }
-       }
-
-       /*
-        * The point of this goop is to grow the buffer
-        * holding the converted number, so that large
-        * values don't overflow a fixed length buffer.
-        */
-#define PREPEND(CH) do {       \
-       if (cp == cpbufs[0].buf) {      \
-               char *prev = cpbufs[0].buf;     \
-               emalloc(cpbufs[0].buf, char *, 2*cpbufs[0].bufsize, \
-                       "format_tree"); \
-               memcpy((cp = cpbufs[0].buf+cpbufs[0].bufsize), prev,    \
-                      cpbufs[0].bufsize);      \
-               cpbufs[0].bufsize *= 2; \
-               if (prev != cpbufs[0].stackbuf) \
-                       efree(prev);    \
-               cend = cpbufs[0].buf+cpbufs[0].bufsize; \
-       }       \
-       *--cp = (CH);   \
-} while(0)
-
-       /*
-        * Check first for use of `count$'.
-        * If plain argument retrieval was used earlier, choke.
-        *      Otherwise, return the requested argument.
-        * If not `count$' now, but it was used earlier, choke.
-        * If this format is more than total number of args, choke.
-        * Otherwise, return the current argument.
-        */
-#define parse_next_arg() { \
-       if (argnum > 0) { \
-               if (cur_arg > 1) { \
-                       msg(_("fatal: must use `count$' on all formats or 
none")); \
-                       goto out; \
-               } \
-               arg = the_args[argnum]; \
-       } else if (used_dollar) { \
-               msg(_("fatal: must use `count$' on all formats or none")); \
-               arg = 0; /* shutup the compiler */ \
-               goto out; \
-       } else if (cur_arg >= num_args) { \
-               arg = 0; /* shutup the compiler */ \
-               toofew = true; \
-               break; \
-       } else { \
-               arg = the_args[cur_arg]; \
-               cur_arg++; \
-       } \
-}
-
-       need_format = false;
-       used_dollar = false;
-
-       s0 = s1 = fmt_string;
-       while (n0-- > 0) {
-               if (*s1 != '%') {
-                       s1++;
-                       continue;
-               }
-               need_format = true;
-               bchunk(s0, s1 - s0);
-               s0 = s1;
-               cur = &fw;
-               fw = 0;
-               prec = 0;
-               base = 0;
-               argnum = 0;
-               base = 0;
-               have_prec = false;
-               signchar = '\0';
-               zero_flag = false;
-               quote_flag = false;
-               nan_inf_val = NULL;
-#ifdef HAVE_MPFR
-               mf = NULL;
-               zi = NULL;
-#endif
-               fmt_type = MP_NONE;
-
-               lj = alt = false;
-               memset(modifier_seen, 0, sizeof(modifier_seen));
-               magic_posix_flag = false;
-               fill = sp;
-               cp = cend;
-               chbuf = lchbuf;
-               s1++;
-
-retry:
-               if (n0-- == 0)  /* ran out early! */
-                       break;
-
-               switch (cs1 = *s1++) {
-               case (-1):      /* dummy case to allow for checking */
-check_pos:
-                       if (cur != &fw)
-                               break;          /* reject as a valid format */
-                       goto retry;
-               case '%':
-                       need_format = false;
-                       /*
-                        * 29 Oct. 2002:
-                        * The C99 standard pages 274 and 279 seem to imply that
-                        * since there's no arg converted, the field width 
doesn't
-                        * apply.  The code already was that way, but this
-                        * comment documents it, at least in the code.
-                        */
-                       if (do_lint) {
-                               const char *msg = NULL;
-
-                               if (fw && ! have_prec)
-                                       msg = _("field width is ignored for 
`%%' specifier");
-                               else if (fw == 0 && have_prec)
-                                       msg = _("precision is ignored for `%%' 
specifier");
-                               else if (fw && have_prec)
-                                       msg = _("field width and precision are 
ignored for `%%' specifier");
-
-                               if (msg != NULL)
-                                       lintwarn("%s", msg);
-                       }
-                       bchunk_one("%");
-                       s0 = s1;
-                       break;
-
-               case '0':
-                       /*
-                        * Only turn on zero_flag if we haven't seen
-                        * the field width or precision yet.  Otherwise,
-                        * screws up floating point formatting.
-                        */
-                       if (cur == & fw)
-                               zero_flag = true;
-                       if (lj)
-                               goto retry;
-                       /* fall through */
-               case '1':
-               case '2':
-               case '3':
-               case '4':
-               case '5':
-               case '6':
-               case '7':
-               case '8':
-               case '9':
-                       if (cur == NULL)
-                               break;
-                       if (prec >= 0)
-                               *cur = cs1 - '0';
-                       /*
-                        * with a negative precision *cur is already set
-                        * to -1, so it will remain negative, but we have
-                        * to "eat" precision digits in any case
-                        */
-                       while (n0 > 0 && *s1 >= '0' && *s1 <= '9') {
-                               --n0;
-                               *cur = *cur * 10 + *s1++ - '0';
-                       }
-                       if (prec < 0)   /* negative precision is discarded */
-                               have_prec = false;
-                       if (cur == &prec)
-                               cur = NULL;
-                       if (n0 == 0)    /* badly formatted control string */
-                               continue;
-                       goto retry;
-               case '$':
-                       if (do_traditional) {
-                               msg(_("fatal: `$' is not permitted in awk 
formats"));
-                               goto out;
-                       }
-
-                       if (cur == &fw) {
-                               argnum = fw;
-                               fw = 0;
-                               used_dollar = true;
-                               if (argnum <= 0) {
-                                       msg(_("fatal: argument index with `$' 
must be > 0"));
-                                       goto out;
-                               }
-                               if (argnum >= num_args) {
-                                       msg(_("fatal: argument index %ld 
greater than total number of supplied arguments"), argnum);
-                                       goto out;
-                               }
-                       } else {
-                               msg(_("fatal: `$' not permitted after period in 
format"));
-                               goto out;
-                       }
-
-                       goto retry;
-               case '*':
-                       if (cur == NULL)
-                               break;
-                       if (! do_traditional && used_dollar && ! 
isdigit((unsigned char) *s1)) {
-                               fatal(_("fatal: must use `count$' on all 
formats or none"));
-                               break;  /* silence warnings */
-                       } else if (! do_traditional && isdigit((unsigned char) 
*s1)) {
-                               int val = 0;
-
-                               for (; n0 > 0 && *s1 && isdigit((unsigned char) 
*s1); s1++, n0--) {
-                                       val *= 10;
-                                       val += *s1 - '0';
-                               }
-                               if (*s1 != '$') {
-                                       msg(_("fatal: no `$' supplied for 
positional field width or precision"));
-                                       goto out;
-                               } else {
-                                       s1++;
-                                       n0--;
-                               }
-                               // val could be less than zero if someone 
provides a field width
-                               // so large that it causes integer overflow. 
Mainly fuzzers do this,
-                               // but let's try to be good anyway.
-                               if (val < 0 || val >= num_args) {
-                                       toofew = true;
-                                       break;
-                               }
-                               arg = the_args[val];
-                       } else {
-                               parse_next_arg();
-                       }
-                       (void) force_number(arg);
-                       *cur = get_number_si(arg);
-                       if (*cur < 0 && cur == &fw) {
-                               *cur = -*cur;
-                               lj = true;
-                       }
-                       if (cur == &prec) {
-                               if (*cur >= 0)
-                                       have_prec = true;
-                               else
-                                       have_prec = false;
-                               cur = NULL;
-                       }
-                       goto retry;
-               case ' ':               /* print ' ' or '-' */
-                                       /* 'space' flag is ignored */
-                                       /* if '+' already present  */
-                       if (signchar != false)
-                               goto check_pos;
-                       /* FALL THROUGH */
-               case '+':               /* print '+' or '-' */
-                       signchar = cs1;
-                       goto check_pos;
-               case '-':
-                       if (prec < 0)
-                               break;
-                       if (cur == &prec) {
-                               prec = -1;
-                               goto retry;
-                       }
-                       fill = sp;      /* if left justified then other */
-                       lj = true;      /* filling is ignored */
-                       goto check_pos;
-               case '.':
-                       if (cur != &fw)
-                               break;
-                       cur = &prec;
-                       have_prec = true;
-                       goto retry;
-               case '#':
-                       alt = true;
-                       goto check_pos;
-               case '\'':
-#if defined(HAVE_LOCALE_H)
-                       quote_flag = true;
-                       goto check_pos;
-#else
-                       goto retry;
-#endif
-               case 'h':
-               case 'j':
-               case 'l':
-               case 'L':
-               case 't':
-               case 'z':
-                       if (modifier_seen[modifier_index(cs1)])
-                               break;
-                       else {
-                               int ind = modifier_index(cs1);
-
-                               if (do_lint && ! warned[ind]) {
-                                       lintwarn(_("`%c' is meaningless in awk 
formats; ignored"), cs1);
-                                       warned[ind] = true;
-                               }
-                               if (do_posix) {
-                                       msg(_("fatal: `%c' is not permitted in 
POSIX awk formats"), cs1);
-                                       goto out;
-                               }
-                       }
-                       modifier_seen[modifier_index(cs1)] = true;
-                       goto retry;
-
-               case 'P':
-                       if (magic_posix_flag)
-                               break;
-                       magic_posix_flag = true;
-                       goto retry;
-               case 'c':
-                       need_format = false;
-                       parse_next_arg();
-                       /* user input that looks numeric is numeric */
-                       fixtype(arg);
-                       if ((arg->flags & NUMBER) != 0) {
-                               uval = get_number_uj(arg);
-                               if (gawk_mb_cur_max > 1) {
-                                       char buf[100];
-                                       wchar_t wc;
-                                       mbstate_t mbs;
-                                       size_t count;
-
-                                       memset(& mbs, 0, sizeof(mbs));
-
-                                       /* handle systems with too small 
wchar_t */
-                                       if (sizeof(wchar_t) < 4 && uval > 
0xffff) {
-                                               if (do_lint)
-                                                       lintwarn(
-                                               _("[s]printf: value %g is too 
big for %%c format"),
-                                                                       
arg->numbr);
-
-                                               goto out0;
-                                       }
-
-                                       wc = uval;
-
-                                       count = wcrtomb(buf, wc, & mbs);
-                                       if (count == 0
-                                           || count == (size_t) -1) {
-                                               if (do_lint)
-                                                       lintwarn(
-                                               _("[s]printf: value %g is not a 
valid wide character"),
-                                                                       
arg->numbr);
-
-                                               goto out0;
-                                       }
-
-                                       memcpy(cpbuf, buf, count);
-                                       prec = count;
-                                       cp = cpbuf;
-                                       goto pr_tail;
-                               }
-out0:
-                               ;
-                               /* else,
-                                       fall through */
-
-                               cpbuf[0] = uval;
-                               prec = 1;
-                               cp = cpbuf;
-                               goto pr_tail;
-                       }
-                       /*
-                        * As per POSIX, only output first character of a
-                        * string value.  Thus, we ignore any provided
-                        * precision, forcing it to 1.  (Didn't this
-                        * used to work? 6/2003.)
-                        */
-                       cp = arg->stptr;
-                       prec = 1;
-                       /*
-                        * First character can be multiple bytes if
-                        * it's a multibyte character. Grr.
-                        */
-                       if (gawk_mb_cur_max > 1) {
-                               mbstate_t state;
-                               size_t count;
-
-                               memset(& state, 0, sizeof(state));
-                               count = mbrlen(cp, arg->stlen, & state);
-                               if (count != (size_t) -1 && count != (size_t) 
-2 && count > 0) {
-                                       prec = count;
-                                       /* may need to increase fw so that 
padding happens, see pr_tail code */
-                                       if (fw > 0)
-                                               fw += count - 1;
-                               }
-                       }
-                       goto pr_tail;
-               case 's':
-                       need_format = false;
-                       parse_next_arg();
-                       arg = force_string(arg);
-                       if (fw == 0 && ! have_prec)
-                               prec = arg->stlen;
-                       else {
-                               char_count = mbc_char_count(arg->stptr, 
arg->stlen);
-                               if (! have_prec || prec > char_count)
-                                       prec = char_count;
-                       }
-                       cp = arg->stptr;
-                       goto pr_tail;
-               case 'd':
-               case 'i':
-                       need_format = false;
-                       parse_next_arg();
-                       (void) force_number(arg);
-
-                       /*
-                        * Check for Nan or Inf.
-                        */
-                       if (out_of_range(arg))
-                               goto out_of_range;
-#ifdef HAVE_MPFR
-                       if (is_mpg_float(arg))
-                               goto mpf0;
-                       else if (is_mpg_integer(arg))
-                               goto mpz0;
-                       else
-#endif
-                       tmpval = double_to_int(arg->numbr);
-
-                       /*
-                        * ``The result of converting a zero value with a
-                        * precision of zero is no characters.''
-                        */
-                       if (have_prec && prec == 0 && tmpval == 0)
-                               goto pr_tail;
-
-                       if (tmpval < 0) {
-                               tmpval = -tmpval;
-                               sgn = true;
-                       } else {
-                               if (tmpval == -0.0)
-                                       /* avoid printing -0 */
-                                       tmpval = 0.0;
-                               sgn = false;
-                       }
-                       /*
-                        * Use snprintf return value to tell if there
-                        * is enough room in the buffer or not.
-                        */
-                       while ((i = snprintf(cpbufs[1].buf,
-                                            cpbufs[1].bufsize, "%.0f",
-                                            tmpval)) >=
-                              cpbufs[1].bufsize) {
-                               if (cpbufs[1].buf == cpbufs[1].stackbuf)
-                                       cpbufs[1].buf = NULL;
-                               if (i > 0) {
-                                       cpbufs[1].bufsize += ((i > 
cpbufs[1].bufsize) ?
-                                                             i : 
cpbufs[1].bufsize);
-                               }
-                               else
-                                       cpbufs[1].bufsize *= 2;
-                               assert(cpbufs[1].bufsize > 0);
-                               erealloc(cpbufs[1].buf, char *,
-                                        cpbufs[1].bufsize, "format_tree");
-                       }
-                       if (i < 1)
-                               goto out_of_range;
-#if defined(HAVE_LOCALE_H)
-                       quote_flag = (quote_flag && loc.thousands_sep[0] != 0);
-#endif
-                       chp = &cpbufs[1].buf[i-1];
-                       ii = jj = 0;
-                       do {
-                               PREPEND(*chp);
-                               chp--; i--;
-#if defined(HAVE_LOCALE_H)
-                               if (quote_flag && loc.grouping[ii] && ++jj == 
loc.grouping[ii]) {
-                                       if (i) {        /* only add if more 
digits coming */
-                                               int k;
-                                               const char *ts = 
loc.thousands_sep;
-
-                                               for (k = strlen(ts) - 1; k >= 
0; k--) {
-                                                       PREPEND(ts[k]);
-                                               }
-                                       }
-                                       if (loc.grouping[ii+1] == 0)
-                                               jj = 0;         /* keep using 
current val in loc.grouping[ii] */
-                                       else if (loc.grouping[ii+1] == CHAR_MAX)
-                                               quote_flag = false;
-                                       else {
-                                               ii++;
-                                               jj = 0;
-                                       }
-                               }
-#endif
-                       } while (i > 0);
-
-                       /* add more output digits to match the precision */
-                       if (have_prec) {
-                               while (cend - cp < prec)
-                                       PREPEND('0');
-                       }
-
-                       if (sgn)
-                               PREPEND('-');
-                       else if (signchar)
-                               PREPEND(signchar);
-                       /*
-                        * When to fill with zeroes is of course not simple.
-                        * First: No zero fill if left-justifying.
-                        * Next: There seem to be two cases:
-                        *      A '0' without a precision, e.g. %06d
-                        *      A precision with no field width, e.g. %.10d
-                        * Any other case, we don't want to fill with zeroes.
-                        */
-                       if (! lj
-                           && ((zero_flag && ! have_prec)
-                                || (fw == 0 && have_prec)))
-                               fill = zero_string;
-                       if (prec > fw)
-                               fw = prec;
-                       prec = cend - cp;
-                       if (fw > prec && ! lj && fill != sp
-                           && (*cp == '-' || signchar)) {
-                               bchunk_one(cp);
-                               cp++;
-                               prec--;
-                               fw--;
-                       }
-                       goto pr_tail;
-               case 'X':
-                       chbuf = Uchbuf; /* FALL THROUGH */
-               case 'x':
-                       base += 6;      /* FALL THROUGH */
-               case 'u':
-                       base += 2;      /* FALL THROUGH */
-               case 'o':
-                       base += 8;
-                       need_format = false;
-                       parse_next_arg();
-                       (void) force_number(arg);
-
-                       if (out_of_range(arg))
-                               goto out_of_range;
-#ifdef HAVE_MPFR
-                       if (is_mpg_integer(arg)) {
-mpz0:
-                               zi = arg->mpg_i;
-
-                               if (cs1 != 'd' && cs1 != '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 
'+' */
-                               }
-
-                               /* See comments above about when to fill with 
zeros */
-                               zero_flag = (! lj
-                                                   && ((zero_flag && ! 
have_prec)
-                                                        || (fw == 0 && 
have_prec)));
-
-                               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)) {
-                                       /* inf or NaN */
-                                       cs1 = 'g';
-                                       fmt_type = MP_FLOAT;
-                                       goto fmt1;
-                               }
-
-                               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)) {
-                                                       /* -ve number is too 
large */
-                                                       cs1 = 'g';
-                                                       fmt_type = MP_FLOAT;
-                                                       goto fmt1;
-                                               }
-
-                                               tmpval = uval = (uintmax_t) 
mpfr_get_sj(mf, ROUND_MODE);
-                                               if (! alt && have_prec && prec 
== 0 && tmpval == 0)
-                                                       goto pr_tail;   /* 
printf("%.0x", 0) is no characters */
-                                               goto int0;
-                                       }
-                                       signchar = '\0';        /* Don't print 
'+' */
-                               }
-
-                               /* 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
-#endif
-                               tmpval = arg->numbr;
-
-                       /*
-                        * ``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 (! alt && have_prec && prec == 0 && tmpval == 0)
-                               goto pr_tail;
-
-                       if (tmpval < 0) {
-                               uval = (uintmax_t) (intmax_t) tmpval;
-                               if ((AWKNUM)(intmax_t)uval != 
double_to_int(tmpval))
-                                       goto out_of_range;
-                       } else {
-                               uval = (uintmax_t) tmpval;
-                               if ((AWKNUM)uval != double_to_int(tmpval))
-                                       goto out_of_range;
-                       }
-#ifdef HAVE_MPFR
-       int0:
-#endif
-#if defined(HAVE_LOCALE_H)
-                       quote_flag = (quote_flag && loc.thousands_sep[0] != 0);
-#endif
-                       /*
-                        * When to fill with zeroes is of course not simple.
-                        * First: No zero fill if left-justifying.
-                        * Next: There seem to be two cases:
-                        *      A '0' without a precision, e.g. %06d
-                        *      A precision with no field width, e.g. %.10d
-                        * Any other case, we don't want to fill with zeroes.
-                        */
-                       if (! lj
-                           && ((zero_flag && ! have_prec)
-                                || (fw == 0 && have_prec)))
-                               fill = zero_string;
-                       ii = jj = 0;
-                       do {
-                               PREPEND(chbuf[uval % base]);
-                               uval /= base;
-#if defined(HAVE_LOCALE_H)
-                               if (base == 10 && quote_flag && 
loc.grouping[ii] && ++jj == loc.grouping[ii]) {
-                                       if (uval) {     /* only add if more 
digits coming */
-                                               int k;
-                                               const char *ts = 
loc.thousands_sep;
-
-                                               for (k = strlen(ts) - 1; k >= 
0; k--) {
-                                                       PREPEND(ts[k]);
-                                               }
-                                       }
-                                       if (loc.grouping[ii+1] == 0)
-                                               jj = 0;     /* keep using 
current val in loc.grouping[ii] */
-                                       else if (loc.grouping[ii+1] == CHAR_MAX)
-                                               quote_flag = false;
-                                       else {
-                                               ii++;
-                                               jj = 0;
-                                       }
-                               }
-#endif
-                       } while (uval > 0);
-
-                       /* add more output digits to match the precision */
-                       if (have_prec) {
-                               while (cend - cp < prec)
-                                       PREPEND('0');
-                       }
-
-                       if (alt && tmpval != 0) {
-                               if (base == 16) {
-                                       PREPEND(cs1);
-                                       PREPEND('0');
-                                       if (fill != sp) {
-                                               bchunk(cp, 2);
-                                               cp += 2;
-                                               fw -= 2;
-                                       }
-                               } else if (base == 8)
-                                       PREPEND('0');
-                       }
-                       base = 0;
-                       if (prec > fw)
-                               fw = prec;
-                       prec = cend - cp;
-       pr_tail:
-                       if (! lj) {
-                               while (fw > prec) {
-                                       bchunk_one(fill);
-                                       fw--;
-                               }
-                       }
-                       copy_count = prec;
-                       if (fw == 0 && ! have_prec)
-                               ;
-                       else if (gawk_mb_cur_max > 1) {
-                               if (cs1 == 's') {
-                                       assert(cp == arg->stptr || cp == cpbuf);
-                                       copy_count = mbc_byte_count(arg->stptr, 
prec);
-                               }
-                               /* prec was set by code for %c */
-                               /* else
-                                       copy_count = prec; */
-                       }
-                       bchunk(cp, copy_count);
-                       while (fw > prec) {
-                               bchunk_one(fill);
-                               fw--;
-                       }
-                       s0 = s1;
-                       break;
-
-     out_of_range:
-                       /*
-                        * out of range - emergency use of %g format,
-                        * or format NaN and INF values.
-                        */
-                       nan_inf_val = format_nan_inf(arg, cs1);
-                       if (do_posix || magic_posix_flag || nan_inf_val == 
NULL) {
-                               if (do_lint && ! do_posix && ! magic_posix_flag)
-                                       lintwarn(_("[s]printf: value %g is out 
of range for `%%%c' format"),
-                                                               (double) 
tmpval, cs1);
-                               tmpval = arg->numbr;
-                               if (strchr("aAeEfFgG", cs1) == NULL)
-                                       cs1 = 'g';
-                               goto fmt1;
-                       } else {
-                               if (do_lint)
-                                       lintwarn(_("[s]printf: value %s is out 
of range for `%%%c' format"),
-                                                               nan_inf_val, 
cs1);
-                               bchunk(nan_inf_val, strlen(nan_inf_val));
-                               s0 = s1;
-                               break;
-                       }
-
-               case 'F':
-#if ! defined(PRINTF_HAS_F_FORMAT) || PRINTF_HAS_F_FORMAT != 1
-                       cs1 = 'f';
-                       /* FALL THROUGH */
-#endif
-               case 'g':
-               case 'G':
-               case 'e':
-               case 'f':
-               case 'E':
-#if defined(PRINTF_HAS_A_FORMAT) && PRINTF_HAS_A_FORMAT == 1
-               case 'A':
-               case 'a':
-               {
-                       static bool warned = false;
-
-                       if (do_lint && tolower(cs1) == 'a' && ! warned) {
-                               warned = true;
-                               lintwarn(_("%%%c format is POSIX standard but 
not portable to other awks"), cs1);
-                       }
-               }
-#endif
-                       need_format = false;
-                       parse_next_arg();
-                       (void) force_number(arg);
-
-                       if (! is_mpg_number(arg))
-                               tmpval = arg->numbr;
-#ifdef HAVE_MPFR
-                       else if (is_mpg_float(arg)) {
-                               mf = arg->mpg_numbr;
-                               fmt_type = MP_FLOAT;
-                       } else {
-                               /* arbitrary-precision integer, convert to MPFR 
float */
-                               assert(mf == NULL);
-                               mf = mpz2mpfr(arg->mpg_i);
-                               fmt_type = MP_FLOAT;
-                       }
-#endif
-                       if (out_of_range(arg))
-                               goto out_of_range;
-
-     fmt1:
-                       if (! have_prec)
-                               prec = DEFAULT_G_PRECISION;
-#ifdef HAVE_MPFR
-     fmt0:
-#endif
-                       chksize(fw + prec + 11);        /* 11 == slop */
-                       cp = cpbuf;
-                       *cp++ = '%';
-                       if (lj)
-                               *cp++ = '-';
-                       if (signchar)
-                               *cp++ = signchar;
-                       if (alt)
-                               *cp++ = '#';
-                       if (zero_flag)
-                               *cp++ = '0';
-                       if (quote_flag)
-                               *cp++ = '\'';
-
-#if defined(LC_NUMERIC)
-                       if (quote_flag && ! use_lc_numeric)
-                               setlocale(LC_NUMERIC, "");
-#endif
-
-                       bool need_to_add_thousands = false;
-                       switch (fmt_type) {
-#ifdef HAVE_MPFR
-                       case MP_INT_WITH_PREC:
-                               sprintf(cp, "*.*Z%c", cs1);
-                               while ((nc = mpfr_snprintf(obufout, ofre, cpbuf,
-                                            (int) fw, (int) prec, zi)) >= 
(int) ofre)
-                                       chksize(nc)
-                               need_to_add_thousands = true;
-                               break;
-                       case MP_INT_WITHOUT_PREC:
-                               sprintf(cp, "*Z%c", cs1);
-                               while ((nc = mpfr_snprintf(obufout, ofre, cpbuf,
-                                            (int) fw, zi)) >= (int) ofre)
-                                       chksize(nc)
-                               need_to_add_thousands = true;
-                               break;
-                       case MP_FLOAT:
-                               sprintf(cp, "*.*R*%c", cs1);
-                               while ((nc = mpfr_snprintf(obufout, ofre, cpbuf,
-                                            (int) fw, (int) prec, ROUND_MODE, 
mf)) >= (int) ofre)
-                                       chksize(nc)
-                               break;
-#endif
-                       default:
-                               if (have_prec || tolower(cs1) != 'a') {
-                                       sprintf(cp, "*.*%c", cs1);
-                                       while ((nc = snprintf(obufout, ofre, 
cpbuf,
-                                                    (int) fw, (int) prec,
-                                                    (double) tmpval)) >= (int) 
ofre)
-                                               chksize(nc)
-                               } else {
-                                       // For %a and %A, use the default 
precision if it
-                                       // wasn't supplied by the user.
-                                       sprintf(cp, "*%c", cs1);
-                                       while ((nc = snprintf(obufout, ofre, 
cpbuf,
-                                                    (int) fw,
-                                                    (double) tmpval)) >= (int) 
ofre)
-                                               chksize(nc)
-                               }
-                       }
-
-#if defined(LC_NUMERIC)
-                       if (quote_flag && ! use_lc_numeric)
-                               setlocale(LC_NUMERIC, "C");
-#endif
-                       len = strlen(obufout);
-                       if (quote_flag && need_to_add_thousands) {
-                               const char *new_text = add_thousands(obufout/*, 
& loc*/);
-
-                               len = strlen(new_text);
-                               chksize(len)
-                               strcpy(obufout, new_text);
-                               free((void *) new_text);
-                       }
-
-                       ofre -= len;
-                       obufout += len;
-                       s0 = s1;
-                       break;
-               default:
-                       if (do_lint && is_alpha(cs1))
-                               lintwarn(_("ignoring unknown format specifier 
character `%c': no argument converted"), cs1);
-                       break;
-               }
-               if (toofew) {
-                       msg("%s\n\t`%s'\n\t%*s%s",
-                             _("fatal: not enough arguments to satisfy format 
string"),
-                             fmt_string, (int) (s1 - fmt_string - 1), "",
-                             _("^ ran out for this one"));
-                       goto out;
-               }
-       }
-       if (do_lint) {
-               if (need_format)
-                       lintwarn(
-                       _("[s]printf: format specifier does not have control 
letter"));
-               if (cur_arg < num_args)
-                       lintwarn(
-                       _("too many arguments supplied for format string"));
-       }
-       bchunk(s0, s1 - s0);
-       olen_final = obufout - obuf;
-#define GIVE_BACK_SIZE (INITIAL_OUT_SIZE * 2)
-       if (ofre > GIVE_BACK_SIZE)
-               erealloc(obuf, char *, olen_final + 1, "format_tree");
-       r = make_str_node(obuf, olen_final, ALREADY_MALLOCED);
-       obuf = NULL;
-out:
-       {
-               size_t k;
-               size_t count = sizeof(cpbufs)/sizeof(cpbufs[0]);
-               for (k = 0; k < count; k++) {
-                       if (cpbufs[k].buf != cpbufs[k].stackbuf)
-                               efree(cpbufs[k].buf);
-               }
-               if (obuf != NULL)
-                       efree(obuf);
-       }
-
-       if (r == NULL)
-               gawk_exit(EXIT_FATAL);
-       return r;
-}
-#undef bchunk
-#undef bchunk_one
-#undef chksize
+ *
+ * July 2024: Refactored into something manageable.
+ */
 
 NODE *
-format_tree_new(
+format_args(
        const char *fmt_string,
        size_t n0,
        NODE *the_args[],
@@ -1148,7 +121,7 @@ format_tree_new(
 #define bchunk(s, l) if (l) { \
        while ((l) > ofre) { \
                size_t olen = obufout - obuf; \
-               erealloc(obuf, char *, osiz * 2, "format_tree"); \
+               erealloc(obuf, char *, osiz * 2, "format_args"); \
                ofre += osiz; \
                osiz *= 2; \
                obufout = obuf + olen; \
@@ -1162,7 +135,7 @@ format_tree_new(
 #define bchunk_one(s) { \
        if (ofre < 1) { \
                size_t olen = obufout - obuf; \
-               erealloc(obuf, char *, osiz * 2, "format_tree"); \
+               erealloc(obuf, char *, osiz * 2, "format_args"); \
                ofre += osiz; \
                osiz *= 2; \
                obufout = obuf + olen; \
@@ -1175,7 +148,7 @@ format_tree_new(
 #define chksize(l)  if ((l) >= ofre) { \
        size_t olen = obufout - obuf; \
        size_t delta = osiz+l-ofre; \
-       erealloc(obuf, char *, osiz + delta, "format_tree"); \
+       erealloc(obuf, char *, osiz + delta, "format_args"); \
        obufout = obuf + olen; \
        ofre += delta; \
        osiz += delta; \
@@ -1183,11 +156,9 @@ format_tree_new(
 
        size_t cur_arg = 0;
        NODE *r = NULL;
-       int i, nc;
        bool toofew = false;
        char *obuf, *obufout;
        size_t osiz, ofre, olen_final;
-       const char *chbuf;
        const char *s0, *s1;
        int cs1;
        NODE *arg;
@@ -1196,7 +167,6 @@ format_tree_new(
        bool lj, alt, have_prec, need_format;
        long *cur = NULL;
        uintmax_t uval;
-       bool sgn;
        int base;
        bool space_flag;
        bool plus_flag;
@@ -1218,35 +188,24 @@ format_tree_new(
        char *cend = &cpbufs[0].stackbuf[sizeof(cpbufs[0].stackbuf)];
        char *cp;
        const char *fill;
-       AWKNUM tmpval = 0.0;
        char signchar = '\0';
        size_t len;
        bool zero_flag = false;
        bool quote_flag = false;
-       int ii, jj;
-       char *chp;
        size_t copy_count, char_count;
-       char *nan_inf_val;
        bool magic_posix_flag;
-#ifdef HAVE_MPFR
-       mpz_ptr zi;
-       mpfr_ptr mf;
-#endif
-       enum { MP_NONE = 0, MP_INT_WITH_PREC = 1, MP_INT_WITHOUT_PREC, MP_FLOAT 
} fmt_type;
        struct flags flags;
 
        static const char sp[] = " ";
-       static const char zero_string[] = "0";
-       static const char lchbuf[] = "0123456789abcdef";
-       static const char Uchbuf[] = "0123456789ABCDEF";
        static const char bad_modifiers[] = "DHhjLltwz";
        static bool warned[sizeof(bad_modifiers)-1];    // auto-init to zero
 
        bool modifier_seen[sizeof(bad_modifiers)-1];
 #define modifier_index(c)  (strchr(bad_modifiers, c) - bad_modifiers)
+       const char *formatted = NULL;
 
 #define INITIAL_OUT_SIZE       64
-       emalloc(obuf, char *, INITIAL_OUT_SIZE, "format_tree");
+       emalloc(obuf, char *, INITIAL_OUT_SIZE, "format_args");
        obufout = obuf;
        osiz = INITIAL_OUT_SIZE;
        ofre = osiz - 1;
@@ -1270,7 +229,7 @@ format_tree_new(
        if (cp == cpbufs[0].buf) {      \
                char *prev = cpbufs[0].buf;     \
                emalloc(cpbufs[0].buf, char *, 2*cpbufs[0].bufsize, \
-                       "format_tree"); \
+                       "format_args"); \
                memcpy((cp = cpbufs[0].buf+cpbufs[0].bufsize), prev,    \
                       cpbufs[0].bufsize);      \
                cpbufs[0].bufsize *= 2; \
@@ -1332,21 +291,14 @@ format_tree_new(
                signchar = '\0';
                zero_flag = false;
                quote_flag = false;
-               nan_inf_val = NULL;
                space_flag = false;
                plus_flag = false;
-#ifdef HAVE_MPFR
-               mf = NULL;
-               zi = NULL;
-#endif
-               fmt_type = MP_NONE;
 
                lj = alt = false;
                memset(modifier_seen, 0, sizeof(modifier_seen));
                magic_posix_flag = false;
                fill = sp;
                cp = cend;
-               chbuf = lchbuf;
                s1++;
                memset(& flags, 0, sizeof(flags));
 
@@ -1674,7 +626,33 @@ out0:
                                        prec = char_count;
                        }
                        cp = arg->stptr;
-                       goto pr_tail;
+       pr_tail:
+                       if (! lj) {
+                               while (fw > prec) {
+                                       bchunk_one(fill);
+                                       fw--;
+                               }
+                       }
+                       copy_count = prec;
+                       if (fw == 0 && ! have_prec)
+                               ;
+                       else if (gawk_mb_cur_max > 1) {
+                               if (cs1 == 's') {
+                                       assert(cp == arg->stptr || cp == cpbuf);
+                                       copy_count = mbc_byte_count(arg->stptr, 
prec);
+                               }
+                               /* prec was set by code for %c */
+                               /* else
+                                       copy_count = prec; */
+                       }
+                       bchunk(cp, copy_count);
+                       while (fw > prec) {
+                               bchunk_one(fill);
+                               fw--;
+                       }
+                       s0 = s1;
+                       break;
+
                case 'd':
                case 'i':
                        need_format = false;
@@ -1697,8 +675,8 @@ out0:
 
                        set_flags();
                        adjust_flags(& flags);
-                       {
-                       const char *formatted = format_signed_integer(arg, & 
flags);
+
+                       formatted = format_signed_integer(arg, & flags);
                        len = strlen(formatted);
                        chksize(len)
                        strcpy(obufout, formatted);
@@ -1708,125 +686,8 @@ out0:
                        obufout += len;
                        s0 = s1;
                        break;
-                       }
-
-                       /*
-                        * Check for Nan or Inf.
-                        */
-                       if (out_of_range(arg))
-                               goto out_of_range;
-#ifdef HAVE_MPFR
-                       if (is_mpg_float(arg))
-                               goto mpf0;
-                       else if (is_mpg_integer(arg))
-                               goto mpz0;
-                       else
-#endif
-                       tmpval = double_to_int(arg->numbr);
-
-                       /*
-                        * ``The result of converting a zero value with a
-                        * precision of zero is no characters.''
-                        */
-                       if (have_prec && prec == 0 && tmpval == 0)
-                               goto pr_tail;
-
-                       if (tmpval < 0) {
-                               tmpval = -tmpval;
-                               sgn = true;
-                       } else {
-                               if (tmpval == -0.0)
-                                       /* avoid printing -0 */
-                                       tmpval = 0.0;
-                               sgn = false;
-                       }
-                       /*
-                        * Use snprintf return value to tell if there
-                        * is enough room in the buffer or not.
-                        */
-                       while ((i = snprintf(cpbufs[1].buf,
-                                            cpbufs[1].bufsize, "%.0f",
-                                            tmpval)) >=
-                              cpbufs[1].bufsize) {
-                               if (cpbufs[1].buf == cpbufs[1].stackbuf)
-                                       cpbufs[1].buf = NULL;
-                               if (i > 0) {
-                                       cpbufs[1].bufsize += ((i > 
cpbufs[1].bufsize) ?
-                                                             i : 
cpbufs[1].bufsize);
-                               }
-                               else
-                                       cpbufs[1].bufsize *= 2;
-                               assert(cpbufs[1].bufsize > 0);
-                               erealloc(cpbufs[1].buf, char *,
-                                        cpbufs[1].bufsize, "format_tree");
-                       }
-                       if (i < 1)
-                               goto out_of_range;
-#if defined(HAVE_LOCALE_H)
-                       quote_flag = (quote_flag && loc.thousands_sep[0] != 0);
-#endif
-                       chp = &cpbufs[1].buf[i-1];
-                       ii = jj = 0;
-                       do {
-                               PREPEND(*chp);
-                               chp--; i--;
-#if defined(HAVE_LOCALE_H)
-                               if (quote_flag && loc.grouping[ii] && ++jj == 
loc.grouping[ii]) {
-                                       if (i) {        /* only add if more 
digits coming */
-                                               int k;
-                                               const char *ts = 
loc.thousands_sep;
-
-                                               for (k = strlen(ts) - 1; k >= 
0; k--) {
-                                                       PREPEND(ts[k]);
-                                               }
-                                       }
-                                       if (loc.grouping[ii+1] == 0)
-                                               jj = 0;         /* keep using 
current val in loc.grouping[ii] */
-                                       else if (loc.grouping[ii+1] == CHAR_MAX)
-                                               quote_flag = false;
-                                       else {
-                                               ii++;
-                                               jj = 0;
-                                       }
-                               }
-#endif
-                       } while (i > 0);
 
-                       /* add more output digits to match the precision */
-                       if (have_prec) {
-                               while (cend - cp < prec)
-                                       PREPEND('0');
-                       }
-
-                       if (sgn)
-                               PREPEND('-');
-                       else if (signchar)
-                               PREPEND(signchar);
-                       /*
-                        * When to fill with zeroes is of course not simple.
-                        * First: No zero fill if left-justifying.
-                        * Next: There seem to be two cases:
-                        *      A '0' without a precision, e.g. %06d
-                        *      A precision with no field width, e.g. %.10d
-                        * Any other case, we don't want to fill with zeroes.
-                        */
-                       if (! lj
-                           && ((zero_flag && ! have_prec)
-                                || (fw == 0 && have_prec)))
-                               fill = zero_string;
-                       if (prec > fw)
-                               fw = prec;
-                       prec = cend - cp;
-                       if (fw > prec && ! lj && fill != sp
-                           && (*cp == '-' || signchar)) {
-                               bchunk_one(cp);
-                               cp++;
-                               prec--;
-                               fw--;
-                       }
-                       goto pr_tail;
                case 'X':
-                       chbuf = Uchbuf; /* FALL THROUGH */
                case 'x':
                        base += 6;      /* FALL THROUGH */
                case 'u':
@@ -1839,8 +700,8 @@ out0:
 
                        set_flags();
                        adjust_flags(& flags);
-                       {
-                       const char *formatted = format_unsigned_integer(arg, & 
flags);
+
+                       formatted = format_unsigned_integer(arg, & flags);
                        len = strlen(formatted);
                        chksize(len)
                        strcpy(obufout, formatted);
@@ -1850,222 +711,6 @@ out0:
                        obufout += len;
                        s0 = s1;
                        break;
-                       }
-
-
-                       if (out_of_range(arg))
-                               goto out_of_range;
-#ifdef HAVE_MPFR
-                       if (is_mpg_integer(arg)) {
-mpz0:
-                               zi = arg->mpg_i;
-
-                               if (cs1 != 'd' && cs1 != '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 
'+' */
-                               }
-
-                               /* See comments above about when to fill with 
zeros */
-                               zero_flag = (! lj
-                                                   && ((zero_flag && ! 
have_prec)
-                                                        || (fw == 0 && 
have_prec)));
-
-                               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)) {
-                                       /* inf or NaN */
-                                       cs1 = 'g';
-                                       fmt_type = MP_FLOAT;
-                                       goto fmt1;
-                               }
-
-                               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)) {
-                                                       /* -ve number is too 
large */
-                                                       cs1 = 'g';
-                                                       fmt_type = MP_FLOAT;
-                                                       goto fmt1;
-                                               }
-
-                                               tmpval = uval = (uintmax_t) 
mpfr_get_sj(mf, ROUND_MODE);
-                                               if (! alt && have_prec && prec 
== 0 && tmpval == 0)
-                                                       goto pr_tail;   /* 
printf("%.0x", 0) is no characters */
-                                               goto int0;
-                                       }
-                                       signchar = '\0';        /* Don't print 
'+' */
-                               }
-
-                               /* 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
-#endif
-                               tmpval = arg->numbr;
-
-                       /*
-                        * ``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 (! alt && have_prec && prec == 0 && tmpval == 0)
-                               goto pr_tail;
-
-                       if (tmpval < 0) {
-                               uval = (uintmax_t) (intmax_t) tmpval;
-                               if ((AWKNUM)(intmax_t)uval != 
double_to_int(tmpval))
-                                       goto out_of_range;
-                       } else {
-                               uval = (uintmax_t) tmpval;
-                               if ((AWKNUM)uval != double_to_int(tmpval))
-                                       goto out_of_range;
-                       }
-#ifdef HAVE_MPFR
-       int0:
-#endif
-#if defined(HAVE_LOCALE_H)
-                       quote_flag = (quote_flag && loc.thousands_sep[0] != 0);
-#endif
-                       /*
-                        * When to fill with zeroes is of course not simple.
-                        * First: No zero fill if left-justifying.
-                        * Next: There seem to be two cases:
-                        *      A '0' without a precision, e.g. %06d
-                        *      A precision with no field width, e.g. %.10d
-                        * Any other case, we don't want to fill with zeroes.
-                        */
-                       if (! lj
-                           && ((zero_flag && ! have_prec)
-                                || (fw == 0 && have_prec)))
-                               fill = zero_string;
-                       ii = jj = 0;
-                       do {
-                               PREPEND(chbuf[uval % base]);
-                               uval /= base;
-#if defined(HAVE_LOCALE_H)
-                               if (base == 10 && quote_flag && 
loc.grouping[ii] && ++jj == loc.grouping[ii]) {
-                                       if (uval) {     /* only add if more 
digits coming */
-                                               int k;
-                                               const char *ts = 
loc.thousands_sep;
-
-                                               for (k = strlen(ts) - 1; k >= 
0; k--) {
-                                                       PREPEND(ts[k]);
-                                               }
-                                       }
-                                       if (loc.grouping[ii+1] == 0)
-                                               jj = 0;     /* keep using 
current val in loc.grouping[ii] */
-                                       else if (loc.grouping[ii+1] == CHAR_MAX)
-                                               quote_flag = false;
-                                       else {
-                                               ii++;
-                                               jj = 0;
-                                       }
-                               }
-#endif
-                       } while (uval > 0);
-
-                       /* add more output digits to match the precision */
-                       if (have_prec) {
-                               while (cend - cp < prec)
-                                       PREPEND('0');
-                       }
-
-                       if (alt && tmpval != 0) {
-                               if (base == 16) {
-                                       PREPEND(cs1);
-                                       PREPEND('0');
-                                       if (fill != sp) {
-                                               bchunk(cp, 2);
-                                               cp += 2;
-                                               fw -= 2;
-                                       }
-                               } else if (base == 8)
-                                       PREPEND('0');
-                       }
-                       base = 0;
-                       if (prec > fw)
-                               fw = prec;
-                       prec = cend - cp;
-       pr_tail:
-                       if (! lj) {
-                               while (fw > prec) {
-                                       bchunk_one(fill);
-                                       fw--;
-                               }
-                       }
-                       copy_count = prec;
-                       if (fw == 0 && ! have_prec)
-                               ;
-                       else if (gawk_mb_cur_max > 1) {
-                               if (cs1 == 's') {
-                                       assert(cp == arg->stptr || cp == cpbuf);
-                                       copy_count = mbc_byte_count(arg->stptr, 
prec);
-                               }
-                               /* prec was set by code for %c */
-                               /* else
-                                       copy_count = prec; */
-                       }
-                       bchunk(cp, copy_count);
-                       while (fw > prec) {
-                               bchunk_one(fill);
-                               fw--;
-                       }
-                       s0 = s1;
-                       break;
-
-     out_of_range:
-                       /*
-                        * out of range - emergency use of %g format,
-                        * or format NaN and INF values.
-                        */
-                       nan_inf_val = format_nan_inf(arg, cs1);
-                       if (do_posix || magic_posix_flag || nan_inf_val == 
NULL) {
-                               if (do_lint && ! do_posix && ! magic_posix_flag)
-                                       lintwarn(_("[s]printf: value %g is out 
of range for `%%%c' format"),
-                                                               (double) 
tmpval, cs1);
-                               tmpval = arg->numbr;
-                               if (strchr("aAeEfFgG", cs1) == NULL)
-                                       cs1 = 'g';
-                               goto fmt1;
-                       } else {
-                               if (do_lint)
-                                       lintwarn(_("[s]printf: value %s is out 
of range for `%%%c' format"),
-                                                               nan_inf_val, 
cs1);
-                               bchunk(nan_inf_val, strlen(nan_inf_val));
-                               s0 = s1;
-                               break;
-                       }
 
 #if defined(PRINTF_HAS_A_FORMAT) && PRINTF_HAS_A_FORMAT == 1
                case 'A':
@@ -2097,116 +742,13 @@ mpf1:
 
                        set_flags();
                        adjust_flags(& flags);
-                       {
-                       const char *formatted = format_float(arg, & flags);
+
+                       formatted = format_float(arg, & flags);
                        len = strlen(formatted);
                        chksize(len)
                        strcpy(obufout, formatted);
                        free((void *) formatted);
 
-                       ofre -= len;
-                       obufout += len;
-                       s0 = s1;
-                       break;
-                       }
-
-                       if (! is_mpg_number(arg))
-                               tmpval = arg->numbr;
-#ifdef HAVE_MPFR
-                       else if (is_mpg_float(arg)) {
-                               mf = arg->mpg_numbr;
-                               fmt_type = MP_FLOAT;
-                       } else {
-                               /* arbitrary-precision integer, convert to MPFR 
float */
-                               assert(mf == NULL);
-                               mf = mpz2mpfr(arg->mpg_i);
-                               fmt_type = MP_FLOAT;
-                       }
-#endif
-                       if (out_of_range(arg))
-                               goto out_of_range;
-
-     fmt1:
-                       if (! have_prec)
-                               prec = DEFAULT_G_PRECISION;
-#ifdef HAVE_MPFR
-     fmt0:
-#endif
-                       chksize(fw + prec + 11);        /* 11 == slop */
-                       cp = cpbuf;
-                       *cp++ = '%';
-                       if (lj)
-                               *cp++ = '-';
-                       if (signchar)
-                               *cp++ = signchar;
-                       if (alt)
-                               *cp++ = '#';
-                       if (zero_flag)
-                               *cp++ = '0';
-                       if (quote_flag)
-                               *cp++ = '\'';
-
-#if defined(LC_NUMERIC)
-                       if (quote_flag && ! use_lc_numeric)
-                               setlocale(LC_NUMERIC, "");
-#endif
-
-                       bool need_to_add_thousands = false;
-                       switch (fmt_type) {
-#ifdef HAVE_MPFR
-                       case MP_INT_WITH_PREC:
-                               sprintf(cp, "*.*Z%c", cs1);
-                               while ((nc = mpfr_snprintf(obufout, ofre, cpbuf,
-                                            (int) fw, (int) prec, zi)) >= 
(int) ofre)
-                                       chksize(nc)
-                               need_to_add_thousands = true;
-                               break;
-                       case MP_INT_WITHOUT_PREC:
-                               sprintf(cp, "*Z%c", cs1);
-                               while ((nc = mpfr_snprintf(obufout, ofre, cpbuf,
-                                            (int) fw, zi)) >= (int) ofre)
-                                       chksize(nc)
-                               need_to_add_thousands = true;
-                               break;
-                       case MP_FLOAT:
-                               sprintf(cp, "*.*R*%c", cs1);
-                               while ((nc = mpfr_snprintf(obufout, ofre, cpbuf,
-                                            (int) fw, (int) prec, ROUND_MODE, 
mf)) >= (int) ofre)
-                                       chksize(nc)
-                               break;
-#endif
-                       default:
-                               if (have_prec || tolower(cs1) != 'a') {
-                                       sprintf(cp, "*.*%c", cs1);
-                                       while ((nc = snprintf(obufout, ofre, 
cpbuf,
-                                                    (int) fw, (int) prec,
-                                                    (double) tmpval)) >= (int) 
ofre)
-                                               chksize(nc)
-                               } else {
-                                       // For %a and %A, use the default 
precision if it
-                                       // wasn't supplied by the user.
-                                       sprintf(cp, "*%c", cs1);
-                                       while ((nc = snprintf(obufout, ofre, 
cpbuf,
-                                                    (int) fw,
-                                                    (double) tmpval)) >= (int) 
ofre)
-                                               chksize(nc)
-                               }
-                       }
-
-#if defined(LC_NUMERIC)
-                       if (quote_flag && ! use_lc_numeric)
-                               setlocale(LC_NUMERIC, "C");
-#endif
-                       len = strlen(obufout);
-                       if (quote_flag && need_to_add_thousands) {
-                               const char *new_text = add_thousands(obufout);
-
-                               len = strlen(new_text);
-                               chksize(len)
-                               strcpy(obufout, new_text);
-                               free((void *) new_text);
-                       }
-
                        ofre -= len;
                        obufout += len;
                        s0 = s1;
@@ -2236,7 +778,7 @@ mpf1:
        olen_final = obufout - obuf;
 #define GIVE_BACK_SIZE (INITIAL_OUT_SIZE * 2)
        if (ofre > GIVE_BACK_SIZE)
-               erealloc(obuf, char *, olen_final + 1, "format_tree");
+               erealloc(obuf, char *, olen_final + 1, "format_args");
        r = make_str_node(obuf, olen_final, ALREADY_MALLOCED);
        obuf = NULL;
 out:
@@ -2278,7 +820,7 @@ printf_common(int nargs)
        args_array[0] = force_string(args_array[0]);
        if (do_lint && (fixtype(args_array[0])->flags & STRING) == 0)
                lintwarn(_("%s: received non-string format string argument"), 
"printf/sprintf");
-       r = format_tree(args_array[0]->stptr, args_array[0]->stlen, args_array, 
nargs);
+       r = format_args(args_array[0]->stptr, args_array[0]->stlen, args_array, 
nargs);
        for (i = 0; i < nargs; i++)
                DEREF(args_array[i]);
        return r;
@@ -2418,7 +960,7 @@ format_integer_digits(NODE *arg, struct flags *flags)
                        else
                                buflen *= 2;
                        assert(buflen > 0);
-                       erealloc(buf, char *, buflen, "format_tree");
+                       erealloc(buf, char *, buflen, "format_args");
                }
        } else {
                // octal or hex
@@ -2923,9 +1465,6 @@ format_mpg_integer_digits(NODE *arg, struct flags *flags, 
bool *used_float)
        mpfr_ptr mf;
        char *buf;
        size_t buflen;
-       double tmpval;
-       uintmax_t uval;
-       char *cp;
        char cpbuf[30];
        int nc;
        bool need_to_add_thousands = (strchr("diu", flags->format) != NULL);

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

Summary of changes:
 ChangeLog |    9 +
 awk.h     |    4 +-
 debug.c   |    2 +-
 main.c    |    7 -
 mpfr.c    |    6 +-
 node.c    |    6 +-
 printf.c  | 1555 ++-----------------------------------------------------------
 7 files changed, 64 insertions(+), 1525 deletions(-)


hooks/post-receive
-- 
gawk



reply via email to

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