17c478bd9Sstevel@tonic-gate %{ 27c478bd9Sstevel@tonic-gate /* 37c478bd9Sstevel@tonic-gate * CDDL HEADER START 47c478bd9Sstevel@tonic-gate * 57c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 67c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 77c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 87c478bd9Sstevel@tonic-gate * with the License. 97c478bd9Sstevel@tonic-gate * 107c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 117c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 127c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 137c478bd9Sstevel@tonic-gate * and limitations under the License. 147c478bd9Sstevel@tonic-gate * 157c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 167c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 177c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 187c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 197c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 207c478bd9Sstevel@tonic-gate * 217c478bd9Sstevel@tonic-gate * CDDL HEADER END 227c478bd9Sstevel@tonic-gate */ 23*1ee2e5faSnakanon 24*1ee2e5faSnakanon /* 25*1ee2e5faSnakanon * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 26*1ee2e5faSnakanon * Use is subject to license terms. 27*1ee2e5faSnakanon */ 28*1ee2e5faSnakanon 29*1ee2e5faSnakanon /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 30*1ee2e5faSnakanon /* All Rights Reserved */ 317c478bd9Sstevel@tonic-gate %} 327c478bd9Sstevel@tonic-gate 337c478bd9Sstevel@tonic-gate %{ 34*1ee2e5faSnakanon #pragma ident "%Z%%M% %I% %E% SMI" 357c478bd9Sstevel@tonic-gate %} 367c478bd9Sstevel@tonic-gate 377c478bd9Sstevel@tonic-gate %Start A str sc reg comment 387c478bd9Sstevel@tonic-gate 397c478bd9Sstevel@tonic-gate %{ 407c478bd9Sstevel@tonic-gate 417c478bd9Sstevel@tonic-gate #include <sys/types.h> 427c478bd9Sstevel@tonic-gate #include "awk.h" 437c478bd9Sstevel@tonic-gate #include "y.tab.h" 447c478bd9Sstevel@tonic-gate 457c478bd9Sstevel@tonic-gate #undef input /* defeat lex */ 467c478bd9Sstevel@tonic-gate #undef unput 477c478bd9Sstevel@tonic-gate 48*1ee2e5faSnakanon static void unput(int); 49*1ee2e5faSnakanon static void unputstr(char *); 50*1ee2e5faSnakanon 517c478bd9Sstevel@tonic-gate extern YYSTYPE yylval; 527c478bd9Sstevel@tonic-gate extern int infunc; 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate off_t lineno = 1; 557c478bd9Sstevel@tonic-gate int bracecnt = 0; 567c478bd9Sstevel@tonic-gate int brackcnt = 0; 577c478bd9Sstevel@tonic-gate int parencnt = 0; 587c478bd9Sstevel@tonic-gate #define DEBUG 597c478bd9Sstevel@tonic-gate #ifdef DEBUG 607c478bd9Sstevel@tonic-gate # define RET(x) {if(dbg)printf("lex %s [%s]\n", tokname(x), yytext); return(x); } 617c478bd9Sstevel@tonic-gate #else 627c478bd9Sstevel@tonic-gate # define RET(x) return(x) 637c478bd9Sstevel@tonic-gate #endif 647c478bd9Sstevel@tonic-gate 65*1ee2e5faSnakanon /* 66*1ee2e5faSnakanon * The standards (SUSV2) requires that Record size be atleast LINE_MAX. 67*1ee2e5faSnakanon * LINE_MAX is a standard variable defined in limits.h. 68*1ee2e5faSnakanon * Though nawk is not standards compliant, we let RECSIZE 69*1ee2e5faSnakanon * grow with LINE_MAX instead of the magic number 1024. 70*1ee2e5faSnakanon */ 71*1ee2e5faSnakanon #define CBUFLEN (3 * LINE_MAX) 72*1ee2e5faSnakanon 737c478bd9Sstevel@tonic-gate #define CADD cbuf[clen++] = yytext[0]; \ 74*1ee2e5faSnakanon if (clen >= CBUFLEN-1) { \ 757c478bd9Sstevel@tonic-gate ERROR "string/reg expr %.10s... too long", cbuf SYNTAX; \ 767c478bd9Sstevel@tonic-gate BEGIN A; \ 777c478bd9Sstevel@tonic-gate } 787c478bd9Sstevel@tonic-gate 79*1ee2e5faSnakanon static uchar cbuf[CBUFLEN]; 80*1ee2e5faSnakanon static uchar *s; 81*1ee2e5faSnakanon static int clen, cflag; 827c478bd9Sstevel@tonic-gate %} 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate A [a-zA-Z_] 857c478bd9Sstevel@tonic-gate B [a-zA-Z0-9_] 867c478bd9Sstevel@tonic-gate D [0-9] 877c478bd9Sstevel@tonic-gate O [0-7] 887c478bd9Sstevel@tonic-gate H [0-9a-fA-F] 897c478bd9Sstevel@tonic-gate WS [ \t] 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate %% 927c478bd9Sstevel@tonic-gate switch (yybgin-yysvec-1) { /* witchcraft */ 937c478bd9Sstevel@tonic-gate case 0: 947c478bd9Sstevel@tonic-gate BEGIN A; 957c478bd9Sstevel@tonic-gate break; 967c478bd9Sstevel@tonic-gate case sc: 977c478bd9Sstevel@tonic-gate BEGIN A; 987c478bd9Sstevel@tonic-gate RET('}'); 997c478bd9Sstevel@tonic-gate } 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate <A>\n { lineno++; RET(NL); } 1027c478bd9Sstevel@tonic-gate <A>#.* { ; } /* strip comments */ 1037c478bd9Sstevel@tonic-gate <A>{WS}+ { ; } 1047c478bd9Sstevel@tonic-gate <A>; { RET(';'); } 1057c478bd9Sstevel@tonic-gate 1067c478bd9Sstevel@tonic-gate <A>"\\"\n { lineno++; } 1077c478bd9Sstevel@tonic-gate <A>BEGIN { RET(XBEGIN); } 1087c478bd9Sstevel@tonic-gate <A>END { RET(XEND); } 1097c478bd9Sstevel@tonic-gate <A>func(tion)? { if (infunc) ERROR "illegal nested function" SYNTAX; RET(FUNC); } 1107c478bd9Sstevel@tonic-gate <A>return { if (!infunc) ERROR "return not in function" SYNTAX; RET(RETURN); } 1117c478bd9Sstevel@tonic-gate <A>"&&" { RET(AND); } 1127c478bd9Sstevel@tonic-gate <A>"||" { RET(BOR); } 1137c478bd9Sstevel@tonic-gate <A>"!" { RET(NOT); } 1147c478bd9Sstevel@tonic-gate <A>"!=" { yylval.i = NE; RET(NE); } 1157c478bd9Sstevel@tonic-gate <A>"~" { yylval.i = MATCH; RET(MATCHOP); } 1167c478bd9Sstevel@tonic-gate <A>"!~" { yylval.i = NOTMATCH; RET(MATCHOP); } 1177c478bd9Sstevel@tonic-gate <A>"<" { yylval.i = LT; RET(LT); } 1187c478bd9Sstevel@tonic-gate <A>"<=" { yylval.i = LE; RET(LE); } 1197c478bd9Sstevel@tonic-gate <A>"==" { yylval.i = EQ; RET(EQ); } 1207c478bd9Sstevel@tonic-gate <A>">=" { yylval.i = GE; RET(GE); } 1217c478bd9Sstevel@tonic-gate <A>">" { yylval.i = GT; RET(GT); } 1227c478bd9Sstevel@tonic-gate <A>">>" { yylval.i = APPEND; RET(APPEND); } 1237c478bd9Sstevel@tonic-gate <A>"++" { yylval.i = INCR; RET(INCR); } 1247c478bd9Sstevel@tonic-gate <A>"--" { yylval.i = DECR; RET(DECR); } 1257c478bd9Sstevel@tonic-gate <A>"+=" { yylval.i = ADDEQ; RET(ASGNOP); } 1267c478bd9Sstevel@tonic-gate <A>"-=" { yylval.i = SUBEQ; RET(ASGNOP); } 1277c478bd9Sstevel@tonic-gate <A>"*=" { yylval.i = MULTEQ; RET(ASGNOP); } 1287c478bd9Sstevel@tonic-gate <A>"/=" { yylval.i = DIVEQ; RET(ASGNOP); } 1297c478bd9Sstevel@tonic-gate <A>"%=" { yylval.i = MODEQ; RET(ASGNOP); } 1307c478bd9Sstevel@tonic-gate <A>"^=" { yylval.i = POWEQ; RET(ASGNOP); } 1317c478bd9Sstevel@tonic-gate <A>"**=" { yylval.i = POWEQ; RET(ASGNOP); } 1327c478bd9Sstevel@tonic-gate <A>"=" { yylval.i = ASSIGN; RET(ASGNOP); } 1337c478bd9Sstevel@tonic-gate <A>"**" { RET(POWER); } 1347c478bd9Sstevel@tonic-gate <A>"^" { RET(POWER); } 1357c478bd9Sstevel@tonic-gate 1367c478bd9Sstevel@tonic-gate <A>"$"{D}+ { yylval.cp = fieldadr(atoi(yytext+1)); RET(FIELD); } 1377c478bd9Sstevel@tonic-gate <A>"$NF" { unputstr("(NF)"); return(INDIRECT); } 1387c478bd9Sstevel@tonic-gate <A>"$"{A}{B}* { int c, n; 1397c478bd9Sstevel@tonic-gate c = input(); unput(c); 1407c478bd9Sstevel@tonic-gate if (c == '(' || c == '[' || infunc && (n=isarg(yytext+1)) >= 0) { 1417c478bd9Sstevel@tonic-gate unputstr(yytext+1); 1427c478bd9Sstevel@tonic-gate return(INDIRECT); 1437c478bd9Sstevel@tonic-gate } else { 144*1ee2e5faSnakanon yylval.cp = setsymtab((uchar *)yytext+1, 145*1ee2e5faSnakanon (uchar *)"",0.0,STR|NUM,symtab); 1467c478bd9Sstevel@tonic-gate RET(IVAR); 1477c478bd9Sstevel@tonic-gate } 1487c478bd9Sstevel@tonic-gate } 1497c478bd9Sstevel@tonic-gate <A>"$" { RET(INDIRECT); } 150*1ee2e5faSnakanon <A>NF { yylval.cp = setsymtab((uchar *)yytext, (uchar *)"", 0.0, NUM, symtab); RET(VARNF); } 1517c478bd9Sstevel@tonic-gate 1527c478bd9Sstevel@tonic-gate <A>({D}+("."?){D}*|"."{D}+)((e|E)("+"|-)?{D}+)? { 153*1ee2e5faSnakanon yylval.cp = setsymtab((uchar *)yytext, tostring((uchar *)yytext), atof(yytext), CON|NUM, symtab); 1547c478bd9Sstevel@tonic-gate RET(NUMBER); } 1557c478bd9Sstevel@tonic-gate 1567c478bd9Sstevel@tonic-gate <A>while { RET(WHILE); } 1577c478bd9Sstevel@tonic-gate <A>for { RET(FOR); } 1587c478bd9Sstevel@tonic-gate <A>do { RET(DO); } 1597c478bd9Sstevel@tonic-gate <A>if { RET(IF); } 1607c478bd9Sstevel@tonic-gate <A>else { RET(ELSE); } 1617c478bd9Sstevel@tonic-gate <A>next { RET(NEXT); } 1627c478bd9Sstevel@tonic-gate <A>exit { RET(EXIT); } 1637c478bd9Sstevel@tonic-gate <A>break { RET(BREAK); } 1647c478bd9Sstevel@tonic-gate <A>continue { RET(CONTINUE); } 1657c478bd9Sstevel@tonic-gate <A>print { yylval.i = PRINT; RET(PRINT); } 1667c478bd9Sstevel@tonic-gate <A>printf { yylval.i = PRINTF; RET(PRINTF); } 1677c478bd9Sstevel@tonic-gate <A>sprintf { yylval.i = SPRINTF; RET(SPRINTF); } 1687c478bd9Sstevel@tonic-gate <A>split { yylval.i = SPLIT; RET(SPLIT); } 1697c478bd9Sstevel@tonic-gate <A>substr { RET(SUBSTR); } 1707c478bd9Sstevel@tonic-gate <A>sub { yylval.i = SUB; RET(SUB); } 1717c478bd9Sstevel@tonic-gate <A>gsub { yylval.i = GSUB; RET(GSUB); } 1727c478bd9Sstevel@tonic-gate <A>index { RET(INDEX); } 1737c478bd9Sstevel@tonic-gate <A>match { RET(MATCHFCN); } 1747c478bd9Sstevel@tonic-gate <A>in { RET(IN); } 1757c478bd9Sstevel@tonic-gate <A>getline { RET(GETLINE); } 1767c478bd9Sstevel@tonic-gate <A>close { RET(CLOSE); } 1777c478bd9Sstevel@tonic-gate <A>delete { RET(DELETE); } 1787c478bd9Sstevel@tonic-gate <A>length { yylval.i = FLENGTH; RET(BLTIN); } 1797c478bd9Sstevel@tonic-gate <A>log { yylval.i = FLOG; RET(BLTIN); } 1807c478bd9Sstevel@tonic-gate <A>int { yylval.i = FINT; RET(BLTIN); } 1817c478bd9Sstevel@tonic-gate <A>exp { yylval.i = FEXP; RET(BLTIN); } 1827c478bd9Sstevel@tonic-gate <A>sqrt { yylval.i = FSQRT; RET(BLTIN); } 1837c478bd9Sstevel@tonic-gate <A>sin { yylval.i = FSIN; RET(BLTIN); } 1847c478bd9Sstevel@tonic-gate <A>cos { yylval.i = FCOS; RET(BLTIN); } 1857c478bd9Sstevel@tonic-gate <A>atan2 { yylval.i = FATAN; RET(BLTIN); } 1867c478bd9Sstevel@tonic-gate <A>system { yylval.i = FSYSTEM; RET(BLTIN); } 1877c478bd9Sstevel@tonic-gate <A>rand { yylval.i = FRAND; RET(BLTIN); } 1887c478bd9Sstevel@tonic-gate <A>srand { yylval.i = FSRAND; RET(BLTIN); } 1897c478bd9Sstevel@tonic-gate <A>toupper { yylval.i = FTOUPPER; RET(BLTIN); } 1907c478bd9Sstevel@tonic-gate <A>tolower { yylval.i = FTOLOWER; RET(BLTIN); } 1917c478bd9Sstevel@tonic-gate 1927c478bd9Sstevel@tonic-gate <A>{A}{B}* { int n, c; 1937c478bd9Sstevel@tonic-gate c = input(); unput(c); /* look for '(' */ 1947c478bd9Sstevel@tonic-gate if (c != '(' && infunc && (n=isarg(yytext)) >= 0) { 1957c478bd9Sstevel@tonic-gate yylval.i = n; 1967c478bd9Sstevel@tonic-gate RET(ARG); 1977c478bd9Sstevel@tonic-gate } else { 198*1ee2e5faSnakanon yylval.cp = setsymtab((uchar *)yytext, 199*1ee2e5faSnakanon (uchar *)"",0.0,STR|NUM,symtab); 2007c478bd9Sstevel@tonic-gate if (c == '(') { 2017c478bd9Sstevel@tonic-gate RET(CALL); 2027c478bd9Sstevel@tonic-gate } else { 2037c478bd9Sstevel@tonic-gate RET(VAR); 2047c478bd9Sstevel@tonic-gate } 2057c478bd9Sstevel@tonic-gate } 2067c478bd9Sstevel@tonic-gate } 2077c478bd9Sstevel@tonic-gate <A>\" { BEGIN str; clen = 0; } 2087c478bd9Sstevel@tonic-gate 2097c478bd9Sstevel@tonic-gate <A>"}" { if (--bracecnt < 0) ERROR "extra }" SYNTAX; BEGIN sc; RET(';'); } 2107c478bd9Sstevel@tonic-gate <A>"]" { if (--brackcnt < 0) ERROR "extra ]" SYNTAX; RET(']'); } 2117c478bd9Sstevel@tonic-gate <A>")" { if (--parencnt < 0) ERROR "extra )" SYNTAX; RET(')'); } 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate <A>. { if (yytext[0] == '{') bracecnt++; 2147c478bd9Sstevel@tonic-gate else if (yytext[0] == '[') brackcnt++; 2157c478bd9Sstevel@tonic-gate else if (yytext[0] == '(') parencnt++; 2167c478bd9Sstevel@tonic-gate RET(yylval.i = yytext[0]); /* everything else */ } 2177c478bd9Sstevel@tonic-gate 2187c478bd9Sstevel@tonic-gate <reg>\\. { cbuf[clen++] = '\\'; cbuf[clen++] = yytext[1]; } 2197c478bd9Sstevel@tonic-gate <reg>\n { ERROR "newline in regular expression %.10s...", cbuf SYNTAX; lineno++; BEGIN A; } 2207c478bd9Sstevel@tonic-gate <reg>"/" { BEGIN A; 2217c478bd9Sstevel@tonic-gate cbuf[clen] = 0; 2227c478bd9Sstevel@tonic-gate yylval.s = tostring(cbuf); 2237c478bd9Sstevel@tonic-gate unput('/'); 2247c478bd9Sstevel@tonic-gate RET(REGEXPR); } 2257c478bd9Sstevel@tonic-gate <reg>. { CADD; } 2267c478bd9Sstevel@tonic-gate 2277c478bd9Sstevel@tonic-gate <str>\" { BEGIN A; 2287c478bd9Sstevel@tonic-gate cbuf[clen] = 0; s = tostring(cbuf); 2297c478bd9Sstevel@tonic-gate cbuf[clen] = ' '; cbuf[++clen] = 0; 2307c478bd9Sstevel@tonic-gate yylval.cp = setsymtab(cbuf, s, 0.0, CON|STR, symtab); 2317c478bd9Sstevel@tonic-gate RET(STRING); } 2327c478bd9Sstevel@tonic-gate <str>\n { ERROR "newline in string %.10s...", cbuf SYNTAX; lineno++; BEGIN A; } 2337c478bd9Sstevel@tonic-gate <str>"\\\"" { cbuf[clen++] = '"'; } 2347c478bd9Sstevel@tonic-gate <str>"\\"n { cbuf[clen++] = '\n'; } 2357c478bd9Sstevel@tonic-gate <str>"\\"t { cbuf[clen++] = '\t'; } 2367c478bd9Sstevel@tonic-gate <str>"\\"f { cbuf[clen++] = '\f'; } 2377c478bd9Sstevel@tonic-gate <str>"\\"r { cbuf[clen++] = '\r'; } 2387c478bd9Sstevel@tonic-gate <str>"\\"b { cbuf[clen++] = '\b'; } 2397c478bd9Sstevel@tonic-gate <str>"\\"v { cbuf[clen++] = '\v'; } /* these ANSIisms may not be known by */ 2407c478bd9Sstevel@tonic-gate <str>"\\"a { cbuf[clen++] = '\007'; } /* your compiler. hence 007 for bell */ 2417c478bd9Sstevel@tonic-gate <str>"\\\\" { cbuf[clen++] = '\\'; } 2427c478bd9Sstevel@tonic-gate <str>"\\"({O}{O}{O}|{O}{O}|{O}) { int n; 2437c478bd9Sstevel@tonic-gate sscanf(yytext+1, "%o", &n); cbuf[clen++] = n; } 2447c478bd9Sstevel@tonic-gate <str>"\\"x({H}+) { int n; /* ANSI permits any number! */ 2457c478bd9Sstevel@tonic-gate sscanf(yytext+2, "%x", &n); cbuf[clen++] = n; } 2467c478bd9Sstevel@tonic-gate <str>"\\". { cbuf[clen++] = yytext[1]; } 2477c478bd9Sstevel@tonic-gate <str>. { CADD; } 2487c478bd9Sstevel@tonic-gate 2497c478bd9Sstevel@tonic-gate %% 2507c478bd9Sstevel@tonic-gate 251*1ee2e5faSnakanon void 2527c478bd9Sstevel@tonic-gate startreg() 2537c478bd9Sstevel@tonic-gate { 2547c478bd9Sstevel@tonic-gate BEGIN reg; 2557c478bd9Sstevel@tonic-gate clen = 0; 2567c478bd9Sstevel@tonic-gate } 2577c478bd9Sstevel@tonic-gate 2587c478bd9Sstevel@tonic-gate /* input() and unput() are transcriptions of the standard lex 2597c478bd9Sstevel@tonic-gate macros for input and output with additions for error message 2607c478bd9Sstevel@tonic-gate printing. God help us all if someone changes how lex works. 2617c478bd9Sstevel@tonic-gate */ 2627c478bd9Sstevel@tonic-gate 2637c478bd9Sstevel@tonic-gate uchar ebuf[300]; 2647c478bd9Sstevel@tonic-gate uchar *ep = ebuf; 2657c478bd9Sstevel@tonic-gate 266*1ee2e5faSnakanon int 267*1ee2e5faSnakanon input(void) 2687c478bd9Sstevel@tonic-gate { 2697c478bd9Sstevel@tonic-gate register int c; 2707c478bd9Sstevel@tonic-gate extern uchar *lexprog; 2717c478bd9Sstevel@tonic-gate 2727c478bd9Sstevel@tonic-gate if (yysptr > yysbuf) 2737c478bd9Sstevel@tonic-gate c = U(*--yysptr); 2747c478bd9Sstevel@tonic-gate else if (lexprog != NULL) /* awk '...' */ 2757c478bd9Sstevel@tonic-gate c = *lexprog++; 2767c478bd9Sstevel@tonic-gate else /* awk -f ... */ 2777c478bd9Sstevel@tonic-gate c = pgetc(); 2787c478bd9Sstevel@tonic-gate if (c == '\n') 2797c478bd9Sstevel@tonic-gate yylineno++; 2807c478bd9Sstevel@tonic-gate else if (c == EOF) 2817c478bd9Sstevel@tonic-gate c = 0; 2827c478bd9Sstevel@tonic-gate if (ep >= ebuf + sizeof ebuf) 2837c478bd9Sstevel@tonic-gate ep = ebuf; 2847c478bd9Sstevel@tonic-gate return *ep++ = c; 2857c478bd9Sstevel@tonic-gate } 2867c478bd9Sstevel@tonic-gate 287*1ee2e5faSnakanon static void 288*1ee2e5faSnakanon unput(int c) 2897c478bd9Sstevel@tonic-gate { 2907c478bd9Sstevel@tonic-gate yytchar = c; 2917c478bd9Sstevel@tonic-gate if (yytchar == '\n') 2927c478bd9Sstevel@tonic-gate yylineno--; 2937c478bd9Sstevel@tonic-gate *yysptr++ = yytchar; 2947c478bd9Sstevel@tonic-gate if (--ep < ebuf) 2957c478bd9Sstevel@tonic-gate ep = ebuf + sizeof(ebuf) - 1; 2967c478bd9Sstevel@tonic-gate } 2977c478bd9Sstevel@tonic-gate 2987c478bd9Sstevel@tonic-gate 299*1ee2e5faSnakanon static void 300*1ee2e5faSnakanon unputstr(char *s) 3017c478bd9Sstevel@tonic-gate { 3027c478bd9Sstevel@tonic-gate int i; 3037c478bd9Sstevel@tonic-gate 3047c478bd9Sstevel@tonic-gate for (i = strlen(s)-1; i >= 0; i--) 3057c478bd9Sstevel@tonic-gate unput(s[i]); 3067c478bd9Sstevel@tonic-gate } 307