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