5 * The contents of this file are subject to the terms of the
6 * Common Development and Distribution License, Version 1.0 only
7 * (the "License"). You may not use this file except in compliance
10 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
11 * or http://www.opensolaris.org/os/licensing.
12 * See the License for the specific language governing permissions
13 * and limitations under the License.
15 * When distributing Covered Code, include this CDDL HEADER in each
16 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
17 * If applicable, add the following below this CDDL HEADER, with the
18 * fields enclosed by brackets "[]" replaced with your own identifying
19 * information: Portions Copyright [yyyy] [name of copyright owner]
25 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
26 * Use is subject to license terms.
29 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
30 /* All Rights Reserved */
34 #pragma ident "%Z%%M% %I% %E% SMI"
37 %Start A str sc reg comment
41 #include <sys/types.h>
45 #undef input /* defeat lex */
48 static void unput(int);
49 static void unputstr(char *);
51 extern YYSTYPE yylval;
60 # define RET(x) {if(dbg)printf("lex %s [%s]\n", tokname(x), yytext); return(x); }
62 # define RET(x) return(x)
66 * The standards (SUSV2) requires that Record size be atleast LINE_MAX.
67 * LINE_MAX is a standard variable defined in limits.h.
68 * Though nawk is not standards compliant, we let RECSIZE
69 * grow with LINE_MAX instead of the magic number 1024.
71 #define CBUFLEN (3 * LINE_MAX)
73 #define CADD cbuf[clen++] = yytext[0]; \
74 if (clen >= CBUFLEN-1) { \
75 ERROR "string/reg expr %.10s... too long", cbuf SYNTAX; \
79 static uchar cbuf[CBUFLEN];
81 static int clen, cflag;
92 switch (yybgin-yysvec-1) { /* witchcraft */
101 <A>\n { lineno++; RET(NL); }
102 <A>#.* { ; } /* strip comments */
106 <A>"\\"\n { lineno++; }
107 <A>BEGIN { RET(XBEGIN); }
108 <A>END { RET(XEND); }
109 <A>func(tion)? { if (infunc) ERROR "illegal nested function" SYNTAX; RET(FUNC); }
110 <A>return { if (!infunc) ERROR "return not in function" SYNTAX; RET(RETURN); }
111 <A>"&&" { RET(AND); }
112 <A>"||" { RET(BOR); }
114 <A>"!=" { yylval.i = NE; RET(NE); }
115 <A>"~" { yylval.i = MATCH; RET(MATCHOP); }
116 <A>"!~" { yylval.i = NOTMATCH; RET(MATCHOP); }
117 <A>"<" { yylval.i = LT; RET(LT); }
118 <A>"<=" { yylval.i = LE; RET(LE); }
119 <A>"==" { yylval.i = EQ; RET(EQ); }
120 <A>">=" { yylval.i = GE; RET(GE); }
121 <A>">" { yylval.i = GT; RET(GT); }
122 <A>">>" { yylval.i = APPEND; RET(APPEND); }
123 <A>"++" { yylval.i = INCR; RET(INCR); }
124 <A>"--" { yylval.i = DECR; RET(DECR); }
125 <A>"+=" { yylval.i = ADDEQ; RET(ASGNOP); }
126 <A>"-=" { yylval.i = SUBEQ; RET(ASGNOP); }
127 <A>"*=" { yylval.i = MULTEQ; RET(ASGNOP); }
128 <A>"/=" { yylval.i = DIVEQ; RET(ASGNOP); }
129 <A>"%=" { yylval.i = MODEQ; RET(ASGNOP); }
130 <A>"^=" { yylval.i = POWEQ; RET(ASGNOP); }
131 <A>"**=" { yylval.i = POWEQ; RET(ASGNOP); }
132 <A>"=" { yylval.i = ASSIGN; RET(ASGNOP); }
133 <A>"**" { RET(POWER); }
134 <A>"^" { RET(POWER); }
136 <A>"$"{D}+ { yylval.cp = fieldadr(atoi(yytext+1)); RET(FIELD); }
137 <A>"$NF" { unputstr("(NF)"); return(INDIRECT); }
138 <A>"$"{A}{B}* { int c, n;
139 c = input(); unput(c);
140 if (c == '(' || c == '[' || infunc && (n=isarg(yytext+1)) >= 0) {
144 yylval.cp = setsymtab((uchar *)yytext+1,
145 (uchar *)"",0.0,STR|NUM,symtab);
149 <A>"$" { RET(INDIRECT); }
150 <A>NF { yylval.cp = setsymtab((uchar *)yytext, (uchar *)"", 0.0, NUM, symtab); RET(VARNF); }
152 <A>({D}+("."?){D}*|"."{D}+)((e|E)("+"|-)?{D}+)? {
153 yylval.cp = setsymtab((uchar *)yytext, tostring((uchar *)yytext), atof(yytext), CON|NUM, symtab);
156 <A>while { RET(WHILE); }
160 <A>else { RET(ELSE); }
161 <A>next { RET(NEXT); }
162 <A>exit { RET(EXIT); }
163 <A>break { RET(BREAK); }
164 <A>continue { RET(CONTINUE); }
165 <A>print { yylval.i = PRINT; RET(PRINT); }
166 <A>printf { yylval.i = PRINTF; RET(PRINTF); }
167 <A>sprintf { yylval.i = SPRINTF; RET(SPRINTF); }
168 <A>split { yylval.i = SPLIT; RET(SPLIT); }
169 <A>substr { RET(SUBSTR); }
170 <A>sub { yylval.i = SUB; RET(SUB); }
171 <A>gsub { yylval.i = GSUB; RET(GSUB); }
172 <A>index { RET(INDEX); }
173 <A>match { RET(MATCHFCN); }
175 <A>getline { RET(GETLINE); }
176 <A>close { RET(CLOSE); }
177 <A>delete { RET(DELETE); }
178 <A>length { yylval.i = FLENGTH; RET(BLTIN); }
179 <A>log { yylval.i = FLOG; RET(BLTIN); }
180 <A>int { yylval.i = FINT; RET(BLTIN); }
181 <A>exp { yylval.i = FEXP; RET(BLTIN); }
182 <A>sqrt { yylval.i = FSQRT; RET(BLTIN); }
183 <A>sin { yylval.i = FSIN; RET(BLTIN); }
184 <A>cos { yylval.i = FCOS; RET(BLTIN); }
185 <A>atan2 { yylval.i = FATAN; RET(BLTIN); }
186 <A>system { yylval.i = FSYSTEM; RET(BLTIN); }
187 <A>rand { yylval.i = FRAND; RET(BLTIN); }
188 <A>srand { yylval.i = FSRAND; RET(BLTIN); }
189 <A>toupper { yylval.i = FTOUPPER; RET(BLTIN); }
190 <A>tolower { yylval.i = FTOLOWER; RET(BLTIN); }
192 <A>{A}{B}* { int n, c;
193 c = input(); unput(c); /* look for '(' */
194 if (c != '(' && infunc && (n=isarg(yytext)) >= 0) {
198 yylval.cp = setsymtab((uchar *)yytext,
199 (uchar *)"",0.0,STR|NUM,symtab);
207 <A>\" { BEGIN str; clen = 0; }
209 <A>"}" { if (--bracecnt < 0) ERROR "extra }" SYNTAX; BEGIN sc; RET(';'); }
210 <A>"]" { if (--brackcnt < 0) ERROR "extra ]" SYNTAX; RET(']'); }
211 <A>")" { if (--parencnt < 0) ERROR "extra )" SYNTAX; RET(')'); }
213 <A>. { if (yytext[0] == '{') bracecnt++;
214 else if (yytext[0] == '[') brackcnt++;
215 else if (yytext[0] == '(') parencnt++;
216 RET(yylval.i = yytext[0]); /* everything else */ }
218 <reg>\\. { cbuf[clen++] = '\\'; cbuf[clen++] = yytext[1]; }
219 <reg>\n { ERROR "newline in regular expression %.10s...", cbuf SYNTAX; lineno++; BEGIN A; }
222 yylval.s = tostring(cbuf);
228 cbuf[clen] = 0; s = tostring(cbuf);
229 cbuf[clen] = ' '; cbuf[++clen] = 0;
230 yylval.cp = setsymtab(cbuf, s, 0.0, CON|STR, symtab);
232 <str>\n { ERROR "newline in string %.10s...", cbuf SYNTAX; lineno++; BEGIN A; }
233 <str>"\\\"" { cbuf[clen++] = '"'; }
234 <str>"\\"n { cbuf[clen++] = '\n'; }
235 <str>"\\"t { cbuf[clen++] = '\t'; }
236 <str>"\\"f { cbuf[clen++] = '\f'; }
237 <str>"\\"r { cbuf[clen++] = '\r'; }
238 <str>"\\"b { cbuf[clen++] = '\b'; }
239 <str>"\\"v { cbuf[clen++] = '\v'; } /* these ANSIisms may not be known by */
240 <str>"\\"a { cbuf[clen++] = '\007'; } /* your compiler. hence 007 for bell */
241 <str>"\\\\" { cbuf[clen++] = '\\'; }
242 <str>"\\"({O}{O}{O}|{O}{O}|{O}) { int n;
243 sscanf(yytext+1, "%o", &n); cbuf[clen++] = n; }
244 <str>"\\"x({H}+) { int n; /* ANSI permits any number! */
245 sscanf(yytext+2, "%x", &n); cbuf[clen++] = n; }
246 <str>"\\". { cbuf[clen++] = yytext[1]; }
258 /* input() and unput() are transcriptions of the standard lex
259 macros for input and output with additions for error message
260 printing. God help us all if someone changes how lex works.
270 extern uchar *lexprog;
274 else if (lexprog != NULL) /* awk '...' */
276 else /* awk -f ... */
282 if (ep >= ebuf + sizeof ebuf)
295 ep = ebuf + sizeof(ebuf) - 1;
304 for (i = strlen(s)-1; i >= 0; i--)