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