1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate *
4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate * with the License.
8*7c478bd9Sstevel@tonic-gate *
9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate *
14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate *
20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate * awk -- functions
24*7c478bd9Sstevel@tonic-gate *
25*7c478bd9Sstevel@tonic-gate * Copyright (c) 1995, 1996 by Sun Microsystems, Inc.
26*7c478bd9Sstevel@tonic-gate * All rights reserved.
27*7c478bd9Sstevel@tonic-gate *
28*7c478bd9Sstevel@tonic-gate * Copyright 1986, 1994 by Mortice Kern Systems Inc. All rights reserved.
29*7c478bd9Sstevel@tonic-gate *
30*7c478bd9Sstevel@tonic-gate * Based on MKS awk(1) ported to be /usr/xpg4/bin/awk with POSIX/XCU4 changes
31*7c478bd9Sstevel@tonic-gate */
32*7c478bd9Sstevel@tonic-gate
33*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
34*7c478bd9Sstevel@tonic-gate
35*7c478bd9Sstevel@tonic-gate #include "awk.h"
36*7c478bd9Sstevel@tonic-gate #include "y.tab.h"
37*7c478bd9Sstevel@tonic-gate #include <time.h>
38*7c478bd9Sstevel@tonic-gate #include <sys/wait.h>
39*7c478bd9Sstevel@tonic-gate
40*7c478bd9Sstevel@tonic-gate static uint nargs(NODE *np);
41*7c478bd9Sstevel@tonic-gate static NODE *dosub(NODE *np, int glob);
42*7c478bd9Sstevel@tonic-gate static NODE *docasetr(NODE *np, int upper);
43*7c478bd9Sstevel@tonic-gate static int asortcmp(const void *npp1, const void *npp2);
44*7c478bd9Sstevel@tonic-gate
45*7c478bd9Sstevel@tonic-gate static char nargerr[] = "wrong number of arguments to function \"%s\"";
46*7c478bd9Sstevel@tonic-gate static NODE *asortfunc; /* Function call for asort() */
47*7c478bd9Sstevel@tonic-gate static NODE *asnp1, *asnp2; /* index1, index2 nodes */
48*7c478bd9Sstevel@tonic-gate static int asarraylen; /* strlen(array)+1 for asort */
49*7c478bd9Sstevel@tonic-gate
50*7c478bd9Sstevel@tonic-gate /*
51*7c478bd9Sstevel@tonic-gate * Return the value of exp(x).
52*7c478bd9Sstevel@tonic-gate * Usage: y = exp(x)
53*7c478bd9Sstevel@tonic-gate * y = exp()
54*7c478bd9Sstevel@tonic-gate */
55*7c478bd9Sstevel@tonic-gate NODE *
f_exp(NODE * np)56*7c478bd9Sstevel@tonic-gate f_exp(NODE *np)
57*7c478bd9Sstevel@tonic-gate {
58*7c478bd9Sstevel@tonic-gate register uint na;
59*7c478bd9Sstevel@tonic-gate
60*7c478bd9Sstevel@tonic-gate if ((na = nargs(np)) > 1)
61*7c478bd9Sstevel@tonic-gate awkerr(nargerr, s_exp);
62*7c478bd9Sstevel@tonic-gate return (realnode(exp(exprreal(na==0 ? field0 : getlist(&np)))));
63*7c478bd9Sstevel@tonic-gate }
64*7c478bd9Sstevel@tonic-gate
65*7c478bd9Sstevel@tonic-gate /*
66*7c478bd9Sstevel@tonic-gate * Return the integer part of the argument.
67*7c478bd9Sstevel@tonic-gate * Usage: i = int(r)
68*7c478bd9Sstevel@tonic-gate * i = int()
69*7c478bd9Sstevel@tonic-gate */
70*7c478bd9Sstevel@tonic-gate NODE *
f_int(NODE * np)71*7c478bd9Sstevel@tonic-gate f_int(NODE *np)
72*7c478bd9Sstevel@tonic-gate {
73*7c478bd9Sstevel@tonic-gate register uint na;
74*7c478bd9Sstevel@tonic-gate
75*7c478bd9Sstevel@tonic-gate if ((na = nargs(np)) > 1)
76*7c478bd9Sstevel@tonic-gate awkerr(nargerr, s_int);
77*7c478bd9Sstevel@tonic-gate return (intnode(exprint(na==0 ? field0 : getlist(&np))));
78*7c478bd9Sstevel@tonic-gate }
79*7c478bd9Sstevel@tonic-gate
80*7c478bd9Sstevel@tonic-gate /*
81*7c478bd9Sstevel@tonic-gate * Logarithm function.
82*7c478bd9Sstevel@tonic-gate * Usage: y = log(x)
83*7c478bd9Sstevel@tonic-gate * y = log()
84*7c478bd9Sstevel@tonic-gate */
85*7c478bd9Sstevel@tonic-gate NODE *
f_log(NODE * np)86*7c478bd9Sstevel@tonic-gate f_log(NODE *np)
87*7c478bd9Sstevel@tonic-gate {
88*7c478bd9Sstevel@tonic-gate register uint na;
89*7c478bd9Sstevel@tonic-gate
90*7c478bd9Sstevel@tonic-gate if ((na = nargs(np)) > 1)
91*7c478bd9Sstevel@tonic-gate awkerr(nargerr, s_log);
92*7c478bd9Sstevel@tonic-gate return (realnode(log(exprreal(na==0 ? field0 : getlist(&np)))));
93*7c478bd9Sstevel@tonic-gate }
94*7c478bd9Sstevel@tonic-gate
95*7c478bd9Sstevel@tonic-gate /*
96*7c478bd9Sstevel@tonic-gate * Square root function.
97*7c478bd9Sstevel@tonic-gate * Usage: y = sqrt(x)
98*7c478bd9Sstevel@tonic-gate * y = sqrt()
99*7c478bd9Sstevel@tonic-gate */
100*7c478bd9Sstevel@tonic-gate NODE *
f_sqrt(NODE * np)101*7c478bd9Sstevel@tonic-gate f_sqrt(NODE *np)
102*7c478bd9Sstevel@tonic-gate {
103*7c478bd9Sstevel@tonic-gate register uint na;
104*7c478bd9Sstevel@tonic-gate
105*7c478bd9Sstevel@tonic-gate if ((na = nargs(np)) > 1)
106*7c478bd9Sstevel@tonic-gate awkerr(nargerr, s_sqrt);
107*7c478bd9Sstevel@tonic-gate return (realnode(sqrt(exprreal(na==0 ? field0 : getlist(&np)))));
108*7c478bd9Sstevel@tonic-gate }
109*7c478bd9Sstevel@tonic-gate
110*7c478bd9Sstevel@tonic-gate /*
111*7c478bd9Sstevel@tonic-gate * Trigonometric sine function.
112*7c478bd9Sstevel@tonic-gate * Usage: y = sin(x)
113*7c478bd9Sstevel@tonic-gate */
114*7c478bd9Sstevel@tonic-gate NODE *
f_sin(NODE * np)115*7c478bd9Sstevel@tonic-gate f_sin(NODE *np)
116*7c478bd9Sstevel@tonic-gate {
117*7c478bd9Sstevel@tonic-gate if (nargs(np) != 1)
118*7c478bd9Sstevel@tonic-gate awkerr(nargerr, s_sin);
119*7c478bd9Sstevel@tonic-gate return (realnode(sin(exprreal(getlist(&np)))));
120*7c478bd9Sstevel@tonic-gate }
121*7c478bd9Sstevel@tonic-gate
122*7c478bd9Sstevel@tonic-gate /*
123*7c478bd9Sstevel@tonic-gate * Trigonometric cosine function.
124*7c478bd9Sstevel@tonic-gate * Usage: y = cos(x)
125*7c478bd9Sstevel@tonic-gate */
126*7c478bd9Sstevel@tonic-gate NODE *
f_cos(NODE * np)127*7c478bd9Sstevel@tonic-gate f_cos(NODE *np)
128*7c478bd9Sstevel@tonic-gate {
129*7c478bd9Sstevel@tonic-gate if (nargs(np) != 1)
130*7c478bd9Sstevel@tonic-gate awkerr(nargerr, s_cos);
131*7c478bd9Sstevel@tonic-gate return (realnode(cos(exprreal(getlist(&np)))));
132*7c478bd9Sstevel@tonic-gate }
133*7c478bd9Sstevel@tonic-gate
134*7c478bd9Sstevel@tonic-gate /*
135*7c478bd9Sstevel@tonic-gate * Arctangent of y/x.
136*7c478bd9Sstevel@tonic-gate * Usage: z = atan2(y, x)
137*7c478bd9Sstevel@tonic-gate */
138*7c478bd9Sstevel@tonic-gate NODE *
f_atan2(NODE * np)139*7c478bd9Sstevel@tonic-gate f_atan2(NODE *np)
140*7c478bd9Sstevel@tonic-gate {
141*7c478bd9Sstevel@tonic-gate double y, x;
142*7c478bd9Sstevel@tonic-gate
143*7c478bd9Sstevel@tonic-gate if (nargs(np) != 2)
144*7c478bd9Sstevel@tonic-gate awkerr(nargerr, s_atan2);
145*7c478bd9Sstevel@tonic-gate y = (double)exprreal(getlist(&np));
146*7c478bd9Sstevel@tonic-gate x = (double)exprreal(getlist(&np));
147*7c478bd9Sstevel@tonic-gate return (realnode(atan2(y, x)));
148*7c478bd9Sstevel@tonic-gate }
149*7c478bd9Sstevel@tonic-gate
150*7c478bd9Sstevel@tonic-gate /*
151*7c478bd9Sstevel@tonic-gate * Set the seed for the random number generator function -- rand.
152*7c478bd9Sstevel@tonic-gate * Usage: srand(x)
153*7c478bd9Sstevel@tonic-gate * srand()
154*7c478bd9Sstevel@tonic-gate */
155*7c478bd9Sstevel@tonic-gate NODE *
f_srand(NODE * np)156*7c478bd9Sstevel@tonic-gate f_srand(NODE *np)
157*7c478bd9Sstevel@tonic-gate {
158*7c478bd9Sstevel@tonic-gate register uint na;
159*7c478bd9Sstevel@tonic-gate register uint seed;
160*7c478bd9Sstevel@tonic-gate static uint oldseed = 0;
161*7c478bd9Sstevel@tonic-gate
162*7c478bd9Sstevel@tonic-gate if ((na = nargs(np)) > 1)
163*7c478bd9Sstevel@tonic-gate awkerr(nargerr, s_srand);
164*7c478bd9Sstevel@tonic-gate if (na == 0)
165*7c478bd9Sstevel@tonic-gate seed = (uint)time((time_t *)0); else
166*7c478bd9Sstevel@tonic-gate seed = (uint)exprint(getlist(&np));
167*7c478bd9Sstevel@tonic-gate srand(seed);
168*7c478bd9Sstevel@tonic-gate na = oldseed;
169*7c478bd9Sstevel@tonic-gate oldseed = seed;
170*7c478bd9Sstevel@tonic-gate return (intnode((INT)na));
171*7c478bd9Sstevel@tonic-gate }
172*7c478bd9Sstevel@tonic-gate
173*7c478bd9Sstevel@tonic-gate /*
174*7c478bd9Sstevel@tonic-gate * Generate a random number.
175*7c478bd9Sstevel@tonic-gate * Usage: x = rand()
176*7c478bd9Sstevel@tonic-gate */
177*7c478bd9Sstevel@tonic-gate NODE *
f_rand(NODE * np)178*7c478bd9Sstevel@tonic-gate f_rand(NODE *np)
179*7c478bd9Sstevel@tonic-gate {
180*7c478bd9Sstevel@tonic-gate double result;
181*7c478bd9Sstevel@tonic-gate int expon;
182*7c478bd9Sstevel@tonic-gate ushort rint;
183*7c478bd9Sstevel@tonic-gate
184*7c478bd9Sstevel@tonic-gate if (nargs(np) != 0)
185*7c478bd9Sstevel@tonic-gate awkerr(nargerr, s_rand);
186*7c478bd9Sstevel@tonic-gate rint = rand() & SHRT_MAX;
187*7c478bd9Sstevel@tonic-gate result = frexp((double)rint, &expon);
188*7c478bd9Sstevel@tonic-gate return (realnode((REAL)ldexp(result, expon-15)));
189*7c478bd9Sstevel@tonic-gate }
190*7c478bd9Sstevel@tonic-gate
191*7c478bd9Sstevel@tonic-gate /*
192*7c478bd9Sstevel@tonic-gate * Substitute function.
193*7c478bd9Sstevel@tonic-gate * Usage: n = sub(regex, replace, target)
194*7c478bd9Sstevel@tonic-gate * n = sub(regex, replace)
195*7c478bd9Sstevel@tonic-gate */
196*7c478bd9Sstevel@tonic-gate NODE *
f_sub(NODE * np)197*7c478bd9Sstevel@tonic-gate f_sub(NODE *np)
198*7c478bd9Sstevel@tonic-gate {
199*7c478bd9Sstevel@tonic-gate return (dosub(np, 1));
200*7c478bd9Sstevel@tonic-gate }
201*7c478bd9Sstevel@tonic-gate
202*7c478bd9Sstevel@tonic-gate /*
203*7c478bd9Sstevel@tonic-gate * Global substitution function.
204*7c478bd9Sstevel@tonic-gate * Usage: n = gsub(regex, replace, target)
205*7c478bd9Sstevel@tonic-gate * n = gsub(regex, replace)
206*7c478bd9Sstevel@tonic-gate */
207*7c478bd9Sstevel@tonic-gate NODE *
f_gsub(NODE * np)208*7c478bd9Sstevel@tonic-gate f_gsub(NODE *np)
209*7c478bd9Sstevel@tonic-gate {
210*7c478bd9Sstevel@tonic-gate return (dosub(np, 0));
211*7c478bd9Sstevel@tonic-gate }
212*7c478bd9Sstevel@tonic-gate
213*7c478bd9Sstevel@tonic-gate /*
214*7c478bd9Sstevel@tonic-gate * Do actual substitutions.
215*7c478bd9Sstevel@tonic-gate * `glob' is the number to substitute, 0 for all.
216*7c478bd9Sstevel@tonic-gate */
217*7c478bd9Sstevel@tonic-gate static NODE *
dosub(NODE * np,int glob)218*7c478bd9Sstevel@tonic-gate dosub(NODE *np, int glob)
219*7c478bd9Sstevel@tonic-gate {
220*7c478bd9Sstevel@tonic-gate wchar_t *text;
221*7c478bd9Sstevel@tonic-gate register wchar_t *sub;
222*7c478bd9Sstevel@tonic-gate register uint n;
223*7c478bd9Sstevel@tonic-gate register uint na;
224*7c478bd9Sstevel@tonic-gate register REGEXP rp;
225*7c478bd9Sstevel@tonic-gate NODE *left;
226*7c478bd9Sstevel@tonic-gate static wchar_t *buf;
227*7c478bd9Sstevel@tonic-gate
228*7c478bd9Sstevel@tonic-gate if ((na = nargs(np)) != 2 && na != 3)
229*7c478bd9Sstevel@tonic-gate awkerr(nargerr, glob==0 ? s_gsub : s_sub);
230*7c478bd9Sstevel@tonic-gate rp = getregexp(getlist(&np));
231*7c478bd9Sstevel@tonic-gate sub = exprstring(getlist(&np));
232*7c478bd9Sstevel@tonic-gate if (na == 3) {
233*7c478bd9Sstevel@tonic-gate left = getlist(&np);
234*7c478bd9Sstevel@tonic-gate text = exprstring(left);
235*7c478bd9Sstevel@tonic-gate } else {
236*7c478bd9Sstevel@tonic-gate left = field0;
237*7c478bd9Sstevel@tonic-gate text = linebuf;
238*7c478bd9Sstevel@tonic-gate }
239*7c478bd9Sstevel@tonic-gate switch (REGWDOSUBA(rp, sub, text, &buf, 256, &glob)) {
240*7c478bd9Sstevel@tonic-gate case REG_OK:
241*7c478bd9Sstevel@tonic-gate case REG_NOMATCH:
242*7c478bd9Sstevel@tonic-gate n = glob;
243*7c478bd9Sstevel@tonic-gate break;
244*7c478bd9Sstevel@tonic-gate case REG_ESPACE:
245*7c478bd9Sstevel@tonic-gate if (buf != NULL)
246*7c478bd9Sstevel@tonic-gate free(buf);
247*7c478bd9Sstevel@tonic-gate awkerr(nomem);
248*7c478bd9Sstevel@tonic-gate default:
249*7c478bd9Sstevel@tonic-gate awkerr(gettext("regular expression error"));
250*7c478bd9Sstevel@tonic-gate }
251*7c478bd9Sstevel@tonic-gate (void)assign(left, stringnode(buf, FNOALLOC, wcslen(buf)));
252*7c478bd9Sstevel@tonic-gate return (intnode((INT)n));
253*7c478bd9Sstevel@tonic-gate }
254*7c478bd9Sstevel@tonic-gate
255*7c478bd9Sstevel@tonic-gate /*
256*7c478bd9Sstevel@tonic-gate * Match function. Return position (origin 1) or 0 for regular
257*7c478bd9Sstevel@tonic-gate * expression match in string. Set new variables RSTART and RLENGTH
258*7c478bd9Sstevel@tonic-gate * as well.
259*7c478bd9Sstevel@tonic-gate * Usage: pos = match(string, re)
260*7c478bd9Sstevel@tonic-gate */
261*7c478bd9Sstevel@tonic-gate NODE *
f_match(NODE * np)262*7c478bd9Sstevel@tonic-gate f_match(NODE *np)
263*7c478bd9Sstevel@tonic-gate {
264*7c478bd9Sstevel@tonic-gate register wchar_t *text;
265*7c478bd9Sstevel@tonic-gate register REGEXP rp;
266*7c478bd9Sstevel@tonic-gate register int pos, length;
267*7c478bd9Sstevel@tonic-gate REGWMATCH_T match[10];
268*7c478bd9Sstevel@tonic-gate
269*7c478bd9Sstevel@tonic-gate if (nargs(np) != 2)
270*7c478bd9Sstevel@tonic-gate awkerr(nargerr, s_match);
271*7c478bd9Sstevel@tonic-gate text = exprstring(getlist(&np));
272*7c478bd9Sstevel@tonic-gate rp = getregexp(getlist(&np));
273*7c478bd9Sstevel@tonic-gate if (REGWEXEC(rp, text, 10, match, 0) == REG_OK) {
274*7c478bd9Sstevel@tonic-gate pos = match[0].rm_sp-text+1;
275*7c478bd9Sstevel@tonic-gate length = match[0].rm_ep - match[0].rm_sp;
276*7c478bd9Sstevel@tonic-gate } else {
277*7c478bd9Sstevel@tonic-gate pos = 0;
278*7c478bd9Sstevel@tonic-gate length = -1;
279*7c478bd9Sstevel@tonic-gate }
280*7c478bd9Sstevel@tonic-gate constant->n_int = length;
281*7c478bd9Sstevel@tonic-gate (void)assign(vlook(M_MB_L("RLENGTH")), constant);
282*7c478bd9Sstevel@tonic-gate return (assign(vlook(M_MB_L("RSTART")), intnode((INT)pos)));
283*7c478bd9Sstevel@tonic-gate }
284*7c478bd9Sstevel@tonic-gate
285*7c478bd9Sstevel@tonic-gate /*
286*7c478bd9Sstevel@tonic-gate * Call shell or command interpreter.
287*7c478bd9Sstevel@tonic-gate * Usage: status = system(command)
288*7c478bd9Sstevel@tonic-gate */
289*7c478bd9Sstevel@tonic-gate NODE *
f_system(NODE * np)290*7c478bd9Sstevel@tonic-gate f_system(NODE *np)
291*7c478bd9Sstevel@tonic-gate {
292*7c478bd9Sstevel@tonic-gate int retcode;
293*7c478bd9Sstevel@tonic-gate
294*7c478bd9Sstevel@tonic-gate if (nargs(np) != 1)
295*7c478bd9Sstevel@tonic-gate awkerr(nargerr, s_system);
296*7c478bd9Sstevel@tonic-gate (void) fflush(stdout);
297*7c478bd9Sstevel@tonic-gate retcode = system(mbunconvert(exprstring(getlist(&np))));
298*7c478bd9Sstevel@tonic-gate return (intnode((INT)WEXITSTATUS(retcode)));
299*7c478bd9Sstevel@tonic-gate }
300*7c478bd9Sstevel@tonic-gate
301*7c478bd9Sstevel@tonic-gate /*
302*7c478bd9Sstevel@tonic-gate * Search for string within string.
303*7c478bd9Sstevel@tonic-gate * Usage: pos = index(string1, string2)
304*7c478bd9Sstevel@tonic-gate */
305*7c478bd9Sstevel@tonic-gate NODE *
f_index(NODE * np)306*7c478bd9Sstevel@tonic-gate f_index(NODE *np)
307*7c478bd9Sstevel@tonic-gate {
308*7c478bd9Sstevel@tonic-gate register wchar_t *s1, *s2;
309*7c478bd9Sstevel@tonic-gate register int l1, l2;
310*7c478bd9Sstevel@tonic-gate register int result;
311*7c478bd9Sstevel@tonic-gate
312*7c478bd9Sstevel@tonic-gate if (nargs(np) != 2)
313*7c478bd9Sstevel@tonic-gate awkerr(nargerr, s_index);
314*7c478bd9Sstevel@tonic-gate s1 = (wchar_t *)exprstring(getlist(&np));
315*7c478bd9Sstevel@tonic-gate s2 = (wchar_t *)exprstring(getlist(&np));
316*7c478bd9Sstevel@tonic-gate l1 = wcslen(s1);
317*7c478bd9Sstevel@tonic-gate l2 = wcslen(s2);
318*7c478bd9Sstevel@tonic-gate result = 1;
319*7c478bd9Sstevel@tonic-gate while (l2 <= l1) {
320*7c478bd9Sstevel@tonic-gate if (memcmp(s1, s2, l2 * sizeof(wchar_t)) == 0)
321*7c478bd9Sstevel@tonic-gate break;
322*7c478bd9Sstevel@tonic-gate result++;
323*7c478bd9Sstevel@tonic-gate s1++;
324*7c478bd9Sstevel@tonic-gate l1--;
325*7c478bd9Sstevel@tonic-gate }
326*7c478bd9Sstevel@tonic-gate if (l2 > l1)
327*7c478bd9Sstevel@tonic-gate result = 0;
328*7c478bd9Sstevel@tonic-gate return (intnode((INT)result));
329*7c478bd9Sstevel@tonic-gate }
330*7c478bd9Sstevel@tonic-gate
331*7c478bd9Sstevel@tonic-gate /*
332*7c478bd9Sstevel@tonic-gate * Return length of argument or $0
333*7c478bd9Sstevel@tonic-gate * Usage: n = length(string)
334*7c478bd9Sstevel@tonic-gate * n = length()
335*7c478bd9Sstevel@tonic-gate * n = length
336*7c478bd9Sstevel@tonic-gate */
337*7c478bd9Sstevel@tonic-gate NODE *
f_length(NODE * np)338*7c478bd9Sstevel@tonic-gate f_length(NODE *np)
339*7c478bd9Sstevel@tonic-gate {
340*7c478bd9Sstevel@tonic-gate register uint na;
341*7c478bd9Sstevel@tonic-gate
342*7c478bd9Sstevel@tonic-gate if ((na = nargs(np)) > 1)
343*7c478bd9Sstevel@tonic-gate awkerr(nargerr, s_length);
344*7c478bd9Sstevel@tonic-gate if (na == 0)
345*7c478bd9Sstevel@tonic-gate na = lbuflen; else
346*7c478bd9Sstevel@tonic-gate na = wcslen((wchar_t *)exprstring(getlist(&np)));
347*7c478bd9Sstevel@tonic-gate return (intnode((INT)na));
348*7c478bd9Sstevel@tonic-gate }
349*7c478bd9Sstevel@tonic-gate
350*7c478bd9Sstevel@tonic-gate /*
351*7c478bd9Sstevel@tonic-gate * Split string into fields.
352*7c478bd9Sstevel@tonic-gate * Usage: nfields = split(string, array [, separator]);
353*7c478bd9Sstevel@tonic-gate */
354*7c478bd9Sstevel@tonic-gate NODE *
f_split(NODE * np)355*7c478bd9Sstevel@tonic-gate f_split(NODE *np)
356*7c478bd9Sstevel@tonic-gate {
357*7c478bd9Sstevel@tonic-gate register wchar_t *cp;
358*7c478bd9Sstevel@tonic-gate wchar_t *ep, *saved = 0;
359*7c478bd9Sstevel@tonic-gate register NODE *tnp, *snp, *otnp;
360*7c478bd9Sstevel@tonic-gate register NODE *sep;
361*7c478bd9Sstevel@tonic-gate REGEXP old_resep = 0;
362*7c478bd9Sstevel@tonic-gate size_t seplen;
363*7c478bd9Sstevel@tonic-gate uint n;
364*7c478bd9Sstevel@tonic-gate wint_t c;
365*7c478bd9Sstevel@tonic-gate wchar_t savesep[20];
366*7c478bd9Sstevel@tonic-gate wchar_t *(*old_awkfield)(wchar_t **) = 0;
367*7c478bd9Sstevel@tonic-gate
368*7c478bd9Sstevel@tonic-gate if ((n = nargs(np))<2 || n>3)
369*7c478bd9Sstevel@tonic-gate awkerr(nargerr, s_split);
370*7c478bd9Sstevel@tonic-gate ep = exprstring(snp = getlist(&np));
371*7c478bd9Sstevel@tonic-gate tnp = getlist(&np);
372*7c478bd9Sstevel@tonic-gate if (snp->n_type == INDEX && snp->n_left == tnp)
373*7c478bd9Sstevel@tonic-gate ep = saved = wsdup(ep);
374*7c478bd9Sstevel@tonic-gate if (n == 3) {
375*7c478bd9Sstevel@tonic-gate sep = getlist(&np);
376*7c478bd9Sstevel@tonic-gate } else
377*7c478bd9Sstevel@tonic-gate sep = NNULL;
378*7c478bd9Sstevel@tonic-gate switch (tnp->n_type) {
379*7c478bd9Sstevel@tonic-gate case ARRAY:
380*7c478bd9Sstevel@tonic-gate delarray(tnp);
381*7c478bd9Sstevel@tonic-gate break;
382*7c478bd9Sstevel@tonic-gate
383*7c478bd9Sstevel@tonic-gate case PARM:
384*7c478bd9Sstevel@tonic-gate break;
385*7c478bd9Sstevel@tonic-gate
386*7c478bd9Sstevel@tonic-gate case VAR:
387*7c478bd9Sstevel@tonic-gate if (isstring(tnp->n_flags) && tnp->n_string==_null)
388*7c478bd9Sstevel@tonic-gate break;
389*7c478bd9Sstevel@tonic-gate default:
390*7c478bd9Sstevel@tonic-gate awkerr(gettext(
391*7c478bd9Sstevel@tonic-gate "second parameter to \"split\" must be an array"));
392*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/
393*7c478bd9Sstevel@tonic-gate }
394*7c478bd9Sstevel@tonic-gate /*
395*7c478bd9Sstevel@tonic-gate * If an argument has been passed in to be used as the
396*7c478bd9Sstevel@tonic-gate * field separator check to see if it is a constant regular
397*7c478bd9Sstevel@tonic-gate * expression. If so, use it directly otherwise reduce the
398*7c478bd9Sstevel@tonic-gate * expression, convert the result into a string and assign it
399*7c478bd9Sstevel@tonic-gate * to "FS" (after saving the old value for FS.)
400*7c478bd9Sstevel@tonic-gate */
401*7c478bd9Sstevel@tonic-gate if (sep != NNULL) {
402*7c478bd9Sstevel@tonic-gate if (sep->n_type == PARM)
403*7c478bd9Sstevel@tonic-gate sep = sep->n_next;
404*7c478bd9Sstevel@tonic-gate if (sep->n_type == RE) {
405*7c478bd9Sstevel@tonic-gate old_resep = resep;
406*7c478bd9Sstevel@tonic-gate resep = sep->n_regexp;
407*7c478bd9Sstevel@tonic-gate old_awkfield = awkfield;
408*7c478bd9Sstevel@tonic-gate awkfield = refield;
409*7c478bd9Sstevel@tonic-gate } else {
410*7c478bd9Sstevel@tonic-gate sep = exprreduce(sep);
411*7c478bd9Sstevel@tonic-gate seplen = wcslen(cp = (wchar_t *)exprstring(varFS));
412*7c478bd9Sstevel@tonic-gate (void) memcpy(savesep, cp,
413*7c478bd9Sstevel@tonic-gate (seplen+1) * sizeof(wchar_t));
414*7c478bd9Sstevel@tonic-gate (void) assign(varFS, sep);
415*7c478bd9Sstevel@tonic-gate }
416*7c478bd9Sstevel@tonic-gate }
417*7c478bd9Sstevel@tonic-gate /*
418*7c478bd9Sstevel@tonic-gate * Iterate over the record, extracting each field and assigning it to
419*7c478bd9Sstevel@tonic-gate * the corresponding element in the array.
420*7c478bd9Sstevel@tonic-gate */
421*7c478bd9Sstevel@tonic-gate otnp = tnp; /* save tnp for possible promotion */
422*7c478bd9Sstevel@tonic-gate tnp = node(INDEX, tnp, constant);
423*7c478bd9Sstevel@tonic-gate fcount = 0;
424*7c478bd9Sstevel@tonic-gate for (;;) {
425*7c478bd9Sstevel@tonic-gate if ((cp = (*awkfield)(&ep)) == NULL) {
426*7c478bd9Sstevel@tonic-gate if (fcount == 0) {
427*7c478bd9Sstevel@tonic-gate if (otnp->n_type == PARM)
428*7c478bd9Sstevel@tonic-gate otnp = otnp->n_next;
429*7c478bd9Sstevel@tonic-gate promote(otnp);
430*7c478bd9Sstevel@tonic-gate }
431*7c478bd9Sstevel@tonic-gate break;
432*7c478bd9Sstevel@tonic-gate }
433*7c478bd9Sstevel@tonic-gate c = *ep;
434*7c478bd9Sstevel@tonic-gate *ep = '\0';
435*7c478bd9Sstevel@tonic-gate constant->n_int = ++fcount;
436*7c478bd9Sstevel@tonic-gate (void)assign(tnp, stringnode(cp,FALLOC|FSENSE,(size_t)(ep-cp)));
437*7c478bd9Sstevel@tonic-gate *ep = c;
438*7c478bd9Sstevel@tonic-gate }
439*7c478bd9Sstevel@tonic-gate /*
440*7c478bd9Sstevel@tonic-gate * Restore the old record separator/and or regular expression.
441*7c478bd9Sstevel@tonic-gate */
442*7c478bd9Sstevel@tonic-gate if (sep != NNULL) {
443*7c478bd9Sstevel@tonic-gate if (old_awkfield != 0) {
444*7c478bd9Sstevel@tonic-gate resep = old_resep;
445*7c478bd9Sstevel@tonic-gate awkfield = old_awkfield;
446*7c478bd9Sstevel@tonic-gate } else {
447*7c478bd9Sstevel@tonic-gate (void)assign(varFS,
448*7c478bd9Sstevel@tonic-gate stringnode(savesep, FSTATIC, seplen));
449*7c478bd9Sstevel@tonic-gate }
450*7c478bd9Sstevel@tonic-gate }
451*7c478bd9Sstevel@tonic-gate if (saved)
452*7c478bd9Sstevel@tonic-gate free(saved);
453*7c478bd9Sstevel@tonic-gate return (intnode((INT)fcount));
454*7c478bd9Sstevel@tonic-gate }
455*7c478bd9Sstevel@tonic-gate
456*7c478bd9Sstevel@tonic-gate /*
457*7c478bd9Sstevel@tonic-gate * Sprintf function.
458*7c478bd9Sstevel@tonic-gate * Usage: string = sprintf(format, arg, ...)
459*7c478bd9Sstevel@tonic-gate */
460*7c478bd9Sstevel@tonic-gate NODE *
f_sprintf(NODE * np)461*7c478bd9Sstevel@tonic-gate f_sprintf(NODE *np)
462*7c478bd9Sstevel@tonic-gate {
463*7c478bd9Sstevel@tonic-gate wchar_t *cp;
464*7c478bd9Sstevel@tonic-gate size_t length;
465*7c478bd9Sstevel@tonic-gate
466*7c478bd9Sstevel@tonic-gate if (nargs(np) == 0)
467*7c478bd9Sstevel@tonic-gate awkerr(nargerr, s_sprintf);
468*7c478bd9Sstevel@tonic-gate length = xprintf(np, (FILE *)NULL, &cp);
469*7c478bd9Sstevel@tonic-gate np = stringnode(cp, FNOALLOC, length);
470*7c478bd9Sstevel@tonic-gate return (np);
471*7c478bd9Sstevel@tonic-gate }
472*7c478bd9Sstevel@tonic-gate
473*7c478bd9Sstevel@tonic-gate /*
474*7c478bd9Sstevel@tonic-gate * Substring.
475*7c478bd9Sstevel@tonic-gate * newstring = substr(string, start, [length])
476*7c478bd9Sstevel@tonic-gate */
477*7c478bd9Sstevel@tonic-gate NODE *
f_substr(NODE * np)478*7c478bd9Sstevel@tonic-gate f_substr(NODE *np)
479*7c478bd9Sstevel@tonic-gate {
480*7c478bd9Sstevel@tonic-gate register STRING str;
481*7c478bd9Sstevel@tonic-gate register size_t n;
482*7c478bd9Sstevel@tonic-gate register int start;
483*7c478bd9Sstevel@tonic-gate register size_t len;
484*7c478bd9Sstevel@tonic-gate
485*7c478bd9Sstevel@tonic-gate if ((n = nargs(np))<2 || n>3)
486*7c478bd9Sstevel@tonic-gate awkerr(nargerr, s_substr);
487*7c478bd9Sstevel@tonic-gate str = exprstring(getlist(&np));
488*7c478bd9Sstevel@tonic-gate if ((start = (int)exprint(getlist(&np))-1) < 0)
489*7c478bd9Sstevel@tonic-gate start = 0;
490*7c478bd9Sstevel@tonic-gate if (n == 3) {
491*7c478bd9Sstevel@tonic-gate int x;
492*7c478bd9Sstevel@tonic-gate x = (int)exprint(getlist(&np));
493*7c478bd9Sstevel@tonic-gate if (x < 0)
494*7c478bd9Sstevel@tonic-gate len = 0;
495*7c478bd9Sstevel@tonic-gate else
496*7c478bd9Sstevel@tonic-gate len = (size_t)x;
497*7c478bd9Sstevel@tonic-gate } else
498*7c478bd9Sstevel@tonic-gate len = LARGE;
499*7c478bd9Sstevel@tonic-gate n = wcslen((wchar_t *)str);
500*7c478bd9Sstevel@tonic-gate if (start > n)
501*7c478bd9Sstevel@tonic-gate start = n;
502*7c478bd9Sstevel@tonic-gate n -= start;
503*7c478bd9Sstevel@tonic-gate if (len > n)
504*7c478bd9Sstevel@tonic-gate len = n;
505*7c478bd9Sstevel@tonic-gate str += start;
506*7c478bd9Sstevel@tonic-gate n = str[len];
507*7c478bd9Sstevel@tonic-gate str[len] = '\0';
508*7c478bd9Sstevel@tonic-gate np = stringnode(str, FALLOC, len);
509*7c478bd9Sstevel@tonic-gate str[len] = n;
510*7c478bd9Sstevel@tonic-gate return (np);
511*7c478bd9Sstevel@tonic-gate }
512*7c478bd9Sstevel@tonic-gate
513*7c478bd9Sstevel@tonic-gate /*
514*7c478bd9Sstevel@tonic-gate * Close an output or input file stream.
515*7c478bd9Sstevel@tonic-gate */
516*7c478bd9Sstevel@tonic-gate NODE *
f_close(NODE * np)517*7c478bd9Sstevel@tonic-gate f_close(NODE *np)
518*7c478bd9Sstevel@tonic-gate {
519*7c478bd9Sstevel@tonic-gate register OFILE *op;
520*7c478bd9Sstevel@tonic-gate register char *name;
521*7c478bd9Sstevel@tonic-gate
522*7c478bd9Sstevel@tonic-gate if (nargs(np) != 1)
523*7c478bd9Sstevel@tonic-gate awkerr(nargerr, s_close);
524*7c478bd9Sstevel@tonic-gate name = mbunconvert(exprstring(getlist(&np)));
525*7c478bd9Sstevel@tonic-gate for (op = &ofiles[0]; op < &ofiles[NIOSTREAM]; op++)
526*7c478bd9Sstevel@tonic-gate if (op->f_fp!=FNULL && strcmp(name, op->f_name)==0) {
527*7c478bd9Sstevel@tonic-gate awkclose(op);
528*7c478bd9Sstevel@tonic-gate break;
529*7c478bd9Sstevel@tonic-gate }
530*7c478bd9Sstevel@tonic-gate if (op >= &ofiles[NIOSTREAM])
531*7c478bd9Sstevel@tonic-gate return (const1);
532*7c478bd9Sstevel@tonic-gate return (const0);
533*7c478bd9Sstevel@tonic-gate }
534*7c478bd9Sstevel@tonic-gate
535*7c478bd9Sstevel@tonic-gate /*
536*7c478bd9Sstevel@tonic-gate * Return the integer value of the first character of a string.
537*7c478bd9Sstevel@tonic-gate * Usage: char = ord(string)
538*7c478bd9Sstevel@tonic-gate */
539*7c478bd9Sstevel@tonic-gate NODE *
f_ord(NODE * np)540*7c478bd9Sstevel@tonic-gate f_ord(NODE *np)
541*7c478bd9Sstevel@tonic-gate {
542*7c478bd9Sstevel@tonic-gate if (nargs(np) != 1)
543*7c478bd9Sstevel@tonic-gate awkerr(nargerr, s_ord);
544*7c478bd9Sstevel@tonic-gate return (intnode((INT)*exprstring(getlist(&np))));
545*7c478bd9Sstevel@tonic-gate }
546*7c478bd9Sstevel@tonic-gate
547*7c478bd9Sstevel@tonic-gate /*
548*7c478bd9Sstevel@tonic-gate * Return the argument string in lower case:
549*7c478bd9Sstevel@tonic-gate * Usage:
550*7c478bd9Sstevel@tonic-gate * lower = tolower(upper)
551*7c478bd9Sstevel@tonic-gate */
552*7c478bd9Sstevel@tonic-gate NODE *
f_tolower(NODE * np)553*7c478bd9Sstevel@tonic-gate f_tolower(NODE *np)
554*7c478bd9Sstevel@tonic-gate {
555*7c478bd9Sstevel@tonic-gate return (docasetr(np, 0));
556*7c478bd9Sstevel@tonic-gate }
557*7c478bd9Sstevel@tonic-gate
558*7c478bd9Sstevel@tonic-gate /*
559*7c478bd9Sstevel@tonic-gate * Return the argument string in upper case:
560*7c478bd9Sstevel@tonic-gate * Usage:
561*7c478bd9Sstevel@tonic-gate * upper = toupper(lower)
562*7c478bd9Sstevel@tonic-gate */
563*7c478bd9Sstevel@tonic-gate NODE *
f_toupper(NODE * np)564*7c478bd9Sstevel@tonic-gate f_toupper(NODE *np)
565*7c478bd9Sstevel@tonic-gate {
566*7c478bd9Sstevel@tonic-gate return (docasetr(np, 1));
567*7c478bd9Sstevel@tonic-gate }
568*7c478bd9Sstevel@tonic-gate
569*7c478bd9Sstevel@tonic-gate /*
570*7c478bd9Sstevel@tonic-gate * Sort the array into traversal order by the next "for (i in array)" loop.
571*7c478bd9Sstevel@tonic-gate * Usage:
572*7c478bd9Sstevel@tonic-gate * asort(array, "cmpfunc")
573*7c478bd9Sstevel@tonic-gate * cmpfunc(array, index1, index2)
574*7c478bd9Sstevel@tonic-gate * returns:
575*7c478bd9Sstevel@tonic-gate * <0 if array[index1] < array[index2]
576*7c478bd9Sstevel@tonic-gate * 0 if array[index1] == array[index2]
577*7c478bd9Sstevel@tonic-gate * >0 if array[index1] > array[index2]
578*7c478bd9Sstevel@tonic-gate */
579*7c478bd9Sstevel@tonic-gate NODE *
f_asort(NODE * np)580*7c478bd9Sstevel@tonic-gate f_asort(NODE *np)
581*7c478bd9Sstevel@tonic-gate {
582*7c478bd9Sstevel@tonic-gate NODE *array;
583*7c478bd9Sstevel@tonic-gate STRING funcname;
584*7c478bd9Sstevel@tonic-gate register size_t nel;
585*7c478bd9Sstevel@tonic-gate register NODE *tnp;
586*7c478bd9Sstevel@tonic-gate register NODE *funcnp;
587*7c478bd9Sstevel@tonic-gate register NODE **alist, **npp;
588*7c478bd9Sstevel@tonic-gate
589*7c478bd9Sstevel@tonic-gate if (nargs(np) != 2)
590*7c478bd9Sstevel@tonic-gate awkerr(nargerr, s_asort);
591*7c478bd9Sstevel@tonic-gate array = getlist(&np);
592*7c478bd9Sstevel@tonic-gate if (array->n_type == PARM)
593*7c478bd9Sstevel@tonic-gate array = array->n_next;
594*7c478bd9Sstevel@tonic-gate if (array->n_type != ARRAY)
595*7c478bd9Sstevel@tonic-gate awkerr(gettext("%s function requires an array"),
596*7c478bd9Sstevel@tonic-gate s_asort);
597*7c478bd9Sstevel@tonic-gate funcname = exprstring(getlist(&np));
598*7c478bd9Sstevel@tonic-gate if ((funcnp = vlookup(funcname, 1)) == NNULL
599*7c478bd9Sstevel@tonic-gate || funcnp->n_type != UFUNC)
600*7c478bd9Sstevel@tonic-gate awkerr(gettext("%s: %s is not a function\n"),
601*7c478bd9Sstevel@tonic-gate s_asort, funcname);
602*7c478bd9Sstevel@tonic-gate /*
603*7c478bd9Sstevel@tonic-gate * Count size of array, allowing one extra for NULL at end
604*7c478bd9Sstevel@tonic-gate */
605*7c478bd9Sstevel@tonic-gate nel = 1;
606*7c478bd9Sstevel@tonic-gate for (tnp = array->n_alink; tnp != NNULL; tnp = tnp->n_alink)
607*7c478bd9Sstevel@tonic-gate ++nel;
608*7c478bd9Sstevel@tonic-gate /*
609*7c478bd9Sstevel@tonic-gate * Create UFUNC node that points at the funcnp on left and the
610*7c478bd9Sstevel@tonic-gate * list of three variables on right (array, index1, index2)
611*7c478bd9Sstevel@tonic-gate * UFUNC
612*7c478bd9Sstevel@tonic-gate * / \
613*7c478bd9Sstevel@tonic-gate * funcnp COMMA
614*7c478bd9Sstevel@tonic-gate * / \
615*7c478bd9Sstevel@tonic-gate * array COMMA
616*7c478bd9Sstevel@tonic-gate * / \
617*7c478bd9Sstevel@tonic-gate * index1 index2
618*7c478bd9Sstevel@tonic-gate */
619*7c478bd9Sstevel@tonic-gate if (asortfunc == NNULL) {
620*7c478bd9Sstevel@tonic-gate running = 0;
621*7c478bd9Sstevel@tonic-gate asortfunc = node(CALLUFUNC, NNULL,
622*7c478bd9Sstevel@tonic-gate node(COMMA, NNULL,
623*7c478bd9Sstevel@tonic-gate node(COMMA,
624*7c478bd9Sstevel@tonic-gate asnp1=stringnode(_null, FSTATIC, 0),
625*7c478bd9Sstevel@tonic-gate asnp2=stringnode(_null, FSTATIC, 0))));
626*7c478bd9Sstevel@tonic-gate running = 1;
627*7c478bd9Sstevel@tonic-gate }
628*7c478bd9Sstevel@tonic-gate asortfunc->n_left = funcnp;
629*7c478bd9Sstevel@tonic-gate asortfunc->n_right->n_left = array;
630*7c478bd9Sstevel@tonic-gate asarraylen = wcslen(array->n_name)+1;
631*7c478bd9Sstevel@tonic-gate alist = (NODE **) emalloc(nel*sizeof(NODE *));
632*7c478bd9Sstevel@tonic-gate /*
633*7c478bd9Sstevel@tonic-gate * Copy array into alist.
634*7c478bd9Sstevel@tonic-gate */
635*7c478bd9Sstevel@tonic-gate npp = alist;
636*7c478bd9Sstevel@tonic-gate for (tnp = array->n_alink; tnp != NNULL; tnp = tnp->n_alink)
637*7c478bd9Sstevel@tonic-gate *npp++ = tnp;
638*7c478bd9Sstevel@tonic-gate *npp = NNULL;
639*7c478bd9Sstevel@tonic-gate /*
640*7c478bd9Sstevel@tonic-gate * Re-order array to this list
641*7c478bd9Sstevel@tonic-gate */
642*7c478bd9Sstevel@tonic-gate qsort((wchar_t *)alist, nel-1, sizeof (NODE *), asortcmp);
643*7c478bd9Sstevel@tonic-gate tnp = array;
644*7c478bd9Sstevel@tonic-gate npp = alist;
645*7c478bd9Sstevel@tonic-gate do {
646*7c478bd9Sstevel@tonic-gate tnp = tnp->n_alink = *npp;
647*7c478bd9Sstevel@tonic-gate } while (*npp++ != NNULL);
648*7c478bd9Sstevel@tonic-gate free((wchar_t *)alist);
649*7c478bd9Sstevel@tonic-gate return (constundef);
650*7c478bd9Sstevel@tonic-gate }
651*7c478bd9Sstevel@tonic-gate
652*7c478bd9Sstevel@tonic-gate /*
653*7c478bd9Sstevel@tonic-gate * Return the number of arguments of a function.
654*7c478bd9Sstevel@tonic-gate */
655*7c478bd9Sstevel@tonic-gate static uint
nargs(NODE * np)656*7c478bd9Sstevel@tonic-gate nargs(NODE *np)
657*7c478bd9Sstevel@tonic-gate {
658*7c478bd9Sstevel@tonic-gate register int n;
659*7c478bd9Sstevel@tonic-gate
660*7c478bd9Sstevel@tonic-gate if (np == NNULL)
661*7c478bd9Sstevel@tonic-gate return (0);
662*7c478bd9Sstevel@tonic-gate n = 1;
663*7c478bd9Sstevel@tonic-gate while (np!=NNULL && np->n_type==COMMA) {
664*7c478bd9Sstevel@tonic-gate np = np->n_right;
665*7c478bd9Sstevel@tonic-gate n++;
666*7c478bd9Sstevel@tonic-gate }
667*7c478bd9Sstevel@tonic-gate return (n);
668*7c478bd9Sstevel@tonic-gate }
669*7c478bd9Sstevel@tonic-gate
670*7c478bd9Sstevel@tonic-gate /*
671*7c478bd9Sstevel@tonic-gate * Do case translation.
672*7c478bd9Sstevel@tonic-gate */
673*7c478bd9Sstevel@tonic-gate static NODE *
docasetr(NODE * np,int upper)674*7c478bd9Sstevel@tonic-gate docasetr(NODE *np, int upper)
675*7c478bd9Sstevel@tonic-gate {
676*7c478bd9Sstevel@tonic-gate register int c;
677*7c478bd9Sstevel@tonic-gate register wchar_t *cp;
678*7c478bd9Sstevel@tonic-gate register wchar_t *str;
679*7c478bd9Sstevel@tonic-gate register uint na;
680*7c478bd9Sstevel@tonic-gate
681*7c478bd9Sstevel@tonic-gate if ((na = nargs(np)) > 1)
682*7c478bd9Sstevel@tonic-gate awkerr(nargerr, upper ? s_toupper : s_tolower);
683*7c478bd9Sstevel@tonic-gate str = strsave(na==0 ? linebuf : exprstring(getlist(&np)));
684*7c478bd9Sstevel@tonic-gate cp = str;
685*7c478bd9Sstevel@tonic-gate if (upper) {
686*7c478bd9Sstevel@tonic-gate while ((c = *cp++) != '\0')
687*7c478bd9Sstevel@tonic-gate cp[-1] = towupper(c);
688*7c478bd9Sstevel@tonic-gate } else {
689*7c478bd9Sstevel@tonic-gate while ((c = *cp++) != '\0')
690*7c478bd9Sstevel@tonic-gate cp[-1] = towlower(c);
691*7c478bd9Sstevel@tonic-gate }
692*7c478bd9Sstevel@tonic-gate return (stringnode((STRING)str, FNOALLOC, (size_t)(cp-str-1)));
693*7c478bd9Sstevel@tonic-gate }
694*7c478bd9Sstevel@tonic-gate
695*7c478bd9Sstevel@tonic-gate /*
696*7c478bd9Sstevel@tonic-gate * The comparison routine used by qsort inside f_asort()
697*7c478bd9Sstevel@tonic-gate */
698*7c478bd9Sstevel@tonic-gate static int
asortcmp(const void * npp1,const void * npp2)699*7c478bd9Sstevel@tonic-gate asortcmp(const void *npp1, const void *npp2)
700*7c478bd9Sstevel@tonic-gate {
701*7c478bd9Sstevel@tonic-gate asnp1->n_strlen =
702*7c478bd9Sstevel@tonic-gate wcslen(asnp1->n_string = (*(NODE **)npp1)->n_name+asarraylen);
703*7c478bd9Sstevel@tonic-gate asnp2->n_strlen =
704*7c478bd9Sstevel@tonic-gate wcslen(asnp2->n_string = (*(NODE **)npp2)->n_name+asarraylen);
705*7c478bd9Sstevel@tonic-gate return ((int)exprint(asortfunc));
706*7c478bd9Sstevel@tonic-gate }
707*7c478bd9Sstevel@tonic-gate
708*7c478bd9Sstevel@tonic-gate #if M_MATHERR
709*7c478bd9Sstevel@tonic-gate #if !defined(__BORLANDC__)&&defined(__TURBOC__)&&__COMPACT__&&__EMULATE__
710*7c478bd9Sstevel@tonic-gate /* So it won't optimize registers our FP is using */
711*7c478bd9Sstevel@tonic-gate #define flushesbx() (_BX = 0, _ES = _BX)
712*7c478bd9Sstevel@tonic-gate #else
713*7c478bd9Sstevel@tonic-gate #define flushesbx() (0)
714*7c478bd9Sstevel@tonic-gate #endif
715*7c478bd9Sstevel@tonic-gate
716*7c478bd9Sstevel@tonic-gate /*
717*7c478bd9Sstevel@tonic-gate * Math error for awk.
718*7c478bd9Sstevel@tonic-gate */
719*7c478bd9Sstevel@tonic-gate int
matherr(struct exception * ep)720*7c478bd9Sstevel@tonic-gate matherr(struct exception *ep)
721*7c478bd9Sstevel@tonic-gate {
722*7c478bd9Sstevel@tonic-gate register uint type;
723*7c478bd9Sstevel@tonic-gate static char msgs[7][256];
724*7c478bd9Sstevel@tonic-gate static int first_time = 1;
725*7c478bd9Sstevel@tonic-gate
726*7c478bd9Sstevel@tonic-gate if (first_time) {
727*7c478bd9Sstevel@tonic-gate msgs[0] = gettext("Unknown FP error"),
728*7c478bd9Sstevel@tonic-gate msgs[1] = gettext("Domain"),
729*7c478bd9Sstevel@tonic-gate msgs[2] = gettext("Singularity"),
730*7c478bd9Sstevel@tonic-gate msgs[3] = gettext("Overflow"),
731*7c478bd9Sstevel@tonic-gate msgs[4] = gettext("Underflow"),
732*7c478bd9Sstevel@tonic-gate msgs[5] = gettext("Total loss of precision"),
733*7c478bd9Sstevel@tonic-gate msgs[6] = gettext("Partial loss of precision")
734*7c478bd9Sstevel@tonic-gate first_time = 0;
735*7c478bd9Sstevel@tonic-gate }
736*7c478bd9Sstevel@tonic-gate
737*7c478bd9Sstevel@tonic-gate if ((type = ep->type) > (uint)PLOSS)
738*7c478bd9Sstevel@tonic-gate type = 0;
739*7c478bd9Sstevel@tonic-gate (void)fprintf(stderr, "awk: %s", strmsg(msgs[type]));
740*7c478bd9Sstevel@tonic-gate (void)fprintf(stderr, gettext(
741*7c478bd9Sstevel@tonic-gate " error in function %s(%g) at NR=%lld\n"),
742*7c478bd9Sstevel@tonic-gate ((void) flushesbx(), ep->name), ep->arg1, (INT)exprint(varNR));
743*7c478bd9Sstevel@tonic-gate return (1);
744*7c478bd9Sstevel@tonic-gate }
745*7c478bd9Sstevel@tonic-gate #endif /*M_MATHERR*/
746