xref: /titanic_52/usr/src/cmd/expr/expr.c (revision 9d14cf08bcba73bac30314cd22629a0fec28f929)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
237c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
247c478bd9Sstevel@tonic-gate 
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate /*
27*9d14cf08Spd155743  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
287c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
297c478bd9Sstevel@tonic-gate  */
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate #include <stdlib.h>
347c478bd9Sstevel@tonic-gate #include <regexpr.h>
357c478bd9Sstevel@tonic-gate #include <locale.h>
367c478bd9Sstevel@tonic-gate #include <string.h>
377c478bd9Sstevel@tonic-gate #include <unistd.h>
387c478bd9Sstevel@tonic-gate #include <regex.h>
397c478bd9Sstevel@tonic-gate #include <limits.h>
407c478bd9Sstevel@tonic-gate #include <stdio.h>
417c478bd9Sstevel@tonic-gate #include <ctype.h>
427c478bd9Sstevel@tonic-gate #include <errno.h>
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate #define	A_STRING 258
457c478bd9Sstevel@tonic-gate #define	NOARG 259
467c478bd9Sstevel@tonic-gate #define	OR 260
477c478bd9Sstevel@tonic-gate #define	AND 261
487c478bd9Sstevel@tonic-gate #define	EQ 262
497c478bd9Sstevel@tonic-gate #define	LT 263
507c478bd9Sstevel@tonic-gate #define	GT 264
517c478bd9Sstevel@tonic-gate #define	GEQ 265
527c478bd9Sstevel@tonic-gate #define	LEQ 266
537c478bd9Sstevel@tonic-gate #define	NEQ 267
547c478bd9Sstevel@tonic-gate #define	ADD 268
557c478bd9Sstevel@tonic-gate #define	SUBT 269
567c478bd9Sstevel@tonic-gate #define	MULT 270
577c478bd9Sstevel@tonic-gate #define	DIV 271
587c478bd9Sstevel@tonic-gate #define	REM 272
597c478bd9Sstevel@tonic-gate #define	MCH 273
607c478bd9Sstevel@tonic-gate #define	MATCH 274
617c478bd9Sstevel@tonic-gate #ifdef  _iBCS2
627c478bd9Sstevel@tonic-gate #define	SUBSTR 276
637c478bd9Sstevel@tonic-gate #define	LENGTH 277
647c478bd9Sstevel@tonic-gate #define	INDEX  278
657c478bd9Sstevel@tonic-gate #endif  /* _iBCS2 */
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate /* size of subexpression array */
687c478bd9Sstevel@tonic-gate #define	MSIZE	LINE_MAX
697c478bd9Sstevel@tonic-gate #define	error(c)	errxx()
707c478bd9Sstevel@tonic-gate #define	EQL(x, y) (strcmp(x, y) == 0)
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate #define	ERROR(c)	errxx()
737c478bd9Sstevel@tonic-gate #define	MAX_MATCH 20
747c478bd9Sstevel@tonic-gate static int ematch(char *, char *);
757c478bd9Sstevel@tonic-gate static void yyerror(char *);
767c478bd9Sstevel@tonic-gate static void errxx();
777c478bd9Sstevel@tonic-gate static void *exprmalloc(size_t size);
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate long atol();
807c478bd9Sstevel@tonic-gate char *strcpy(), *strncpy();
817c478bd9Sstevel@tonic-gate void exit();
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate static char *ltoa();
847c478bd9Sstevel@tonic-gate static char *lltoa();
857c478bd9Sstevel@tonic-gate static char	**Av;
867c478bd9Sstevel@tonic-gate static char *buf;
877c478bd9Sstevel@tonic-gate static int	Ac;
887c478bd9Sstevel@tonic-gate static int	Argi;
897c478bd9Sstevel@tonic-gate static int noarg;
907c478bd9Sstevel@tonic-gate static int paren;
917c478bd9Sstevel@tonic-gate #ifdef  _iBCS2
927c478bd9Sstevel@tonic-gate char    *sysv3_set;
937c478bd9Sstevel@tonic-gate #endif  /* _iBCS2 */
947c478bd9Sstevel@tonic-gate /*
957c478bd9Sstevel@tonic-gate  *	Array used to store subexpressions in regular expressions
967c478bd9Sstevel@tonic-gate  *	Only one subexpression allowed per regular expression currently
977c478bd9Sstevel@tonic-gate  */
987c478bd9Sstevel@tonic-gate static char Mstring[1][MSIZE];
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate static char *operator[] = {
1027c478bd9Sstevel@tonic-gate 	"|", "&", "+", "-", "*", "/", "%", ":",
1037c478bd9Sstevel@tonic-gate 	"=", "==", "<", "<=", ">", ">=", "!=",
1047c478bd9Sstevel@tonic-gate 	"match",
1057c478bd9Sstevel@tonic-gate #ifdef	_iBCS2
1067c478bd9Sstevel@tonic-gate 	"substr", "length", "index",
1077c478bd9Sstevel@tonic-gate #endif	/* _iBCS2 */
1087c478bd9Sstevel@tonic-gate 	"\0" };
1097c478bd9Sstevel@tonic-gate static	int op[] = {
1107c478bd9Sstevel@tonic-gate 	OR, AND, ADD,  SUBT, MULT, DIV, REM, MCH,
1117c478bd9Sstevel@tonic-gate 	EQ, EQ, LT, LEQ, GT, GEQ, NEQ,
1127c478bd9Sstevel@tonic-gate 	MATCH
1137c478bd9Sstevel@tonic-gate #ifdef	_iBCS2
1147c478bd9Sstevel@tonic-gate , SUBSTR, LENGTH, INDEX
1157c478bd9Sstevel@tonic-gate #endif	/* _iBCS2 */
1167c478bd9Sstevel@tonic-gate 	};
1177c478bd9Sstevel@tonic-gate static	int pri[] = {
1187c478bd9Sstevel@tonic-gate 	1, 2, 3, 3, 3, 3, 3, 3, 4, 4, 5, 5, 5, 6, 7
1197c478bd9Sstevel@tonic-gate #ifdef	_iBCS2
1207c478bd9Sstevel@tonic-gate , 7, 7, 7
1217c478bd9Sstevel@tonic-gate #endif	/* _iBCS2 */
1227c478bd9Sstevel@tonic-gate 	};
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate /*
1267c478bd9Sstevel@tonic-gate  * clean_buf - XCU4 mod to remove leading zeros from negative signed
1277c478bd9Sstevel@tonic-gate  *		numeric output, e.g., -00001 becomes -1
1287c478bd9Sstevel@tonic-gate  */
1297c478bd9Sstevel@tonic-gate static void
1307c478bd9Sstevel@tonic-gate clean_buf(buf)
1317c478bd9Sstevel@tonic-gate 	char *buf;
1327c478bd9Sstevel@tonic-gate {
1337c478bd9Sstevel@tonic-gate 	int i = 0;
1347c478bd9Sstevel@tonic-gate 	int is_a_num = 1;
1357c478bd9Sstevel@tonic-gate 	int len;
1367c478bd9Sstevel@tonic-gate 	long long num;
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate 	if (buf[0] == '\0')
1397c478bd9Sstevel@tonic-gate 		return;
1407c478bd9Sstevel@tonic-gate 	len = strlen(buf);
1417c478bd9Sstevel@tonic-gate 	if (len <= 0)
1427c478bd9Sstevel@tonic-gate 		return;
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate 	if (buf[0] == '-') {
1457c478bd9Sstevel@tonic-gate 		i++;		/* Skip the leading '-' see while loop */
1467c478bd9Sstevel@tonic-gate 		if (len <= 1)	/* Is it a '-' all by itself? */
1477c478bd9Sstevel@tonic-gate 			return; /* Yes, so return */
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate 		while (i < len) {
1507c478bd9Sstevel@tonic-gate 			if (! isdigit(buf[i])) {
1517c478bd9Sstevel@tonic-gate 				is_a_num = 0;
1527c478bd9Sstevel@tonic-gate 				break;
1537c478bd9Sstevel@tonic-gate 			}
1547c478bd9Sstevel@tonic-gate 			i++;
1557c478bd9Sstevel@tonic-gate 		}
1567c478bd9Sstevel@tonic-gate 		if (is_a_num) {
1577c478bd9Sstevel@tonic-gate 			(void) sscanf(buf, "%lld", &num);
1587c478bd9Sstevel@tonic-gate 			(void) sprintf(buf, "%lld", num);
1597c478bd9Sstevel@tonic-gate 		}
1607c478bd9Sstevel@tonic-gate 	}
1617c478bd9Sstevel@tonic-gate }
1627c478bd9Sstevel@tonic-gate 
1637c478bd9Sstevel@tonic-gate /*
1647c478bd9Sstevel@tonic-gate  * End XCU4 mods.
1657c478bd9Sstevel@tonic-gate  */
1667c478bd9Sstevel@tonic-gate 
1677c478bd9Sstevel@tonic-gate static int
1687c478bd9Sstevel@tonic-gate yylex()
1697c478bd9Sstevel@tonic-gate {
1707c478bd9Sstevel@tonic-gate 	char *p;
1717c478bd9Sstevel@tonic-gate 	int i;
1727c478bd9Sstevel@tonic-gate 
1737c478bd9Sstevel@tonic-gate 	if (Argi >= Ac)
1747c478bd9Sstevel@tonic-gate 		return (NOARG);
1757c478bd9Sstevel@tonic-gate 
1767c478bd9Sstevel@tonic-gate 	p = Av[Argi];
1777c478bd9Sstevel@tonic-gate 
1787c478bd9Sstevel@tonic-gate 	if ((*p == '(' || *p == ')') && p[1] == '\0')
1797c478bd9Sstevel@tonic-gate 		return ((int)*p);
1807c478bd9Sstevel@tonic-gate 	for (i = 0; *operator[i]; ++i)
1817c478bd9Sstevel@tonic-gate 		if (EQL(operator[i], p))
1827c478bd9Sstevel@tonic-gate 			return (op[i]);
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate 	return (A_STRING);
1867c478bd9Sstevel@tonic-gate }
1877c478bd9Sstevel@tonic-gate 
1887c478bd9Sstevel@tonic-gate static char
1897c478bd9Sstevel@tonic-gate *rel(oper, r1, r2) register char *r1, *r2;
1907c478bd9Sstevel@tonic-gate {
191*9d14cf08Spd155743 	long long i, l1, l2;
1927c478bd9Sstevel@tonic-gate 
1937c478bd9Sstevel@tonic-gate 	if (ematch(r1, "-\\{0,1\\}[0-9]*$") &&
1947c478bd9Sstevel@tonic-gate 	    ematch(r2, "-\\{0,1\\}[0-9]*$")) {
1957c478bd9Sstevel@tonic-gate 		errno = 0;
196*9d14cf08Spd155743 		l1 = strtoll(r1, (char **)NULL, 10);
197*9d14cf08Spd155743 		l2 = strtoll(r2, (char **)NULL, 10);
1987c478bd9Sstevel@tonic-gate 		if (errno) {
1997c478bd9Sstevel@tonic-gate #ifdef XPG6
2007c478bd9Sstevel@tonic-gate 		/* XPG6: stdout will always contain newline even on error */
2017c478bd9Sstevel@tonic-gate 			(void) write(1, "\n", 1);
2027c478bd9Sstevel@tonic-gate #endif
2037c478bd9Sstevel@tonic-gate 			if (errno == ERANGE) {
2047c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, gettext(
2057c478bd9Sstevel@tonic-gate 				    "expr: Integer argument too large\n"));
2067c478bd9Sstevel@tonic-gate 				exit(3);
2077c478bd9Sstevel@tonic-gate 			} else {
2087c478bd9Sstevel@tonic-gate 				perror("expr");
2097c478bd9Sstevel@tonic-gate 				exit(3);
2107c478bd9Sstevel@tonic-gate 			}
2117c478bd9Sstevel@tonic-gate 		}
212*9d14cf08Spd155743 		switch (oper) {
213*9d14cf08Spd155743 		case EQ:
214*9d14cf08Spd155743 			i = (l1 == l2);
215*9d14cf08Spd155743 			break;
216*9d14cf08Spd155743 		case GT:
217*9d14cf08Spd155743 			i = (l1 > l2);
218*9d14cf08Spd155743 			break;
219*9d14cf08Spd155743 		case GEQ:
220*9d14cf08Spd155743 			i = (l1 >= l2);
221*9d14cf08Spd155743 			break;
222*9d14cf08Spd155743 		case LT:
223*9d14cf08Spd155743 			i = (l1 < l2);
224*9d14cf08Spd155743 			break;
225*9d14cf08Spd155743 		case LEQ:
226*9d14cf08Spd155743 			i = (l1 <= l2);
227*9d14cf08Spd155743 			break;
228*9d14cf08Spd155743 		case NEQ:
229*9d14cf08Spd155743 			i = (l1 != l2);
230*9d14cf08Spd155743 			break;
231*9d14cf08Spd155743 		}
2327c478bd9Sstevel@tonic-gate 	}
2337c478bd9Sstevel@tonic-gate 	else
234*9d14cf08Spd155743 	{
2357c478bd9Sstevel@tonic-gate 			i = strcoll(r1, r2);
2367c478bd9Sstevel@tonic-gate 		switch (oper) {
2377c478bd9Sstevel@tonic-gate 		case EQ:
2387c478bd9Sstevel@tonic-gate 			i = i == 0;
2397c478bd9Sstevel@tonic-gate 			break;
2407c478bd9Sstevel@tonic-gate 		case GT:
2417c478bd9Sstevel@tonic-gate 			i = i > 0;
2427c478bd9Sstevel@tonic-gate 			break;
2437c478bd9Sstevel@tonic-gate 		case GEQ:
2447c478bd9Sstevel@tonic-gate 			i = i >= 0;
2457c478bd9Sstevel@tonic-gate 			break;
2467c478bd9Sstevel@tonic-gate 		case LT:
2477c478bd9Sstevel@tonic-gate 			i = i < 0;
2487c478bd9Sstevel@tonic-gate 			break;
2497c478bd9Sstevel@tonic-gate 		case LEQ:
2507c478bd9Sstevel@tonic-gate 			i = i <= 0;
2517c478bd9Sstevel@tonic-gate 			break;
2527c478bd9Sstevel@tonic-gate 		case NEQ:
2537c478bd9Sstevel@tonic-gate 			i = i != 0;
2547c478bd9Sstevel@tonic-gate 			break;
2557c478bd9Sstevel@tonic-gate 		}
256*9d14cf08Spd155743 	}
2577c478bd9Sstevel@tonic-gate 	return (i ? "1": "0");
2587c478bd9Sstevel@tonic-gate }
2597c478bd9Sstevel@tonic-gate 
2607c478bd9Sstevel@tonic-gate static char
2617c478bd9Sstevel@tonic-gate *arith(oper, r1, r2) char *r1, *r2;
2627c478bd9Sstevel@tonic-gate {
2637c478bd9Sstevel@tonic-gate 	long long i1, i2;
2647c478bd9Sstevel@tonic-gate 	register char *rv;
2657c478bd9Sstevel@tonic-gate 
2667c478bd9Sstevel@tonic-gate 	if (!(ematch(r1, "-\\{0,1\\}[0-9]*$") &&
2677c478bd9Sstevel@tonic-gate 	    ematch(r2, "-\\{0,1\\}[0-9]*$")))
2687c478bd9Sstevel@tonic-gate 		yyerror("non-numeric argument");
2697c478bd9Sstevel@tonic-gate 	errno = 0;
2707c478bd9Sstevel@tonic-gate 	i1 = strtoll(r1, (char **)NULL, 10);
2717c478bd9Sstevel@tonic-gate 	i2 = strtoll(r2, (char **)NULL, 10);
2727c478bd9Sstevel@tonic-gate 	if (errno) {
2737c478bd9Sstevel@tonic-gate #ifdef XPG6
2747c478bd9Sstevel@tonic-gate 	/* XPG6: stdout will always contain newline even on error */
2757c478bd9Sstevel@tonic-gate 		(void) write(1, "\n", 1);
2767c478bd9Sstevel@tonic-gate #endif
2777c478bd9Sstevel@tonic-gate 		if (errno == ERANGE) {
2787c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(
2797c478bd9Sstevel@tonic-gate 			    "expr: Integer argument too large\n"));
2807c478bd9Sstevel@tonic-gate 			exit(3);
2817c478bd9Sstevel@tonic-gate 		} else {
2827c478bd9Sstevel@tonic-gate 			perror("expr");
2837c478bd9Sstevel@tonic-gate 			exit(3);
2847c478bd9Sstevel@tonic-gate 		}
2857c478bd9Sstevel@tonic-gate 	}
2867c478bd9Sstevel@tonic-gate 
2877c478bd9Sstevel@tonic-gate 	switch (oper) {
2887c478bd9Sstevel@tonic-gate 	case ADD:
2897c478bd9Sstevel@tonic-gate 		i1 = i1 + i2;
2907c478bd9Sstevel@tonic-gate 		break;
2917c478bd9Sstevel@tonic-gate 	case SUBT:
2927c478bd9Sstevel@tonic-gate 		i1 = i1 - i2;
2937c478bd9Sstevel@tonic-gate 		break;
2947c478bd9Sstevel@tonic-gate 	case MULT:
2957c478bd9Sstevel@tonic-gate 		i1 = i1 * i2;
2967c478bd9Sstevel@tonic-gate 		break;
2977c478bd9Sstevel@tonic-gate 	case DIV:
2987c478bd9Sstevel@tonic-gate 		if (i2 == 0)
2997c478bd9Sstevel@tonic-gate 			yyerror("division by zero");
3007c478bd9Sstevel@tonic-gate 		i1 = i1 / i2;
3017c478bd9Sstevel@tonic-gate 		break;
3027c478bd9Sstevel@tonic-gate 	case REM:
3037c478bd9Sstevel@tonic-gate 		if (i2 == 0)
3047c478bd9Sstevel@tonic-gate 			yyerror("division by zero");
3057c478bd9Sstevel@tonic-gate 		i1 = i1 % i2;
3067c478bd9Sstevel@tonic-gate 		break;
3077c478bd9Sstevel@tonic-gate 	}
3087c478bd9Sstevel@tonic-gate 	rv = exprmalloc(25);
3097c478bd9Sstevel@tonic-gate 	(void) strcpy(rv, lltoa(i1));
3107c478bd9Sstevel@tonic-gate 	return (rv);
3117c478bd9Sstevel@tonic-gate }
3127c478bd9Sstevel@tonic-gate 
3137c478bd9Sstevel@tonic-gate static char
3147c478bd9Sstevel@tonic-gate *conj(oper, r1, r2)
3157c478bd9Sstevel@tonic-gate 	char *r1, *r2;
3167c478bd9Sstevel@tonic-gate {
3177c478bd9Sstevel@tonic-gate 	register char *rv;
3187c478bd9Sstevel@tonic-gate 
3197c478bd9Sstevel@tonic-gate 	switch (oper) {
3207c478bd9Sstevel@tonic-gate 
3217c478bd9Sstevel@tonic-gate 	case OR:
3227c478bd9Sstevel@tonic-gate 		if (EQL(r1, "0") || EQL(r1, "")) {
3237c478bd9Sstevel@tonic-gate 			if (EQL(r2, "0") || EQL(r2, ""))
3247c478bd9Sstevel@tonic-gate 				rv = "0";
3257c478bd9Sstevel@tonic-gate 			else
3267c478bd9Sstevel@tonic-gate 				rv = r2;
3277c478bd9Sstevel@tonic-gate 		} else
3287c478bd9Sstevel@tonic-gate 			rv = r1;
3297c478bd9Sstevel@tonic-gate 		break;
3307c478bd9Sstevel@tonic-gate 	case AND:
3317c478bd9Sstevel@tonic-gate 		if (EQL(r1, "0") || EQL(r1, ""))
3327c478bd9Sstevel@tonic-gate 			rv = "0";
3337c478bd9Sstevel@tonic-gate 		else if (EQL(r2, "0") || EQL(r2, ""))
3347c478bd9Sstevel@tonic-gate 			rv = "0";
3357c478bd9Sstevel@tonic-gate 		else
3367c478bd9Sstevel@tonic-gate 			rv = r1;
3377c478bd9Sstevel@tonic-gate 		break;
3387c478bd9Sstevel@tonic-gate 	}
3397c478bd9Sstevel@tonic-gate 	return (rv);
3407c478bd9Sstevel@tonic-gate }
3417c478bd9Sstevel@tonic-gate 
3427c478bd9Sstevel@tonic-gate #ifdef	_iBCS2
3437c478bd9Sstevel@tonic-gate char *
3447c478bd9Sstevel@tonic-gate substr(char *v, char *s, char *w)
3457c478bd9Sstevel@tonic-gate {
3467c478bd9Sstevel@tonic-gate 	int si, wi;
3477c478bd9Sstevel@tonic-gate 	char *res;
3487c478bd9Sstevel@tonic-gate 
3497c478bd9Sstevel@tonic-gate 	si = atol(s);
3507c478bd9Sstevel@tonic-gate 	wi = atol(w);
3517c478bd9Sstevel@tonic-gate 	while (--si)
3527c478bd9Sstevel@tonic-gate 		if (*v) ++v;
3537c478bd9Sstevel@tonic-gate 
3547c478bd9Sstevel@tonic-gate 	res = v;
3557c478bd9Sstevel@tonic-gate 
3567c478bd9Sstevel@tonic-gate 	while (wi--)
3577c478bd9Sstevel@tonic-gate 		if (*v) ++v;
3587c478bd9Sstevel@tonic-gate 
3597c478bd9Sstevel@tonic-gate 	*v = '\0';
3607c478bd9Sstevel@tonic-gate 	return (res);
3617c478bd9Sstevel@tonic-gate }
3627c478bd9Sstevel@tonic-gate 
3637c478bd9Sstevel@tonic-gate char *
3647c478bd9Sstevel@tonic-gate index(char *s, char *t)
3657c478bd9Sstevel@tonic-gate {
3667c478bd9Sstevel@tonic-gate 	long i, j;
3677c478bd9Sstevel@tonic-gate 	char *rv;
3687c478bd9Sstevel@tonic-gate 
3697c478bd9Sstevel@tonic-gate 	for (i = 0; s[i]; ++i)
3707c478bd9Sstevel@tonic-gate 		for (j = 0; t[j]; ++j)
3717c478bd9Sstevel@tonic-gate 			if (s[i] == t[j]) {
3727c478bd9Sstevel@tonic-gate 				(void) strcpy(rv = exprmalloc(8), ltoa(++i));
3737c478bd9Sstevel@tonic-gate 				return (rv);
3747c478bd9Sstevel@tonic-gate 			}
3757c478bd9Sstevel@tonic-gate 	return ("0");
3767c478bd9Sstevel@tonic-gate }
3777c478bd9Sstevel@tonic-gate 
3787c478bd9Sstevel@tonic-gate char *
3797c478bd9Sstevel@tonic-gate length(char *s)
3807c478bd9Sstevel@tonic-gate {
3817c478bd9Sstevel@tonic-gate 	long i = 0;
3827c478bd9Sstevel@tonic-gate 	char *rv;
3837c478bd9Sstevel@tonic-gate 
3847c478bd9Sstevel@tonic-gate 	while (*s++) ++i;
3857c478bd9Sstevel@tonic-gate 
3867c478bd9Sstevel@tonic-gate 	rv = exprmalloc(8);
3877c478bd9Sstevel@tonic-gate 	(void) strcpy(rv, ltoa(i));
3887c478bd9Sstevel@tonic-gate 	return (rv);
3897c478bd9Sstevel@tonic-gate }
3907c478bd9Sstevel@tonic-gate #endif	/* _iBCS2 */
3917c478bd9Sstevel@tonic-gate 
3927c478bd9Sstevel@tonic-gate static char *
3937c478bd9Sstevel@tonic-gate match(char *s, char *p)
3947c478bd9Sstevel@tonic-gate {
3957c478bd9Sstevel@tonic-gate 	char *rv;
3967c478bd9Sstevel@tonic-gate 	long val;			/* XCU4 */
3977c478bd9Sstevel@tonic-gate 
3987c478bd9Sstevel@tonic-gate 	(void) strcpy(rv = exprmalloc(8), ltoa(val = (long)ematch(s, p)));
3997c478bd9Sstevel@tonic-gate 	if (nbra /* && val != 0 */) {
4007c478bd9Sstevel@tonic-gate 		rv = exprmalloc((unsigned)strlen(Mstring[0]) + 1);
4017c478bd9Sstevel@tonic-gate 		(void) strcpy(rv, Mstring[0]);
4027c478bd9Sstevel@tonic-gate 	}
4037c478bd9Sstevel@tonic-gate 	return (rv);
4047c478bd9Sstevel@tonic-gate }
4057c478bd9Sstevel@tonic-gate 
4067c478bd9Sstevel@tonic-gate 
4077c478bd9Sstevel@tonic-gate /*
4087c478bd9Sstevel@tonic-gate  * ematch 	- XCU4 mods involve calling compile/advance which simulate
4097c478bd9Sstevel@tonic-gate  *		  the obsolete compile/advance functions using regcomp/regexec
4107c478bd9Sstevel@tonic-gate  */
4117c478bd9Sstevel@tonic-gate static int
4127c478bd9Sstevel@tonic-gate ematch(char *s, char *p)
4137c478bd9Sstevel@tonic-gate {
4147c478bd9Sstevel@tonic-gate 	static char *expbuf;
4157c478bd9Sstevel@tonic-gate 	char *nexpbuf;
4167c478bd9Sstevel@tonic-gate 	int num;
4177c478bd9Sstevel@tonic-gate #ifdef XPG4
4187c478bd9Sstevel@tonic-gate 	int nmatch;		/* number of matched bytes */
4197c478bd9Sstevel@tonic-gate 	char tempbuf[256];
4207c478bd9Sstevel@tonic-gate 	char *tmptr1 = 0;	/* If tempbuf is not large enough */
4217c478bd9Sstevel@tonic-gate 	char *tmptr;
4227c478bd9Sstevel@tonic-gate 	int nmbchars;		/* number characters in multibyte string */
4237c478bd9Sstevel@tonic-gate #endif
4247c478bd9Sstevel@tonic-gate 
4257c478bd9Sstevel@tonic-gate 	nexpbuf = compile(p, (char *)0, (char *)0);	/* XCU4 regex mod */
4267c478bd9Sstevel@tonic-gate 	if (0 /* XXX nbra > 1*/)
4277c478bd9Sstevel@tonic-gate 		yyerror("Too many '\\('s");
4287c478bd9Sstevel@tonic-gate 	if (regerrno) {
4297c478bd9Sstevel@tonic-gate 		if (regerrno != 41 || expbuf == NULL)
4307c478bd9Sstevel@tonic-gate 			errxx();
4317c478bd9Sstevel@tonic-gate 	} else {
4327c478bd9Sstevel@tonic-gate 		if (expbuf)
4337c478bd9Sstevel@tonic-gate 			free(expbuf);
4347c478bd9Sstevel@tonic-gate 		expbuf = nexpbuf;
4357c478bd9Sstevel@tonic-gate 	}
4367c478bd9Sstevel@tonic-gate 	if (advance(s, expbuf)) {
4377c478bd9Sstevel@tonic-gate 		if (nbra > 0) {
4387c478bd9Sstevel@tonic-gate 			p = braslist[0];
4397c478bd9Sstevel@tonic-gate 			num = braelist[0] - p;
4407c478bd9Sstevel@tonic-gate 			if ((num > MSIZE - 1) || (num < 0))
4417c478bd9Sstevel@tonic-gate 				yyerror("string too long");
4427c478bd9Sstevel@tonic-gate 			(void) strncpy(Mstring[0], p, num);
4437c478bd9Sstevel@tonic-gate 			Mstring[0][num] = '\0';
4447c478bd9Sstevel@tonic-gate 		}
4457c478bd9Sstevel@tonic-gate #ifdef XPG4
4467c478bd9Sstevel@tonic-gate 		/*
4477c478bd9Sstevel@tonic-gate 		 *  Use mbstowcs to find the number of multibyte characters
4487c478bd9Sstevel@tonic-gate 		 *  in the multibyte string beginning at s, and
4497c478bd9Sstevel@tonic-gate 		 *  ending at loc2.  Create a separate string
4507c478bd9Sstevel@tonic-gate 		 *  of the substring, so it can be passed to mbstowcs.
4517c478bd9Sstevel@tonic-gate 		 */
4527c478bd9Sstevel@tonic-gate 		nmatch = loc2 - s;
4537c478bd9Sstevel@tonic-gate 		if (nmatch > ((sizeof (tempbuf) / sizeof (char)) - 1)) {
4547c478bd9Sstevel@tonic-gate 			tmptr1 = exprmalloc(nmatch + 1);
4557c478bd9Sstevel@tonic-gate 			tmptr = tmptr1;
4567c478bd9Sstevel@tonic-gate 		} else {
4577c478bd9Sstevel@tonic-gate 			tmptr = tempbuf;
4587c478bd9Sstevel@tonic-gate 		}
4597c478bd9Sstevel@tonic-gate 		memcpy(tmptr, s, nmatch);
4607c478bd9Sstevel@tonic-gate 		*(tmptr + nmatch) = '\0';
4617c478bd9Sstevel@tonic-gate 		if ((nmbchars = mbstowcs(NULL, tmptr, NULL)) == -1) {
4627c478bd9Sstevel@tonic-gate 			yyerror("invalid multibyte character encountered");
4637c478bd9Sstevel@tonic-gate 			if (tmptr1 != NULL)
4647c478bd9Sstevel@tonic-gate 				free(tmptr1);
4657c478bd9Sstevel@tonic-gate 			return (0);
4667c478bd9Sstevel@tonic-gate 		}
4677c478bd9Sstevel@tonic-gate 		if (tmptr1 != NULL)
4687c478bd9Sstevel@tonic-gate 			free(tmptr1);
4697c478bd9Sstevel@tonic-gate 		return (nmbchars);
4707c478bd9Sstevel@tonic-gate #else
4717c478bd9Sstevel@tonic-gate 		return (loc2-s);
4727c478bd9Sstevel@tonic-gate #endif
4737c478bd9Sstevel@tonic-gate 	}
4747c478bd9Sstevel@tonic-gate 	return (0);
4757c478bd9Sstevel@tonic-gate }
4767c478bd9Sstevel@tonic-gate 
4777c478bd9Sstevel@tonic-gate static void
4787c478bd9Sstevel@tonic-gate errxx()
4797c478bd9Sstevel@tonic-gate {
4807c478bd9Sstevel@tonic-gate 	yyerror("RE error");
4817c478bd9Sstevel@tonic-gate }
4827c478bd9Sstevel@tonic-gate 
4837c478bd9Sstevel@tonic-gate static void
4847c478bd9Sstevel@tonic-gate yyerror(char *s)
4857c478bd9Sstevel@tonic-gate {
4867c478bd9Sstevel@tonic-gate #ifdef XPG6
4877c478bd9Sstevel@tonic-gate 	/* XPG6: stdout will always contain newline even on error */
4887c478bd9Sstevel@tonic-gate 	(void) write(1, "\n", 1);
4897c478bd9Sstevel@tonic-gate #endif
4907c478bd9Sstevel@tonic-gate 	(void) write(2, "expr: ", 6);
4917c478bd9Sstevel@tonic-gate 	(void) write(2, gettext(s), (unsigned)strlen(gettext(s)));
4927c478bd9Sstevel@tonic-gate 	(void) write(2, "\n", 1);
4937c478bd9Sstevel@tonic-gate 	exit(2);
4947c478bd9Sstevel@tonic-gate 	/* NOTREACHED */
4957c478bd9Sstevel@tonic-gate }
4967c478bd9Sstevel@tonic-gate 
4977c478bd9Sstevel@tonic-gate static char *
4987c478bd9Sstevel@tonic-gate ltoa(long l)
4997c478bd9Sstevel@tonic-gate {
5007c478bd9Sstevel@tonic-gate 	static char str[20];
5017c478bd9Sstevel@tonic-gate 	char *sp = &str[18];	/* u370 */
5027c478bd9Sstevel@tonic-gate 	int i;
5037c478bd9Sstevel@tonic-gate 	int neg = 0;
5047c478bd9Sstevel@tonic-gate 
5057c478bd9Sstevel@tonic-gate 	if ((unsigned long)l == 0x80000000UL)
5067c478bd9Sstevel@tonic-gate 		return ("-2147483648");
5077c478bd9Sstevel@tonic-gate 	if (l < 0)
5087c478bd9Sstevel@tonic-gate 		++neg, l = -l;
5097c478bd9Sstevel@tonic-gate 	str[19] = '\0';
5107c478bd9Sstevel@tonic-gate 	do {
5117c478bd9Sstevel@tonic-gate 		i = l % 10;
5127c478bd9Sstevel@tonic-gate 		*sp-- = '0' + i;
5137c478bd9Sstevel@tonic-gate 		l /= 10;
5147c478bd9Sstevel@tonic-gate 	} while (l);
5157c478bd9Sstevel@tonic-gate 	if (neg)
5167c478bd9Sstevel@tonic-gate 		*sp-- = '-';
5177c478bd9Sstevel@tonic-gate 	return (++sp);
5187c478bd9Sstevel@tonic-gate }
5197c478bd9Sstevel@tonic-gate 
5207c478bd9Sstevel@tonic-gate static char *
5217c478bd9Sstevel@tonic-gate lltoa(long long l)
5227c478bd9Sstevel@tonic-gate {
5237c478bd9Sstevel@tonic-gate 	static char str[25];
5247c478bd9Sstevel@tonic-gate 	char *sp = &str[23];
5257c478bd9Sstevel@tonic-gate 	int i;
5267c478bd9Sstevel@tonic-gate 	int neg = 0;
5277c478bd9Sstevel@tonic-gate 
5287c478bd9Sstevel@tonic-gate 	if (l == 0x8000000000000000ULL)
5297c478bd9Sstevel@tonic-gate 		return ("-9223372036854775808");
5307c478bd9Sstevel@tonic-gate 	if (l < 0)
5317c478bd9Sstevel@tonic-gate 		++neg, l = -l;
5327c478bd9Sstevel@tonic-gate 	str[24] = '\0';
5337c478bd9Sstevel@tonic-gate 	do {
5347c478bd9Sstevel@tonic-gate 		i = l % 10;
5357c478bd9Sstevel@tonic-gate 		*sp-- = '0' + i;
5367c478bd9Sstevel@tonic-gate 		l /= 10;
5377c478bd9Sstevel@tonic-gate 	} while (l);
5387c478bd9Sstevel@tonic-gate 	if (neg)
5397c478bd9Sstevel@tonic-gate 		*sp-- = '-';
5407c478bd9Sstevel@tonic-gate 	return (++sp);
5417c478bd9Sstevel@tonic-gate }
5427c478bd9Sstevel@tonic-gate 
5437c478bd9Sstevel@tonic-gate static char *
5447c478bd9Sstevel@tonic-gate expres(int prior, int par)
5457c478bd9Sstevel@tonic-gate {
5467c478bd9Sstevel@tonic-gate 	int ylex, temp, op1;
5477c478bd9Sstevel@tonic-gate 	char *r1, *ra, *rb, *rc;
5487c478bd9Sstevel@tonic-gate 	ylex = yylex();
5497c478bd9Sstevel@tonic-gate 	if (ylex >= NOARG && ylex < MATCH) {
5507c478bd9Sstevel@tonic-gate 		yyerror("syntax error");
5517c478bd9Sstevel@tonic-gate 	}
5527c478bd9Sstevel@tonic-gate 	if (ylex == A_STRING) {
5537c478bd9Sstevel@tonic-gate 		r1 = Av[Argi++];
5547c478bd9Sstevel@tonic-gate 		temp = Argi;
5557c478bd9Sstevel@tonic-gate 	} else {
5567c478bd9Sstevel@tonic-gate 		if (ylex == '(') {
5577c478bd9Sstevel@tonic-gate 			paren++;
5587c478bd9Sstevel@tonic-gate 			Argi++;
5597c478bd9Sstevel@tonic-gate 			r1 = expres(0, Argi);
5607c478bd9Sstevel@tonic-gate 			Argi--;
5617c478bd9Sstevel@tonic-gate 		}
5627c478bd9Sstevel@tonic-gate 	}
5637c478bd9Sstevel@tonic-gate lop:
5647c478bd9Sstevel@tonic-gate 	ylex = yylex();
5657c478bd9Sstevel@tonic-gate 	if (ylex > NOARG && ylex < MATCH) {
5667c478bd9Sstevel@tonic-gate 		op1 = ylex;
5677c478bd9Sstevel@tonic-gate 		Argi++;
5687c478bd9Sstevel@tonic-gate 		if (pri[op1-OR] <= prior)
5697c478bd9Sstevel@tonic-gate 			return (r1);
5707c478bd9Sstevel@tonic-gate 		else {
5717c478bd9Sstevel@tonic-gate 			switch (op1) {
5727c478bd9Sstevel@tonic-gate 			case OR:
5737c478bd9Sstevel@tonic-gate 			case AND:
5747c478bd9Sstevel@tonic-gate 				r1 = conj(op1, r1, expres(pri[op1-OR], 0));
5757c478bd9Sstevel@tonic-gate 				break;
5767c478bd9Sstevel@tonic-gate 			case EQ:
5777c478bd9Sstevel@tonic-gate 			case LT:
5787c478bd9Sstevel@tonic-gate 			case GT:
5797c478bd9Sstevel@tonic-gate 			case LEQ:
5807c478bd9Sstevel@tonic-gate 			case GEQ:
5817c478bd9Sstevel@tonic-gate 			case NEQ:
5827c478bd9Sstevel@tonic-gate 				r1 = rel(op1, r1, expres(pri[op1-OR], 0));
5837c478bd9Sstevel@tonic-gate 				break;
5847c478bd9Sstevel@tonic-gate 			case ADD:
5857c478bd9Sstevel@tonic-gate 			case SUBT:
5867c478bd9Sstevel@tonic-gate 			case MULT:
5877c478bd9Sstevel@tonic-gate 			case DIV:
5887c478bd9Sstevel@tonic-gate 			case REM:
5897c478bd9Sstevel@tonic-gate 				r1 = arith(op1, r1, expres(pri[op1-OR], 0));
5907c478bd9Sstevel@tonic-gate 				break;
5917c478bd9Sstevel@tonic-gate 			case MCH:
5927c478bd9Sstevel@tonic-gate 				r1 = match(r1, expres(pri[op1-OR], 0));
5937c478bd9Sstevel@tonic-gate 				break;
5947c478bd9Sstevel@tonic-gate 			}
5957c478bd9Sstevel@tonic-gate 			if (noarg == 1) {
5967c478bd9Sstevel@tonic-gate 				return (r1);
5977c478bd9Sstevel@tonic-gate 			}
5987c478bd9Sstevel@tonic-gate 			Argi--;
5997c478bd9Sstevel@tonic-gate 			goto lop;
6007c478bd9Sstevel@tonic-gate 		}
6017c478bd9Sstevel@tonic-gate 	}
6027c478bd9Sstevel@tonic-gate 	ylex = yylex();
6037c478bd9Sstevel@tonic-gate 	if (ylex == ')') {
6047c478bd9Sstevel@tonic-gate 		if (par == Argi) {
6057c478bd9Sstevel@tonic-gate 			yyerror("syntax error");
6067c478bd9Sstevel@tonic-gate 		}
6077c478bd9Sstevel@tonic-gate 		if (par != 0) {
6087c478bd9Sstevel@tonic-gate 			paren--;
6097c478bd9Sstevel@tonic-gate 			Argi++;
6107c478bd9Sstevel@tonic-gate 		}
6117c478bd9Sstevel@tonic-gate 		Argi++;
6127c478bd9Sstevel@tonic-gate 		return (r1);
6137c478bd9Sstevel@tonic-gate 	}
6147c478bd9Sstevel@tonic-gate 	ylex = yylex();
6157c478bd9Sstevel@tonic-gate #ifdef	_iBCS2
6167c478bd9Sstevel@tonic-gate 	if (ylex > MCH && ((sysv3_set && ylex <= INDEX) || ylex <= MATCH)) {
6177c478bd9Sstevel@tonic-gate #else
6187c478bd9Sstevel@tonic-gate 	if (ylex > MCH && ylex <= MATCH) {
6197c478bd9Sstevel@tonic-gate #endif	/* _iBCS2 */
6207c478bd9Sstevel@tonic-gate 		if (Argi == temp) {
6217c478bd9Sstevel@tonic-gate 			return (r1);
6227c478bd9Sstevel@tonic-gate 		}
6237c478bd9Sstevel@tonic-gate 		op1 = ylex;
6247c478bd9Sstevel@tonic-gate 		Argi++;
6257c478bd9Sstevel@tonic-gate 		switch (op1) {
6267c478bd9Sstevel@tonic-gate 		case MATCH:
6277c478bd9Sstevel@tonic-gate 			rb = expres(pri[op1-OR], 0);
6287c478bd9Sstevel@tonic-gate 			ra = expres(pri[op1-OR], 0);
6297c478bd9Sstevel@tonic-gate 			break;
6307c478bd9Sstevel@tonic-gate #ifdef	_iBCS2
6317c478bd9Sstevel@tonic-gate 		case SUBSTR:
6327c478bd9Sstevel@tonic-gate 			rc = expres(pri[op1-OR], 0);
6337c478bd9Sstevel@tonic-gate 			rb = expres(pri[op1-OR], 0);
6347c478bd9Sstevel@tonic-gate 			ra = expres(pri[op1-OR], 0);
6357c478bd9Sstevel@tonic-gate 			break;
6367c478bd9Sstevel@tonic-gate 		case LENGTH:
6377c478bd9Sstevel@tonic-gate 			ra = expres(pri[op1-OR], 0);
6387c478bd9Sstevel@tonic-gate 			break;
6397c478bd9Sstevel@tonic-gate 		case INDEX:
6407c478bd9Sstevel@tonic-gate 			rb = expres(pri[op1-OR], 0);
6417c478bd9Sstevel@tonic-gate 			ra = expres(pri[op1-OR], 0);
6427c478bd9Sstevel@tonic-gate 			break;
6437c478bd9Sstevel@tonic-gate #endif	/* _iBCS2 */
6447c478bd9Sstevel@tonic-gate 		}
6457c478bd9Sstevel@tonic-gate 		switch (op1) {
6467c478bd9Sstevel@tonic-gate 		case MATCH:
6477c478bd9Sstevel@tonic-gate 			r1 = match(rb, ra);
6487c478bd9Sstevel@tonic-gate 			break;
6497c478bd9Sstevel@tonic-gate #ifdef	_iBCS2
6507c478bd9Sstevel@tonic-gate 		case SUBSTR:
6517c478bd9Sstevel@tonic-gate 			r1 = substr(rc, rb, ra);
6527c478bd9Sstevel@tonic-gate 			break;
6537c478bd9Sstevel@tonic-gate 		case LENGTH:
6547c478bd9Sstevel@tonic-gate 			r1 = length(ra);
6557c478bd9Sstevel@tonic-gate 			break;
6567c478bd9Sstevel@tonic-gate 		case INDEX:
6577c478bd9Sstevel@tonic-gate 			r1 = index(rb, ra);
6587c478bd9Sstevel@tonic-gate 			break;
6597c478bd9Sstevel@tonic-gate #endif	/* _iBCS2 */
6607c478bd9Sstevel@tonic-gate 		}
6617c478bd9Sstevel@tonic-gate 		if (noarg == 1) {
6627c478bd9Sstevel@tonic-gate 			return (r1);
6637c478bd9Sstevel@tonic-gate 		}
6647c478bd9Sstevel@tonic-gate 		Argi--;
6657c478bd9Sstevel@tonic-gate 		goto lop;
6667c478bd9Sstevel@tonic-gate 	}
6677c478bd9Sstevel@tonic-gate 	ylex = yylex();
6687c478bd9Sstevel@tonic-gate 	if (ylex == NOARG) {
6697c478bd9Sstevel@tonic-gate 		noarg = 1;
6707c478bd9Sstevel@tonic-gate 	}
6717c478bd9Sstevel@tonic-gate 	return (r1);
6727c478bd9Sstevel@tonic-gate }
6737c478bd9Sstevel@tonic-gate 
6747c478bd9Sstevel@tonic-gate void *
6757c478bd9Sstevel@tonic-gate exprmalloc(size_t size)
6767c478bd9Sstevel@tonic-gate {
6777c478bd9Sstevel@tonic-gate 	void *rv;
6787c478bd9Sstevel@tonic-gate 
6797c478bd9Sstevel@tonic-gate 	if ((rv = malloc(size)) == NULL) {
6807c478bd9Sstevel@tonic-gate 		char *s = gettext("malloc error");
6817c478bd9Sstevel@tonic-gate 
6827c478bd9Sstevel@tonic-gate 		(void) write(2, "expr: ", 6);
6837c478bd9Sstevel@tonic-gate 		(void) write(2, s, (unsigned)strlen(s));
6847c478bd9Sstevel@tonic-gate 		(void) write(2, "\n", 1);
6857c478bd9Sstevel@tonic-gate 		exit(3);
6867c478bd9Sstevel@tonic-gate 	}
6877c478bd9Sstevel@tonic-gate 	return (rv);
6887c478bd9Sstevel@tonic-gate }
6897c478bd9Sstevel@tonic-gate 
6907c478bd9Sstevel@tonic-gate int
6917c478bd9Sstevel@tonic-gate main(int argc, char **argv)
6927c478bd9Sstevel@tonic-gate {
6937c478bd9Sstevel@tonic-gate 	/*
6947c478bd9Sstevel@tonic-gate 	 * XCU4 allow "--" as argument
6957c478bd9Sstevel@tonic-gate 	 */
6967c478bd9Sstevel@tonic-gate 	if (argc > 1 && strcmp(argv[1], "--") == 0)
6977c478bd9Sstevel@tonic-gate 		argv++, argc--;
6987c478bd9Sstevel@tonic-gate 	/*
6997c478bd9Sstevel@tonic-gate 	 * XCU4 - print usage message when invoked without args
7007c478bd9Sstevel@tonic-gate 	 */
7017c478bd9Sstevel@tonic-gate 	if (argc < 2) {
7027c478bd9Sstevel@tonic-gate #ifdef XPG6
7037c478bd9Sstevel@tonic-gate 	/* XPG6: stdout will always contain newline even on error */
7047c478bd9Sstevel@tonic-gate 		(void) write(1, "\n", 1);
7057c478bd9Sstevel@tonic-gate #endif
7067c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext("Usage: expr expression\n"));
7077c478bd9Sstevel@tonic-gate 		exit(3);
7087c478bd9Sstevel@tonic-gate 	}
7097c478bd9Sstevel@tonic-gate 	Ac = argc;
7107c478bd9Sstevel@tonic-gate 	Argi = 1;
7117c478bd9Sstevel@tonic-gate 	noarg = 0;
7127c478bd9Sstevel@tonic-gate 	paren = 0;
7137c478bd9Sstevel@tonic-gate 	Av = argv;
7147c478bd9Sstevel@tonic-gate #ifdef	_iBCS2
7157c478bd9Sstevel@tonic-gate 	sysv3_set = getenv("SYSV3");
7167c478bd9Sstevel@tonic-gate #endif	/* _iBCS2 */
7177c478bd9Sstevel@tonic-gate 
7187c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
7197c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)	/* Should be defined by cc -D */
7207c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN "SYS_TEST"	/* Use this only if it weren't */
7217c478bd9Sstevel@tonic-gate #endif
7227c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
7237c478bd9Sstevel@tonic-gate 	buf = expres(0, 1);
7247c478bd9Sstevel@tonic-gate 	if (Ac != Argi || paren != 0) {
7257c478bd9Sstevel@tonic-gate 		yyerror("syntax error");
7267c478bd9Sstevel@tonic-gate 	}
7277c478bd9Sstevel@tonic-gate 	/*
7287c478bd9Sstevel@tonic-gate 	 * XCU4 - strip leading zeros from numeric output
7297c478bd9Sstevel@tonic-gate 	 */
7307c478bd9Sstevel@tonic-gate 	clean_buf(buf);
7317c478bd9Sstevel@tonic-gate 	(void) write(1, buf, (unsigned)strlen(buf));
7327c478bd9Sstevel@tonic-gate 	(void) write(1, "\n", 1);
7337c478bd9Sstevel@tonic-gate 	return ((strcmp(buf, "0") == 0 || buf[0] == 0) ? 1 : 0);
7347c478bd9Sstevel@tonic-gate }
735