Index: builtin.c =================================================================== RCS file: /cvsroot/xmlgawk/xmlgawk/builtin.c,v retrieving revision 1.6 diff -b -u -p -r1.6 builtin.c --- builtin.c 14 Nov 2005 15:27:24 -0000 1.6 +++ builtin.c 23 Dec 2005 20:56:35 -0000 @@ -575,8 +575,13 @@ format_tree( uintmax_t uval; int sgn; int base = 0; - char cpbuf[30]; /* if we have numbers bigger than 30 */ - char *cend = &cpbuf[30];/* chars, we lose, but seems unlikely */ + struct { + char *buf; + size_t bufsize; + char stackbuf[30]; + } cpbufs[1]; +#define cpbuf cpbufs[0].buf + char *cend = &cpbufs[0].stackbuf[sizeof(cpbufs[0].stackbuf)]; char *cp; const char *fill; AWKNUM tmpval; @@ -596,6 +601,29 @@ format_tree( osiz = INITIAL_OUT_SIZE; ofre = osiz - 1; + { + u_int k; + for (k = 0; k < sizeof(cpbufs)/sizeof(cpbufs[0]); k++) { + cpbufs[k].bufsize = sizeof(cpbufs[k].stackbuf); + cpbufs[k].buf = cpbufs[k].stackbuf; + } + } + +#define PREPEND(CH) { \ + 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) \ + free(prev); \ + cend = cpbufs[0].buf+cpbufs[0].bufsize; \ + } \ + *--cp = (CH); \ +} + /* * Icky problem. If the args make a nested call to printf/sprintf, * we end up clobbering the static variable `the_args'. Not good. @@ -950,10 +978,10 @@ check_pos: } ii = jj = 0; do { - *--cp = (char) ('0' + uval % 10); + PREPEND((char) ('0' + uval % 10)) #if ENABLE_NLS && defined(HAVE_LOCALE_H) if (quote_flag && loc.grouping[ii] && ++jj == loc.grouping[ii]) { - *--cp = loc.thousands_sep[0]; /* XXX - assumption it's one char */ + PREPEND(loc.thousands_sep[0]) /* XXX - assumption it's one char */ if (loc.grouping[ii+1] == 0) jj = 0; /* keep using current val in loc.grouping[ii] */ else if (loc.grouping[ii+1] == CHAR_MAX) @@ -970,13 +998,13 @@ check_pos: /* add more output digits to match the precision */ if (have_prec) { while (cend - cp < prec) - *--cp = '0'; + PREPEND('0') } if (sgn) - *--cp = '-'; + PREPEND('-') else if (signchar) - *--cp = signchar; + PREPEND(signchar) /* * When to fill with zeroes is of course not simple. * First: No zero fill if left-justifying. @@ -1052,10 +1080,10 @@ check_pos: ii = jj = 0; do { - *--cp = chbuf[uval % base]; + PREPEND(chbuf[uval % base]) #if ENABLE_NLS && defined(HAVE_LOCALE_H) if (base == 10 && quote_flag && loc.grouping[ii] && ++jj == loc.grouping[ii]) { - *--cp = loc.thousands_sep[0]; /* XXX --- assumption it's one char */ + PREPEND(loc.thousands_sep[0]) /* XXX --- assumption it's one char */ if (loc.grouping[ii+1] == 0) jj = 0; /* keep using current val in loc.grouping[ii] */ else if (loc.grouping[ii+1] == CHAR_MAX) @@ -1072,20 +1100,20 @@ check_pos: /* add more output digits to match the precision */ if (have_prec) { while (cend - cp < prec) - *--cp = '0'; + PREPEND('0') } if (alt && tmpval != 0) { if (base == 16) { - *--cp = cs1; - *--cp = '0'; + PREPEND(cs1) + PREPEND('0') if (fill != sp) { bchunk(cp, 2); cp += 2; fw -= 2; } } else if (base == 8) - *--cp = '0'; + PREPEND('0') } base = 0; if (prec > fw) @@ -1204,6 +1232,14 @@ check_pos: args_size = save_args_size; } + { + u_int k; + for (k = 0; k < sizeof(cpbufs)/sizeof(cpbufs[0]); k++) { + if (cpbufs[k].buf != cpbufs[k].stackbuf) + free(cpbufs[k].buf); + } + } + return r; }