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