1/*
2 * builtin.c - Builtin functions and various utility procedures
3 */
4
5/*
6 * Copyright (C) 1986, 1988, 1989, 1991-2003 the Free Software Foundation, Inc.
7 *
8 * This file is part of GAWK, the GNU implementation of the
9 * AWK Programming Language.
10 *
11 * GAWK is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * GAWK is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
24 */
25
26
27#include "awk.h"
28#if defined(HAVE_FCNTL_H)
29#include <fcntl.h>
30#endif
31#undef HUGE
32#undef CHARBITS
33#undef INTBITS
34#if HAVE_INTTYPES_H
35# include <inttypes.h>
36#else
37# if HAVE_STDINT_H
38#  include <stdint.h>
39# endif
40#endif
41#include <math.h>
42#include "random.h"
43
44#ifndef CHAR_BIT
45# define CHAR_BIT 8
46#endif
47
48/* The extra casts work around common compiler bugs.  */
49#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
50/* The outer cast is needed to work around a bug in Cray C 5.0.3.0.
51   It is necessary at least when t == time_t.  */
52#define TYPE_MINIMUM(t) ((t) (TYPE_SIGNED (t) \
53			      ? ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1) : (t) 0))
54#define TYPE_MAXIMUM(t) ((t) (~ (t) 0 - TYPE_MINIMUM (t)))
55
56#ifndef INTMAX_MIN
57# define INTMAX_MIN TYPE_MINIMUM (intmax_t)
58#endif
59#ifndef UINTMAX_MAX
60# define UINTMAX_MAX TYPE_MAXIMUM (uintmax_t)
61#endif
62
63#ifndef SIZE_MAX	/* C99 constant, can't rely on it everywhere */
64#define SIZE_MAX ((size_t) -1)
65#endif
66
67/* can declare these, since we always use the random shipped with gawk */
68extern char *initstate P((unsigned long seed, char *state, long n));
69extern char *setstate P((char *state));
70extern long random P((void));
71extern void srandom P((unsigned long seed));
72
73extern NODE **fields_arr;
74extern int output_is_tty;
75
76static NODE *sub_common P((NODE *tree, long how_many, int backdigs));
77
78#ifdef _CRAY
79/* Work around a problem in conversion of doubles to exact integers. */
80#include <float.h>
81#define Floor(n) floor((n) * (1.0 + DBL_EPSILON))
82#define Ceil(n) ceil((n) * (1.0 + DBL_EPSILON))
83
84/* Force the standard C compiler to use the library math functions. */
85extern double exp(double);
86double (*Exp)() = exp;
87#define exp(x) (*Exp)(x)
88extern double log(double);
89double (*Log)() = log;
90#define log(x) (*Log)(x)
91#else
92#define Floor(n) floor(n)
93#define Ceil(n) ceil(n)
94#endif
95
96#define DEFAULT_G_PRECISION 6
97
98#ifdef GFMT_WORKAROUND
99/* semi-temporary hack, mostly to gracefully handle VMS */
100static void sgfmt P((char *buf, const char *format, int alt,
101		     int fwidth, int precision, double value));
102#endif /* GFMT_WORKAROUND */
103
104/*
105 * Since we supply the version of random(), we know what
106 * value to use here.
107 */
108#define GAWK_RANDOM_MAX 0x7fffffffL
109
110static void efwrite P((const void *ptr, size_t size, size_t count, FILE *fp,
111		       const char *from, struct redirect *rp, int flush));
112
113/* efwrite --- like fwrite, but with error checking */
114
115static void
116efwrite(const void *ptr,
117	size_t size,
118	size_t count,
119	FILE *fp,
120	const char *from,
121	struct redirect *rp,
122	int flush)
123{
124	errno = 0;
125	if (fwrite(ptr, size, count, fp) != count)
126		goto wrerror;
127	if (flush
128	  && ((fp == stdout && output_is_tty)
129	   || (rp != NULL && (rp->flag & RED_NOBUF)))) {
130		fflush(fp);
131		if (ferror(fp))
132			goto wrerror;
133	}
134	return;
135
136wrerror:
137	fatal(_("%s to \"%s\" failed (%s)"), from,
138		rp ? rp->value : _("standard output"),
139		errno ? strerror(errno) : _("reason unknown"));
140}
141
142/* do_exp --- exponential function */
143
144NODE *
145do_exp(NODE *tree)
146{
147	NODE *tmp;
148	double d, res;
149
150	tmp = tree_eval(tree->lnode);
151	if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
152		lintwarn(_("exp: received non-numeric argument"));
153	d = force_number(tmp);
154	free_temp(tmp);
155	errno = 0;
156	res = exp(d);
157	if (errno == ERANGE)
158		warning(_("exp: argument %g is out of range"), d);
159	return tmp_number((AWKNUM) res);
160}
161
162/* stdfile --- return fp for a standard file */
163
164/*
165 * This function allows `fflush("/dev/stdout")' to work.
166 * The other files will be available via getredirect().
167 * /dev/stdin is not included, since fflush is only for output.
168 */
169
170static FILE *
171stdfile(const char *name, size_t len)
172{
173	if (len == 11) {
174		if (STREQN(name, "/dev/stderr", 11))
175			return stderr;
176		else if (STREQN(name, "/dev/stdout", 11))
177			return stdout;
178	}
179
180	return NULL;
181}
182
183/* do_fflush --- flush output, either named file or pipe or everything */
184
185NODE *
186do_fflush(NODE *tree)
187{
188	struct redirect *rp;
189	NODE *tmp;
190	FILE *fp;
191	int status = 0;
192	const char *file;
193
194	/* fflush() --- flush stdout */
195	if (tree == NULL) {
196		status = fflush(stdout);
197		return tmp_number((AWKNUM) status);
198	}
199
200	tmp = tree_eval(tree->lnode);
201	tmp = force_string(tmp);
202	file = tmp->stptr;
203
204	/* fflush("") --- flush all */
205	if (tmp->stlen == 0) {
206		status = flush_io();
207		free_temp(tmp);
208		return tmp_number((AWKNUM) status);
209	}
210
211	rp = getredirect(tmp->stptr, tmp->stlen);
212	status = -1;
213	if (rp != NULL) {
214		if ((rp->flag & (RED_WRITE|RED_APPEND)) == 0) {
215			if (rp->flag & RED_PIPE)
216				warning(_("fflush: cannot flush: pipe `%s' opened for reading, not writing"),
217					file);
218			else
219				warning(_("fflush: cannot flush: file `%s' opened for reading, not writing"),
220					file);
221			free_temp(tmp);
222			return tmp_number((AWKNUM) status);
223		}
224		fp = rp->fp;
225		if (fp != NULL)
226			status = fflush(fp);
227	} else if ((fp = stdfile(tmp->stptr, tmp->stlen)) != NULL) {
228		status = fflush(fp);
229	} else {
230		status = -1;
231		warning(_("fflush: `%s' is not an open file, pipe or co-process"), file);
232	}
233	free_temp(tmp);
234	return tmp_number((AWKNUM) status);
235}
236
237#ifdef MBS_SUPPORT
238/* strncasecmpmbs --- like strncasecmp(multibyte string version)  */
239int
240strncasecmpmbs(const char *s1, mbstate_t mbs1, const char *s2,
241			   mbstate_t mbs2, size_t n)
242{
243	int i1, i2, mbclen1, mbclen2, gap;
244	wchar_t wc1, wc2;
245	for (i1 = i2 = 0 ; i1 < n && i2 < n ;i1 += mbclen1, i2 += mbclen2) {
246		mbclen1 = mbrtowc(&wc1, s1 + i1, n - i1, &mbs1);
247		if (mbclen1 == (size_t) -1 || mbclen1 == (size_t) -2 || mbclen1 == 0) {
248			/* We treat it as a singlebyte character.  */
249			mbclen1 = 1;
250			wc1 = s1[i1];
251		}
252		mbclen2 = mbrtowc(&wc2, s2 + i2, n - i2, &mbs2);
253		if (mbclen2 == (size_t) -1 || mbclen2 == (size_t) -2 || mbclen2 == 0) {
254			/* We treat it as a singlebyte character.  */
255			mbclen2 = 1;
256			wc2 = s2[i2];
257		}
258		if ((gap = towlower(wc1) - towlower(wc2)) != 0)
259			/* s1 and s2 are not equivalent.  */
260			return gap;
261	}
262	/* s1 and s2 are equivalent.  */
263	return 0;
264}
265
266/* Inspect the buffer `src' and write the index of each byte to `dest'.
267   Caller must allocate `dest'.
268   e.g. str = <mb1(1)>, <mb1(2)>, a, b, <mb2(1)>, <mb2(2)>, <mb2(3)>, c
269        where mb(i) means the `i'-th byte of a multibyte character.
270		dest =       1,        2, 1, 1,        1,        2,        3. 1
271*/
272static void
273index_multibyte_buffer(char* src, char* dest, int len)
274{
275	int idx, prev_idx;
276	mbstate_t mbs, prevs;
277	memset(&prevs, 0, sizeof(mbstate_t));
278
279	for (idx = prev_idx = 0 ; idx < len ; idx++) {
280		size_t mbclen;
281		mbs = prevs;
282		mbclen = mbrlen(src + prev_idx, idx - prev_idx + 1, &mbs);
283		if (mbclen == (size_t) -1 || mbclen == 1 || mbclen == 0) {
284			/* singlebyte character.  */
285			mbclen = 1;
286			prev_idx = idx + 1;
287		} else if (mbclen == (size_t) -2) {
288			/* a part of a multibyte character.  */
289			mbclen = idx - prev_idx + 1;
290		} else if (mbclen > 1) {
291			/* the end of a multibyte character.  */
292			prev_idx = idx + 1;
293			prevs = mbs;
294		} else {
295			/* Can't reach.  */
296		}
297		dest[idx] = mbclen;
298    }
299}
300#endif
301
302/* do_index --- find index of a string */
303
304NODE *
305do_index(NODE *tree)
306{
307	NODE *s1, *s2;
308	register const char *p1, *p2;
309	register size_t l1, l2;
310	long ret;
311#ifdef MBS_SUPPORT
312	size_t mbclen = 0;
313	mbstate_t mbs1, mbs2;
314	if (gawk_mb_cur_max > 1) {
315		memset(&mbs1, 0, sizeof(mbstate_t));
316		memset(&mbs2, 0, sizeof(mbstate_t));
317	}
318#endif
319
320
321	s1 = tree_eval(tree->lnode);
322	s2 = tree_eval(tree->rnode->lnode);
323	if (do_lint) {
324		if ((s1->flags & (STRING|STRCUR)) == 0)
325			lintwarn(_("index: received non-string first argument"));
326		if ((s2->flags & (STRING|STRCUR)) == 0)
327			lintwarn(_("index: received non-string second argument"));
328	}
329	force_string(s1);
330	force_string(s2);
331	p1 = s1->stptr;
332	p2 = s2->stptr;
333	l1 = s1->stlen;
334	l2 = s2->stlen;
335	ret = 0;
336
337	/*
338	 * Icky special case, index(foo, "") should return 1,
339	 * since both bwk awk and mawk do, and since match("foo", "")
340	 * returns 1. This makes index("", "") work, too, fwiw.
341	 */
342	if (l2 == 0) {
343		ret = 1;
344		goto out;
345	}
346
347	/* IGNORECASE will already be false if posix */
348	if (IGNORECASE) {
349		while (l1 > 0) {
350			if (l2 > l1)
351				break;
352#ifdef MBS_SUPPORT
353			if (gawk_mb_cur_max > 1) {
354				if (strncasecmpmbs(p1, mbs1, p2, mbs2, l2) == 0) {
355					ret = 1 + s1->stlen - l1;
356					break;
357				}
358				/* Update l1, and p1.  */
359				mbclen = mbrlen(p1, l1, &mbs1);
360				if ((mbclen == 1) || (mbclen == (size_t) -1)
361					|| (mbclen == (size_t) -2) || (mbclen == 0)) {
362					/* We treat it as a singlebyte character.  */
363					mbclen = 1;
364				}
365				l1 -= mbclen;
366				p1 += mbclen;
367			} else {
368#endif
369			if (casetable[(unsigned char)*p1] == casetable[(unsigned char)*p2]
370			    && (l2 == 1 || strncasecmp(p1, p2, l2) == 0)) {
371				ret = 1 + s1->stlen - l1;
372				break;
373			}
374			l1--;
375			p1++;
376#ifdef MBS_SUPPORT
377			}
378#endif
379		}
380	} else {
381		while (l1 > 0) {
382			if (l2 > l1)
383				break;
384			if (*p1 == *p2
385			    && (l2 == 1 || STREQN(p1, p2, l2))) {
386				ret = 1 + s1->stlen - l1;
387				break;
388			}
389#ifdef MBS_SUPPORT
390			if (gawk_mb_cur_max > 1) {
391				mbclen = mbrlen(p1, l1, &mbs1);
392				if ((mbclen == 1) || (mbclen == (size_t) -1) ||
393					(mbclen == (size_t) -2) || (mbclen == 0)) {
394					/* We treat it as a singlebyte character.  */
395					mbclen = 1;
396				}
397				l1 -= mbclen;
398				p1 += mbclen;
399			} else {
400				l1--;
401				p1++;
402			}
403#else
404			l1--;
405			p1++;
406#endif
407		}
408	}
409out:
410	free_temp(s1);
411	free_temp(s2);
412	return tmp_number((AWKNUM) ret);
413}
414
415/* double_to_int --- convert double to int, used several places */
416
417double
418double_to_int(double d)
419{
420	if (d >= 0)
421		d = Floor(d);
422	else
423		d = Ceil(d);
424	return d;
425}
426
427/* do_int --- convert double to int for awk */
428
429NODE *
430do_int(NODE *tree)
431{
432	NODE *tmp;
433	double d;
434
435	tmp = tree_eval(tree->lnode);
436	if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
437		lintwarn(_("int: received non-numeric argument"));
438	d = force_number(tmp);
439	d = double_to_int(d);
440	free_temp(tmp);
441	return tmp_number((AWKNUM) d);
442}
443
444/* do_length --- length of a string or $0 */
445
446NODE *
447do_length(NODE *tree)
448{
449	NODE *tmp;
450	size_t len;
451
452	tmp = tree_eval(tree->lnode);
453	if (do_lint && (tmp->flags & (STRING|STRCUR)) == 0)
454		lintwarn(_("length: received non-string argument"));
455	len = force_string(tmp)->stlen;
456	free_temp(tmp);
457	return tmp_number((AWKNUM) len);
458}
459
460/* do_log --- the log function */
461
462NODE *
463do_log(NODE *tree)
464{
465	NODE *tmp;
466	double d, arg;
467
468	tmp = tree_eval(tree->lnode);
469	if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
470		lintwarn(_("log: received non-numeric argument"));
471	arg = (double) force_number(tmp);
472	if (arg < 0.0)
473		warning(_("log: received negative argument %g"), arg);
474	d = log(arg);
475	free_temp(tmp);
476	return tmp_number((AWKNUM) d);
477}
478
479/*
480 * format_tree() formats nodes of a tree, starting with a left node,
481 * and accordingly to a fmt_string providing a format like in
482 * printf family from C library.  Returns a string node which value
483 * is a formatted string.  Called by  sprintf function.
484 *
485 * It is one of the uglier parts of gawk.  Thanks to Michal Jaegermann
486 * for taming this beast and making it compatible with ANSI C.
487 */
488
489NODE *
490format_tree(
491	const char *fmt_string,
492	size_t n0,
493	register NODE *carg,
494	long num_args)
495{
496/* copy 'l' bytes from 's' to 'obufout' checking for space in the process */
497/* difference of pointers should be of ptrdiff_t type, but let us be kind */
498#define bchunk(s, l) if (l) { \
499	while ((l) > ofre) { \
500		long olen = obufout - obuf; \
501		erealloc(obuf, char *, osiz * 2, "format_tree"); \
502		ofre += osiz; \
503		osiz *= 2; \
504		obufout = obuf + olen; \
505	} \
506	memcpy(obufout, s, (size_t) (l)); \
507	obufout += (l); \
508	ofre -= (l); \
509}
510
511/* copy one byte from 's' to 'obufout' checking for space in the process */
512#define bchunk_one(s) { \
513	if (ofre < 1) { \
514		long olen = obufout - obuf; \
515		erealloc(obuf, char *, osiz * 2, "format_tree"); \
516		ofre += osiz; \
517		osiz *= 2; \
518		obufout = obuf + olen; \
519	} \
520	*obufout++ = *s; \
521	--ofre; \
522}
523
524/* Is there space for something L big in the buffer? */
525#define chksize(l)  if ((l) > ofre) { \
526	long olen = obufout - obuf; \
527	erealloc(obuf, char *, osiz * 2, "format_tree"); \
528	obufout = obuf + olen; \
529	ofre += osiz; \
530	osiz *= 2; \
531}
532
533	static NODE **the_args = 0;
534	static size_t args_size = 0;
535	size_t cur_arg = 0;
536
537	auto NODE **save_args = 0;
538	auto size_t save_args_size = 0;
539	static int call_level = 0;
540
541	NODE *r;
542	int i;
543	int toofew = FALSE;
544	char *obuf, *obufout;
545	size_t osiz, ofre;
546	const char *chbuf;
547	const char *s0, *s1;
548	int cs1;
549	NODE *arg;
550	long fw, prec, argnum;
551	int used_dollar;
552	int lj, alt, big, bigbig, small, have_prec, need_format;
553	long *cur = NULL;
554#ifdef sun386		/* Can't cast unsigned (int/long) from ptr->value */
555	long tmp_uval;	/* on 386i 4.0.1 C compiler -- it just hangs */
556#endif
557	uintmax_t uval;
558	int sgn;
559	int base = 0;
560	char cpbuf[30];		/* if we have numbers bigger than 30 */
561	char *cend = &cpbuf[30];/* chars, we lose, but seems unlikely */
562	char *cp;
563	const char *fill;
564	double tmpval;
565	char signchar = FALSE;
566	size_t len;
567	int zero_flag = FALSE;
568	static const char sp[] = " ";
569	static const char zero_string[] = "0";
570	static const char lchbuf[] = "0123456789abcdef";
571	static const char Uchbuf[] = "0123456789ABCDEF";
572
573#define INITIAL_OUT_SIZE	512
574	emalloc(obuf, char *, INITIAL_OUT_SIZE, "format_tree");
575	obufout = obuf;
576	osiz = INITIAL_OUT_SIZE;
577	ofre = osiz - 1;
578
579	/*
580	 * Icky problem.  If the args make a nested call to printf/sprintf,
581	 * we end up clobbering the static variable `the_args'.  Not good.
582	 * We don't just malloc and free the_args each time, since most of the
583	 * time there aren't nested calls.  But if this is a nested call,
584	 * save the memory pointed to by the_args and allocate a fresh
585	 * array.  Then free it on end.
586	 */
587	if (++call_level > 1) {	/* nested */
588		save_args = the_args;
589		save_args_size = args_size;
590
591		args_size = 0;	/* force fresh allocation */
592	}
593
594	if (args_size == 0) {
595		/* allocate array */
596		emalloc(the_args, NODE **, (num_args+1) * sizeof(NODE *), "format_tree");
597		args_size = num_args + 1;
598	} else if (num_args + 1 > args_size) {
599		/* grow it */
600		erealloc(the_args, NODE **, (num_args+1) * sizeof(NODE *), "format_tree");
601		args_size = num_args + 1;
602	}
603
604
605	/* fill it in */
606	/*
607	 * We ignore the_args[0] since format strings use
608	 * 1-based numbers to indicate the arguments.  It's
609	 * easiest to just convert to int and index, without
610	 * having to remember to subtract 1.
611	 */
612	memset(the_args, '\0', num_args * sizeof(NODE *));
613	for (i = 1; carg != NULL; i++, carg = carg->rnode) {
614		NODE *tmp;
615
616		/* Here lies the wumpus's other brother. R.I.P. */
617		tmp = tree_eval(carg->lnode);
618		the_args[i] = dupnode(tmp);
619		free_temp(tmp);
620	}
621	assert(i == num_args);
622	cur_arg = 1;
623
624	/*
625	 * Check first for use of `count$'.
626	 * If plain argument retrieval was used earlier, choke.
627	 *	Otherwise, return the requested argument.
628	 * If not `count$' now, but it was used earlier, choke.
629	 * If this format is more than total number of args, choke.
630	 * Otherwise, return the current argument.
631	 */
632#define parse_next_arg() { \
633	if (argnum > 0) { \
634		if (cur_arg > 1) \
635			fatal(_("must use `count$' on all formats or none")); \
636		arg = the_args[argnum]; \
637	} else if (used_dollar) { \
638		fatal(_("must use `count$' on all formats or none")); \
639		arg = 0; /* shutup the compiler */ \
640	} else if (cur_arg >= num_args) { \
641		arg = 0; /* shutup the compiler */ \
642		toofew = TRUE; \
643		break; \
644	} else { \
645		arg = the_args[cur_arg]; \
646		cur_arg++; \
647	} \
648}
649
650	need_format = FALSE;
651	used_dollar = FALSE;
652
653	s0 = s1 = fmt_string;
654	while (n0-- > 0) {
655		if (*s1 != '%') {
656			s1++;
657			continue;
658		}
659		need_format = TRUE;
660		bchunk(s0, s1 - s0);
661		s0 = s1;
662		cur = &fw;
663		fw = 0;
664		prec = 0;
665		argnum = 0;
666		have_prec = FALSE;
667		signchar = FALSE;
668		zero_flag = FALSE;
669		lj = alt = big = bigbig = small = FALSE;
670		fill = sp;
671		cp = cend;
672		chbuf = lchbuf;
673		s1++;
674
675retry:
676		if (n0-- == 0)	/* ran out early! */
677			break;
678
679		switch (cs1 = *s1++) {
680		case (-1):	/* dummy case to allow for checking */
681check_pos:
682			if (cur != &fw)
683				break;		/* reject as a valid format */
684			goto retry;
685		case '%':
686			need_format = FALSE;
687			/*
688			 * 29 Oct. 2002:
689			 * The C99 standard pages 274 and 279 seem to imply that
690			 * since there's no arg converted, the field width doesn't
691			 * apply.  The code already was that way, but this
692			 * comment documents it, at least in the code.
693			 */
694			bchunk_one("%");
695			s0 = s1;
696			break;
697
698		case '0':
699			/*
700			 * Only turn on zero_flag if we haven't seen
701			 * the field width or precision yet.  Otherwise,
702			 * screws up floating point formatting.
703			 */
704			if (cur == & fw)
705				zero_flag = TRUE;
706			if (lj)
707				goto retry;
708			/* FALL through */
709		case '1':
710		case '2':
711		case '3':
712		case '4':
713		case '5':
714		case '6':
715		case '7':
716		case '8':
717		case '9':
718			if (cur == NULL)
719				break;
720			if (prec >= 0)
721				*cur = cs1 - '0';
722			/*
723			 * with a negative precision *cur is already set
724			 * to -1, so it will remain negative, but we have
725			 * to "eat" precision digits in any case
726			 */
727			while (n0 > 0 && *s1 >= '0' && *s1 <= '9') {
728				--n0;
729				*cur = *cur * 10 + *s1++ - '0';
730			}
731			if (prec < 0) 	/* negative precision is discarded */
732				have_prec = FALSE;
733			if (cur == &prec)
734				cur = NULL;
735			if (n0 == 0)	/* badly formatted control string */
736				continue;
737			goto retry;
738		case '$':
739			if (do_traditional)
740				fatal(_("`$' is not permitted in awk formats"));
741			if (cur == &fw) {
742				argnum = fw;
743				fw = 0;
744				used_dollar = TRUE;
745				if (argnum <= 0)
746					fatal(_("arg count with `$' must be > 0"));
747				if (argnum >= num_args)
748					fatal(_("arg count %ld greater than total number of supplied arguments"), argnum);
749			} else
750				fatal(_("`$' not permitted after period in format"));
751			goto retry;
752		case '*':
753			if (cur == NULL)
754				break;
755			if (! do_traditional && ISDIGIT(*s1)) {
756				int val = 0;
757
758				for (; n0 > 0 && *s1 && ISDIGIT(*s1); s1++, n0--) {
759					val *= 10;
760					val += *s1 - '0';
761				}
762				if (*s1 != '$') {
763					fatal(_("no `$' supplied for positional field width or precision"));
764				} else {
765					s1++;
766					n0--;
767				}
768
769				arg = the_args[val];
770			} else {
771				parse_next_arg();
772			}
773			*cur = force_number(arg);
774			if (*cur < 0 && cur == &fw) {
775				*cur = -*cur;
776				lj++;
777			}
778			if (cur == &prec) {
779				if (*cur >= 0)
780					have_prec = TRUE;
781				else
782					have_prec = FALSE;
783				cur = NULL;
784			}
785			goto retry;
786		case ' ':		/* print ' ' or '-' */
787					/* 'space' flag is ignored */
788					/* if '+' already present  */
789			if (signchar != FALSE)
790				goto check_pos;
791			/* FALL THROUGH */
792		case '+':		/* print '+' or '-' */
793			signchar = cs1;
794			goto check_pos;
795		case '-':
796			if (prec < 0)
797				break;
798			if (cur == &prec) {
799				prec = -1;
800				goto retry;
801			}
802			fill = sp;      /* if left justified then other */
803			lj++; 		/* filling is ignored */
804			goto check_pos;
805		case '.':
806			if (cur != &fw)
807				break;
808			cur = &prec;
809			have_prec = TRUE;
810			goto retry;
811		case '#':
812			alt = TRUE;
813			goto check_pos;
814		case 'l':
815			if (big)
816				break;
817			else {
818				static int warned = FALSE;
819
820				if (do_lint && ! warned) {
821					lintwarn(_("`l' is meaningless in awk formats; ignored"));
822					warned = TRUE;
823				}
824				if (do_posix)
825					fatal(_("`l' is not permitted in POSIX awk formats"));
826			}
827			big = TRUE;
828			goto retry;
829		case 'L':
830			if (bigbig)
831				break;
832			else {
833				static int warned = FALSE;
834
835				if (do_lint && ! warned) {
836					lintwarn(_("`L' is meaningless in awk formats; ignored"));
837					warned = TRUE;
838				}
839				if (do_posix)
840					fatal(_("`L' is not permitted in POSIX awk formats"));
841			}
842			bigbig = TRUE;
843			goto retry;
844		case 'h':
845			if (small)
846				break;
847			else {
848				static int warned = FALSE;
849
850				if (do_lint && ! warned) {
851					lintwarn(_("`h' is meaningless in awk formats; ignored"));
852					warned = TRUE;
853				}
854				if (do_posix)
855					fatal(_("`h' is not permitted in POSIX awk formats"));
856			}
857			small = TRUE;
858			goto retry;
859		case 'c':
860			need_format = FALSE;
861			if (zero_flag && ! lj)
862				fill = zero_string;
863			parse_next_arg();
864			/* user input that looks numeric is numeric */
865			if ((arg->flags & (MAYBE_NUM|NUMBER)) == MAYBE_NUM)
866				(void) force_number(arg);
867			if (arg->flags & NUMBER) {
868#ifdef sun386
869				tmp_uval = arg->numbr;
870				uval = (unsigned long) tmp_uval;
871#else
872				uval = (uintmax_t) arg->numbr;
873#endif
874				cpbuf[0] = uval;
875				prec = 1;
876				cp = cpbuf;
877				goto pr_tail;
878			}
879			/*
880			 * As per POSIX, only output first character of a
881			 * string value.  Thus, we ignore any provided
882			 * precision, forcing it to 1.  (Didn't this
883			 * used to work? 6/2003.)
884			 */
885			prec = 1;
886			cp = arg->stptr;
887			goto pr_tail;
888		case 's':
889			need_format = FALSE;
890			if (zero_flag && ! lj)
891				fill = zero_string;
892			parse_next_arg();
893			arg = force_string(arg);
894			if (! have_prec || prec > arg->stlen)
895				prec = arg->stlen;
896			cp = arg->stptr;
897			goto pr_tail;
898		case 'd':
899		case 'i':
900			need_format = FALSE;
901			parse_next_arg();
902			tmpval = force_number(arg);
903
904			/*
905			 * ``The result of converting a zero value with a
906			 * precision of zero is no characters.''
907			 */
908			if (have_prec && prec == 0 && tmpval == 0)
909				goto pr_tail;
910
911			if (tmpval < 0) {
912				if (tmpval < INTMAX_MIN)
913					goto out_of_range;
914				sgn = TRUE;
915				uval = - (uintmax_t) (intmax_t) tmpval;
916			} else {
917				/* Use !, so that NaNs are out of range.  */
918				if (! (tmpval <= UINTMAX_MAX))
919					goto out_of_range;
920				sgn = FALSE;
921				uval = (uintmax_t) tmpval;
922			}
923			do {
924				*--cp = (char) ('0' + uval % 10);
925				uval /= 10;
926			} while (uval > 0);
927
928			/* add more output digits to match the precision */
929			if (have_prec) {
930				while (cend - cp < prec)
931					*--cp = '0';
932			}
933
934			if (sgn)
935				*--cp = '-';
936			else if (signchar)
937				*--cp = signchar;
938			/*
939			 * When to fill with zeroes is of course not simple.
940			 * First: No zero fill if left-justifying.
941			 * Next: There seem to be two cases:
942			 * 	A '0' without a precision, e.g. %06d
943			 * 	A precision with no field width, e.g. %.10d
944			 * Any other case, we don't want to fill with zeroes.
945			 */
946			if (! lj
947			    && ((zero_flag && ! have_prec)
948				 || (fw == 0 && have_prec)))
949				fill = zero_string;
950			if (prec > fw)
951				fw = prec;
952			prec = cend - cp;
953			if (fw > prec && ! lj && fill != sp
954			    && (*cp == '-' || signchar)) {
955				bchunk_one(cp);
956				cp++;
957				prec--;
958				fw--;
959			}
960			goto pr_tail;
961		case 'X':
962			chbuf = Uchbuf;	/* FALL THROUGH */
963		case 'x':
964			base += 6;	/* FALL THROUGH */
965		case 'u':
966			base += 2;	/* FALL THROUGH */
967		case 'o':
968			base += 8;
969			need_format = FALSE;
970			parse_next_arg();
971			tmpval = force_number(arg);
972
973			/*
974			 * ``The result of converting a zero value with a
975			 * precision of zero is no characters.''
976			 *
977			 * If I remember the ANSI C standard, though,
978			 * it says that for octal conversions
979			 * the precision is artificially increased
980			 * to add an extra 0 if # is supplied.
981			 * Indeed, in C,
982			 * 	printf("%#.0o\n", 0);
983			 * prints a single 0.
984			 */
985			if (! alt && have_prec && prec == 0 && tmpval == 0)
986				goto pr_tail;
987
988			if (tmpval < 0) {
989				if (tmpval < INTMAX_MIN)
990					goto out_of_range;
991				uval = (uintmax_t) (intmax_t) tmpval;
992			} else {
993				/* Use !, so that NaNs are out of range.  */
994				if (! (tmpval <= UINTMAX_MAX))
995					goto out_of_range;
996				uval = (uintmax_t) tmpval;
997			}
998			/*
999			 * When to fill with zeroes is of course not simple.
1000			 * First: No zero fill if left-justifying.
1001			 * Next: There seem to be two cases:
1002			 * 	A '0' without a precision, e.g. %06d
1003			 * 	A precision with no field width, e.g. %.10d
1004			 * Any other case, we don't want to fill with zeroes.
1005			 */
1006			if (! lj
1007			    && ((zero_flag && ! have_prec)
1008				 || (fw == 0 && have_prec)))
1009				fill = zero_string;
1010			do {
1011				*--cp = chbuf[uval % base];
1012				uval /= base;
1013			} while (uval > 0);
1014
1015			/* add more output digits to match the precision */
1016			if (have_prec) {
1017				while (cend - cp < prec)
1018					*--cp = '0';
1019			}
1020
1021			if (alt && tmpval != 0) {
1022				if (base == 16) {
1023					*--cp = cs1;
1024					*--cp = '0';
1025					if (fill != sp) {
1026						bchunk(cp, 2);
1027						cp += 2;
1028						fw -= 2;
1029					}
1030				} else if (base == 8)
1031					*--cp = '0';
1032			}
1033			base = 0;
1034			if (prec > fw)
1035				fw = prec;
1036			prec = cend - cp;
1037	pr_tail:
1038			if (! lj) {
1039				while (fw > prec) {
1040			    		bchunk_one(fill);
1041					fw--;
1042				}
1043			}
1044			bchunk(cp, (int) prec);
1045			while (fw > prec) {
1046				bchunk_one(fill);
1047				fw--;
1048			}
1049			s0 = s1;
1050			break;
1051
1052     out_of_range:
1053			/* out of range - emergency use of %g format */
1054			if (do_lint)
1055				lintwarn(_("[s]printf: value %g is out of range for `%%%c' format"),
1056							tmpval, cs1);
1057			cs1 = 'g';
1058			goto format_float;
1059
1060		case 'g':
1061		case 'G':
1062		case 'e':
1063		case 'f':
1064		case 'E':
1065			need_format = FALSE;
1066			parse_next_arg();
1067			tmpval = force_number(arg);
1068     format_float:
1069			if (! have_prec)
1070				prec = DEFAULT_G_PRECISION;
1071			chksize(fw + prec + 9);	/* 9 == slop */
1072
1073			cp = cpbuf;
1074			*cp++ = '%';
1075			if (lj)
1076				*cp++ = '-';
1077			if (signchar)
1078				*cp++ = signchar;
1079			if (alt)
1080				*cp++ = '#';
1081			if (zero_flag)
1082				*cp++ = '0';
1083			strcpy(cp, "*.*");
1084			cp += 3;
1085			*cp++ = cs1;
1086			*cp = '\0';
1087#ifndef GFMT_WORKAROUND
1088			(void) sprintf(obufout, cpbuf,
1089				       (int) fw, (int) prec, (double) tmpval);
1090#else	/* GFMT_WORKAROUND */
1091			if (cs1 == 'g' || cs1 == 'G')
1092				sgfmt(obufout, cpbuf, (int) alt,
1093				       (int) fw, (int) prec, (double) tmpval);
1094			else
1095				(void) sprintf(obufout, cpbuf,
1096				       (int) fw, (int) prec, (double) tmpval);
1097#endif	/* GFMT_WORKAROUND */
1098			len = strlen(obufout);
1099			ofre -= len;
1100			obufout += len;
1101			s0 = s1;
1102			break;
1103		default:
1104			break;
1105		}
1106		if (toofew)
1107			fatal("%s\n\t`%s'\n\t%*s%s",
1108			      _("not enough arguments to satisfy format string"),
1109			      fmt_string, (int) (s1 - fmt_string - 1), "",
1110			      _("^ ran out for this one"));
1111	}
1112	if (do_lint) {
1113		if (need_format)
1114			lintwarn(
1115			_("[s]printf: format specifier does not have control letter"));
1116		if (cur_arg < num_args)
1117			lintwarn(
1118			_("too many arguments supplied for format string"));
1119	}
1120	bchunk(s0, s1 - s0);
1121	r = make_str_node(obuf, obufout - obuf, ALREADY_MALLOCED);
1122	r->flags |= TEMP;
1123
1124	for (i = 1; i < num_args; i++) {
1125		unref(the_args[i]);
1126	}
1127
1128	if (call_level-- > 1) {
1129		free(the_args);
1130		the_args = save_args;
1131		args_size = save_args_size;
1132	}
1133
1134	return r;
1135}
1136
1137/* do_sprintf --- perform sprintf */
1138
1139NODE *
1140do_sprintf(NODE *tree)
1141{
1142	NODE *r;
1143	NODE *sfmt = force_string(tree_eval(tree->lnode));
1144
1145	r = format_tree(sfmt->stptr, sfmt->stlen, tree->rnode, tree->printf_count);
1146	free_temp(sfmt);
1147	return r;
1148}
1149
1150/*
1151 * redirect_to_fp --- return fp for redirection, NULL on failure
1152 * or stdout if no redirection, used by all print routines
1153 */
1154
1155static inline FILE *
1156redirect_to_fp(NODE *tree, struct redirect **rpp)
1157{
1158	int errflg;	/* not used, sigh */
1159	struct redirect *rp;
1160
1161	if (tree == NULL)
1162		return stdout;
1163
1164	rp = redirect(tree, &errflg);
1165	if (rp != NULL) {
1166		*rpp = rp;
1167		return  rp->fp;
1168	}
1169
1170	return NULL;
1171}
1172
1173/* do_printf --- perform printf, including redirection */
1174
1175void
1176do_printf(NODE *tree)
1177{
1178	struct redirect *rp = NULL;
1179	register FILE *fp;
1180
1181	if (tree->lnode == NULL) {
1182		if (do_traditional) {
1183			if (do_lint)
1184				lintwarn(_("printf: no arguments"));
1185			return;	/* bwk accepts it silently */
1186		}
1187		fatal(_("printf: no arguments"));
1188	}
1189
1190	fp = redirect_to_fp(tree->rnode, & rp);
1191	if (fp == NULL)
1192		return;
1193	tree->lnode->printf_count = tree->printf_count;
1194	tree = do_sprintf(tree->lnode);
1195	efwrite(tree->stptr, sizeof(char), tree->stlen, fp, "printf", rp, TRUE);
1196	if (rp != NULL && (rp->flag & RED_TWOWAY) != 0)
1197		fflush(rp->fp);
1198	free_temp(tree);
1199}
1200
1201/* do_sqrt --- do the sqrt function */
1202
1203NODE *
1204do_sqrt(NODE *tree)
1205{
1206	NODE *tmp;
1207	double arg;
1208
1209	tmp = tree_eval(tree->lnode);
1210	if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
1211		lintwarn(_("sqrt: received non-numeric argument"));
1212	arg = (double) force_number(tmp);
1213	free_temp(tmp);
1214	if (arg < 0.0)
1215		warning(_("sqrt: called with negative argument %g"), arg);
1216	return tmp_number((AWKNUM) sqrt(arg));
1217}
1218
1219/* do_substr --- do the substr function */
1220
1221NODE *
1222do_substr(NODE *tree)
1223{
1224	NODE *t1, *t2, *t3;
1225	NODE *r;
1226	register size_t indx;
1227	size_t length;
1228	double d_index, d_length;
1229
1230	t1 = force_string(tree_eval(tree->lnode));
1231	t2 = tree_eval(tree->rnode->lnode);
1232	d_index = force_number(t2);
1233	free_temp(t2);
1234
1235	/* the weird `! (foo)' tests help catch NaN values. */
1236	if (! (d_index >= 1)) {
1237		if (do_lint)
1238			lintwarn(_("substr: start index %g is invalid, using 1"),
1239				 d_index);
1240		d_index = 1;
1241	}
1242	if (do_lint && double_to_int(d_index) != d_index)
1243		lintwarn(_("substr: non-integer start index %g will be truncated"),
1244			 d_index);
1245
1246	/* awk indices are from 1, C's are from 0 */
1247	if (d_index <= SIZE_MAX)
1248		indx = d_index - 1;
1249	else
1250		indx = SIZE_MAX;
1251
1252	if (tree->rnode->rnode == NULL) {	/* third arg. missing */
1253		/* use remainder of string */
1254		length = t1->stlen - indx;
1255		d_length = length;	/* set here in case used in diagnostics, below */
1256	} else {
1257		t3 = tree_eval(tree->rnode->rnode->lnode);
1258		d_length = force_number(t3);
1259		free_temp(t3);
1260		if (! (d_length >= 1)) {
1261			if (do_lint == LINT_ALL)
1262				lintwarn(_("substr: length %g is not >= 1"), d_length);
1263			else if (do_lint == LINT_INVALID && ! (d_length >= 0))
1264				lintwarn(_("substr: length %g is not >= 0"), d_length);
1265			free_temp(t1);
1266			return Nnull_string;
1267		}
1268		if (do_lint) {
1269			if (double_to_int(d_length) != d_length)
1270				lintwarn(
1271			_("substr: non-integer length %g will be truncated"),
1272					d_length);
1273
1274			if (d_length > SIZE_MAX)
1275				lintwarn(
1276			_("substr: length %g too big for string indexing, truncating to %g"),
1277					d_length, (double) SIZE_MAX);
1278		}
1279		if (d_length < SIZE_MAX)
1280			length = d_length;
1281		else
1282			length = SIZE_MAX;
1283	}
1284
1285	if (t1->stlen == 0) {
1286		/* substr("", 1, 0) produces a warning only if LINT_ALL */
1287		if (do_lint && (do_lint == LINT_ALL || ((indx | length) != 0)))
1288			lintwarn(_("substr: source string is zero length"));
1289		free_temp(t1);
1290		return Nnull_string;
1291	}
1292	if (indx >= t1->stlen) {
1293		if (do_lint)
1294			lintwarn(_("substr: start index %g is past end of string"),
1295				d_index);
1296		free_temp(t1);
1297		return Nnull_string;
1298	}
1299	if (length > t1->stlen - indx) {
1300		if (do_lint)
1301			lintwarn(
1302	_("substr: length %g at start index %g exceeds length of first argument (%lu)"),
1303			d_length, d_index, (unsigned long int) t1->stlen);
1304		length = t1->stlen - indx;
1305	}
1306	r = tmp_string(t1->stptr + indx, length);
1307	free_temp(t1);
1308	return r;
1309}
1310
1311/* do_strftime --- format a time stamp */
1312
1313NODE *
1314do_strftime(NODE *tree)
1315{
1316	NODE *t1, *t2, *ret;
1317	struct tm *tm;
1318	time_t fclock;
1319	char *bufp;
1320	size_t buflen, bufsize;
1321	char buf[BUFSIZ];
1322	/* FIXME: One day make %d be %e, after C 99 is common. */
1323	static const char def_format[] = "%a %b %d %H:%M:%S %Z %Y";
1324	const char *format;
1325	int formatlen;
1326
1327	/* set defaults first */
1328	format = def_format;	/* traditional date format */
1329	formatlen = strlen(format);
1330	(void) time(&fclock);	/* current time of day */
1331
1332	t1 = t2 = NULL;
1333	if (tree != NULL) {	/* have args */
1334		if (tree->lnode != NULL) {
1335			NODE *tmp = tree_eval(tree->lnode);
1336			if (do_lint && (tmp->flags & (STRING|STRCUR)) == 0)
1337				lintwarn(_("strftime: received non-string first argument"));
1338			t1 = force_string(tmp);
1339			format = t1->stptr;
1340			formatlen = t1->stlen;
1341			if (formatlen == 0) {
1342				if (do_lint)
1343					lintwarn(_("strftime: received empty format string"));
1344				free_temp(t1);
1345				return tmp_string("", 0);
1346			}
1347		}
1348
1349		if (tree->rnode != NULL) {
1350			t2 = tree_eval(tree->rnode->lnode);
1351			if (do_lint && (t2->flags & (NUMCUR|NUMBER)) == 0)
1352				lintwarn(_("strftime: received non-numeric second argument"));
1353			fclock = (time_t) force_number(t2);
1354			free_temp(t2);
1355		}
1356	}
1357
1358	tm = localtime(&fclock);
1359
1360	bufp = buf;
1361	bufsize = sizeof(buf);
1362	for (;;) {
1363		*bufp = '\0';
1364		buflen = strftime(bufp, bufsize, format, tm);
1365		/*
1366		 * buflen can be zero EITHER because there's not enough
1367		 * room in the string, or because the control command
1368		 * goes to the empty string. Make a reasonable guess that
1369		 * if the buffer is 1024 times bigger than the length of the
1370		 * format string, it's not failing for lack of room.
1371		 * Thanks to Paul Eggert for pointing out this issue.
1372		 */
1373		if (buflen > 0 || bufsize >= 1024 * formatlen)
1374			break;
1375		bufsize *= 2;
1376		if (bufp == buf)
1377			emalloc(bufp, char *, bufsize, "do_strftime");
1378		else
1379			erealloc(bufp, char *, bufsize, "do_strftime");
1380	}
1381	ret = tmp_string(bufp, buflen);
1382	if (bufp != buf)
1383		free(bufp);
1384	if (t1)
1385		free_temp(t1);
1386	return ret;
1387}
1388
1389/* do_systime --- get the time of day */
1390
1391NODE *
1392do_systime(NODE *tree ATTRIBUTE_UNUSED)
1393{
1394	time_t lclock;
1395
1396	(void) time(&lclock);
1397	return tmp_number((AWKNUM) lclock);
1398}
1399
1400/* do_mktime --- turn a time string into a timestamp */
1401
1402NODE *
1403do_mktime(NODE *tree)
1404{
1405	NODE *t1;
1406	struct tm then;
1407	long year;
1408	int month, day, hour, minute, second, count;
1409	int dst = -1; /* default is unknown */
1410	time_t then_stamp;
1411	char save;
1412
1413	t1 = tree_eval(tree->lnode);
1414	if (do_lint && (t1->flags & (STRING|STRCUR)) == 0)
1415		lintwarn(_("mktime: received non-string argument"));
1416	t1 = force_string(t1);
1417
1418	save = t1->stptr[t1->stlen];
1419	t1->stptr[t1->stlen] = '\0';
1420
1421	count = sscanf(t1->stptr, "%ld %d %d %d %d %d %d",
1422		        & year, & month, & day,
1423			& hour, & minute, & second,
1424		        & dst);
1425
1426	t1->stptr[t1->stlen] = save;
1427	free_temp(t1);
1428
1429	if (count < 6
1430	    || month < month - 1
1431	    || year < year - 1900 || year - 1900 != (int) (year - 1900))
1432		return tmp_number((AWKNUM) -1);
1433
1434	memset(& then, '\0', sizeof(then));
1435	then.tm_sec = second;
1436	then.tm_min = minute;
1437	then.tm_hour = hour;
1438	then.tm_mday = day;
1439	then.tm_mon = month - 1;
1440	then.tm_year = year - 1900;
1441	then.tm_isdst = dst;
1442
1443	then_stamp = mktime(& then);
1444	return tmp_number((AWKNUM) then_stamp);
1445}
1446
1447/* do_system --- run an external command */
1448
1449NODE *
1450do_system(NODE *tree)
1451{
1452	NODE *tmp;
1453	int ret = 0;
1454	char *cmd;
1455	char save;
1456
1457	(void) flush_io();     /* so output is synchronous with gawk's */
1458	tmp = tree_eval(tree->lnode);
1459	if (do_lint && (tmp->flags & (STRING|STRCUR)) == 0)
1460		lintwarn(_("system: received non-string argument"));
1461	cmd = force_string(tmp)->stptr;
1462
1463	if (cmd && *cmd) {
1464		/* insure arg to system is zero-terminated */
1465
1466		/*
1467		 * From: David Trueman <david@cs.dal.ca>
1468		 * To: arnold@cc.gatech.edu (Arnold Robbins)
1469		 * Date: Wed, 3 Nov 1993 12:49:41 -0400
1470		 *
1471		 * It may not be necessary to save the character, but
1472		 * I'm not sure.  It would normally be the field
1473		 * separator.  If the parse has not yet gone beyond
1474		 * that, it could mess up (although I doubt it).  If
1475		 * FIELDWIDTHS is being used, it might be the first
1476		 * character of the next field.  Unless someone wants
1477		 * to check it out exhaustively, I suggest saving it
1478		 * for now...
1479		 */
1480		save = cmd[tmp->stlen];
1481		cmd[tmp->stlen] = '\0';
1482
1483		os_restore_mode(fileno(stdin));
1484		ret = system(cmd);
1485		if (ret != -1)
1486			ret = WEXITSTATUS(ret);
1487#ifdef O_BINARY
1488		if ((BINMODE & 1) != 0)
1489			os_setbinmode(fileno(stdin), O_BINARY);
1490#endif
1491		cmd[tmp->stlen] = save;
1492	}
1493	free_temp(tmp);
1494	return tmp_number((AWKNUM) ret);
1495}
1496
1497extern NODE **fmt_list;  /* declared in eval.c */
1498
1499/* do_print --- print items, separated by OFS, terminated with ORS */
1500
1501void
1502do_print(register NODE *tree)
1503{
1504	register NODE **t;
1505	struct redirect *rp = NULL;
1506	register FILE *fp;
1507	int numnodes, i;
1508	NODE *save;
1509	NODE *tval;
1510
1511	fp = redirect_to_fp(tree->rnode, & rp);
1512	if (fp == NULL)
1513		return;
1514
1515	/*
1516	 * General idea is to evaluate all the expressions first and
1517	 * then print them, otherwise you get suprising behavior.
1518	 * See test/prtoeval.awk for an example program.
1519	 */
1520	save = tree = tree->lnode;
1521	for (numnodes = 0; tree != NULL; tree = tree->rnode)
1522		numnodes++;
1523	emalloc(t, NODE **, numnodes * sizeof(NODE *), "do_print");
1524
1525	tree = save;
1526	for (i = 0; tree != NULL; i++, tree = tree->rnode) {
1527		NODE *n;
1528
1529		/* Here lies the wumpus. R.I.P. */
1530		n = tree_eval(tree->lnode);
1531		t[i] = dupnode(n);
1532		free_temp(n);
1533
1534		if ((t[i]->flags & (NUMBER|STRING)) == NUMBER) {
1535			if (OFMTidx == CONVFMTidx)
1536				(void) force_string(t[i]);
1537			else {
1538				tval = tmp_number(t[i]->numbr);
1539				unref(t[i]);
1540				t[i] = format_val(OFMT, OFMTidx, tval);
1541			}
1542		}
1543	}
1544
1545	for (i = 0; i < numnodes; i++) {
1546		efwrite(t[i]->stptr, sizeof(char), t[i]->stlen, fp, "print", rp, FALSE);
1547		unref(t[i]);
1548
1549		if (i != numnodes - 1 && OFSlen > 0)
1550			efwrite(OFS, sizeof(char), (size_t) OFSlen,
1551				fp, "print", rp, FALSE);
1552
1553	}
1554	if (ORSlen > 0)
1555		efwrite(ORS, sizeof(char), (size_t) ORSlen, fp, "print", rp, TRUE);
1556
1557	if (rp != NULL && (rp->flag & RED_TWOWAY) != 0)
1558		fflush(rp->fp);
1559
1560	free(t);
1561}
1562
1563/* do_print_rec --- special case printing of $0, for speed */
1564
1565void
1566do_print_rec(register NODE *tree)
1567{
1568	struct redirect *rp = NULL;
1569	register FILE *fp;
1570	register NODE *f0;
1571
1572	fp = redirect_to_fp(tree->rnode, & rp);
1573	if (fp == NULL)
1574		return;
1575
1576	if (! field0_valid)
1577		(void) get_field(0L, NULL);	/* rebuild record */
1578
1579	f0 = fields_arr[0];
1580
1581	if (do_lint && f0 == Nnull_string)
1582		lintwarn(_("reference to uninitialized field `$%d'"), 0);
1583
1584	efwrite(f0->stptr, sizeof(char), f0->stlen, fp, "print", rp, FALSE);
1585
1586	if (ORSlen > 0)
1587		efwrite(ORS, sizeof(char), (size_t) ORSlen, fp, "print", rp, TRUE);
1588
1589	if (rp != NULL && (rp->flag & RED_TWOWAY) != 0)
1590		fflush(rp->fp);
1591}
1592
1593/* do_tolower --- lower case a string */
1594
1595NODE *
1596do_tolower(NODE *tree)
1597{
1598	NODE *t1, *t2;
1599	register unsigned char *cp, *cp2;
1600#ifdef MBS_SUPPORT
1601	size_t mbclen = 0;
1602	mbstate_t mbs, prev_mbs;
1603	if (gawk_mb_cur_max > 1)
1604		memset(&mbs, 0, sizeof(mbstate_t));
1605#endif
1606
1607	t1 = tree_eval(tree->lnode);
1608	if (do_lint && (t1->flags & (STRING|STRCUR)) == 0)
1609		lintwarn(_("tolower: received non-string argument"));
1610	t1 = force_string(t1);
1611	t2 = tmp_string(t1->stptr, t1->stlen);
1612	for (cp = (unsigned char *)t2->stptr,
1613	     cp2 = (unsigned char *)(t2->stptr + t2->stlen); cp < cp2; cp++)
1614#ifdef MBS_SUPPORT
1615		if (gawk_mb_cur_max > 1) {
1616			wchar_t wc;
1617			prev_mbs = mbs;
1618			mbclen = (size_t) mbrtowc(&wc, (char *) cp, cp2 - cp,
1619						  &mbs);
1620			if ((mbclen != 1) && (mbclen != (size_t) -1) &&
1621				(mbclen != (size_t) -2) && (mbclen != 0)) {
1622				/* a multibyte character.  */
1623				if (iswupper(wc)) {
1624					wc = towlower(wc);
1625					wcrtomb((char *) cp, wc, &prev_mbs);
1626				}
1627				/* Adjust the pointer.  */
1628				cp += mbclen - 1;
1629			} else {
1630				/* Otherwise we treat it as a singlebyte character.  */
1631				if (ISUPPER(*cp))
1632					*cp = tolower(*cp);
1633			}
1634		} else
1635#endif
1636		if (ISUPPER(*cp))
1637			*cp = TOLOWER(*cp);
1638	free_temp(t1);
1639	return t2;
1640}
1641
1642/* do_toupper --- upper case a string */
1643
1644NODE *
1645do_toupper(NODE *tree)
1646{
1647	NODE *t1, *t2;
1648	register unsigned char *cp, *cp2;
1649#ifdef MBS_SUPPORT
1650	size_t mbclen = 0;
1651	mbstate_t mbs, prev_mbs;
1652	if (gawk_mb_cur_max > 1)
1653		memset(&mbs, 0, sizeof(mbstate_t));
1654#endif
1655
1656	t1 = tree_eval(tree->lnode);
1657	if (do_lint && (t1->flags & (STRING|STRCUR)) == 0)
1658		lintwarn(_("toupper: received non-string argument"));
1659	t1 = force_string(t1);
1660	t2 = tmp_string(t1->stptr, t1->stlen);
1661	for (cp = (unsigned char *)t2->stptr,
1662	     cp2 = (unsigned char *)(t2->stptr + t2->stlen); cp < cp2; cp++)
1663#ifdef MBS_SUPPORT
1664		if (gawk_mb_cur_max > 1) {
1665			wchar_t wc;
1666			prev_mbs = mbs;
1667			mbclen = (size_t) mbrtowc(&wc, (char *) cp, cp2 - cp,
1668						  &mbs);
1669			if ((mbclen != 1) && (mbclen != (size_t) -1) &&
1670				(mbclen != (size_t) -2) && (mbclen != 0)) {
1671				/* a multibyte character.  */
1672				if (iswlower(wc)) {
1673					wc = towupper(wc);
1674					wcrtomb((char *) cp, wc, &prev_mbs);
1675				}
1676				/* Adjust the pointer.  */
1677				cp += mbclen - 1;
1678			} else {
1679				/* Otherwise we treat it as a singlebyte character.  */
1680				if (ISLOWER(*cp))
1681					*cp = toupper(*cp);
1682			}
1683		} else
1684#endif
1685		if (ISLOWER(*cp))
1686			*cp = TOUPPER(*cp);
1687	free_temp(t1);
1688	return t2;
1689}
1690
1691/* do_atan2 --- do the atan2 function */
1692
1693NODE *
1694do_atan2(NODE *tree)
1695{
1696	NODE *t1, *t2;
1697	double d1, d2;
1698
1699	t1 = tree_eval(tree->lnode);
1700	t2 = tree_eval(tree->rnode->lnode);
1701	if (do_lint) {
1702		if ((t1->flags & (NUMCUR|NUMBER)) == 0)
1703			lintwarn(_("atan2: received non-numeric first argument"));
1704		if ((t2->flags & (NUMCUR|NUMBER)) == 0)
1705			lintwarn(_("atan2: received non-numeric second argument"));
1706	}
1707	d1 = force_number(t1);
1708	d2 = force_number(t2);
1709	free_temp(t1);
1710	free_temp(t2);
1711	return tmp_number((AWKNUM) atan2(d1, d2));
1712}
1713
1714/* do_sin --- do the sin function */
1715
1716NODE *
1717do_sin(NODE *tree)
1718{
1719	NODE *tmp;
1720	double d;
1721
1722	tmp = tree_eval(tree->lnode);
1723	if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
1724		lintwarn(_("sin: received non-numeric argument"));
1725	d = sin((double) force_number(tmp));
1726	free_temp(tmp);
1727	return tmp_number((AWKNUM) d);
1728}
1729
1730/* do_cos --- do the cos function */
1731
1732NODE *
1733do_cos(NODE *tree)
1734{
1735	NODE *tmp;
1736	double d;
1737
1738	tmp = tree_eval(tree->lnode);
1739	if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
1740		lintwarn(_("cos: received non-numeric argument"));
1741	d = cos((double) force_number(tmp));
1742	free_temp(tmp);
1743	return tmp_number((AWKNUM) d);
1744}
1745
1746/* do_rand --- do the rand function */
1747
1748static int firstrand = TRUE;
1749static char state[512];
1750
1751/* ARGSUSED */
1752NODE *
1753do_rand(NODE *tree ATTRIBUTE_UNUSED)
1754{
1755	if (firstrand) {
1756		(void) initstate((unsigned) 1, state, sizeof state);
1757		srandom(1);
1758		firstrand = FALSE;
1759	}
1760	/*
1761	 * Per historical practice and POSIX, return value N is
1762	 *
1763	 * 	0 <= n < 1
1764	 */
1765	return tmp_number((AWKNUM) (random() % GAWK_RANDOM_MAX) / GAWK_RANDOM_MAX);
1766}
1767
1768/* do_srand --- seed the random number generator */
1769
1770NODE *
1771do_srand(NODE *tree)
1772{
1773	NODE *tmp;
1774	static long save_seed = 1;
1775	long ret = save_seed;	/* SVR4 awk srand returns previous seed */
1776
1777	if (firstrand) {
1778		(void) initstate((unsigned) 1, state, sizeof state);
1779		/* don't need to srandom(1), we're changing the seed below */
1780		firstrand = FALSE;
1781	} else
1782		(void) setstate(state);
1783
1784	if (tree == NULL)
1785		srandom((unsigned int) (save_seed = (long) time((time_t *) 0)));
1786	else {
1787		tmp = tree_eval(tree->lnode);
1788		if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
1789			lintwarn(_("srand: received non-numeric argument"));
1790		srandom((unsigned int) (save_seed = (long) force_number(tmp)));
1791		free_temp(tmp);
1792	}
1793	return tmp_number((AWKNUM) ret);
1794}
1795
1796/* do_match --- match a regexp, set RSTART and RLENGTH,
1797 * 	optional third arg is array filled with text of
1798 * 	subpatterns enclosed in parens and start and len info.
1799 */
1800
1801NODE *
1802do_match(NODE *tree)
1803{
1804	NODE *t1, *dest, *it;
1805	int rstart, len, ii;
1806	AWKNUM rlength;
1807	Regexp *rp;
1808	regoff_t s;
1809	char *start;
1810	char *buf = NULL;
1811	char buff[100];
1812	size_t amt, oldamt = 0, ilen, slen;
1813	char *subsepstr;
1814	size_t subseplen;
1815
1816	t1 = force_string(tree_eval(tree->lnode));
1817	tree = tree->rnode;
1818	rp = re_update(tree->lnode);
1819
1820	dest = NULL;
1821	if (tree->rnode != NULL) {	/* 3rd optional arg for the subpatterns */
1822		dest = get_param(tree->rnode->lnode);
1823		if (dest->type != Node_var_array)
1824			fatal(_("match: third argument is not an array"));
1825
1826		assoc_clear(dest);
1827	}
1828
1829	rstart = research(rp, t1->stptr, 0, t1->stlen, TRUE);
1830	if (rstart >= 0) {	/* match succeded */
1831		rstart++;	/* 1-based indexing */
1832		rlength = REEND(rp, t1->stptr) - RESTART(rp, t1->stptr);
1833
1834		/* Build the array only if the caller wants the optional subpatterns */
1835		if (dest != NULL) {
1836			subsepstr = SUBSEP_node->var_value->stptr;
1837			subseplen = SUBSEP_node->var_value->stlen;
1838
1839			for (ii = 0; ii < NUMSUBPATS(rp, t1->stptr); ii++) {
1840				/*
1841				 * Loop over all the subpats; some of them may have
1842				 * matched even if all of them did not.
1843				 */
1844				if ((s = SUBPATSTART(rp, t1->stptr, ii)) != -1) {
1845					start = t1->stptr + s;
1846					len = SUBPATEND(rp, t1->stptr, ii) - s;
1847
1848					it = make_string(start, len);
1849					/*
1850					 * assoc_lookup() does free_temp() on 2nd arg.
1851					 */
1852					*assoc_lookup(dest, tmp_number((AWKNUM) (ii)), FALSE) = it;
1853
1854					sprintf(buff, "%d", ii);
1855					ilen = strlen(buff);
1856					amt = ilen + subseplen + strlen("length") + 2;
1857
1858					if (oldamt == 0) {
1859						emalloc(buf, char *, amt, "do_match");
1860					} else if (amt > oldamt) {
1861						erealloc(buf, char *, amt, "do_match");
1862					}
1863					oldamt = amt;
1864					memcpy(buf, buff, ilen);
1865					memcpy(buf + ilen, subsepstr, subseplen);
1866					memcpy(buf + ilen + subseplen, "start", 6);
1867
1868					slen = ilen + subseplen + 5;
1869
1870					it = make_number((AWKNUM) s + 1);
1871					*assoc_lookup(dest, tmp_string(buf, slen), FALSE) = it;
1872
1873					memcpy(buf, buff, ilen);
1874					memcpy(buf + ilen, subsepstr, subseplen);
1875					memcpy(buf + ilen + subseplen, "length", 7);
1876
1877					slen = ilen + subseplen + 6;
1878
1879					it = make_number((AWKNUM) len);
1880					*assoc_lookup(dest, tmp_string(buf, slen), FALSE) = it;
1881				}
1882			}
1883
1884			free(buf);
1885		}
1886	} else {		/* match failed */
1887		rstart = 0;
1888		rlength = -1.0;
1889	}
1890	free_temp(t1);
1891	unref(RSTART_node->var_value);
1892	RSTART_node->var_value = make_number((AWKNUM) rstart);
1893	unref(RLENGTH_node->var_value);
1894	RLENGTH_node->var_value = make_number(rlength);
1895	return tmp_number((AWKNUM) rstart);
1896}
1897
1898/* sub_common --- the common code (does the work) for sub, gsub, and gensub */
1899
1900/*
1901 * Gsub can be tricksy; particularly when handling the case of null strings.
1902 * The following awk code was useful in debugging problems.  It is too bad
1903 * that it does not readily translate directly into the C code, below.
1904 *
1905 * #! /usr/local/bin/mawk -f
1906 *
1907 * BEGIN {
1908 * 	TRUE = 1; FALSE = 0
1909 * 	print "--->", mygsub("abc", "b+", "FOO")
1910 * 	print "--->", mygsub("abc", "x*", "X")
1911 * 	print "--->", mygsub("abc", "b*", "X")
1912 * 	print "--->", mygsub("abc", "c", "X")
1913 * 	print "--->", mygsub("abc", "c+", "X")
1914 * 	print "--->", mygsub("abc", "x*$", "X")
1915 * }
1916 *
1917 * function mygsub(str, regex, replace,	origstr, newstr, eosflag, nonzeroflag)
1918 * {
1919 * 	origstr = str;
1920 * 	eosflag = nonzeroflag = FALSE
1921 * 	while (match(str, regex)) {
1922 * 		if (RLENGTH > 0) {	# easy case
1923 * 			nonzeroflag = TRUE
1924 * 			if (RSTART == 1) {	# match at front of string
1925 * 				newstr = newstr replace
1926 * 			} else {
1927 * 				newstr = newstr substr(str, 1, RSTART-1) replace
1928 * 			}
1929 * 			str = substr(str, RSTART+RLENGTH)
1930 * 		} else if (nonzeroflag) {
1931 * 			# last match was non-zero in length, and at the
1932 * 			# current character, we get a zero length match,
1933 * 			# which we don't really want, so skip over it
1934 * 			newstr = newstr substr(str, 1, 1)
1935 * 			str = substr(str, 2)
1936 * 			nonzeroflag = FALSE
1937 * 		} else {
1938 * 			# 0-length match
1939 * 			if (RSTART == 1) {
1940 * 				newstr = newstr replace substr(str, 1, 1)
1941 * 				str = substr(str, 2)
1942 * 			} else {
1943 * 				return newstr str replace
1944 * 			}
1945 * 		}
1946 * 		if (length(str) == 0)
1947 * 			if (eosflag)
1948 * 				break;
1949 * 			else
1950 * 				eosflag = TRUE
1951 * 	}
1952 * 	if (length(str) > 0)
1953 * 		newstr = newstr str	# rest of string
1954 *
1955 * 	return newstr
1956 * }
1957 */
1958
1959/*
1960 * NB: `howmany' conflicts with a SunOS 4.x macro in <sys/param.h>.
1961 */
1962
1963static NODE *
1964sub_common(NODE *tree, long how_many, int backdigs)
1965{
1966	register char *scan;
1967	register char *bp, *cp;
1968	char *buf;
1969	size_t buflen;
1970	register char *matchend;
1971	register size_t len;
1972	char *matchstart;
1973	char *text;
1974	size_t textlen;
1975	char *repl;
1976	char *replend;
1977	size_t repllen;
1978	int sofar;
1979	int ampersands;
1980	int matches = 0;
1981	Regexp *rp;
1982	NODE *s;		/* subst. pattern */
1983	NODE *t;		/* string to make sub. in; $0 if none given */
1984	NODE *tmp;
1985	NODE **lhs = &tree;	/* value not used -- just different from NULL */
1986	int priv = FALSE;
1987	Func_ptr after_assign = NULL;
1988
1989	int global = (how_many == -1);
1990	long current;
1991	int lastmatchnonzero;
1992#ifdef MBS_SUPPORT
1993	char *mb_indices;
1994#endif
1995
1996	tmp = tree->lnode;		/* regexp */
1997	rp = re_update(tmp);
1998
1999	tree = tree->rnode;		/* replacement text */
2000	s = tree->lnode;
2001	s = force_string(tree_eval(s));
2002
2003	tree = tree->rnode;		/* original string */
2004	tmp = tree->lnode;
2005	t = force_string(tree_eval(tmp));
2006
2007	/* do the search early to avoid work on non-match */
2008	if (research(rp, t->stptr, 0, t->stlen, TRUE) == -1 ||
2009	    RESTART(rp, t->stptr) > t->stlen) {
2010		free_temp(t);
2011		free_temp(s);
2012		return tmp_number((AWKNUM) 0.0);
2013	}
2014
2015	if (tmp->type == Node_val)
2016		lhs = NULL;
2017	else
2018		lhs = get_lhs(tmp, &after_assign, FALSE);
2019	t->flags |= STRING;
2020	/*
2021	 * create a private copy of the string
2022	 */
2023	if (t->stref > 1 || (t->flags & (PERM|FIELD)) != 0) {
2024		tmp = copynode(t);
2025		t = tmp;
2026		priv = TRUE;
2027	}
2028	text = t->stptr;
2029	textlen = t->stlen;
2030	buflen = textlen + 2;
2031
2032	repl = s->stptr;
2033	replend = repl + s->stlen;
2034	repllen = replend - repl;
2035	emalloc(buf, char *, buflen + 2, "sub_common");
2036	buf[buflen] = '\0';
2037	buf[buflen + 1] = '\0';
2038	ampersands = 0;
2039#ifdef MBS_SUPPORT
2040	/*
2041	 * Some systems' malloc() can't handle being called with an
2042	 * argument of zero.  Thus we have to have some special case
2043	 * code to check for `repllen == 0'.  This can occur for
2044	 * something like:
2045	 * 	sub(/foo/, "", mystring)
2046	 * for example.
2047	 */
2048	if (gawk_mb_cur_max > 1 && repllen > 0) {
2049		emalloc(mb_indices, char *, repllen * sizeof(char), "sub_common");
2050		index_multibyte_buffer(repl, mb_indices, repllen);
2051	} else
2052		mb_indices = NULL;
2053#endif
2054	for (scan = repl; scan < replend; scan++) {
2055#ifdef MBS_SUPPORT
2056		if ((gawk_mb_cur_max == 1 || (repllen > 0 && mb_indices[scan - repl] == 1))
2057			&& (*scan == '&')) {
2058#else
2059		if (*scan == '&') {
2060#endif
2061			repllen--;
2062			ampersands++;
2063		} else if (*scan == '\\') {
2064			if (backdigs) {	/* gensub, behave sanely */
2065				if (ISDIGIT(scan[1])) {
2066					ampersands++;
2067					scan++;
2068				} else {	/* \q for any q --> q */
2069					repllen--;
2070					scan++;
2071				}
2072			} else {	/* (proposed) posix '96 mode */
2073				if (strncmp(scan, "\\\\\\&", 4) == 0) {
2074					/* \\\& --> \& */
2075					repllen -= 2;
2076					scan += 3;
2077				} else if (strncmp(scan, "\\\\&", 3) == 0) {
2078					/* \\& --> \<string> */
2079					ampersands++;
2080					repllen--;
2081					scan += 2;
2082				} else if (scan[1] == '&') {
2083					/* \& --> & */
2084					repllen--;
2085					scan++;
2086				} /* else
2087					leave alone, it goes into the output */
2088			}
2089		}
2090	}
2091
2092	lastmatchnonzero = FALSE;
2093	bp = buf;
2094	for (current = 1;; current++) {
2095		matches++;
2096		matchstart = t->stptr + RESTART(rp, t->stptr);
2097		matchend = t->stptr + REEND(rp, t->stptr);
2098
2099		/*
2100		 * create the result, copying in parts of the original
2101		 * string
2102		 */
2103		len = matchstart - text + repllen
2104		      + ampersands * (matchend - matchstart);
2105		sofar = bp - buf;
2106		while (buflen < (sofar + len + 1)) {
2107			buflen *= 2;
2108			erealloc(buf, char *, buflen, "sub_common");
2109			bp = buf + sofar;
2110		}
2111		for (scan = text; scan < matchstart; scan++)
2112			*bp++ = *scan;
2113		if (global || current == how_many) {
2114			/*
2115			 * If the current match matched the null string,
2116			 * and the last match didn't and did a replacement,
2117			 * and the match of the null string is at the front of
2118			 * the text (meaning right after end of the previous
2119			 * replacement), then skip this one.
2120			 */
2121			if (matchstart == matchend
2122			    && lastmatchnonzero
2123			    && matchstart == text) {
2124				lastmatchnonzero = FALSE;
2125				matches--;
2126				goto empty;
2127			}
2128			/*
2129			 * If replacing all occurrences, or this is the
2130			 * match we want, copy in the replacement text,
2131			 * making substitutions as we go.
2132			 */
2133			for (scan = repl; scan < replend; scan++)
2134#ifdef MBS_SUPPORT
2135				if ((gawk_mb_cur_max == 1
2136					 || (repllen > 0 && mb_indices[scan - repl] == 1))
2137					&& (*scan == '&'))
2138#else
2139				if (*scan == '&')
2140#endif
2141					for (cp = matchstart; cp < matchend; cp++)
2142						*bp++ = *cp;
2143#ifdef MBS_SUPPORT
2144				else if ((gawk_mb_cur_max == 1
2145					 || (repllen > 0 && mb_indices[scan - repl] == 1))
2146						 && (*scan == '\\')) {
2147#else
2148				else if (*scan == '\\') {
2149#endif
2150					if (backdigs) {	/* gensub, behave sanely */
2151						if (ISDIGIT(scan[1])) {
2152							int dig = scan[1] - '0';
2153							char *start, *end;
2154
2155							start = t->stptr
2156							      + SUBPATSTART(rp, t->stptr, dig);
2157							end = t->stptr
2158							      + SUBPATEND(rp, t->stptr, dig);
2159
2160							for (cp = start; cp < end; cp++)
2161								*bp++ = *cp;
2162							scan++;
2163						} else	/* \q for any q --> q */
2164							*bp++ = *++scan;
2165					} else {	/* posix '96 mode, bleah */
2166						if (strncmp(scan, "\\\\\\&", 4) == 0) {
2167							/* \\\& --> \& */
2168							*bp++ = '\\';
2169							*bp++ = '&';
2170							scan += 3;
2171						} else if (strncmp(scan, "\\\\&", 3) == 0) {
2172							/* \\& --> \<string> */
2173							*bp++ = '\\';
2174							for (cp = matchstart; cp < matchend; cp++)
2175								*bp++ = *cp;
2176							scan += 2;
2177						} else if (scan[1] == '&') {
2178							/* \& --> & */
2179							*bp++ = '&';
2180							scan++;
2181						} else
2182							*bp++ = *scan;
2183					}
2184				} else
2185					*bp++ = *scan;
2186			if (matchstart != matchend)
2187				lastmatchnonzero = TRUE;
2188		} else {
2189			/*
2190			 * don't want this match, skip over it by copying
2191			 * in current text.
2192			 */
2193			for (cp = matchstart; cp < matchend; cp++)
2194				*bp++ = *cp;
2195		}
2196	empty:
2197		/* catch the case of gsub(//, "blah", whatever), i.e. empty regexp */
2198		if (matchstart == matchend && matchend < text + textlen) {
2199			*bp++ = *matchend;
2200			matchend++;
2201		}
2202		textlen = text + textlen - matchend;
2203		text = matchend;
2204
2205		if ((current >= how_many && !global)
2206		    || ((long) textlen <= 0 && matchstart == matchend)
2207		    || research(rp, t->stptr, text - t->stptr, textlen, TRUE) == -1)
2208			break;
2209
2210	}
2211	sofar = bp - buf;
2212	if (buflen - sofar - textlen - 1) {
2213		buflen = sofar + textlen + 2;
2214		erealloc(buf, char *, buflen, "sub_common");
2215		bp = buf + sofar;
2216	}
2217	for (scan = matchend; scan < text + textlen; scan++)
2218		*bp++ = *scan;
2219	*bp = '\0';
2220	textlen = bp - buf;
2221	free(t->stptr);
2222	t->stptr = buf;
2223	t->stlen = textlen;
2224
2225	free_temp(s);
2226	if (matches > 0 && lhs) {
2227		if (priv) {
2228			unref(*lhs);
2229			*lhs = t;
2230		}
2231		if (after_assign != NULL)
2232			(*after_assign)();
2233		t->flags &= ~(NUMCUR|NUMBER);
2234	}
2235#ifdef MBS_SUPPORT
2236	if (mb_indices != NULL)
2237		free(mb_indices);
2238#endif
2239	return tmp_number((AWKNUM) matches);
2240}
2241
2242/* do_gsub --- global substitution */
2243
2244NODE *
2245do_gsub(NODE *tree)
2246{
2247	return sub_common(tree, -1, FALSE);
2248}
2249
2250/* do_sub --- single substitution */
2251
2252NODE *
2253do_sub(NODE *tree)
2254{
2255	return sub_common(tree, 1, FALSE);
2256}
2257
2258/* do_gensub --- fix up the tree for sub_common for the gensub function */
2259
2260NODE *
2261do_gensub(NODE *tree)
2262{
2263	NODE n1, n2, n3, *t, *tmp, *target, *ret;
2264	long how_many = 1;	/* default is one substitution */
2265	double d;
2266
2267	/*
2268	 * We have to pull out the value of the global flag, and
2269	 * build up a tree without the flag in it, turning it into the
2270	 * kind of tree that sub_common() expects.  It helps to draw
2271	 * a picture of this ...
2272	 */
2273	n1 = *tree;
2274	n2 = *(tree->rnode);
2275	n1.rnode = & n2;
2276
2277	t = tree_eval(n2.rnode->lnode);	/* value of global flag */
2278
2279	tmp = force_string(tree_eval(n2.rnode->rnode->lnode));	/* target */
2280
2281	/*
2282	 * We make copy of the original target string, and pass that
2283	 * in to sub_common() as the target to make the substitution in.
2284	 * We will then return the result string as the return value of
2285	 * this function.
2286	 */
2287	target = make_string(tmp->stptr, tmp->stlen);
2288	free_temp(tmp);
2289
2290	n3 = *(n2.rnode->rnode);
2291	n3.lnode = target;
2292	n2.rnode = & n3;
2293
2294	if ((t->flags & (STRCUR|STRING)) != 0) {
2295		if (t->stlen > 0 && (t->stptr[0] == 'g' || t->stptr[0] == 'G'))
2296			how_many = -1;
2297		else
2298			how_many = 1;
2299	} else {
2300		d = force_number(t);
2301		if (d < 1)
2302			how_many = 1;
2303		else if (d < LONG_MAX)
2304			how_many = d;
2305		else
2306			how_many = LONG_MAX;
2307		if (d == 0)
2308			warning(_("gensub: third argument of 0 treated as 1"));
2309	}
2310
2311	free_temp(t);
2312
2313	ret = sub_common(&n1, how_many, TRUE);
2314	free_temp(ret);
2315
2316	/*
2317	 * Note that we don't care what sub_common() returns, since the
2318	 * easiest thing for the programmer is to return the string, even
2319	 * if no substitutions were done.
2320	 */
2321	target->flags |= TEMP;
2322	return target;
2323}
2324
2325#ifdef GFMT_WORKAROUND
2326/*
2327 * printf's %g format [can't rely on gcvt()]
2328 *	caveat: don't use as argument to *printf()!
2329 * 'format' string HAS to be of "<flags>*.*g" kind, or we bomb!
2330 */
2331static void
2332sgfmt(char *buf,	/* return buffer; assumed big enough to hold result */
2333	const char *format,
2334	int alt,	/* use alternate form flag */
2335	int fwidth,	/* field width in a format */
2336	int prec,	/* indicates desired significant digits, not decimal places */
2337	double g)	/* value to format */
2338{
2339	char dform[40];
2340	register char *gpos;
2341	register char *d, *e, *p;
2342	int again = FALSE;
2343
2344	strncpy(dform, format, sizeof dform - 1);
2345	dform[sizeof dform - 1] = '\0';
2346	gpos = strrchr(dform, '.');
2347
2348	if (g == 0.0 && ! alt) {	/* easy special case */
2349		*gpos++ = 'd';
2350		*gpos = '\0';
2351		(void) sprintf(buf, dform, fwidth, 0);
2352		return;
2353	}
2354
2355	/* advance to location of 'g' in the format */
2356	while (*gpos && *gpos != 'g' && *gpos != 'G')
2357		gpos++;
2358
2359	if (prec <= 0)	      /* negative precision is ignored */
2360		prec = (prec < 0 ?  DEFAULT_G_PRECISION : 1);
2361
2362	if (*gpos == 'G')
2363		again = TRUE;
2364	/* start with 'e' format (it'll provide nice exponent) */
2365	*gpos = 'e';
2366	prec--;
2367	(void) sprintf(buf, dform, fwidth, prec, g);
2368	if ((e = strrchr(buf, 'e')) != NULL) {	/* find exponent  */
2369		int expn = atoi(e+1);		/* fetch exponent */
2370		if (expn >= -4 && expn <= prec) {	/* per K&R2, B1.2 */
2371			/* switch to 'f' format and re-do */
2372			*gpos = 'f';
2373			prec -= expn;		/* decimal precision */
2374			(void) sprintf(buf, dform, fwidth, prec, g);
2375			e = buf + strlen(buf);
2376			while (*--e == ' ')
2377				continue;
2378			e++;
2379		}
2380		else if (again)
2381			*gpos = 'E';
2382
2383		/* if 'alt' in force, then trailing zeros are not removed */
2384		if (! alt && (d = strrchr(buf, '.')) != NULL) {
2385			/* throw away an excess of precision */
2386			for (p = e; p > d && *--p == '0'; )
2387				prec--;
2388			if (d == p)
2389				prec--;
2390			if (prec < 0)
2391				prec = 0;
2392			/* and do that once again */
2393			again = TRUE;
2394		}
2395		if (again)
2396			(void) sprintf(buf, dform, fwidth, prec, g);
2397	}
2398}
2399#endif	/* GFMT_WORKAROUND */
2400
2401/* do_lshift --- perform a << operation */
2402
2403NODE *
2404do_lshift(NODE *tree)
2405{
2406	NODE *s1, *s2;
2407	uintmax_t uval, ushift, res;
2408	AWKNUM val, shift;
2409
2410	s1 = tree_eval(tree->lnode);
2411	s2 = tree_eval(tree->rnode->lnode);
2412	val = force_number(s1);
2413	shift = force_number(s2);
2414
2415	if (do_lint) {
2416		if ((s1->flags & (NUMCUR|NUMBER)) == 0)
2417			lintwarn(_("lshift: received non-numeric first argument"));
2418		if ((s2->flags & (NUMCUR|NUMBER)) == 0)
2419			lintwarn(_("lshift: received non-numeric first argument"));
2420		if (val < 0 || shift < 0)
2421			lintwarn(_("lshift(%lf, %lf): negative values will give strange results"), val, shift);
2422		if (double_to_int(val) != val || double_to_int(shift) != shift)
2423			lintwarn(_("lshift(%lf, %lf): fractional values will be truncated"), val, shift);
2424		if (shift >= sizeof(uintmax_t) * CHAR_BIT)
2425			lintwarn(_("lshift(%lf, %lf): too large shift value will give strange results"), val, shift);
2426	}
2427
2428	free_temp(s1);
2429	free_temp(s2);
2430
2431	uval = (uintmax_t) val;
2432	ushift = (uintmax_t) shift;
2433
2434	res = uval << ushift;
2435	return tmp_number((AWKNUM) res);
2436}
2437
2438/* do_rshift --- perform a >> operation */
2439
2440NODE *
2441do_rshift(NODE *tree)
2442{
2443	NODE *s1, *s2;
2444	uintmax_t uval, ushift, res;
2445	AWKNUM val, shift;
2446
2447	s1 = tree_eval(tree->lnode);
2448	s2 = tree_eval(tree->rnode->lnode);
2449	val = force_number(s1);
2450	shift = force_number(s2);
2451
2452	if (do_lint) {
2453		if ((s1->flags & (NUMCUR|NUMBER)) == 0)
2454			lintwarn(_("rshift: received non-numeric first argument"));
2455		if ((s2->flags & (NUMCUR|NUMBER)) == 0)
2456			lintwarn(_("rshift: received non-numeric first argument"));
2457		if (val < 0 || shift < 0)
2458			lintwarn(_("rshift(%lf, %lf): negative values will give strange results"), val, shift);
2459		if (double_to_int(val) != val || double_to_int(shift) != shift)
2460			lintwarn(_("rshift(%lf, %lf): fractional values will be truncated"), val, shift);
2461		if (shift >= sizeof(uintmax_t) * CHAR_BIT)
2462			lintwarn(_("rshift(%lf, %lf): too large shift value will give strange results"), val, shift);
2463	}
2464
2465	free_temp(s1);
2466	free_temp(s2);
2467
2468	uval = (uintmax_t) val;
2469	ushift = (uintmax_t) shift;
2470
2471	res = uval >> ushift;
2472	return tmp_number((AWKNUM) res);
2473}
2474
2475/* do_and --- perform an & operation */
2476
2477NODE *
2478do_and(NODE *tree)
2479{
2480	NODE *s1, *s2;
2481	uintmax_t uleft, uright, res;
2482	AWKNUM left, right;
2483
2484	s1 = tree_eval(tree->lnode);
2485	s2 = tree_eval(tree->rnode->lnode);
2486	left = force_number(s1);
2487	right = force_number(s2);
2488
2489	if (do_lint) {
2490		if ((s1->flags & (NUMCUR|NUMBER)) == 0)
2491			lintwarn(_("and: received non-numeric first argument"));
2492		if ((s2->flags & (NUMCUR|NUMBER)) == 0)
2493			lintwarn(_("and: received non-numeric first argument"));
2494		if (left < 0 || right < 0)
2495			lintwarn(_("and(%lf, %lf): negative values will give strange results"), left, right);
2496		if (double_to_int(left) != left || double_to_int(right) != right)
2497			lintwarn(_("and(%lf, %lf): fractional values will be truncated"), left, right);
2498	}
2499
2500	free_temp(s1);
2501	free_temp(s2);
2502
2503	uleft = (uintmax_t) left;
2504	uright = (uintmax_t) right;
2505
2506	res = uleft & uright;
2507	return tmp_number((AWKNUM) res);
2508}
2509
2510/* do_or --- perform an | operation */
2511
2512NODE *
2513do_or(NODE *tree)
2514{
2515	NODE *s1, *s2;
2516	uintmax_t uleft, uright, res;
2517	AWKNUM left, right;
2518
2519	s1 = tree_eval(tree->lnode);
2520	s2 = tree_eval(tree->rnode->lnode);
2521	left = force_number(s1);
2522	right = force_number(s2);
2523
2524	if (do_lint) {
2525		if ((s1->flags & (NUMCUR|NUMBER)) == 0)
2526			lintwarn(_("or: received non-numeric first argument"));
2527		if ((s2->flags & (NUMCUR|NUMBER)) == 0)
2528			lintwarn(_("or: received non-numeric first argument"));
2529		if (left < 0 || right < 0)
2530			lintwarn(_("or(%lf, %lf): negative values will give strange results"), left, right);
2531		if (double_to_int(left) != left || double_to_int(right) != right)
2532			lintwarn(_("or(%lf, %lf): fractional values will be truncated"), left, right);
2533	}
2534
2535	free_temp(s1);
2536	free_temp(s2);
2537
2538	uleft = (uintmax_t) left;
2539	uright = (uintmax_t) right;
2540
2541	res = uleft | uright;
2542	return tmp_number((AWKNUM) res);
2543}
2544
2545/* do_xor --- perform an ^ operation */
2546
2547NODE *
2548do_xor(NODE *tree)
2549{
2550	NODE *s1, *s2;
2551	uintmax_t uleft, uright, res;
2552	AWKNUM left, right;
2553
2554	s1 = tree_eval(tree->lnode);
2555	s2 = tree_eval(tree->rnode->lnode);
2556	left = force_number(s1);
2557	right = force_number(s2);
2558
2559	if (do_lint) {
2560		if ((s1->flags & (NUMCUR|NUMBER)) == 0)
2561			lintwarn(_("xor: received non-numeric first argument"));
2562		if ((s2->flags & (NUMCUR|NUMBER)) == 0)
2563			lintwarn(_("xor: received non-numeric first argument"));
2564		if (left < 0 || right < 0)
2565			lintwarn(_("xor(%lf, %lf): negative values will give strange results"), left, right);
2566		if (double_to_int(left) != left || double_to_int(right) != right)
2567			lintwarn(_("xor(%lf, %lf): fractional values will be truncated"), left, right);
2568	}
2569
2570	free_temp(s1);
2571	free_temp(s2);
2572
2573	uleft = (uintmax_t) left;
2574	uright = (uintmax_t) right;
2575
2576	res = uleft ^ uright;
2577	return tmp_number((AWKNUM) res);
2578}
2579
2580/* do_compl --- perform a ~ operation */
2581
2582NODE *
2583do_compl(NODE *tree)
2584{
2585	NODE *tmp;
2586	double d;
2587	uintmax_t uval;
2588
2589	tmp = tree_eval(tree->lnode);
2590	d = force_number(tmp);
2591	free_temp(tmp);
2592
2593	if (do_lint) {
2594		if ((tmp->flags & (NUMCUR|NUMBER)) == 0)
2595			lintwarn(_("compl: received non-numeric argument"));
2596		if (d < 0)
2597			lintwarn(_("compl(%lf): negative value will give strange results"), d);
2598		if (double_to_int(d) != d)
2599			lintwarn(_("compl(%lf): fractional value will be truncated"), d);
2600	}
2601
2602	uval = (uintmax_t) d;
2603	uval = ~ uval;
2604	return tmp_number((AWKNUM) uval);
2605}
2606
2607/* do_strtonum --- the strtonum function */
2608
2609NODE *
2610do_strtonum(NODE *tree)
2611{
2612	NODE *tmp;
2613	double d;
2614
2615	tmp = tree_eval(tree->lnode);
2616
2617	if ((tmp->flags & (NUMBER|NUMCUR)) != 0)
2618		d = (double) force_number(tmp);
2619	else if (isnondecimal(tmp->stptr))
2620		d = nondec2awknum(tmp->stptr, tmp->stlen);
2621	else
2622		d = (double) force_number(tmp);
2623
2624	free_temp(tmp);
2625	return tmp_number((AWKNUM) d);
2626}
2627
2628/* nondec2awknum --- convert octal or hex value to double */
2629
2630/*
2631 * Because of awk's concatenation rules and the way awk.y:yylex()
2632 * collects a number, this routine has to be willing to stop on the
2633 * first invalid character.
2634 */
2635
2636AWKNUM
2637nondec2awknum(char *str, size_t len)
2638{
2639	AWKNUM retval = 0.0;
2640	char save;
2641	short val;
2642	char *start = str;
2643
2644	if (*str == '0' && (str[1] == 'x' || str[1] == 'X')) {
2645		/*
2646		 * User called strtonum("0x") or some such,
2647		 * so just quit early.
2648		 */
2649		if (len <= 2)
2650			return (AWKNUM) 0.0;
2651
2652		for (str += 2, len -= 2; len > 0; len--, str++) {
2653			switch (*str) {
2654			case '0':
2655			case '1':
2656			case '2':
2657			case '3':
2658			case '4':
2659			case '5':
2660			case '6':
2661			case '7':
2662			case '8':
2663			case '9':
2664				val = *str - '0';
2665				break;
2666			case 'a':
2667			case 'b':
2668			case 'c':
2669			case 'd':
2670			case 'e':
2671			case 'f':
2672				val = *str - 'a' + 10;
2673				break;
2674			case 'A':
2675			case 'B':
2676			case 'C':
2677			case 'D':
2678			case 'E':
2679			case 'F':
2680				val = *str - 'A' + 10;
2681				break;
2682			default:
2683				goto done;
2684			}
2685			retval = (retval * 16) + val;
2686		}
2687	} else if (*str == '0') {
2688		for (; len > 0; len--) {
2689			if (! ISDIGIT(*str))
2690				goto done;
2691			else if (*str == '8' || *str == '9') {
2692				str = start;
2693				goto decimal;
2694			}
2695			retval = (retval * 8) + (*str - '0');
2696			str++;
2697		}
2698	} else {
2699decimal:
2700		save = str[len];
2701		retval = strtod(str, NULL);
2702		str[len] = save;
2703	}
2704done:
2705	return retval;
2706}
2707
2708/* do_dcgettext, do_dcngettext --- handle i18n translations */
2709
2710#if ENABLE_NLS && HAVE_LC_MESSAGES && HAVE_DCGETTEXT
2711
2712static int
2713localecategory_from_argument(NODE *tree)
2714{
2715	static const struct category_table {
2716		int val;
2717		const char *name;
2718	} cat_tab[] = {
2719#ifdef LC_ALL
2720		{ LC_ALL,	"LC_ALL" },
2721#endif /* LC_ALL */
2722#ifdef LC_COLLATE
2723		{ LC_COLLATE,	"LC_COLLATE" },
2724#endif /* LC_COLLATE */
2725#ifdef LC_CTYPE
2726		{ LC_CTYPE,	"LC_CTYPE" },
2727#endif /* LC_CTYPE */
2728#ifdef LC_MESSAGES
2729		{ LC_MESSAGES,	"LC_MESSAGES" },
2730#endif /* LC_MESSAGES */
2731#ifdef LC_MONETARY
2732		{ LC_MONETARY,	"LC_MONETARY" },
2733#endif /* LC_MONETARY */
2734#ifdef LC_NUMERIC
2735		{ LC_NUMERIC,	"LC_NUMERIC" },
2736#endif /* LC_NUMERIC */
2737#ifdef LC_RESPONSE
2738		{ LC_RESPONSE,	"LC_RESPONSE" },
2739#endif /* LC_RESPONSE */
2740#ifdef LC_TIME
2741		{ LC_TIME,	"LC_TIME" },
2742#endif /* LC_TIME */
2743	};
2744
2745	if (tree != NULL) {
2746		int low, high, i, mid;
2747		NODE *tmp, *t;
2748		char *category;
2749		int lc_cat = -1;
2750
2751		tmp = tree->lnode;
2752		t = force_string(tree_eval(tmp));
2753		category = t->stptr;
2754
2755		/* binary search the table */
2756		low = 0;
2757		high = (sizeof(cat_tab) / sizeof(cat_tab[0])) - 1;
2758		while (low <= high) {
2759			mid = (low + high) / 2;
2760			i = strcmp(category, cat_tab[mid].name);
2761
2762			if (i < 0)		/* category < mid */
2763				high = mid - 1;
2764			else if (i > 0)		/* category > mid */
2765				low = mid + 1;
2766			else {
2767				lc_cat = cat_tab[mid].val;
2768				break;
2769			}
2770		}
2771		if (lc_cat == -1)	/* not there */
2772			fatal(_("dcgettext: `%s' is not a valid locale category"), category);
2773
2774		free_temp(t);
2775		return lc_cat;
2776	} else
2777		return LC_MESSAGES;
2778}
2779
2780#endif
2781
2782/*
2783 * awk usage is
2784 *
2785 * 	str = dcgettext(string [, domain [, category]])
2786 * 	str = dcngettext(string1, string2, number [, domain [, category]])
2787 *
2788 * Default domain is TEXTDOMAIN, default category is LC_MESSAGES.
2789 */
2790
2791NODE *
2792do_dcgettext(NODE *tree)
2793{
2794	NODE *tmp, *t1, *t2;
2795	char *string;
2796	char *the_result;
2797#if ENABLE_NLS && HAVE_LC_MESSAGES && HAVE_DCGETTEXT
2798	int lc_cat;
2799	char *domain;
2800#endif /* ENABLE_NLS */
2801
2802	tmp = tree->lnode;	/* first argument */
2803	t1 = force_string(tree_eval(tmp));
2804	string = t1->stptr;
2805
2806	t2 = NULL;
2807#if ENABLE_NLS && HAVE_LC_MESSAGES && HAVE_DCGETTEXT
2808	tree = tree->rnode;	/* second argument */
2809	if (tree != NULL) {
2810		tmp = tree->lnode;
2811		t2 = force_string(tree_eval(tmp));
2812		domain = t2->stptr;
2813	} else
2814		domain = TEXTDOMAIN;
2815
2816	if (tree && tree->rnode != NULL) {	/* third argument */
2817		lc_cat = localecategory_from_argument(tree->rnode);
2818	} else
2819		lc_cat = LC_MESSAGES;
2820
2821	the_result = dcgettext(domain, string, lc_cat);
2822#else
2823	the_result = string;
2824#endif
2825	free_temp(t1);
2826	if (t2 != NULL)
2827		free_temp(t2);
2828
2829	return tmp_string(the_result, strlen(the_result));
2830}
2831
2832NODE *
2833do_dcngettext(NODE *tree)
2834{
2835	NODE *tmp, *t1, *t2, *t3;
2836	char *string1, *string2;
2837	unsigned long number;
2838	char *the_result;
2839#if ENABLE_NLS && HAVE_LC_MESSAGES && HAVE_DCGETTEXT
2840	int lc_cat;
2841	char *domain;
2842#endif /* ENABLE_NLS */
2843
2844	tmp = tree->lnode;	/* first argument */
2845	t1 = force_string(tree_eval(tmp));
2846	string1 = t1->stptr;
2847
2848	tmp = tree->rnode->lnode;	/* second argument */
2849	t2 = force_string(tree_eval(tmp));
2850	string2 = t2->stptr;
2851
2852	tmp = tree->rnode->rnode->lnode;	/* third argument */
2853	number = (unsigned long) double_to_int(force_number(tree_eval(tmp)));
2854
2855	t3 = NULL;
2856#if ENABLE_NLS && HAVE_LC_MESSAGES && HAVE_DCGETTEXT
2857	tree = tree->rnode->rnode->rnode;	/* fourth argument */
2858	if (tree != NULL) {
2859		tmp = tree->lnode;
2860		t3 = force_string(tree_eval(tmp));
2861		domain = t3->stptr;
2862	} else
2863		domain = TEXTDOMAIN;
2864
2865	if (tree && tree->rnode != NULL) {	/* fifth argument */
2866		lc_cat = localecategory_from_argument(tree->rnode);
2867	} else
2868		lc_cat = LC_MESSAGES;
2869
2870	the_result = dcngettext(domain, string1, string2, number, lc_cat);
2871#else
2872	the_result = (number == 1 ? string1 : string2);
2873#endif
2874	free_temp(t1);
2875	free_temp(t2);
2876	if (t3 != NULL)
2877		free_temp(t3);
2878
2879	return tmp_string(the_result, strlen(the_result));
2880}
2881
2882/* do_bindtextdomain --- set the directory for a text domain */
2883
2884/*
2885 * awk usage is
2886 *
2887 * 	binding = bindtextdomain(dir [, domain])
2888 *
2889 * If dir is "", pass NULL to C version.
2890 * Default domain is TEXTDOMAIN.
2891 */
2892
2893NODE *
2894do_bindtextdomain(NODE *tree)
2895{
2896	NODE *tmp, *t1, *t2;
2897	char *directory, *domain;
2898	char *the_result;
2899
2900	t1 = t2 = NULL;
2901	/* set defaults */
2902	directory = NULL;
2903	domain = TEXTDOMAIN;
2904
2905	tmp = tree->lnode;	/* first argument */
2906	t1 = force_string(tree_eval(tmp));
2907	if (t1->stlen > 0)
2908		directory = t1->stptr;
2909
2910	tree = tree->rnode;	/* second argument */
2911	if (tree != NULL) {
2912		tmp = tree->lnode;
2913		t2 = force_string(tree_eval(tmp));
2914		domain = t2->stptr;
2915	}
2916
2917	the_result = bindtextdomain(domain, directory);
2918
2919	free_temp(t1);
2920	if (t2 != NULL)
2921		free_temp(t2);
2922
2923	return tmp_string(the_result, strlen(the_result));
2924}
2925