xref: /titanic_52/usr/src/cmd/expr/expr.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
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 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
23*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
24*7c478bd9Sstevel@tonic-gate 
25*7c478bd9Sstevel@tonic-gate 
26*7c478bd9Sstevel@tonic-gate /*
27*7c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
28*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
29*7c478bd9Sstevel@tonic-gate  */
30*7c478bd9Sstevel@tonic-gate 
31*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
32*7c478bd9Sstevel@tonic-gate 
33*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
34*7c478bd9Sstevel@tonic-gate #include <regexpr.h>
35*7c478bd9Sstevel@tonic-gate #include <locale.h>
36*7c478bd9Sstevel@tonic-gate #include <string.h>
37*7c478bd9Sstevel@tonic-gate #include <unistd.h>
38*7c478bd9Sstevel@tonic-gate #include <regex.h>
39*7c478bd9Sstevel@tonic-gate #include <limits.h>
40*7c478bd9Sstevel@tonic-gate #include <stdio.h>
41*7c478bd9Sstevel@tonic-gate #include <ctype.h>
42*7c478bd9Sstevel@tonic-gate #include <errno.h>
43*7c478bd9Sstevel@tonic-gate 
44*7c478bd9Sstevel@tonic-gate #define	A_STRING 258
45*7c478bd9Sstevel@tonic-gate #define	NOARG 259
46*7c478bd9Sstevel@tonic-gate #define	OR 260
47*7c478bd9Sstevel@tonic-gate #define	AND 261
48*7c478bd9Sstevel@tonic-gate #define	EQ 262
49*7c478bd9Sstevel@tonic-gate #define	LT 263
50*7c478bd9Sstevel@tonic-gate #define	GT 264
51*7c478bd9Sstevel@tonic-gate #define	GEQ 265
52*7c478bd9Sstevel@tonic-gate #define	LEQ 266
53*7c478bd9Sstevel@tonic-gate #define	NEQ 267
54*7c478bd9Sstevel@tonic-gate #define	ADD 268
55*7c478bd9Sstevel@tonic-gate #define	SUBT 269
56*7c478bd9Sstevel@tonic-gate #define	MULT 270
57*7c478bd9Sstevel@tonic-gate #define	DIV 271
58*7c478bd9Sstevel@tonic-gate #define	REM 272
59*7c478bd9Sstevel@tonic-gate #define	MCH 273
60*7c478bd9Sstevel@tonic-gate #define	MATCH 274
61*7c478bd9Sstevel@tonic-gate #ifdef  _iBCS2
62*7c478bd9Sstevel@tonic-gate #define	SUBSTR 276
63*7c478bd9Sstevel@tonic-gate #define	LENGTH 277
64*7c478bd9Sstevel@tonic-gate #define	INDEX  278
65*7c478bd9Sstevel@tonic-gate #endif  /* _iBCS2 */
66*7c478bd9Sstevel@tonic-gate 
67*7c478bd9Sstevel@tonic-gate /* size of subexpression array */
68*7c478bd9Sstevel@tonic-gate #define	MSIZE	LINE_MAX
69*7c478bd9Sstevel@tonic-gate #define	error(c)	errxx()
70*7c478bd9Sstevel@tonic-gate #define	EQL(x, y) (strcmp(x, y) == 0)
71*7c478bd9Sstevel@tonic-gate 
72*7c478bd9Sstevel@tonic-gate #define	ERROR(c)	errxx()
73*7c478bd9Sstevel@tonic-gate #define	MAX_MATCH 20
74*7c478bd9Sstevel@tonic-gate static int ematch(char *, char *);
75*7c478bd9Sstevel@tonic-gate static void yyerror(char *);
76*7c478bd9Sstevel@tonic-gate static void errxx();
77*7c478bd9Sstevel@tonic-gate static void *exprmalloc(size_t size);
78*7c478bd9Sstevel@tonic-gate 
79*7c478bd9Sstevel@tonic-gate long atol();
80*7c478bd9Sstevel@tonic-gate char *strcpy(), *strncpy();
81*7c478bd9Sstevel@tonic-gate void exit();
82*7c478bd9Sstevel@tonic-gate 
83*7c478bd9Sstevel@tonic-gate static char *ltoa();
84*7c478bd9Sstevel@tonic-gate static char *lltoa();
85*7c478bd9Sstevel@tonic-gate static char	**Av;
86*7c478bd9Sstevel@tonic-gate static char *buf;
87*7c478bd9Sstevel@tonic-gate static int	Ac;
88*7c478bd9Sstevel@tonic-gate static int	Argi;
89*7c478bd9Sstevel@tonic-gate static int noarg;
90*7c478bd9Sstevel@tonic-gate static int paren;
91*7c478bd9Sstevel@tonic-gate #ifdef  _iBCS2
92*7c478bd9Sstevel@tonic-gate char    *sysv3_set;
93*7c478bd9Sstevel@tonic-gate #endif  /* _iBCS2 */
94*7c478bd9Sstevel@tonic-gate /*
95*7c478bd9Sstevel@tonic-gate  *	Array used to store subexpressions in regular expressions
96*7c478bd9Sstevel@tonic-gate  *	Only one subexpression allowed per regular expression currently
97*7c478bd9Sstevel@tonic-gate  */
98*7c478bd9Sstevel@tonic-gate static char Mstring[1][MSIZE];
99*7c478bd9Sstevel@tonic-gate 
100*7c478bd9Sstevel@tonic-gate 
101*7c478bd9Sstevel@tonic-gate static char *operator[] = {
102*7c478bd9Sstevel@tonic-gate 	"|", "&", "+", "-", "*", "/", "%", ":",
103*7c478bd9Sstevel@tonic-gate 	"=", "==", "<", "<=", ">", ">=", "!=",
104*7c478bd9Sstevel@tonic-gate 	"match",
105*7c478bd9Sstevel@tonic-gate #ifdef	_iBCS2
106*7c478bd9Sstevel@tonic-gate 	"substr", "length", "index",
107*7c478bd9Sstevel@tonic-gate #endif	/* _iBCS2 */
108*7c478bd9Sstevel@tonic-gate 	"\0" };
109*7c478bd9Sstevel@tonic-gate static	int op[] = {
110*7c478bd9Sstevel@tonic-gate 	OR, AND, ADD,  SUBT, MULT, DIV, REM, MCH,
111*7c478bd9Sstevel@tonic-gate 	EQ, EQ, LT, LEQ, GT, GEQ, NEQ,
112*7c478bd9Sstevel@tonic-gate 	MATCH
113*7c478bd9Sstevel@tonic-gate #ifdef	_iBCS2
114*7c478bd9Sstevel@tonic-gate , SUBSTR, LENGTH, INDEX
115*7c478bd9Sstevel@tonic-gate #endif	/* _iBCS2 */
116*7c478bd9Sstevel@tonic-gate 	};
117*7c478bd9Sstevel@tonic-gate static	int pri[] = {
118*7c478bd9Sstevel@tonic-gate 	1, 2, 3, 3, 3, 3, 3, 3, 4, 4, 5, 5, 5, 6, 7
119*7c478bd9Sstevel@tonic-gate #ifdef	_iBCS2
120*7c478bd9Sstevel@tonic-gate , 7, 7, 7
121*7c478bd9Sstevel@tonic-gate #endif	/* _iBCS2 */
122*7c478bd9Sstevel@tonic-gate 	};
123*7c478bd9Sstevel@tonic-gate 
124*7c478bd9Sstevel@tonic-gate 
125*7c478bd9Sstevel@tonic-gate /*
126*7c478bd9Sstevel@tonic-gate  * clean_buf - XCU4 mod to remove leading zeros from negative signed
127*7c478bd9Sstevel@tonic-gate  *		numeric output, e.g., -00001 becomes -1
128*7c478bd9Sstevel@tonic-gate  */
129*7c478bd9Sstevel@tonic-gate static void
130*7c478bd9Sstevel@tonic-gate clean_buf(buf)
131*7c478bd9Sstevel@tonic-gate 	char *buf;
132*7c478bd9Sstevel@tonic-gate {
133*7c478bd9Sstevel@tonic-gate 	int i = 0;
134*7c478bd9Sstevel@tonic-gate 	int is_a_num = 1;
135*7c478bd9Sstevel@tonic-gate 	int len;
136*7c478bd9Sstevel@tonic-gate 	long long num;
137*7c478bd9Sstevel@tonic-gate 
138*7c478bd9Sstevel@tonic-gate 	if (buf[0] == '\0')
139*7c478bd9Sstevel@tonic-gate 		return;
140*7c478bd9Sstevel@tonic-gate 	len = strlen(buf);
141*7c478bd9Sstevel@tonic-gate 	if (len <= 0)
142*7c478bd9Sstevel@tonic-gate 		return;
143*7c478bd9Sstevel@tonic-gate 
144*7c478bd9Sstevel@tonic-gate 	if (buf[0] == '-') {
145*7c478bd9Sstevel@tonic-gate 		i++;		/* Skip the leading '-' see while loop */
146*7c478bd9Sstevel@tonic-gate 		if (len <= 1)	/* Is it a '-' all by itself? */
147*7c478bd9Sstevel@tonic-gate 			return; /* Yes, so return */
148*7c478bd9Sstevel@tonic-gate 
149*7c478bd9Sstevel@tonic-gate 		while (i < len) {
150*7c478bd9Sstevel@tonic-gate 			if (! isdigit(buf[i])) {
151*7c478bd9Sstevel@tonic-gate 				is_a_num = 0;
152*7c478bd9Sstevel@tonic-gate 				break;
153*7c478bd9Sstevel@tonic-gate 			}
154*7c478bd9Sstevel@tonic-gate 			i++;
155*7c478bd9Sstevel@tonic-gate 		}
156*7c478bd9Sstevel@tonic-gate 		if (is_a_num) {
157*7c478bd9Sstevel@tonic-gate 			(void) sscanf(buf, "%lld", &num);
158*7c478bd9Sstevel@tonic-gate 			(void) sprintf(buf, "%lld", num);
159*7c478bd9Sstevel@tonic-gate 		}
160*7c478bd9Sstevel@tonic-gate 	}
161*7c478bd9Sstevel@tonic-gate }
162*7c478bd9Sstevel@tonic-gate 
163*7c478bd9Sstevel@tonic-gate /*
164*7c478bd9Sstevel@tonic-gate  * End XCU4 mods.
165*7c478bd9Sstevel@tonic-gate  */
166*7c478bd9Sstevel@tonic-gate 
167*7c478bd9Sstevel@tonic-gate static int
168*7c478bd9Sstevel@tonic-gate yylex()
169*7c478bd9Sstevel@tonic-gate {
170*7c478bd9Sstevel@tonic-gate 	char *p;
171*7c478bd9Sstevel@tonic-gate 	int i;
172*7c478bd9Sstevel@tonic-gate 
173*7c478bd9Sstevel@tonic-gate 	if (Argi >= Ac)
174*7c478bd9Sstevel@tonic-gate 		return (NOARG);
175*7c478bd9Sstevel@tonic-gate 
176*7c478bd9Sstevel@tonic-gate 	p = Av[Argi];
177*7c478bd9Sstevel@tonic-gate 
178*7c478bd9Sstevel@tonic-gate 	if ((*p == '(' || *p == ')') && p[1] == '\0')
179*7c478bd9Sstevel@tonic-gate 		return ((int)*p);
180*7c478bd9Sstevel@tonic-gate 	for (i = 0; *operator[i]; ++i)
181*7c478bd9Sstevel@tonic-gate 		if (EQL(operator[i], p))
182*7c478bd9Sstevel@tonic-gate 			return (op[i]);
183*7c478bd9Sstevel@tonic-gate 
184*7c478bd9Sstevel@tonic-gate 
185*7c478bd9Sstevel@tonic-gate 	return (A_STRING);
186*7c478bd9Sstevel@tonic-gate }
187*7c478bd9Sstevel@tonic-gate 
188*7c478bd9Sstevel@tonic-gate static char
189*7c478bd9Sstevel@tonic-gate *rel(oper, r1, r2) register char *r1, *r2;
190*7c478bd9Sstevel@tonic-gate {
191*7c478bd9Sstevel@tonic-gate 	long long i;
192*7c478bd9Sstevel@tonic-gate 
193*7c478bd9Sstevel@tonic-gate 	if (ematch(r1, "-\\{0,1\\}[0-9]*$") &&
194*7c478bd9Sstevel@tonic-gate 	    ematch(r2, "-\\{0,1\\}[0-9]*$")) {
195*7c478bd9Sstevel@tonic-gate 		errno = 0;
196*7c478bd9Sstevel@tonic-gate 		i = strtoll(r1, (char **)NULL, 10) -
197*7c478bd9Sstevel@tonic-gate 		    strtoll(r2, (char **)NULL, 10);
198*7c478bd9Sstevel@tonic-gate 		if (errno) {
199*7c478bd9Sstevel@tonic-gate #ifdef XPG6
200*7c478bd9Sstevel@tonic-gate 		/* XPG6: stdout will always contain newline even on error */
201*7c478bd9Sstevel@tonic-gate 			(void) write(1, "\n", 1);
202*7c478bd9Sstevel@tonic-gate #endif
203*7c478bd9Sstevel@tonic-gate 			if (errno == ERANGE) {
204*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, gettext(
205*7c478bd9Sstevel@tonic-gate 				    "expr: Integer argument too large\n"));
206*7c478bd9Sstevel@tonic-gate 				exit(3);
207*7c478bd9Sstevel@tonic-gate 			} else {
208*7c478bd9Sstevel@tonic-gate 				perror("expr");
209*7c478bd9Sstevel@tonic-gate 				exit(3);
210*7c478bd9Sstevel@tonic-gate 			}
211*7c478bd9Sstevel@tonic-gate 		}
212*7c478bd9Sstevel@tonic-gate 	}
213*7c478bd9Sstevel@tonic-gate 	else
214*7c478bd9Sstevel@tonic-gate 		i = strcoll(r1, r2);
215*7c478bd9Sstevel@tonic-gate 	switch (oper) {
216*7c478bd9Sstevel@tonic-gate 	case EQ:
217*7c478bd9Sstevel@tonic-gate 		i = i == 0;
218*7c478bd9Sstevel@tonic-gate 		break;
219*7c478bd9Sstevel@tonic-gate 	case GT:
220*7c478bd9Sstevel@tonic-gate 		i = i > 0;
221*7c478bd9Sstevel@tonic-gate 		break;
222*7c478bd9Sstevel@tonic-gate 	case GEQ:
223*7c478bd9Sstevel@tonic-gate 		i = i >= 0;
224*7c478bd9Sstevel@tonic-gate 		break;
225*7c478bd9Sstevel@tonic-gate 	case LT:
226*7c478bd9Sstevel@tonic-gate 		i = i < 0;
227*7c478bd9Sstevel@tonic-gate 		break;
228*7c478bd9Sstevel@tonic-gate 	case LEQ:
229*7c478bd9Sstevel@tonic-gate 		i = i <= 0;
230*7c478bd9Sstevel@tonic-gate 		break;
231*7c478bd9Sstevel@tonic-gate 	case NEQ:
232*7c478bd9Sstevel@tonic-gate 		i = i != 0;
233*7c478bd9Sstevel@tonic-gate 		break;
234*7c478bd9Sstevel@tonic-gate 	}
235*7c478bd9Sstevel@tonic-gate 	return (i ? "1": "0");
236*7c478bd9Sstevel@tonic-gate }
237*7c478bd9Sstevel@tonic-gate 
238*7c478bd9Sstevel@tonic-gate static char
239*7c478bd9Sstevel@tonic-gate *arith(oper, r1, r2) char *r1, *r2;
240*7c478bd9Sstevel@tonic-gate {
241*7c478bd9Sstevel@tonic-gate 	long long i1, i2;
242*7c478bd9Sstevel@tonic-gate 	register char *rv;
243*7c478bd9Sstevel@tonic-gate 
244*7c478bd9Sstevel@tonic-gate 	if (!(ematch(r1, "-\\{0,1\\}[0-9]*$") &&
245*7c478bd9Sstevel@tonic-gate 	    ematch(r2, "-\\{0,1\\}[0-9]*$")))
246*7c478bd9Sstevel@tonic-gate 		yyerror("non-numeric argument");
247*7c478bd9Sstevel@tonic-gate 	errno = 0;
248*7c478bd9Sstevel@tonic-gate 	i1 = strtoll(r1, (char **)NULL, 10);
249*7c478bd9Sstevel@tonic-gate 	i2 = strtoll(r2, (char **)NULL, 10);
250*7c478bd9Sstevel@tonic-gate 	if (errno) {
251*7c478bd9Sstevel@tonic-gate #ifdef XPG6
252*7c478bd9Sstevel@tonic-gate 	/* XPG6: stdout will always contain newline even on error */
253*7c478bd9Sstevel@tonic-gate 		(void) write(1, "\n", 1);
254*7c478bd9Sstevel@tonic-gate #endif
255*7c478bd9Sstevel@tonic-gate 		if (errno == ERANGE) {
256*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(
257*7c478bd9Sstevel@tonic-gate 			    "expr: Integer argument too large\n"));
258*7c478bd9Sstevel@tonic-gate 			exit(3);
259*7c478bd9Sstevel@tonic-gate 		} else {
260*7c478bd9Sstevel@tonic-gate 			perror("expr");
261*7c478bd9Sstevel@tonic-gate 			exit(3);
262*7c478bd9Sstevel@tonic-gate 		}
263*7c478bd9Sstevel@tonic-gate 	}
264*7c478bd9Sstevel@tonic-gate 
265*7c478bd9Sstevel@tonic-gate 	switch (oper) {
266*7c478bd9Sstevel@tonic-gate 	case ADD:
267*7c478bd9Sstevel@tonic-gate 		i1 = i1 + i2;
268*7c478bd9Sstevel@tonic-gate 		break;
269*7c478bd9Sstevel@tonic-gate 	case SUBT:
270*7c478bd9Sstevel@tonic-gate 		i1 = i1 - i2;
271*7c478bd9Sstevel@tonic-gate 		break;
272*7c478bd9Sstevel@tonic-gate 	case MULT:
273*7c478bd9Sstevel@tonic-gate 		i1 = i1 * i2;
274*7c478bd9Sstevel@tonic-gate 		break;
275*7c478bd9Sstevel@tonic-gate 	case DIV:
276*7c478bd9Sstevel@tonic-gate 		if (i2 == 0)
277*7c478bd9Sstevel@tonic-gate 			yyerror("division by zero");
278*7c478bd9Sstevel@tonic-gate 		i1 = i1 / i2;
279*7c478bd9Sstevel@tonic-gate 		break;
280*7c478bd9Sstevel@tonic-gate 	case REM:
281*7c478bd9Sstevel@tonic-gate 		if (i2 == 0)
282*7c478bd9Sstevel@tonic-gate 			yyerror("division by zero");
283*7c478bd9Sstevel@tonic-gate 		i1 = i1 % i2;
284*7c478bd9Sstevel@tonic-gate 		break;
285*7c478bd9Sstevel@tonic-gate 	}
286*7c478bd9Sstevel@tonic-gate 	rv = exprmalloc(25);
287*7c478bd9Sstevel@tonic-gate 	(void) strcpy(rv, lltoa(i1));
288*7c478bd9Sstevel@tonic-gate 	return (rv);
289*7c478bd9Sstevel@tonic-gate }
290*7c478bd9Sstevel@tonic-gate 
291*7c478bd9Sstevel@tonic-gate static char
292*7c478bd9Sstevel@tonic-gate *conj(oper, r1, r2)
293*7c478bd9Sstevel@tonic-gate 	char *r1, *r2;
294*7c478bd9Sstevel@tonic-gate {
295*7c478bd9Sstevel@tonic-gate 	register char *rv;
296*7c478bd9Sstevel@tonic-gate 
297*7c478bd9Sstevel@tonic-gate 	switch (oper) {
298*7c478bd9Sstevel@tonic-gate 
299*7c478bd9Sstevel@tonic-gate 	case OR:
300*7c478bd9Sstevel@tonic-gate 		if (EQL(r1, "0") || EQL(r1, "")) {
301*7c478bd9Sstevel@tonic-gate 			if (EQL(r2, "0") || EQL(r2, ""))
302*7c478bd9Sstevel@tonic-gate 				rv = "0";
303*7c478bd9Sstevel@tonic-gate 			else
304*7c478bd9Sstevel@tonic-gate 				rv = r2;
305*7c478bd9Sstevel@tonic-gate 		} else
306*7c478bd9Sstevel@tonic-gate 			rv = r1;
307*7c478bd9Sstevel@tonic-gate 		break;
308*7c478bd9Sstevel@tonic-gate 	case AND:
309*7c478bd9Sstevel@tonic-gate 		if (EQL(r1, "0") || EQL(r1, ""))
310*7c478bd9Sstevel@tonic-gate 			rv = "0";
311*7c478bd9Sstevel@tonic-gate 		else if (EQL(r2, "0") || EQL(r2, ""))
312*7c478bd9Sstevel@tonic-gate 			rv = "0";
313*7c478bd9Sstevel@tonic-gate 		else
314*7c478bd9Sstevel@tonic-gate 			rv = r1;
315*7c478bd9Sstevel@tonic-gate 		break;
316*7c478bd9Sstevel@tonic-gate 	}
317*7c478bd9Sstevel@tonic-gate 	return (rv);
318*7c478bd9Sstevel@tonic-gate }
319*7c478bd9Sstevel@tonic-gate 
320*7c478bd9Sstevel@tonic-gate #ifdef	_iBCS2
321*7c478bd9Sstevel@tonic-gate char *
322*7c478bd9Sstevel@tonic-gate substr(char *v, char *s, char *w)
323*7c478bd9Sstevel@tonic-gate {
324*7c478bd9Sstevel@tonic-gate 	int si, wi;
325*7c478bd9Sstevel@tonic-gate 	char *res;
326*7c478bd9Sstevel@tonic-gate 
327*7c478bd9Sstevel@tonic-gate 	si = atol(s);
328*7c478bd9Sstevel@tonic-gate 	wi = atol(w);
329*7c478bd9Sstevel@tonic-gate 	while (--si)
330*7c478bd9Sstevel@tonic-gate 		if (*v) ++v;
331*7c478bd9Sstevel@tonic-gate 
332*7c478bd9Sstevel@tonic-gate 	res = v;
333*7c478bd9Sstevel@tonic-gate 
334*7c478bd9Sstevel@tonic-gate 	while (wi--)
335*7c478bd9Sstevel@tonic-gate 		if (*v) ++v;
336*7c478bd9Sstevel@tonic-gate 
337*7c478bd9Sstevel@tonic-gate 	*v = '\0';
338*7c478bd9Sstevel@tonic-gate 	return (res);
339*7c478bd9Sstevel@tonic-gate }
340*7c478bd9Sstevel@tonic-gate 
341*7c478bd9Sstevel@tonic-gate char *
342*7c478bd9Sstevel@tonic-gate index(char *s, char *t)
343*7c478bd9Sstevel@tonic-gate {
344*7c478bd9Sstevel@tonic-gate 	long i, j;
345*7c478bd9Sstevel@tonic-gate 	char *rv;
346*7c478bd9Sstevel@tonic-gate 
347*7c478bd9Sstevel@tonic-gate 	for (i = 0; s[i]; ++i)
348*7c478bd9Sstevel@tonic-gate 		for (j = 0; t[j]; ++j)
349*7c478bd9Sstevel@tonic-gate 			if (s[i] == t[j]) {
350*7c478bd9Sstevel@tonic-gate 				(void) strcpy(rv = exprmalloc(8), ltoa(++i));
351*7c478bd9Sstevel@tonic-gate 				return (rv);
352*7c478bd9Sstevel@tonic-gate 			}
353*7c478bd9Sstevel@tonic-gate 	return ("0");
354*7c478bd9Sstevel@tonic-gate }
355*7c478bd9Sstevel@tonic-gate 
356*7c478bd9Sstevel@tonic-gate char *
357*7c478bd9Sstevel@tonic-gate length(char *s)
358*7c478bd9Sstevel@tonic-gate {
359*7c478bd9Sstevel@tonic-gate 	long i = 0;
360*7c478bd9Sstevel@tonic-gate 	char *rv;
361*7c478bd9Sstevel@tonic-gate 
362*7c478bd9Sstevel@tonic-gate 	while (*s++) ++i;
363*7c478bd9Sstevel@tonic-gate 
364*7c478bd9Sstevel@tonic-gate 	rv = exprmalloc(8);
365*7c478bd9Sstevel@tonic-gate 	(void) strcpy(rv, ltoa(i));
366*7c478bd9Sstevel@tonic-gate 	return (rv);
367*7c478bd9Sstevel@tonic-gate }
368*7c478bd9Sstevel@tonic-gate #endif	/* _iBCS2 */
369*7c478bd9Sstevel@tonic-gate 
370*7c478bd9Sstevel@tonic-gate static char *
371*7c478bd9Sstevel@tonic-gate match(char *s, char *p)
372*7c478bd9Sstevel@tonic-gate {
373*7c478bd9Sstevel@tonic-gate 	char *rv;
374*7c478bd9Sstevel@tonic-gate 	long val;			/* XCU4 */
375*7c478bd9Sstevel@tonic-gate 
376*7c478bd9Sstevel@tonic-gate 	(void) strcpy(rv = exprmalloc(8), ltoa(val = (long)ematch(s, p)));
377*7c478bd9Sstevel@tonic-gate 	if (nbra /* && val != 0 */) {
378*7c478bd9Sstevel@tonic-gate 		rv = exprmalloc((unsigned)strlen(Mstring[0]) + 1);
379*7c478bd9Sstevel@tonic-gate 		(void) strcpy(rv, Mstring[0]);
380*7c478bd9Sstevel@tonic-gate 	}
381*7c478bd9Sstevel@tonic-gate 	return (rv);
382*7c478bd9Sstevel@tonic-gate }
383*7c478bd9Sstevel@tonic-gate 
384*7c478bd9Sstevel@tonic-gate 
385*7c478bd9Sstevel@tonic-gate /*
386*7c478bd9Sstevel@tonic-gate  * ematch 	- XCU4 mods involve calling compile/advance which simulate
387*7c478bd9Sstevel@tonic-gate  *		  the obsolete compile/advance functions using regcomp/regexec
388*7c478bd9Sstevel@tonic-gate  */
389*7c478bd9Sstevel@tonic-gate static int
390*7c478bd9Sstevel@tonic-gate ematch(char *s, char *p)
391*7c478bd9Sstevel@tonic-gate {
392*7c478bd9Sstevel@tonic-gate 	static char *expbuf;
393*7c478bd9Sstevel@tonic-gate 	char *nexpbuf;
394*7c478bd9Sstevel@tonic-gate 	int num;
395*7c478bd9Sstevel@tonic-gate #ifdef XPG4
396*7c478bd9Sstevel@tonic-gate 	int nmatch;		/* number of matched bytes */
397*7c478bd9Sstevel@tonic-gate 	char tempbuf[256];
398*7c478bd9Sstevel@tonic-gate 	char *tmptr1 = 0;	/* If tempbuf is not large enough */
399*7c478bd9Sstevel@tonic-gate 	char *tmptr;
400*7c478bd9Sstevel@tonic-gate 	int nmbchars;		/* number characters in multibyte string */
401*7c478bd9Sstevel@tonic-gate #endif
402*7c478bd9Sstevel@tonic-gate 
403*7c478bd9Sstevel@tonic-gate 	nexpbuf = compile(p, (char *)0, (char *)0);	/* XCU4 regex mod */
404*7c478bd9Sstevel@tonic-gate 	if (0 /* XXX nbra > 1*/)
405*7c478bd9Sstevel@tonic-gate 		yyerror("Too many '\\('s");
406*7c478bd9Sstevel@tonic-gate 	if (regerrno) {
407*7c478bd9Sstevel@tonic-gate 		if (regerrno != 41 || expbuf == NULL)
408*7c478bd9Sstevel@tonic-gate 			errxx();
409*7c478bd9Sstevel@tonic-gate 	} else {
410*7c478bd9Sstevel@tonic-gate 		if (expbuf)
411*7c478bd9Sstevel@tonic-gate 			free(expbuf);
412*7c478bd9Sstevel@tonic-gate 		expbuf = nexpbuf;
413*7c478bd9Sstevel@tonic-gate 	}
414*7c478bd9Sstevel@tonic-gate 	if (advance(s, expbuf)) {
415*7c478bd9Sstevel@tonic-gate 		if (nbra > 0) {
416*7c478bd9Sstevel@tonic-gate 			p = braslist[0];
417*7c478bd9Sstevel@tonic-gate 			num = braelist[0] - p;
418*7c478bd9Sstevel@tonic-gate 			if ((num > MSIZE - 1) || (num < 0))
419*7c478bd9Sstevel@tonic-gate 				yyerror("string too long");
420*7c478bd9Sstevel@tonic-gate 			(void) strncpy(Mstring[0], p, num);
421*7c478bd9Sstevel@tonic-gate 			Mstring[0][num] = '\0';
422*7c478bd9Sstevel@tonic-gate 		}
423*7c478bd9Sstevel@tonic-gate #ifdef XPG4
424*7c478bd9Sstevel@tonic-gate 		/*
425*7c478bd9Sstevel@tonic-gate 		 *  Use mbstowcs to find the number of multibyte characters
426*7c478bd9Sstevel@tonic-gate 		 *  in the multibyte string beginning at s, and
427*7c478bd9Sstevel@tonic-gate 		 *  ending at loc2.  Create a separate string
428*7c478bd9Sstevel@tonic-gate 		 *  of the substring, so it can be passed to mbstowcs.
429*7c478bd9Sstevel@tonic-gate 		 */
430*7c478bd9Sstevel@tonic-gate 		nmatch = loc2 - s;
431*7c478bd9Sstevel@tonic-gate 		if (nmatch > ((sizeof (tempbuf) / sizeof (char)) - 1)) {
432*7c478bd9Sstevel@tonic-gate 			tmptr1 = exprmalloc(nmatch + 1);
433*7c478bd9Sstevel@tonic-gate 			tmptr = tmptr1;
434*7c478bd9Sstevel@tonic-gate 		} else {
435*7c478bd9Sstevel@tonic-gate 			tmptr = tempbuf;
436*7c478bd9Sstevel@tonic-gate 		}
437*7c478bd9Sstevel@tonic-gate 		memcpy(tmptr, s, nmatch);
438*7c478bd9Sstevel@tonic-gate 		*(tmptr + nmatch) = '\0';
439*7c478bd9Sstevel@tonic-gate 		if ((nmbchars = mbstowcs(NULL, tmptr, NULL)) == -1) {
440*7c478bd9Sstevel@tonic-gate 			yyerror("invalid multibyte character encountered");
441*7c478bd9Sstevel@tonic-gate 			if (tmptr1 != NULL)
442*7c478bd9Sstevel@tonic-gate 				free(tmptr1);
443*7c478bd9Sstevel@tonic-gate 			return (0);
444*7c478bd9Sstevel@tonic-gate 		}
445*7c478bd9Sstevel@tonic-gate 		if (tmptr1 != NULL)
446*7c478bd9Sstevel@tonic-gate 			free(tmptr1);
447*7c478bd9Sstevel@tonic-gate 		return (nmbchars);
448*7c478bd9Sstevel@tonic-gate #else
449*7c478bd9Sstevel@tonic-gate 		return (loc2-s);
450*7c478bd9Sstevel@tonic-gate #endif
451*7c478bd9Sstevel@tonic-gate 	}
452*7c478bd9Sstevel@tonic-gate 	return (0);
453*7c478bd9Sstevel@tonic-gate }
454*7c478bd9Sstevel@tonic-gate 
455*7c478bd9Sstevel@tonic-gate static void
456*7c478bd9Sstevel@tonic-gate errxx()
457*7c478bd9Sstevel@tonic-gate {
458*7c478bd9Sstevel@tonic-gate 	yyerror("RE error");
459*7c478bd9Sstevel@tonic-gate }
460*7c478bd9Sstevel@tonic-gate 
461*7c478bd9Sstevel@tonic-gate static void
462*7c478bd9Sstevel@tonic-gate yyerror(char *s)
463*7c478bd9Sstevel@tonic-gate {
464*7c478bd9Sstevel@tonic-gate #ifdef XPG6
465*7c478bd9Sstevel@tonic-gate 	/* XPG6: stdout will always contain newline even on error */
466*7c478bd9Sstevel@tonic-gate 	(void) write(1, "\n", 1);
467*7c478bd9Sstevel@tonic-gate #endif
468*7c478bd9Sstevel@tonic-gate 	(void) write(2, "expr: ", 6);
469*7c478bd9Sstevel@tonic-gate 	(void) write(2, gettext(s), (unsigned)strlen(gettext(s)));
470*7c478bd9Sstevel@tonic-gate 	(void) write(2, "\n", 1);
471*7c478bd9Sstevel@tonic-gate 	exit(2);
472*7c478bd9Sstevel@tonic-gate 	/* NOTREACHED */
473*7c478bd9Sstevel@tonic-gate }
474*7c478bd9Sstevel@tonic-gate 
475*7c478bd9Sstevel@tonic-gate static char *
476*7c478bd9Sstevel@tonic-gate ltoa(long l)
477*7c478bd9Sstevel@tonic-gate {
478*7c478bd9Sstevel@tonic-gate 	static char str[20];
479*7c478bd9Sstevel@tonic-gate 	char *sp = &str[18];	/* u370 */
480*7c478bd9Sstevel@tonic-gate 	int i;
481*7c478bd9Sstevel@tonic-gate 	int neg = 0;
482*7c478bd9Sstevel@tonic-gate 
483*7c478bd9Sstevel@tonic-gate 	if ((unsigned long)l == 0x80000000UL)
484*7c478bd9Sstevel@tonic-gate 		return ("-2147483648");
485*7c478bd9Sstevel@tonic-gate 	if (l < 0)
486*7c478bd9Sstevel@tonic-gate 		++neg, l = -l;
487*7c478bd9Sstevel@tonic-gate 	str[19] = '\0';
488*7c478bd9Sstevel@tonic-gate 	do {
489*7c478bd9Sstevel@tonic-gate 		i = l % 10;
490*7c478bd9Sstevel@tonic-gate 		*sp-- = '0' + i;
491*7c478bd9Sstevel@tonic-gate 		l /= 10;
492*7c478bd9Sstevel@tonic-gate 	} while (l);
493*7c478bd9Sstevel@tonic-gate 	if (neg)
494*7c478bd9Sstevel@tonic-gate 		*sp-- = '-';
495*7c478bd9Sstevel@tonic-gate 	return (++sp);
496*7c478bd9Sstevel@tonic-gate }
497*7c478bd9Sstevel@tonic-gate 
498*7c478bd9Sstevel@tonic-gate static char *
499*7c478bd9Sstevel@tonic-gate lltoa(long long l)
500*7c478bd9Sstevel@tonic-gate {
501*7c478bd9Sstevel@tonic-gate 	static char str[25];
502*7c478bd9Sstevel@tonic-gate 	char *sp = &str[23];
503*7c478bd9Sstevel@tonic-gate 	int i;
504*7c478bd9Sstevel@tonic-gate 	int neg = 0;
505*7c478bd9Sstevel@tonic-gate 
506*7c478bd9Sstevel@tonic-gate 	if (l == 0x8000000000000000ULL)
507*7c478bd9Sstevel@tonic-gate 		return ("-9223372036854775808");
508*7c478bd9Sstevel@tonic-gate 	if (l < 0)
509*7c478bd9Sstevel@tonic-gate 		++neg, l = -l;
510*7c478bd9Sstevel@tonic-gate 	str[24] = '\0';
511*7c478bd9Sstevel@tonic-gate 	do {
512*7c478bd9Sstevel@tonic-gate 		i = l % 10;
513*7c478bd9Sstevel@tonic-gate 		*sp-- = '0' + i;
514*7c478bd9Sstevel@tonic-gate 		l /= 10;
515*7c478bd9Sstevel@tonic-gate 	} while (l);
516*7c478bd9Sstevel@tonic-gate 	if (neg)
517*7c478bd9Sstevel@tonic-gate 		*sp-- = '-';
518*7c478bd9Sstevel@tonic-gate 	return (++sp);
519*7c478bd9Sstevel@tonic-gate }
520*7c478bd9Sstevel@tonic-gate 
521*7c478bd9Sstevel@tonic-gate static char *
522*7c478bd9Sstevel@tonic-gate expres(int prior, int par)
523*7c478bd9Sstevel@tonic-gate {
524*7c478bd9Sstevel@tonic-gate 	int ylex, temp, op1;
525*7c478bd9Sstevel@tonic-gate 	char *r1, *ra, *rb, *rc;
526*7c478bd9Sstevel@tonic-gate 	ylex = yylex();
527*7c478bd9Sstevel@tonic-gate 	if (ylex >= NOARG && ylex < MATCH) {
528*7c478bd9Sstevel@tonic-gate 		yyerror("syntax error");
529*7c478bd9Sstevel@tonic-gate 	}
530*7c478bd9Sstevel@tonic-gate 	if (ylex == A_STRING) {
531*7c478bd9Sstevel@tonic-gate 		r1 = Av[Argi++];
532*7c478bd9Sstevel@tonic-gate 		temp = Argi;
533*7c478bd9Sstevel@tonic-gate 	} else {
534*7c478bd9Sstevel@tonic-gate 		if (ylex == '(') {
535*7c478bd9Sstevel@tonic-gate 			paren++;
536*7c478bd9Sstevel@tonic-gate 			Argi++;
537*7c478bd9Sstevel@tonic-gate 			r1 = expres(0, Argi);
538*7c478bd9Sstevel@tonic-gate 			Argi--;
539*7c478bd9Sstevel@tonic-gate 		}
540*7c478bd9Sstevel@tonic-gate 	}
541*7c478bd9Sstevel@tonic-gate lop:
542*7c478bd9Sstevel@tonic-gate 	ylex = yylex();
543*7c478bd9Sstevel@tonic-gate 	if (ylex > NOARG && ylex < MATCH) {
544*7c478bd9Sstevel@tonic-gate 		op1 = ylex;
545*7c478bd9Sstevel@tonic-gate 		Argi++;
546*7c478bd9Sstevel@tonic-gate 		if (pri[op1-OR] <= prior)
547*7c478bd9Sstevel@tonic-gate 			return (r1);
548*7c478bd9Sstevel@tonic-gate 		else {
549*7c478bd9Sstevel@tonic-gate 			switch (op1) {
550*7c478bd9Sstevel@tonic-gate 			case OR:
551*7c478bd9Sstevel@tonic-gate 			case AND:
552*7c478bd9Sstevel@tonic-gate 				r1 = conj(op1, r1, expres(pri[op1-OR], 0));
553*7c478bd9Sstevel@tonic-gate 				break;
554*7c478bd9Sstevel@tonic-gate 			case EQ:
555*7c478bd9Sstevel@tonic-gate 			case LT:
556*7c478bd9Sstevel@tonic-gate 			case GT:
557*7c478bd9Sstevel@tonic-gate 			case LEQ:
558*7c478bd9Sstevel@tonic-gate 			case GEQ:
559*7c478bd9Sstevel@tonic-gate 			case NEQ:
560*7c478bd9Sstevel@tonic-gate 				r1 = rel(op1, r1, expres(pri[op1-OR], 0));
561*7c478bd9Sstevel@tonic-gate 				break;
562*7c478bd9Sstevel@tonic-gate 			case ADD:
563*7c478bd9Sstevel@tonic-gate 			case SUBT:
564*7c478bd9Sstevel@tonic-gate 			case MULT:
565*7c478bd9Sstevel@tonic-gate 			case DIV:
566*7c478bd9Sstevel@tonic-gate 			case REM:
567*7c478bd9Sstevel@tonic-gate 				r1 = arith(op1, r1, expres(pri[op1-OR], 0));
568*7c478bd9Sstevel@tonic-gate 				break;
569*7c478bd9Sstevel@tonic-gate 			case MCH:
570*7c478bd9Sstevel@tonic-gate 				r1 = match(r1, expres(pri[op1-OR], 0));
571*7c478bd9Sstevel@tonic-gate 				break;
572*7c478bd9Sstevel@tonic-gate 			}
573*7c478bd9Sstevel@tonic-gate 			if (noarg == 1) {
574*7c478bd9Sstevel@tonic-gate 				return (r1);
575*7c478bd9Sstevel@tonic-gate 			}
576*7c478bd9Sstevel@tonic-gate 			Argi--;
577*7c478bd9Sstevel@tonic-gate 			goto lop;
578*7c478bd9Sstevel@tonic-gate 		}
579*7c478bd9Sstevel@tonic-gate 	}
580*7c478bd9Sstevel@tonic-gate 	ylex = yylex();
581*7c478bd9Sstevel@tonic-gate 	if (ylex == ')') {
582*7c478bd9Sstevel@tonic-gate 		if (par == Argi) {
583*7c478bd9Sstevel@tonic-gate 			yyerror("syntax error");
584*7c478bd9Sstevel@tonic-gate 		}
585*7c478bd9Sstevel@tonic-gate 		if (par != 0) {
586*7c478bd9Sstevel@tonic-gate 			paren--;
587*7c478bd9Sstevel@tonic-gate 			Argi++;
588*7c478bd9Sstevel@tonic-gate 		}
589*7c478bd9Sstevel@tonic-gate 		Argi++;
590*7c478bd9Sstevel@tonic-gate 		return (r1);
591*7c478bd9Sstevel@tonic-gate 	}
592*7c478bd9Sstevel@tonic-gate 	ylex = yylex();
593*7c478bd9Sstevel@tonic-gate #ifdef	_iBCS2
594*7c478bd9Sstevel@tonic-gate 	if (ylex > MCH && ((sysv3_set && ylex <= INDEX) || ylex <= MATCH)) {
595*7c478bd9Sstevel@tonic-gate #else
596*7c478bd9Sstevel@tonic-gate 	if (ylex > MCH && ylex <= MATCH) {
597*7c478bd9Sstevel@tonic-gate #endif	/* _iBCS2 */
598*7c478bd9Sstevel@tonic-gate 		if (Argi == temp) {
599*7c478bd9Sstevel@tonic-gate 			return (r1);
600*7c478bd9Sstevel@tonic-gate 		}
601*7c478bd9Sstevel@tonic-gate 		op1 = ylex;
602*7c478bd9Sstevel@tonic-gate 		Argi++;
603*7c478bd9Sstevel@tonic-gate 		switch (op1) {
604*7c478bd9Sstevel@tonic-gate 		case MATCH:
605*7c478bd9Sstevel@tonic-gate 			rb = expres(pri[op1-OR], 0);
606*7c478bd9Sstevel@tonic-gate 			ra = expres(pri[op1-OR], 0);
607*7c478bd9Sstevel@tonic-gate 			break;
608*7c478bd9Sstevel@tonic-gate #ifdef	_iBCS2
609*7c478bd9Sstevel@tonic-gate 		case SUBSTR:
610*7c478bd9Sstevel@tonic-gate 			rc = expres(pri[op1-OR], 0);
611*7c478bd9Sstevel@tonic-gate 			rb = expres(pri[op1-OR], 0);
612*7c478bd9Sstevel@tonic-gate 			ra = expres(pri[op1-OR], 0);
613*7c478bd9Sstevel@tonic-gate 			break;
614*7c478bd9Sstevel@tonic-gate 		case LENGTH:
615*7c478bd9Sstevel@tonic-gate 			ra = expres(pri[op1-OR], 0);
616*7c478bd9Sstevel@tonic-gate 			break;
617*7c478bd9Sstevel@tonic-gate 		case INDEX:
618*7c478bd9Sstevel@tonic-gate 			rb = expres(pri[op1-OR], 0);
619*7c478bd9Sstevel@tonic-gate 			ra = expres(pri[op1-OR], 0);
620*7c478bd9Sstevel@tonic-gate 			break;
621*7c478bd9Sstevel@tonic-gate #endif	/* _iBCS2 */
622*7c478bd9Sstevel@tonic-gate 		}
623*7c478bd9Sstevel@tonic-gate 		switch (op1) {
624*7c478bd9Sstevel@tonic-gate 		case MATCH:
625*7c478bd9Sstevel@tonic-gate 			r1 = match(rb, ra);
626*7c478bd9Sstevel@tonic-gate 			break;
627*7c478bd9Sstevel@tonic-gate #ifdef	_iBCS2
628*7c478bd9Sstevel@tonic-gate 		case SUBSTR:
629*7c478bd9Sstevel@tonic-gate 			r1 = substr(rc, rb, ra);
630*7c478bd9Sstevel@tonic-gate 			break;
631*7c478bd9Sstevel@tonic-gate 		case LENGTH:
632*7c478bd9Sstevel@tonic-gate 			r1 = length(ra);
633*7c478bd9Sstevel@tonic-gate 			break;
634*7c478bd9Sstevel@tonic-gate 		case INDEX:
635*7c478bd9Sstevel@tonic-gate 			r1 = index(rb, ra);
636*7c478bd9Sstevel@tonic-gate 			break;
637*7c478bd9Sstevel@tonic-gate #endif	/* _iBCS2 */
638*7c478bd9Sstevel@tonic-gate 		}
639*7c478bd9Sstevel@tonic-gate 		if (noarg == 1) {
640*7c478bd9Sstevel@tonic-gate 			return (r1);
641*7c478bd9Sstevel@tonic-gate 		}
642*7c478bd9Sstevel@tonic-gate 		Argi--;
643*7c478bd9Sstevel@tonic-gate 		goto lop;
644*7c478bd9Sstevel@tonic-gate 	}
645*7c478bd9Sstevel@tonic-gate 	ylex = yylex();
646*7c478bd9Sstevel@tonic-gate 	if (ylex == NOARG) {
647*7c478bd9Sstevel@tonic-gate 		noarg = 1;
648*7c478bd9Sstevel@tonic-gate 	}
649*7c478bd9Sstevel@tonic-gate 	return (r1);
650*7c478bd9Sstevel@tonic-gate }
651*7c478bd9Sstevel@tonic-gate 
652*7c478bd9Sstevel@tonic-gate void *
653*7c478bd9Sstevel@tonic-gate exprmalloc(size_t size)
654*7c478bd9Sstevel@tonic-gate {
655*7c478bd9Sstevel@tonic-gate 	void *rv;
656*7c478bd9Sstevel@tonic-gate 
657*7c478bd9Sstevel@tonic-gate 	if ((rv = malloc(size)) == NULL) {
658*7c478bd9Sstevel@tonic-gate 		char *s = gettext("malloc error");
659*7c478bd9Sstevel@tonic-gate 
660*7c478bd9Sstevel@tonic-gate 		(void) write(2, "expr: ", 6);
661*7c478bd9Sstevel@tonic-gate 		(void) write(2, s, (unsigned)strlen(s));
662*7c478bd9Sstevel@tonic-gate 		(void) write(2, "\n", 1);
663*7c478bd9Sstevel@tonic-gate 		exit(3);
664*7c478bd9Sstevel@tonic-gate 	}
665*7c478bd9Sstevel@tonic-gate 	return (rv);
666*7c478bd9Sstevel@tonic-gate }
667*7c478bd9Sstevel@tonic-gate 
668*7c478bd9Sstevel@tonic-gate int
669*7c478bd9Sstevel@tonic-gate main(int argc, char **argv)
670*7c478bd9Sstevel@tonic-gate {
671*7c478bd9Sstevel@tonic-gate 	/*
672*7c478bd9Sstevel@tonic-gate 	 * XCU4 allow "--" as argument
673*7c478bd9Sstevel@tonic-gate 	 */
674*7c478bd9Sstevel@tonic-gate 	if (argc > 1 && strcmp(argv[1], "--") == 0)
675*7c478bd9Sstevel@tonic-gate 		argv++, argc--;
676*7c478bd9Sstevel@tonic-gate 	/*
677*7c478bd9Sstevel@tonic-gate 	 * XCU4 - print usage message when invoked without args
678*7c478bd9Sstevel@tonic-gate 	 */
679*7c478bd9Sstevel@tonic-gate 	if (argc < 2) {
680*7c478bd9Sstevel@tonic-gate #ifdef XPG6
681*7c478bd9Sstevel@tonic-gate 	/* XPG6: stdout will always contain newline even on error */
682*7c478bd9Sstevel@tonic-gate 		(void) write(1, "\n", 1);
683*7c478bd9Sstevel@tonic-gate #endif
684*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext("Usage: expr expression\n"));
685*7c478bd9Sstevel@tonic-gate 		exit(3);
686*7c478bd9Sstevel@tonic-gate 	}
687*7c478bd9Sstevel@tonic-gate 	Ac = argc;
688*7c478bd9Sstevel@tonic-gate 	Argi = 1;
689*7c478bd9Sstevel@tonic-gate 	noarg = 0;
690*7c478bd9Sstevel@tonic-gate 	paren = 0;
691*7c478bd9Sstevel@tonic-gate 	Av = argv;
692*7c478bd9Sstevel@tonic-gate #ifdef	_iBCS2
693*7c478bd9Sstevel@tonic-gate 	sysv3_set = getenv("SYSV3");
694*7c478bd9Sstevel@tonic-gate #endif	/* _iBCS2 */
695*7c478bd9Sstevel@tonic-gate 
696*7c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
697*7c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)	/* Should be defined by cc -D */
698*7c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN "SYS_TEST"	/* Use this only if it weren't */
699*7c478bd9Sstevel@tonic-gate #endif
700*7c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
701*7c478bd9Sstevel@tonic-gate 	buf = expres(0, 1);
702*7c478bd9Sstevel@tonic-gate 	if (Ac != Argi || paren != 0) {
703*7c478bd9Sstevel@tonic-gate 		yyerror("syntax error");
704*7c478bd9Sstevel@tonic-gate 	}
705*7c478bd9Sstevel@tonic-gate 	/*
706*7c478bd9Sstevel@tonic-gate 	 * XCU4 - strip leading zeros from numeric output
707*7c478bd9Sstevel@tonic-gate 	 */
708*7c478bd9Sstevel@tonic-gate 	clean_buf(buf);
709*7c478bd9Sstevel@tonic-gate 	(void) write(1, buf, (unsigned)strlen(buf));
710*7c478bd9Sstevel@tonic-gate 	(void) write(1, "\n", 1);
711*7c478bd9Sstevel@tonic-gate 	return ((strcmp(buf, "0") == 0 || buf[0] == 0) ? 1 : 0);
712*7c478bd9Sstevel@tonic-gate }
713