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 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 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 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 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 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 * 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 * 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 * 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 * 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 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 4617c478bd9Sstevel@tonic-gate errxx() 4627c478bd9Sstevel@tonic-gate { 4637c478bd9Sstevel@tonic-gate yyerror("RE error"); 4647c478bd9Sstevel@tonic-gate } 4657c478bd9Sstevel@tonic-gate 4667c478bd9Sstevel@tonic-gate static void 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 * 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 * 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 * 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 * 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 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