blob: 2af39880e94bf5b0dd82875e0571a6fef8debfb1 [file] [log] [blame]
Glenn L McGrath545106f2002-11-11 06:21:00 +00001/* vi: set sw=4 ts=4: */
2/*
3 * awk implementation for busybox
4 *
5 * Copyright (C) 2002 by Dmitry Zakharov <dmit@crp.bank.gov.ua>
6 *
Bernhard Reutner-Fischer86f5c992006-01-22 22:55:11 +00007 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
Glenn L McGrath545106f2002-11-11 06:21:00 +00008 */
9
Denis Vlasenkob6adbf12007-05-26 19:00:18 +000010#include "libbb.h"
Rob Landleyd921b2e2006-08-03 15:41:12 +000011#include "xregex.h"
12#include <math.h>
Glenn L McGrath545106f2002-11-11 06:21:00 +000013
Denis Vlasenko99912ca2007-04-10 15:43:37 +000014/* This is a NOEXEC applet. Be very careful! */
15
Glenn L McGrath545106f2002-11-11 06:21:00 +000016
Denis Vlasenko629563b2007-02-24 17:05:52 +000017#define MAXVARFMT 240
18#define MINNVBLOCK 64
Glenn L McGrath545106f2002-11-11 06:21:00 +000019
20/* variable flags */
Denis Vlasenko629563b2007-02-24 17:05:52 +000021#define VF_NUMBER 0x0001 /* 1 = primary type is number */
22#define VF_ARRAY 0x0002 /* 1 = it's an array */
Glenn L McGrath545106f2002-11-11 06:21:00 +000023
Denis Vlasenko629563b2007-02-24 17:05:52 +000024#define VF_CACHED 0x0100 /* 1 = num/str value has cached str/num eq */
25#define VF_USER 0x0200 /* 1 = user input (may be numeric string) */
26#define VF_SPECIAL 0x0400 /* 1 = requires extra handling when changed */
27#define VF_WALK 0x0800 /* 1 = variable has alloc'd x.walker list */
28#define VF_FSTR 0x1000 /* 1 = var::string points to fstring buffer */
29#define VF_CHILD 0x2000 /* 1 = function arg; x.parent points to source */
30#define VF_DIRTY 0x4000 /* 1 = variable was set explicitly */
Glenn L McGrath545106f2002-11-11 06:21:00 +000031
32/* these flags are static, don't change them when value is changed */
Denis Vlasenko629563b2007-02-24 17:05:52 +000033#define VF_DONTTOUCH (VF_ARRAY | VF_SPECIAL | VF_WALK | VF_CHILD | VF_DIRTY)
Glenn L McGrath545106f2002-11-11 06:21:00 +000034
35/* Variable */
36typedef struct var_s {
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +000037 unsigned type; /* flags */
Glenn L McGrath545106f2002-11-11 06:21:00 +000038 double number;
39 char *string;
40 union {
Denis Vlasenko629563b2007-02-24 17:05:52 +000041 int aidx; /* func arg idx (for compilation stage) */
42 struct xhash_s *array; /* array ptr */
43 struct var_s *parent; /* for func args, ptr to actual parameter */
44 char **walker; /* list of array elements (for..in) */
Glenn L McGrath545106f2002-11-11 06:21:00 +000045 } x;
46} var;
47
48/* Node chain (pattern-action chain, BEGIN, END, function bodies) */
49typedef struct chain_s {
50 struct node_s *first;
51 struct node_s *last;
Denis Vlasenkoa41fdf32007-01-29 22:51:00 +000052 const char *programname;
Glenn L McGrath545106f2002-11-11 06:21:00 +000053} chain;
54
55/* Function */
56typedef struct func_s {
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +000057 unsigned nargs;
Glenn L McGrath545106f2002-11-11 06:21:00 +000058 struct chain_s body;
59} func;
60
61/* I/O stream */
62typedef struct rstream_s {
63 FILE *F;
64 char *buffer;
Glenn L McGrath00ed36f2003-10-30 13:36:39 +000065 int adv;
Glenn L McGrath545106f2002-11-11 06:21:00 +000066 int size;
67 int pos;
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +000068 smallint is_pipe;
Glenn L McGrath545106f2002-11-11 06:21:00 +000069} rstream;
70
71typedef struct hash_item_s {
72 union {
Denis Vlasenkoffba9412007-05-17 23:03:35 +000073 struct var_s v; /* variable/array hash */
74 struct rstream_s rs; /* redirect streams hash */
75 struct func_s f; /* functions hash */
Glenn L McGrath545106f2002-11-11 06:21:00 +000076 } data;
Denis Vlasenkoffba9412007-05-17 23:03:35 +000077 struct hash_item_s *next; /* next in chain */
78 char name[1]; /* really it's longer */
Glenn L McGrath545106f2002-11-11 06:21:00 +000079} hash_item;
80
81typedef struct xhash_s {
Denis Vlasenkoffba9412007-05-17 23:03:35 +000082 unsigned nel; /* num of elements */
83 unsigned csize; /* current hash size */
84 unsigned nprime; /* next hash size in PRIMES[] */
85 unsigned glen; /* summary length of item names */
Glenn L McGrath545106f2002-11-11 06:21:00 +000086 struct hash_item_s **items;
87} xhash;
88
89/* Tree node */
90typedef struct node_s {
Mike Frysingerf87b3e32005-09-27 04:16:22 +000091 uint32_t info;
Denis Vlasenkocd5c7862007-05-17 16:37:22 +000092 unsigned lineno;
Glenn L McGrath545106f2002-11-11 06:21:00 +000093 union {
94 struct node_s *n;
95 var *v;
96 int i;
97 char *s;
98 regex_t *re;
99 } l;
100 union {
101 struct node_s *n;
102 regex_t *ire;
103 func *f;
104 int argno;
105 } r;
106 union {
107 struct node_s *n;
108 } a;
109} node;
110
111/* Block of temporary variables */
112typedef struct nvblock_s {
113 int size;
114 var *pos;
115 struct nvblock_s *prev;
116 struct nvblock_s *next;
117 var nv[0];
118} nvblock;
119
120typedef struct tsplitter_s {
121 node n;
122 regex_t re[2];
123} tsplitter;
124
125/* simple token classes */
126/* Order and hex values are very important!!! See next_token() */
127#define TC_SEQSTART 1 /* ( */
128#define TC_SEQTERM (1 << 1) /* ) */
129#define TC_REGEXP (1 << 2) /* /.../ */
130#define TC_OUTRDR (1 << 3) /* | > >> */
131#define TC_UOPPOST (1 << 4) /* unary postfix operator */
132#define TC_UOPPRE1 (1 << 5) /* unary prefix operator */
133#define TC_BINOPX (1 << 6) /* two-opnd operator */
134#define TC_IN (1 << 7)
135#define TC_COMMA (1 << 8)
136#define TC_PIPE (1 << 9) /* input redirection pipe */
137#define TC_UOPPRE2 (1 << 10) /* unary prefix operator */
138#define TC_ARRTERM (1 << 11) /* ] */
139#define TC_GRPSTART (1 << 12) /* { */
140#define TC_GRPTERM (1 << 13) /* } */
141#define TC_SEMICOL (1 << 14)
142#define TC_NEWLINE (1 << 15)
143#define TC_STATX (1 << 16) /* ctl statement (for, next...) */
144#define TC_WHILE (1 << 17)
145#define TC_ELSE (1 << 18)
146#define TC_BUILTIN (1 << 19)
147#define TC_GETLINE (1 << 20)
148#define TC_FUNCDECL (1 << 21) /* `function' `func' */
149#define TC_BEGIN (1 << 22)
150#define TC_END (1 << 23)
151#define TC_EOF (1 << 24)
152#define TC_VARIABLE (1 << 25)
153#define TC_ARRAY (1 << 26)
154#define TC_FUNCTION (1 << 27)
155#define TC_STRING (1 << 28)
156#define TC_NUMBER (1 << 29)
157
Denis Vlasenkoffba9412007-05-17 23:03:35 +0000158#define TC_UOPPRE (TC_UOPPRE1 | TC_UOPPRE2)
Glenn L McGrath545106f2002-11-11 06:21:00 +0000159
160/* combined token classes */
Denis Vlasenkoffba9412007-05-17 23:03:35 +0000161#define TC_BINOP (TC_BINOPX | TC_COMMA | TC_PIPE | TC_IN)
162#define TC_UNARYOP (TC_UOPPRE | TC_UOPPOST)
163#define TC_OPERAND (TC_VARIABLE | TC_ARRAY | TC_FUNCTION \
164 | TC_BUILTIN | TC_GETLINE | TC_SEQSTART | TC_STRING | TC_NUMBER)
Glenn L McGrath545106f2002-11-11 06:21:00 +0000165
Denis Vlasenkoffba9412007-05-17 23:03:35 +0000166#define TC_STATEMNT (TC_STATX | TC_WHILE)
167#define TC_OPTERM (TC_SEMICOL | TC_NEWLINE)
Glenn L McGrath545106f2002-11-11 06:21:00 +0000168
169/* word tokens, cannot mean something else if not expected */
Denis Vlasenkoffba9412007-05-17 23:03:35 +0000170#define TC_WORD (TC_IN | TC_STATEMNT | TC_ELSE | TC_BUILTIN \
171 | TC_GETLINE | TC_FUNCDECL | TC_BEGIN | TC_END)
Glenn L McGrath545106f2002-11-11 06:21:00 +0000172
173/* discard newlines after these */
Denis Vlasenkoffba9412007-05-17 23:03:35 +0000174#define TC_NOTERM (TC_COMMA | TC_GRPSTART | TC_GRPTERM \
175 | TC_BINOP | TC_OPTERM)
Glenn L McGrath545106f2002-11-11 06:21:00 +0000176
177/* what can expression begin with */
Denis Vlasenkoffba9412007-05-17 23:03:35 +0000178#define TC_OPSEQ (TC_OPERAND | TC_UOPPRE | TC_REGEXP)
Glenn L McGrath545106f2002-11-11 06:21:00 +0000179/* what can group begin with */
Denis Vlasenkoffba9412007-05-17 23:03:35 +0000180#define TC_GRPSEQ (TC_OPSEQ | TC_OPTERM | TC_STATEMNT | TC_GRPSTART)
Glenn L McGrath545106f2002-11-11 06:21:00 +0000181
182/* if previous token class is CONCAT1 and next is CONCAT2, concatenation */
183/* operator is inserted between them */
Denis Vlasenkoffba9412007-05-17 23:03:35 +0000184#define TC_CONCAT1 (TC_VARIABLE | TC_ARRTERM | TC_SEQTERM \
185 | TC_STRING | TC_NUMBER | TC_UOPPOST)
186#define TC_CONCAT2 (TC_OPERAND | TC_UOPPRE)
Glenn L McGrath545106f2002-11-11 06:21:00 +0000187
Denis Vlasenkoffba9412007-05-17 23:03:35 +0000188#define OF_RES1 0x010000
189#define OF_RES2 0x020000
190#define OF_STR1 0x040000
191#define OF_STR2 0x080000
192#define OF_NUM1 0x100000
193#define OF_CHECKED 0x200000
Glenn L McGrath545106f2002-11-11 06:21:00 +0000194
195/* combined operator flags */
196#define xx 0
197#define xV OF_RES2
198#define xS (OF_RES2 | OF_STR2)
199#define Vx OF_RES1
200#define VV (OF_RES1 | OF_RES2)
201#define Nx (OF_RES1 | OF_NUM1)
202#define NV (OF_RES1 | OF_NUM1 | OF_RES2)
203#define Sx (OF_RES1 | OF_STR1)
204#define SV (OF_RES1 | OF_STR1 | OF_RES2)
205#define SS (OF_RES1 | OF_STR1 | OF_RES2 | OF_STR2)
206
Denis Vlasenkoffba9412007-05-17 23:03:35 +0000207#define OPCLSMASK 0xFF00
208#define OPNMASK 0x007F
Glenn L McGrath545106f2002-11-11 06:21:00 +0000209
210/* operator priority is a highest byte (even: r->l, odd: l->r grouping)
211 * For builtins it has different meaning: n n s3 s2 s1 v3 v2 v1,
212 * n - min. number of args, vN - resolve Nth arg to var, sN - resolve to string
213 */
Denis Vlasenkoffba9412007-05-17 23:03:35 +0000214#define P(x) (x << 24)
215#define PRIMASK 0x7F000000
216#define PRIMASK2 0x7E000000
Glenn L McGrath545106f2002-11-11 06:21:00 +0000217
218/* Operation classes */
219
220#define SHIFT_TIL_THIS 0x0600
221#define RECUR_FROM_THIS 0x1000
222
223enum {
Denis Vlasenkoffba9412007-05-17 23:03:35 +0000224 OC_DELETE = 0x0100, OC_EXEC = 0x0200, OC_NEWSOURCE = 0x0300,
225 OC_PRINT = 0x0400, OC_PRINTF = 0x0500, OC_WALKINIT = 0x0600,
Glenn L McGrath545106f2002-11-11 06:21:00 +0000226
Denis Vlasenkoffba9412007-05-17 23:03:35 +0000227 OC_BR = 0x0700, OC_BREAK = 0x0800, OC_CONTINUE = 0x0900,
228 OC_EXIT = 0x0a00, OC_NEXT = 0x0b00, OC_NEXTFILE = 0x0c00,
229 OC_TEST = 0x0d00, OC_WALKNEXT = 0x0e00,
Glenn L McGrath545106f2002-11-11 06:21:00 +0000230
Denis Vlasenkoffba9412007-05-17 23:03:35 +0000231 OC_BINARY = 0x1000, OC_BUILTIN = 0x1100, OC_COLON = 0x1200,
232 OC_COMMA = 0x1300, OC_COMPARE = 0x1400, OC_CONCAT = 0x1500,
233 OC_FBLTIN = 0x1600, OC_FIELD = 0x1700, OC_FNARG = 0x1800,
234 OC_FUNC = 0x1900, OC_GETLINE = 0x1a00, OC_IN = 0x1b00,
235 OC_LAND = 0x1c00, OC_LOR = 0x1d00, OC_MATCH = 0x1e00,
236 OC_MOVE = 0x1f00, OC_PGETLINE = 0x2000, OC_REGEXP = 0x2100,
237 OC_REPLACE = 0x2200, OC_RETURN = 0x2300, OC_SPRINTF = 0x2400,
238 OC_TERNARY = 0x2500, OC_UNARY = 0x2600, OC_VAR = 0x2700,
239 OC_DONE = 0x2800,
Glenn L McGrath545106f2002-11-11 06:21:00 +0000240
Denis Vlasenkoffba9412007-05-17 23:03:35 +0000241 ST_IF = 0x3000, ST_DO = 0x3100, ST_FOR = 0x3200,
242 ST_WHILE = 0x3300
Glenn L McGrath545106f2002-11-11 06:21:00 +0000243};
244
245/* simple builtins */
246enum {
Denis Vlasenkoffba9412007-05-17 23:03:35 +0000247 F_in, F_rn, F_co, F_ex, F_lg, F_si, F_sq, F_sr,
Glenn L McGrath545106f2002-11-11 06:21:00 +0000248 F_ti, F_le, F_sy, F_ff, F_cl
249};
250
251/* builtins */
252enum {
Denis Vlasenkoffba9412007-05-17 23:03:35 +0000253 B_a2, B_ix, B_ma, B_sp, B_ss, B_ti, B_lo, B_up,
Denis Vlasenkoe175ff22006-09-26 17:41:00 +0000254 B_ge, B_gs, B_su,
255 B_an, B_co, B_ls, B_or, B_rs, B_xo,
Glenn L McGrath545106f2002-11-11 06:21:00 +0000256};
257
258/* tokens and their corresponding info values */
259
Denis Vlasenkoffba9412007-05-17 23:03:35 +0000260#define NTC "\377" /* switch to next token class (tc<<1) */
261#define NTCC '\377'
Glenn L McGrath545106f2002-11-11 06:21:00 +0000262
263#define OC_B OC_BUILTIN
264
Denis Vlasenko6ca409e2007-08-12 20:58:27 +0000265static const char tokenlist[] ALIGN1 =
Denis Vlasenkof782f522007-01-01 23:51:30 +0000266 "\1(" NTC
267 "\1)" NTC
268 "\1/" NTC /* REGEXP */
269 "\2>>" "\1>" "\1|" NTC /* OUTRDR */
270 "\2++" "\2--" NTC /* UOPPOST */
271 "\2++" "\2--" "\1$" NTC /* UOPPRE1 */
272 "\2==" "\1=" "\2+=" "\2-=" /* BINOPX */
273 "\2*=" "\2/=" "\2%=" "\2^="
274 "\1+" "\1-" "\3**=" "\2**"
275 "\1/" "\1%" "\1^" "\1*"
276 "\2!=" "\2>=" "\2<=" "\1>"
277 "\1<" "\2!~" "\1~" "\2&&"
278 "\2||" "\1?" "\1:" NTC
279 "\2in" NTC
280 "\1," NTC
281 "\1|" NTC
282 "\1+" "\1-" "\1!" NTC /* UOPPRE2 */
283 "\1]" NTC
284 "\1{" NTC
285 "\1}" NTC
286 "\1;" NTC
287 "\1\n" NTC
288 "\2if" "\2do" "\3for" "\5break" /* STATX */
289 "\10continue" "\6delete" "\5print"
290 "\6printf" "\4next" "\10nextfile"
291 "\6return" "\4exit" NTC
292 "\5while" NTC
293 "\4else" NTC
Glenn L McGrath545106f2002-11-11 06:21:00 +0000294
Denis Vlasenkof782f522007-01-01 23:51:30 +0000295 "\3and" "\5compl" "\6lshift" "\2or"
296 "\6rshift" "\3xor"
297 "\5close" "\6system" "\6fflush" "\5atan2" /* BUILTIN */
298 "\3cos" "\3exp" "\3int" "\3log"
299 "\4rand" "\3sin" "\4sqrt" "\5srand"
300 "\6gensub" "\4gsub" "\5index" "\6length"
301 "\5match" "\5split" "\7sprintf" "\3sub"
302 "\6substr" "\7systime" "\10strftime"
303 "\7tolower" "\7toupper" NTC
304 "\7getline" NTC
305 "\4func" "\10function" NTC
306 "\5BEGIN" NTC
307 "\3END" "\0"
Glenn L McGrath545106f2002-11-11 06:21:00 +0000308 ;
309
"Vladimir N. Oleynik"5cf9a032005-10-19 09:21:51 +0000310static const uint32_t tokeninfo[] = {
Glenn L McGrath545106f2002-11-11 06:21:00 +0000311 0,
312 0,
313 OC_REGEXP,
Denis Vlasenkof782f522007-01-01 23:51:30 +0000314 xS|'a', xS|'w', xS|'|',
315 OC_UNARY|xV|P(9)|'p', OC_UNARY|xV|P(9)|'m',
316 OC_UNARY|xV|P(9)|'P', OC_UNARY|xV|P(9)|'M',
317 OC_FIELD|xV|P(5),
318 OC_COMPARE|VV|P(39)|5, OC_MOVE|VV|P(74),
319 OC_REPLACE|NV|P(74)|'+', OC_REPLACE|NV|P(74)|'-',
320 OC_REPLACE|NV|P(74)|'*', OC_REPLACE|NV|P(74)|'/',
321 OC_REPLACE|NV|P(74)|'%', OC_REPLACE|NV|P(74)|'&',
322 OC_BINARY|NV|P(29)|'+', OC_BINARY|NV|P(29)|'-',
323 OC_REPLACE|NV|P(74)|'&', OC_BINARY|NV|P(15)|'&',
324 OC_BINARY|NV|P(25)|'/', OC_BINARY|NV|P(25)|'%',
325 OC_BINARY|NV|P(15)|'&', OC_BINARY|NV|P(25)|'*',
326 OC_COMPARE|VV|P(39)|4, OC_COMPARE|VV|P(39)|3,
327 OC_COMPARE|VV|P(39)|0, OC_COMPARE|VV|P(39)|1,
328 OC_COMPARE|VV|P(39)|2, OC_MATCH|Sx|P(45)|'!',
329 OC_MATCH|Sx|P(45)|'~', OC_LAND|Vx|P(55),
330 OC_LOR|Vx|P(59), OC_TERNARY|Vx|P(64)|'?',
331 OC_COLON|xx|P(67)|':',
Glenn L McGrath545106f2002-11-11 06:21:00 +0000332 OC_IN|SV|P(49),
333 OC_COMMA|SS|P(80),
334 OC_PGETLINE|SV|P(37),
Denis Vlasenkof782f522007-01-01 23:51:30 +0000335 OC_UNARY|xV|P(19)|'+', OC_UNARY|xV|P(19)|'-',
336 OC_UNARY|xV|P(19)|'!',
Glenn L McGrath545106f2002-11-11 06:21:00 +0000337 0,
338 0,
339 0,
340 0,
341 0,
Denis Vlasenkof782f522007-01-01 23:51:30 +0000342 ST_IF, ST_DO, ST_FOR, OC_BREAK,
343 OC_CONTINUE, OC_DELETE|Vx, OC_PRINT,
344 OC_PRINTF, OC_NEXT, OC_NEXTFILE,
345 OC_RETURN|Vx, OC_EXIT|Nx,
Glenn L McGrath545106f2002-11-11 06:21:00 +0000346 ST_WHILE,
347 0,
348
Denis Vlasenkoe175ff22006-09-26 17:41:00 +0000349 OC_B|B_an|P(0x83), OC_B|B_co|P(0x41), OC_B|B_ls|P(0x83), OC_B|B_or|P(0x83),
350 OC_B|B_rs|P(0x83), OC_B|B_xo|P(0x83),
Glenn L McGrath545106f2002-11-11 06:21:00 +0000351 OC_FBLTIN|Sx|F_cl, OC_FBLTIN|Sx|F_sy, OC_FBLTIN|Sx|F_ff, OC_B|B_a2|P(0x83),
352 OC_FBLTIN|Nx|F_co, OC_FBLTIN|Nx|F_ex, OC_FBLTIN|Nx|F_in, OC_FBLTIN|Nx|F_lg,
353 OC_FBLTIN|F_rn, OC_FBLTIN|Nx|F_si, OC_FBLTIN|Nx|F_sq, OC_FBLTIN|Nx|F_sr,
354 OC_B|B_ge|P(0xd6), OC_B|B_gs|P(0xb6), OC_B|B_ix|P(0x9b), OC_FBLTIN|Sx|F_le,
355 OC_B|B_ma|P(0x89), OC_B|B_sp|P(0x8b), OC_SPRINTF, OC_B|B_su|P(0xb6),
356 OC_B|B_ss|P(0x8f), OC_FBLTIN|F_ti, OC_B|B_ti|P(0x0b),
357 OC_B|B_lo|P(0x49), OC_B|B_up|P(0x49),
358 OC_GETLINE|SV|P(0),
359 0, 0,
360 0,
361 0
362};
363
364/* internal variable names and their initial values */
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000365/* asterisk marks SPECIAL vars; $ is just no-named Field0 */
Glenn L McGrath545106f2002-11-11 06:21:00 +0000366enum {
Denis Vlasenkoffba9412007-05-17 23:03:35 +0000367 CONVFMT, OFMT, FS, OFS,
Denis Vlasenkof782f522007-01-01 23:51:30 +0000368 ORS, RS, RT, FILENAME,
369 SUBSEP, ARGIND, ARGC, ARGV,
370 ERRNO, FNR,
371 NR, NF, IGNORECASE,
Denis Vlasenkoffba9412007-05-17 23:03:35 +0000372 ENVIRON, F0, NUM_INTERNAL_VARS
Glenn L McGrath545106f2002-11-11 06:21:00 +0000373};
374
Denis Vlasenko6ca409e2007-08-12 20:58:27 +0000375static const char vNames[] ALIGN1 =
Denis Vlasenkof782f522007-01-01 23:51:30 +0000376 "CONVFMT\0" "OFMT\0" "FS\0*" "OFS\0"
377 "ORS\0" "RS\0*" "RT\0" "FILENAME\0"
378 "SUBSEP\0" "ARGIND\0" "ARGC\0" "ARGV\0"
379 "ERRNO\0" "FNR\0"
380 "NR\0" "NF\0*" "IGNORECASE\0*"
381 "ENVIRON\0" "$\0*" "\0";
Glenn L McGrath545106f2002-11-11 06:21:00 +0000382
Denis Vlasenko6ca409e2007-08-12 20:58:27 +0000383static const char vValues[] ALIGN1 =
Denis Vlasenkof782f522007-01-01 23:51:30 +0000384 "%.6g\0" "%.6g\0" " \0" " \0"
385 "\n\0" "\n\0" "\0" "\0"
Glenn L McGrath545106f2002-11-11 06:21:00 +0000386 "\034\0"
387 "\377";
388
389/* hash size may grow to these values */
Denis Vlasenko6ca409e2007-08-12 20:58:27 +0000390#define FIRST_PRIME 61
391static const uint16_t PRIMES[] ALIGN2 = { 251, 1021, 4093, 16381, 65521 };
Glenn L McGrath545106f2002-11-11 06:21:00 +0000392
Glenn L McGrath545106f2002-11-11 06:21:00 +0000393
Denis Vlasenkoe16e6e72007-06-07 13:14:53 +0000394/* Globals. Split in two parts so that first one is addressed
395 * with (mostly short) negative offsets */
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +0000396struct globals {
Denis Vlasenko574f2f42008-02-27 18:41:59 +0000397 chain beginseq, mainseq, endseq;
398 chain *seq;
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +0000399 node *break_ptr, *continue_ptr;
400 rstream *iF;
401 xhash *vhash, *ahash, *fdhash, *fnhash;
402 const char *g_progname;
403 int g_lineno;
404 int nfields;
405 int maxfields; /* used in fsrealloc() only */
406 var *Fields;
407 nvblock *g_cb;
408 char *g_pos;
409 char *g_buf;
Denis Vlasenkoe16e6e72007-06-07 13:14:53 +0000410 smallint icase;
411 smallint exiting;
412 smallint nextrec;
413 smallint nextfile;
414 smallint is_f0_split;
415};
416struct globals2 {
417 uint32_t t_info; /* often used */
418 uint32_t t_tclass;
419 char *t_string;
420 int t_lineno;
421 int t_rollback;
422
423 var *intvar[NUM_INTERNAL_VARS]; /* often used */
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +0000424
425 /* former statics from various functions */
426 char *split_f0__fstrings;
427
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +0000428 uint32_t next_token__save_tclass;
429 uint32_t next_token__save_info;
430 uint32_t next_token__ltclass;
Denis Vlasenkoe16e6e72007-06-07 13:14:53 +0000431 smallint next_token__concat_inserted;
432
433 smallint next_input_file__files_happen;
434 rstream next_input_file__rsm;
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +0000435
436 var *evaluate__fnargs;
437 unsigned evaluate__seed;
438 regex_t evaluate__sreg;
439
440 var ptest__v;
441
442 tsplitter exec_builtin__tspl;
443
Denis Vlasenkoe16e6e72007-06-07 13:14:53 +0000444 /* biggest and least used members go last */
445 double t_double;
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +0000446 tsplitter fsplitter, rsplitter;
447};
Denis Vlasenkoe16e6e72007-06-07 13:14:53 +0000448#define G1 (ptr_to_globals[-1])
Denis Vlasenko574f2f42008-02-27 18:41:59 +0000449#define G (*(struct globals2 *)ptr_to_globals)
Denis Vlasenkoe16e6e72007-06-07 13:14:53 +0000450/* For debug. nm --size-sort awk.o | grep -vi ' [tr] ' */
451/* char G1size[sizeof(G1)]; - 0x6c */
452/* char Gsize[sizeof(G)]; - 0x1cc */
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +0000453/* Trying to keep most of members accessible with short offsets: */
Denis Vlasenkoe16e6e72007-06-07 13:14:53 +0000454/* char Gofs_seed[offsetof(struct globals2, evaluate__seed)]; - 0x90 */
455#define beginseq (G1.beginseq )
456#define mainseq (G1.mainseq )
457#define endseq (G1.endseq )
458#define seq (G1.seq )
459#define break_ptr (G1.break_ptr )
460#define continue_ptr (G1.continue_ptr)
461#define iF (G1.iF )
462#define vhash (G1.vhash )
463#define ahash (G1.ahash )
464#define fdhash (G1.fdhash )
465#define fnhash (G1.fnhash )
466#define g_progname (G1.g_progname )
467#define g_lineno (G1.g_lineno )
468#define nfields (G1.nfields )
469#define maxfields (G1.maxfields )
470#define Fields (G1.Fields )
471#define g_cb (G1.g_cb )
472#define g_pos (G1.g_pos )
473#define g_buf (G1.g_buf )
474#define icase (G1.icase )
475#define exiting (G1.exiting )
476#define nextrec (G1.nextrec )
477#define nextfile (G1.nextfile )
478#define is_f0_split (G1.is_f0_split )
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +0000479#define t_info (G.t_info )
480#define t_tclass (G.t_tclass )
481#define t_string (G.t_string )
482#define t_double (G.t_double )
483#define t_lineno (G.t_lineno )
484#define t_rollback (G.t_rollback )
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +0000485#define intvar (G.intvar )
486#define fsplitter (G.fsplitter )
487#define rsplitter (G.rsplitter )
488#define INIT_G() do { \
Denis Vlasenko574f2f42008-02-27 18:41:59 +0000489 SET_PTR_TO_GLOBALS(xzalloc(sizeof(G1) + sizeof(G)) + sizeof(G1)); \
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +0000490 G.next_token__ltclass = TC_OPTERM; \
491 G.evaluate__seed = 1; \
492} while (0)
493
Glenn L McGrath545106f2002-11-11 06:21:00 +0000494
495/* function prototypes */
Glenn L McGrath545106f2002-11-11 06:21:00 +0000496static void handle_special(var *);
Mike Frysingerf87b3e32005-09-27 04:16:22 +0000497static node *parse_expr(uint32_t);
Glenn L McGrath545106f2002-11-11 06:21:00 +0000498static void chain_group(void);
499static var *evaluate(node *, var *);
500static rstream *next_input_file(void);
"Vladimir N. Oleynik"5cf9a032005-10-19 09:21:51 +0000501static int fmt_num(char *, int, const char *, double, int);
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +0000502static int awk_exit(int) NORETURN;
Glenn L McGrath545106f2002-11-11 06:21:00 +0000503
504/* ---- error handling ---- */
505
Denis Vlasenko6ca409e2007-08-12 20:58:27 +0000506static const char EMSG_INTERNAL_ERROR[] ALIGN1 = "Internal error";
507static const char EMSG_UNEXP_EOS[] ALIGN1 = "Unexpected end of string";
508static const char EMSG_UNEXP_TOKEN[] ALIGN1 = "Unexpected token";
509static const char EMSG_DIV_BY_ZERO[] ALIGN1 = "Division by zero";
510static const char EMSG_INV_FMT[] ALIGN1 = "Invalid format specifier";
511static const char EMSG_TOO_FEW_ARGS[] ALIGN1 = "Too few arguments for builtin";
512static const char EMSG_NOT_ARRAY[] ALIGN1 = "Not an array";
513static const char EMSG_POSSIBLE_ERROR[] ALIGN1 = "Possible syntax error";
514static const char EMSG_UNDEF_FUNC[] ALIGN1 = "Call to undefined function";
Denis Vlasenkof782f522007-01-01 23:51:30 +0000515#if !ENABLE_FEATURE_AWK_MATH
Denis Vlasenko6ca409e2007-08-12 20:58:27 +0000516static const char EMSG_NO_MATH[] ALIGN1 = "Math support is not compiled in";
Glenn L McGrath545106f2002-11-11 06:21:00 +0000517#endif
518
Denis Vlasenkof782f522007-01-01 23:51:30 +0000519static void zero_out_var(var * vp)
520{
521 memset(vp, 0, sizeof(*vp));
522}
523
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +0000524static void syntax_error(const char *const message) NORETURN;
Denis Vlasenko6ca409e2007-08-12 20:58:27 +0000525static void syntax_error(const char *const message)
Glenn L McGrathd4036f82002-11-28 09:30:40 +0000526{
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +0000527 bb_error_msg_and_die("%s:%i: %s", g_progname, g_lineno, message);
Glenn L McGrath545106f2002-11-11 06:21:00 +0000528}
529
Glenn L McGrath545106f2002-11-11 06:21:00 +0000530/* ---- hash stuff ---- */
531
Denis Vlasenkof782f522007-01-01 23:51:30 +0000532static unsigned hashidx(const char *name)
Mike Frysinger10a11e22005-09-27 02:23:02 +0000533{
Denis Vlasenkof782f522007-01-01 23:51:30 +0000534 unsigned idx = 0;
Glenn L McGrath545106f2002-11-11 06:21:00 +0000535
Denis Vlasenkof782f522007-01-01 23:51:30 +0000536 while (*name) idx = *name++ + (idx << 6) - idx;
Glenn L McGrath545106f2002-11-11 06:21:00 +0000537 return idx;
538}
539
540/* create new hash */
Mike Frysinger10a11e22005-09-27 02:23:02 +0000541static xhash *hash_init(void)
542{
Glenn L McGrath545106f2002-11-11 06:21:00 +0000543 xhash *newhash;
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000544
Denis Vlasenko4cccc032006-12-22 18:37:07 +0000545 newhash = xzalloc(sizeof(xhash));
Glenn L McGrath545106f2002-11-11 06:21:00 +0000546 newhash->csize = FIRST_PRIME;
Denis Vlasenko4cccc032006-12-22 18:37:07 +0000547 newhash->items = xzalloc(newhash->csize * sizeof(hash_item *));
Glenn L McGrath545106f2002-11-11 06:21:00 +0000548
549 return newhash;
550}
551
552/* find item in hash, return ptr to data, NULL if not found */
"Vladimir N. Oleynik"5cf9a032005-10-19 09:21:51 +0000553static void *hash_search(xhash *hash, const char *name)
Mike Frysinger10a11e22005-09-27 02:23:02 +0000554{
Glenn L McGrath545106f2002-11-11 06:21:00 +0000555 hash_item *hi;
556
557 hi = hash->items [ hashidx(name) % hash->csize ];
558 while (hi) {
559 if (strcmp(hi->name, name) == 0)
560 return &(hi->data);
561 hi = hi->next;
562 }
563 return NULL;
564}
565
566/* grow hash if it becomes too big */
Mike Frysinger10a11e22005-09-27 02:23:02 +0000567static void hash_rebuild(xhash *hash)
568{
Denis Vlasenkof782f522007-01-01 23:51:30 +0000569 unsigned newsize, i, idx;
Glenn L McGrath545106f2002-11-11 06:21:00 +0000570 hash_item **newitems, *hi, *thi;
571
Denis Vlasenko80b8b392007-06-25 10:55:35 +0000572 if (hash->nprime == ARRAY_SIZE(PRIMES))
Glenn L McGrath545106f2002-11-11 06:21:00 +0000573 return;
574
575 newsize = PRIMES[hash->nprime++];
Denis Vlasenko4cccc032006-12-22 18:37:07 +0000576 newitems = xzalloc(newsize * sizeof(hash_item *));
Glenn L McGrath545106f2002-11-11 06:21:00 +0000577
Denis Vlasenkoffba9412007-05-17 23:03:35 +0000578 for (i = 0; i < hash->csize; i++) {
Glenn L McGrath545106f2002-11-11 06:21:00 +0000579 hi = hash->items[i];
580 while (hi) {
581 thi = hi;
582 hi = thi->next;
583 idx = hashidx(thi->name) % newsize;
584 thi->next = newitems[idx];
585 newitems[idx] = thi;
586 }
587 }
588
589 free(hash->items);
590 hash->csize = newsize;
591 hash->items = newitems;
592}
593
594/* find item in hash, add it if necessary. Return ptr to data */
"Vladimir N. Oleynik"5cf9a032005-10-19 09:21:51 +0000595static void *hash_find(xhash *hash, const char *name)
Mike Frysinger10a11e22005-09-27 02:23:02 +0000596{
Glenn L McGrath545106f2002-11-11 06:21:00 +0000597 hash_item *hi;
Denis Vlasenkof782f522007-01-01 23:51:30 +0000598 unsigned idx;
Glenn L McGrath545106f2002-11-11 06:21:00 +0000599 int l;
600
601 hi = hash_search(hash, name);
Denis Vlasenkob78c7822007-07-18 18:31:11 +0000602 if (!hi) {
Glenn L McGrath545106f2002-11-11 06:21:00 +0000603 if (++hash->nel / hash->csize > 10)
604 hash_rebuild(hash);
605
Rob Landleya3896512006-05-07 20:20:34 +0000606 l = strlen(name) + 1;
Rob Landley9ffd4232006-05-21 18:30:35 +0000607 hi = xzalloc(sizeof(hash_item) + l);
Glenn L McGrath545106f2002-11-11 06:21:00 +0000608 memcpy(hi->name, name, l);
609
610 idx = hashidx(name) % hash->csize;
611 hi->next = hash->items[idx];
612 hash->items[idx] = hi;
613 hash->glen += l;
614 }
615 return &(hi->data);
616}
617
Denis Vlasenkoffba9412007-05-17 23:03:35 +0000618#define findvar(hash, name) ((var*) hash_find((hash), (name)))
619#define newvar(name) ((var*) hash_find(vhash, (name)))
620#define newfile(name) ((rstream*)hash_find(fdhash, (name)))
621#define newfunc(name) ((func*) hash_find(fnhash, (name)))
Glenn L McGrath545106f2002-11-11 06:21:00 +0000622
"Vladimir N. Oleynik"5cf9a032005-10-19 09:21:51 +0000623static void hash_remove(xhash *hash, const char *name)
Mike Frysinger10a11e22005-09-27 02:23:02 +0000624{
Glenn L McGrath545106f2002-11-11 06:21:00 +0000625 hash_item *hi, **phi;
626
Denis Vlasenkoffba9412007-05-17 23:03:35 +0000627 phi = &(hash->items[hashidx(name) % hash->csize]);
Glenn L McGrath545106f2002-11-11 06:21:00 +0000628 while (*phi) {
629 hi = *phi;
630 if (strcmp(hi->name, name) == 0) {
Rob Landleya3896512006-05-07 20:20:34 +0000631 hash->glen -= (strlen(name) + 1);
Glenn L McGrath545106f2002-11-11 06:21:00 +0000632 hash->nel--;
633 *phi = hi->next;
634 free(hi);
635 break;
636 }
637 phi = &(hi->next);
638 }
639}
640
641/* ------ some useful functions ------ */
642
Mike Frysinger10a11e22005-09-27 02:23:02 +0000643static void skip_spaces(char **s)
644{
"Robert P. J. Day"68229832006-07-01 13:08:46 +0000645 char *p = *s;
Glenn L McGrath545106f2002-11-11 06:21:00 +0000646
Denis Vlasenkocd5c7862007-05-17 16:37:22 +0000647 while (1) {
648 if (*p == '\\' && p[1] == '\n') {
649 p++;
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +0000650 t_lineno++;
Denis Vlasenkocd5c7862007-05-17 16:37:22 +0000651 } else if (*p != ' ' && *p != '\t') {
652 break;
653 }
Mike Frysingerde2b9382005-09-27 03:18:00 +0000654 p++;
Glenn L McGrath545106f2002-11-11 06:21:00 +0000655 }
656 *s = p;
657}
658
Mike Frysinger10a11e22005-09-27 02:23:02 +0000659static char *nextword(char **s)
660{
"Robert P. J. Day"68229832006-07-01 13:08:46 +0000661 char *p = *s;
Glenn L McGrath545106f2002-11-11 06:21:00 +0000662
Denis Vlasenkof782f522007-01-01 23:51:30 +0000663 while (*(*s)++) /* */;
Glenn L McGrath545106f2002-11-11 06:21:00 +0000664
665 return p;
666}
667
Mike Frysinger10a11e22005-09-27 02:23:02 +0000668static char nextchar(char **s)
669{
"Robert P. J. Day"68229832006-07-01 13:08:46 +0000670 char c, *pps;
Glenn L McGrath545106f2002-11-11 06:21:00 +0000671
672 c = *((*s)++);
673 pps = *s;
Manuel Novoa III cad53642003-03-19 09:13:01 +0000674 if (c == '\\') c = bb_process_escape_sequence((const char**)s);
Glenn L McGrath545106f2002-11-11 06:21:00 +0000675 if (c == '\\' && *s == pps) c = *((*s)++);
676 return c;
677}
678
Denis Vlasenko77ad97f2008-05-13 02:27:31 +0000679static ALWAYS_INLINE int isalnum_(int c)
Mike Frysinger10a11e22005-09-27 02:23:02 +0000680{
Glenn L McGrath545106f2002-11-11 06:21:00 +0000681 return (isalnum(c) || c == '_');
682}
683
Glenn L McGrath545106f2002-11-11 06:21:00 +0000684/* -------- working with variables (set/get/copy/etc) -------- */
685
Mike Frysinger10a11e22005-09-27 02:23:02 +0000686static xhash *iamarray(var *v)
687{
Glenn L McGrath545106f2002-11-11 06:21:00 +0000688 var *a = v;
689
690 while (a->type & VF_CHILD)
691 a = a->x.parent;
692
Denis Vlasenkocd5c7862007-05-17 16:37:22 +0000693 if (!(a->type & VF_ARRAY)) {
Glenn L McGrath545106f2002-11-11 06:21:00 +0000694 a->type |= VF_ARRAY;
695 a->x.array = hash_init();
696 }
697 return a->x.array;
698}
699
Mike Frysinger10a11e22005-09-27 02:23:02 +0000700static void clear_array(xhash *array)
701{
Denis Vlasenkof782f522007-01-01 23:51:30 +0000702 unsigned i;
Glenn L McGrath545106f2002-11-11 06:21:00 +0000703 hash_item *hi, *thi;
704
Denis Vlasenkocd5c7862007-05-17 16:37:22 +0000705 for (i = 0; i < array->csize; i++) {
Glenn L McGrath545106f2002-11-11 06:21:00 +0000706 hi = array->items[i];
707 while (hi) {
708 thi = hi;
709 hi = hi->next;
Aaron Lehmanna170e1c2002-11-28 11:27:31 +0000710 free(thi->data.v.string);
Glenn L McGrath545106f2002-11-11 06:21:00 +0000711 free(thi);
712 }
713 array->items[i] = NULL;
714 }
715 array->glen = array->nel = 0;
716}
717
718/* clear a variable */
Mike Frysinger10a11e22005-09-27 02:23:02 +0000719static var *clrvar(var *v)
720{
Aaron Lehmanna170e1c2002-11-28 11:27:31 +0000721 if (!(v->type & VF_FSTR))
Glenn L McGrath545106f2002-11-11 06:21:00 +0000722 free(v->string);
723
724 v->type &= VF_DONTTOUCH;
725 v->type |= VF_DIRTY;
726 v->string = NULL;
727 return v;
728}
729
730/* assign string value to variable */
Mike Frysinger10a11e22005-09-27 02:23:02 +0000731static var *setvar_p(var *v, char *value)
732{
Glenn L McGrath545106f2002-11-11 06:21:00 +0000733 clrvar(v);
734 v->string = value;
735 handle_special(v);
Glenn L McGrath545106f2002-11-11 06:21:00 +0000736 return v;
737}
738
739/* same as setvar_p but make a copy of string */
"Vladimir N. Oleynik"5cf9a032005-10-19 09:21:51 +0000740static var *setvar_s(var *v, const char *value)
Mike Frysinger10a11e22005-09-27 02:23:02 +0000741{
Rob Landleyd921b2e2006-08-03 15:41:12 +0000742 return setvar_p(v, (value && *value) ? xstrdup(value) : NULL);
Glenn L McGrath545106f2002-11-11 06:21:00 +0000743}
744
745/* same as setvar_s but set USER flag */
"Vladimir N. Oleynik"5cf9a032005-10-19 09:21:51 +0000746static var *setvar_u(var *v, const char *value)
Mike Frysinger10a11e22005-09-27 02:23:02 +0000747{
Glenn L McGrath545106f2002-11-11 06:21:00 +0000748 setvar_s(v, value);
749 v->type |= VF_USER;
750 return v;
751}
752
753/* set array element to user string */
"Vladimir N. Oleynik"5cf9a032005-10-19 09:21:51 +0000754static void setari_u(var *a, int idx, const char *s)
Mike Frysinger10a11e22005-09-27 02:23:02 +0000755{
Denis Vlasenkoffba9412007-05-17 23:03:35 +0000756 char sidx[sizeof(int)*3 + 1];
"Robert P. J. Day"68229832006-07-01 13:08:46 +0000757 var *v;
Glenn L McGrath545106f2002-11-11 06:21:00 +0000758
759 sprintf(sidx, "%d", idx);
760 v = findvar(iamarray(a), sidx);
761 setvar_u(v, s);
762}
763
764/* assign numeric value to variable */
Mike Frysinger10a11e22005-09-27 02:23:02 +0000765static var *setvar_i(var *v, double value)
766{
Glenn L McGrath545106f2002-11-11 06:21:00 +0000767 clrvar(v);
768 v->type |= VF_NUMBER;
769 v->number = value;
770 handle_special(v);
771 return v;
772}
773
Denis Vlasenkoa41fdf32007-01-29 22:51:00 +0000774static const char *getvar_s(var *v)
Mike Frysinger10a11e22005-09-27 02:23:02 +0000775{
Glenn L McGrath545106f2002-11-11 06:21:00 +0000776 /* if v is numeric and has no cached string, convert it to string */
777 if ((v->type & (VF_NUMBER | VF_CACHED)) == VF_NUMBER) {
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +0000778 fmt_num(g_buf, MAXVARFMT, getvar_s(intvar[CONVFMT]), v->number, TRUE);
779 v->string = xstrdup(g_buf);
Glenn L McGrath545106f2002-11-11 06:21:00 +0000780 v->type |= VF_CACHED;
781 }
782 return (v->string == NULL) ? "" : v->string;
783}
784
Mike Frysinger10a11e22005-09-27 02:23:02 +0000785static double getvar_i(var *v)
786{
Glenn L McGrath545106f2002-11-11 06:21:00 +0000787 char *s;
788
789 if ((v->type & (VF_NUMBER | VF_CACHED)) == 0) {
790 v->number = 0;
791 s = v->string;
792 if (s && *s) {
793 v->number = strtod(s, &s);
794 if (v->type & VF_USER) {
795 skip_spaces(&s);
796 if (*s != '\0')
797 v->type &= ~VF_USER;
798 }
799 } else {
800 v->type &= ~VF_USER;
801 }
802 v->type |= VF_CACHED;
803 }
804 return v->number;
805}
806
"Vladimir N. Oleynik"5cf9a032005-10-19 09:21:51 +0000807static var *copyvar(var *dest, const var *src)
Mike Frysinger10a11e22005-09-27 02:23:02 +0000808{
Glenn L McGrath545106f2002-11-11 06:21:00 +0000809 if (dest != src) {
810 clrvar(dest);
Denis Vlasenko629563b2007-02-24 17:05:52 +0000811 dest->type |= (src->type & ~(VF_DONTTOUCH | VF_FSTR));
Glenn L McGrath545106f2002-11-11 06:21:00 +0000812 dest->number = src->number;
813 if (src->string)
Rob Landleyd921b2e2006-08-03 15:41:12 +0000814 dest->string = xstrdup(src->string);
Glenn L McGrath545106f2002-11-11 06:21:00 +0000815 }
816 handle_special(dest);
817 return dest;
818}
819
Mike Frysinger10a11e22005-09-27 02:23:02 +0000820static var *incvar(var *v)
821{
Denis Vlasenko6ca409e2007-08-12 20:58:27 +0000822 return setvar_i(v, getvar_i(v) + 1.);
Glenn L McGrath545106f2002-11-11 06:21:00 +0000823}
824
825/* return true if v is number or numeric string */
Mike Frysinger10a11e22005-09-27 02:23:02 +0000826static int is_numeric(var *v)
827{
Glenn L McGrath545106f2002-11-11 06:21:00 +0000828 getvar_i(v);
829 return ((v->type ^ VF_DIRTY) & (VF_NUMBER | VF_USER | VF_DIRTY));
830}
831
832/* return 1 when value of v corresponds to true, 0 otherwise */
Mike Frysinger10a11e22005-09-27 02:23:02 +0000833static int istrue(var *v)
834{
Glenn L McGrath545106f2002-11-11 06:21:00 +0000835 if (is_numeric(v))
836 return (v->number == 0) ? 0 : 1;
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +0000837 return (v->string && *(v->string)) ? 1 : 0;
Glenn L McGrath545106f2002-11-11 06:21:00 +0000838}
839
Eric Andersenaff114c2004-04-14 17:51:38 +0000840/* temporary variables allocator. Last allocated should be first freed */
Mike Frysinger10a11e22005-09-27 02:23:02 +0000841static var *nvalloc(int n)
842{
Glenn L McGrath545106f2002-11-11 06:21:00 +0000843 nvblock *pb = NULL;
844 var *v, *r;
845 int size;
846
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +0000847 while (g_cb) {
848 pb = g_cb;
849 if ((g_cb->pos - g_cb->nv) + n <= g_cb->size) break;
850 g_cb = g_cb->next;
Glenn L McGrath545106f2002-11-11 06:21:00 +0000851 }
852
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +0000853 if (!g_cb) {
Glenn L McGrath545106f2002-11-11 06:21:00 +0000854 size = (n <= MINNVBLOCK) ? MINNVBLOCK : n;
Denis Vlasenkoe0a7fc52008-07-02 11:14:59 +0000855 g_cb = xzalloc(sizeof(nvblock) + size * sizeof(var));
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +0000856 g_cb->size = size;
857 g_cb->pos = g_cb->nv;
858 g_cb->prev = pb;
Denis Vlasenkoe0a7fc52008-07-02 11:14:59 +0000859 /*g_cb->next = NULL; - xzalloc did it */
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +0000860 if (pb) pb->next = g_cb;
Glenn L McGrath545106f2002-11-11 06:21:00 +0000861 }
862
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +0000863 v = r = g_cb->pos;
864 g_cb->pos += n;
Glenn L McGrath545106f2002-11-11 06:21:00 +0000865
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +0000866 while (v < g_cb->pos) {
Glenn L McGrath545106f2002-11-11 06:21:00 +0000867 v->type = 0;
868 v->string = NULL;
869 v++;
870 }
871
872 return r;
873}
874
Mike Frysinger10a11e22005-09-27 02:23:02 +0000875static void nvfree(var *v)
876{
Glenn L McGrath545106f2002-11-11 06:21:00 +0000877 var *p;
878
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +0000879 if (v < g_cb->nv || v >= g_cb->pos)
880 syntax_error(EMSG_INTERNAL_ERROR);
Glenn L McGrath545106f2002-11-11 06:21:00 +0000881
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +0000882 for (p = v; p < g_cb->pos; p++) {
Denis Vlasenkoffba9412007-05-17 23:03:35 +0000883 if ((p->type & (VF_ARRAY | VF_CHILD)) == VF_ARRAY) {
Glenn L McGrath545106f2002-11-11 06:21:00 +0000884 clear_array(iamarray(p));
885 free(p->x.array->items);
886 free(p->x.array);
887 }
888 if (p->type & VF_WALK)
889 free(p->x.walker);
890
891 clrvar(p);
892 }
893
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +0000894 g_cb->pos = v;
895 while (g_cb->prev && g_cb->pos == g_cb->nv) {
896 g_cb = g_cb->prev;
Glenn L McGrath545106f2002-11-11 06:21:00 +0000897 }
898}
899
900/* ------- awk program text parsing ------- */
901
Denis Vlasenkocd5c7862007-05-17 16:37:22 +0000902/* Parse next token pointed by global pos, place results into global ttt.
Glenn L McGrath545106f2002-11-11 06:21:00 +0000903 * If token isn't expected, give away. Return token class
904 */
Mike Frysingerf87b3e32005-09-27 04:16:22 +0000905static uint32_t next_token(uint32_t expected)
Mike Frysinger10a11e22005-09-27 02:23:02 +0000906{
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +0000907#define concat_inserted (G.next_token__concat_inserted)
908#define save_tclass (G.next_token__save_tclass)
909#define save_info (G.next_token__save_info)
910/* Initialized to TC_OPTERM: */
911#define ltclass (G.next_token__ltclass)
Glenn L McGrath545106f2002-11-11 06:21:00 +0000912
Denis Vlasenkof782f522007-01-01 23:51:30 +0000913 char *p, *pp, *s;
914 const char *tl;
915 uint32_t tc;
916 const uint32_t *ti;
917 int l;
918
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +0000919 if (t_rollback) {
920 t_rollback = FALSE;
Glenn L McGrath545106f2002-11-11 06:21:00 +0000921
922 } else if (concat_inserted) {
Glenn L McGrath545106f2002-11-11 06:21:00 +0000923 concat_inserted = FALSE;
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +0000924 t_tclass = save_tclass;
925 t_info = save_info;
Glenn L McGrath545106f2002-11-11 06:21:00 +0000926
927 } else {
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +0000928 p = g_pos;
Denis Vlasenkoe1d3e032007-01-01 23:53:52 +0000929 readnext:
Glenn L McGrath545106f2002-11-11 06:21:00 +0000930 skip_spaces(&p);
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +0000931 g_lineno = t_lineno;
Glenn L McGrath545106f2002-11-11 06:21:00 +0000932 if (*p == '#')
Denis Vlasenkoffba9412007-05-17 23:03:35 +0000933 while (*p != '\n' && *p != '\0')
934 p++;
Glenn L McGrath545106f2002-11-11 06:21:00 +0000935
936 if (*p == '\n')
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +0000937 t_lineno++;
Glenn L McGrath545106f2002-11-11 06:21:00 +0000938
939 if (*p == '\0') {
940 tc = TC_EOF;
941
942 } else if (*p == '\"') {
943 /* it's a string */
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +0000944 t_string = s = ++p;
Glenn L McGrath545106f2002-11-11 06:21:00 +0000945 while (*p != '\"') {
946 if (*p == '\0' || *p == '\n')
947 syntax_error(EMSG_UNEXP_EOS);
948 *(s++) = nextchar(&p);
949 }
950 p++;
951 *s = '\0';
952 tc = TC_STRING;
953
954 } else if ((expected & TC_REGEXP) && *p == '/') {
955 /* it's regexp */
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +0000956 t_string = s = ++p;
Glenn L McGrath545106f2002-11-11 06:21:00 +0000957 while (*p != '/') {
958 if (*p == '\0' || *p == '\n')
959 syntax_error(EMSG_UNEXP_EOS);
Denis Vlasenkod9b5ab82007-05-18 07:30:43 +0000960 *s = *p++;
Denis Vlasenkoffba9412007-05-17 23:03:35 +0000961 if (*s++ == '\\') {
Glenn L McGrath545106f2002-11-11 06:21:00 +0000962 pp = p;
Manuel Novoa III cad53642003-03-19 09:13:01 +0000963 *(s-1) = bb_process_escape_sequence((const char **)&p);
Denis Vlasenkoffba9412007-05-17 23:03:35 +0000964 if (*pp == '\\')
965 *s++ = '\\';
966 if (p == pp)
967 *s++ = *p++;
Glenn L McGrath545106f2002-11-11 06:21:00 +0000968 }
969 }
970 p++;
971 *s = '\0';
972 tc = TC_REGEXP;
973
974 } else if (*p == '.' || isdigit(*p)) {
975 /* it's a number */
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +0000976 t_double = strtod(p, &p);
Glenn L McGrath545106f2002-11-11 06:21:00 +0000977 if (*p == '.')
978 syntax_error(EMSG_UNEXP_TOKEN);
979 tc = TC_NUMBER;
980
981 } else {
982 /* search for something known */
983 tl = tokenlist;
984 tc = 0x00000001;
985 ti = tokeninfo;
986 while (*tl) {
987 l = *(tl++);
988 if (l == NTCC) {
989 tc <<= 1;
990 continue;
991 }
992 /* if token class is expected, token
993 * matches and it's not a longer word,
994 * then this is what we are looking for
995 */
Denis Vlasenkoffba9412007-05-17 23:03:35 +0000996 if ((tc & (expected | TC_WORD | TC_NEWLINE))
997 && *tl == *p && strncmp(p, tl, l) == 0
998 && !((tc & TC_WORD) && isalnum_(p[l]))
999 ) {
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00001000 t_info = *ti;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001001 p += l;
1002 break;
1003 }
1004 ti++;
1005 tl += l;
1006 }
1007
Denis Vlasenkof782f522007-01-01 23:51:30 +00001008 if (!*tl) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00001009 /* it's a name (var/array/function),
1010 * otherwise it's something wrong
1011 */
Denis Vlasenkoe1d3e032007-01-01 23:53:52 +00001012 if (!isalnum_(*p))
Glenn L McGrath545106f2002-11-11 06:21:00 +00001013 syntax_error(EMSG_UNEXP_TOKEN);
1014
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00001015 t_string = --p;
Denis Vlasenkobf0a2012006-12-26 10:42:51 +00001016 while (isalnum_(*(++p))) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00001017 *(p-1) = *p;
1018 }
1019 *(p-1) = '\0';
1020 tc = TC_VARIABLE;
Bernhard Reutner-Fischerbb204622005-10-17 14:21:06 +00001021 /* also consume whitespace between functionname and bracket */
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001022 if (!(expected & TC_VARIABLE))
1023 skip_spaces(&p);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001024 if (*p == '(') {
1025 tc = TC_FUNCTION;
1026 } else {
Glenn L McGrath545106f2002-11-11 06:21:00 +00001027 if (*p == '[') {
1028 p++;
1029 tc = TC_ARRAY;
1030 }
1031 }
1032 }
1033 }
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00001034 g_pos = p;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001035
1036 /* skipping newlines in some cases */
1037 if ((ltclass & TC_NOTERM) && (tc & TC_NEWLINE))
1038 goto readnext;
1039
1040 /* insert concatenation operator when needed */
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001041 if ((ltclass & TC_CONCAT1) && (tc & TC_CONCAT2) && (expected & TC_BINOP)) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00001042 concat_inserted = TRUE;
1043 save_tclass = tc;
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00001044 save_info = t_info;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001045 tc = TC_BINOP;
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00001046 t_info = OC_CONCAT | SS | P(35);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001047 }
1048
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00001049 t_tclass = tc;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001050 }
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00001051 ltclass = t_tclass;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001052
1053 /* Are we ready for this? */
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001054 if (!(ltclass & expected))
Glenn L McGrath545106f2002-11-11 06:21:00 +00001055 syntax_error((ltclass & (TC_NEWLINE | TC_EOF)) ?
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001056 EMSG_UNEXP_EOS : EMSG_UNEXP_TOKEN);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001057
1058 return ltclass;
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00001059#undef concat_inserted
1060#undef save_tclass
1061#undef save_info
1062#undef ltclass
Glenn L McGrath545106f2002-11-11 06:21:00 +00001063}
1064
Denis Vlasenkocd5c7862007-05-17 16:37:22 +00001065static void rollback_token(void)
1066{
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00001067 t_rollback = TRUE;
Denis Vlasenkocd5c7862007-05-17 16:37:22 +00001068}
Glenn L McGrath545106f2002-11-11 06:21:00 +00001069
Mike Frysingerf87b3e32005-09-27 04:16:22 +00001070static node *new_node(uint32_t info)
Mike Frysinger10a11e22005-09-27 02:23:02 +00001071{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001072 node *n;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001073
Denis Vlasenko4cccc032006-12-22 18:37:07 +00001074 n = xzalloc(sizeof(node));
Glenn L McGrath545106f2002-11-11 06:21:00 +00001075 n->info = info;
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00001076 n->lineno = g_lineno;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001077 return n;
1078}
1079
Denis Vlasenkoa41fdf32007-01-29 22:51:00 +00001080static node *mk_re_node(const char *s, node *n, regex_t *re)
Mike Frysinger10a11e22005-09-27 02:23:02 +00001081{
Glenn L McGrath545106f2002-11-11 06:21:00 +00001082 n->info = OC_REGEXP;
1083 n->l.re = re;
1084 n->r.ire = re + 1;
1085 xregcomp(re, s, REG_EXTENDED);
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001086 xregcomp(re + 1, s, REG_EXTENDED | REG_ICASE);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001087
1088 return n;
1089}
1090
Mike Frysinger10a11e22005-09-27 02:23:02 +00001091static node *condition(void)
1092{
Glenn L McGrath545106f2002-11-11 06:21:00 +00001093 next_token(TC_SEQSTART);
1094 return parse_expr(TC_SEQTERM);
1095}
1096
1097/* parse expression terminated by given argument, return ptr
1098 * to built subtree. Terminator is eaten by parse_expr */
Mike Frysingerf87b3e32005-09-27 04:16:22 +00001099static node *parse_expr(uint32_t iexp)
Mike Frysinger10a11e22005-09-27 02:23:02 +00001100{
Glenn L McGrath545106f2002-11-11 06:21:00 +00001101 node sn;
1102 node *cn = &sn;
1103 node *vn, *glptr;
Mike Frysingerf87b3e32005-09-27 04:16:22 +00001104 uint32_t tc, xtc;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001105 var *v;
1106
1107 sn.info = PRIMASK;
1108 sn.r.n = glptr = NULL;
1109 xtc = TC_OPERAND | TC_UOPPRE | TC_REGEXP | iexp;
1110
Denis Vlasenkocd5c7862007-05-17 16:37:22 +00001111 while (!((tc = next_token(xtc)) & iexp)) {
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00001112 if (glptr && (t_info == (OC_COMPARE | VV | P(39) | 2))) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00001113 /* input redirection (<) attached to glptr node */
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001114 cn = glptr->l.n = new_node(OC_CONCAT | SS | P(37));
Glenn L McGrath4bded582004-02-22 11:55:09 +00001115 cn->a.n = glptr;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001116 xtc = TC_OPERAND | TC_UOPPRE;
1117 glptr = NULL;
1118
1119 } else if (tc & (TC_BINOP | TC_UOPPOST)) {
1120 /* for binary and postfix-unary operators, jump back over
1121 * previous operators with higher priority */
1122 vn = cn;
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00001123 while ( ((t_info & PRIMASK) > (vn->a.n->info & PRIMASK2))
1124 || ((t_info == vn->info) && ((t_info & OPCLSMASK) == OC_COLON)) )
Glenn L McGrath545106f2002-11-11 06:21:00 +00001125 vn = vn->a.n;
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00001126 if ((t_info & OPCLSMASK) == OC_TERNARY)
1127 t_info += P(6);
1128 cn = vn->a.n->r.n = new_node(t_info);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001129 cn->a.n = vn->a.n;
1130 if (tc & TC_BINOP) {
1131 cn->l.n = vn;
1132 xtc = TC_OPERAND | TC_UOPPRE | TC_REGEXP;
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00001133 if ((t_info & OPCLSMASK) == OC_PGETLINE) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00001134 /* it's a pipe */
1135 next_token(TC_GETLINE);
1136 /* give maximum priority to this pipe */
1137 cn->info &= ~PRIMASK;
1138 xtc = TC_OPERAND | TC_UOPPRE | TC_BINOP | iexp;
1139 }
1140 } else {
1141 cn->r.n = vn;
1142 xtc = TC_OPERAND | TC_UOPPRE | TC_BINOP | iexp;
1143 }
1144 vn->a.n = cn;
1145
1146 } else {
1147 /* for operands and prefix-unary operators, attach them
1148 * to last node */
1149 vn = cn;
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00001150 cn = vn->r.n = new_node(t_info);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001151 cn->a.n = vn;
1152 xtc = TC_OPERAND | TC_UOPPRE | TC_REGEXP;
1153 if (tc & (TC_OPERAND | TC_REGEXP)) {
Rob Landleyed830e82005-06-07 02:43:52 +00001154 xtc = TC_UOPPRE | TC_UOPPOST | TC_BINOP | TC_OPERAND | iexp;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001155 /* one should be very careful with switch on tclass -
Glenn L McGrath545106f2002-11-11 06:21:00 +00001156 * only simple tclasses should be used! */
1157 switch (tc) {
Denis Vlasenkof782f522007-01-01 23:51:30 +00001158 case TC_VARIABLE:
1159 case TC_ARRAY:
Glenn L McGrath545106f2002-11-11 06:21:00 +00001160 cn->info = OC_VAR;
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00001161 v = hash_search(ahash, t_string);
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001162 if (v != NULL) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00001163 cn->info = OC_FNARG;
1164 cn->l.i = v->x.aidx;
1165 } else {
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00001166 cn->l.v = newvar(t_string);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001167 }
1168 if (tc & TC_ARRAY) {
1169 cn->info |= xS;
1170 cn->r.n = parse_expr(TC_ARRTERM);
1171 }
Glenn L McGrath545106f2002-11-11 06:21:00 +00001172 break;
Mike Frysingerde2b9382005-09-27 03:18:00 +00001173
Denis Vlasenkof782f522007-01-01 23:51:30 +00001174 case TC_NUMBER:
1175 case TC_STRING:
Glenn L McGrath545106f2002-11-11 06:21:00 +00001176 cn->info = OC_VAR;
Rob Landley9ffd4232006-05-21 18:30:35 +00001177 v = cn->l.v = xzalloc(sizeof(var));
Glenn L McGrath545106f2002-11-11 06:21:00 +00001178 if (tc & TC_NUMBER)
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00001179 setvar_i(v, t_double);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001180 else
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00001181 setvar_s(v, t_string);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001182 break;
1183
Denis Vlasenkof782f522007-01-01 23:51:30 +00001184 case TC_REGEXP:
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00001185 mk_re_node(t_string, cn, xzalloc(sizeof(regex_t)*2));
Glenn L McGrath545106f2002-11-11 06:21:00 +00001186 break;
1187
Denis Vlasenkof782f522007-01-01 23:51:30 +00001188 case TC_FUNCTION:
Mike Frysingerde2b9382005-09-27 03:18:00 +00001189 cn->info = OC_FUNC;
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00001190 cn->r.f = newfunc(t_string);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001191 cn->l.n = condition();
1192 break;
1193
Denis Vlasenkof782f522007-01-01 23:51:30 +00001194 case TC_SEQSTART:
Glenn L McGrath545106f2002-11-11 06:21:00 +00001195 cn = vn->r.n = parse_expr(TC_SEQTERM);
1196 cn->a.n = vn;
1197 break;
1198
Denis Vlasenkof782f522007-01-01 23:51:30 +00001199 case TC_GETLINE:
Glenn L McGrath545106f2002-11-11 06:21:00 +00001200 glptr = cn;
1201 xtc = TC_OPERAND | TC_UOPPRE | TC_BINOP | iexp;
1202 break;
1203
Denis Vlasenkof782f522007-01-01 23:51:30 +00001204 case TC_BUILTIN:
Glenn L McGrath545106f2002-11-11 06:21:00 +00001205 cn->l.n = condition();
1206 break;
1207 }
1208 }
1209 }
1210 }
1211 return sn.r.n;
1212}
1213
1214/* add node to chain. Return ptr to alloc'd node */
Mike Frysingerf87b3e32005-09-27 04:16:22 +00001215static node *chain_node(uint32_t info)
Mike Frysinger10a11e22005-09-27 02:23:02 +00001216{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001217 node *n;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001218
Denis Vlasenkocd5c7862007-05-17 16:37:22 +00001219 if (!seq->first)
Glenn L McGrath545106f2002-11-11 06:21:00 +00001220 seq->first = seq->last = new_node(0);
1221
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00001222 if (seq->programname != g_progname) {
1223 seq->programname = g_progname;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001224 n = chain_node(OC_NEWSOURCE);
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00001225 n->l.s = xstrdup(g_progname);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001226 }
1227
1228 n = seq->last;
1229 n->info = info;
1230 seq->last = n->a.n = new_node(OC_DONE);
1231
1232 return n;
1233}
1234
Mike Frysingerf87b3e32005-09-27 04:16:22 +00001235static void chain_expr(uint32_t info)
Mike Frysinger10a11e22005-09-27 02:23:02 +00001236{
Glenn L McGrath545106f2002-11-11 06:21:00 +00001237 node *n;
1238
1239 n = chain_node(info);
1240 n->l.n = parse_expr(TC_OPTERM | TC_GRPTERM);
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00001241 if (t_tclass & TC_GRPTERM)
Glenn L McGrath545106f2002-11-11 06:21:00 +00001242 rollback_token();
1243}
1244
Mike Frysinger10a11e22005-09-27 02:23:02 +00001245static node *chain_loop(node *nn)
1246{
Glenn L McGrath545106f2002-11-11 06:21:00 +00001247 node *n, *n2, *save_brk, *save_cont;
1248
1249 save_brk = break_ptr;
1250 save_cont = continue_ptr;
1251
1252 n = chain_node(OC_BR | Vx);
1253 continue_ptr = new_node(OC_EXEC);
1254 break_ptr = new_node(OC_EXEC);
1255 chain_group();
1256 n2 = chain_node(OC_EXEC | Vx);
1257 n2->l.n = nn;
1258 n2->a.n = n;
1259 continue_ptr->a.n = n2;
1260 break_ptr->a.n = n->r.n = seq->last;
1261
1262 continue_ptr = save_cont;
1263 break_ptr = save_brk;
1264
1265 return n;
1266}
1267
1268/* parse group and attach it to chain */
Mike Frysinger10a11e22005-09-27 02:23:02 +00001269static void chain_group(void)
1270{
Mike Frysingerf87b3e32005-09-27 04:16:22 +00001271 uint32_t c;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001272 node *n, *n2, *n3;
1273
1274 do {
1275 c = next_token(TC_GRPSEQ);
1276 } while (c & TC_NEWLINE);
1277
1278 if (c & TC_GRPSTART) {
Denis Vlasenkobf0a2012006-12-26 10:42:51 +00001279 while (next_token(TC_GRPSEQ | TC_GRPTERM) != TC_GRPTERM) {
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00001280 if (t_tclass & TC_NEWLINE) continue;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001281 rollback_token();
1282 chain_group();
1283 }
1284 } else if (c & (TC_OPSEQ | TC_OPTERM)) {
1285 rollback_token();
1286 chain_expr(OC_EXEC | Vx);
1287 } else { /* TC_STATEMNT */
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00001288 switch (t_info & OPCLSMASK) {
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001289 case ST_IF:
1290 n = chain_node(OC_BR | Vx);
1291 n->l.n = condition();
1292 chain_group();
1293 n2 = chain_node(OC_EXEC);
1294 n->r.n = seq->last;
1295 if (next_token(TC_GRPSEQ | TC_GRPTERM | TC_ELSE) == TC_ELSE) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00001296 chain_group();
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001297 n2->a.n = seq->last;
1298 } else {
1299 rollback_token();
1300 }
1301 break;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001302
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001303 case ST_WHILE:
1304 n2 = condition();
1305 n = chain_loop(NULL);
1306 n->l.n = n2;
1307 break;
1308
1309 case ST_DO:
1310 n2 = chain_node(OC_EXEC);
1311 n = chain_loop(NULL);
1312 n2->a.n = n->a.n;
1313 next_token(TC_WHILE);
1314 n->l.n = condition();
1315 break;
1316
1317 case ST_FOR:
1318 next_token(TC_SEQSTART);
1319 n2 = parse_expr(TC_SEMICOL | TC_SEQTERM);
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00001320 if (t_tclass & TC_SEQTERM) { /* for-in */
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001321 if ((n2->info & OPCLSMASK) != OC_IN)
1322 syntax_error(EMSG_UNEXP_TOKEN);
1323 n = chain_node(OC_WALKINIT | VV);
1324 n->l.n = n2->l.n;
1325 n->r.n = n2->r.n;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001326 n = chain_loop(NULL);
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001327 n->info = OC_WALKNEXT | Vx;
1328 n->l.n = n2->l.n;
1329 } else { /* for (;;) */
1330 n = chain_node(OC_EXEC | Vx);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001331 n->l.n = n2;
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001332 n2 = parse_expr(TC_SEMICOL);
1333 n3 = parse_expr(TC_SEQTERM);
1334 n = chain_loop(n3);
1335 n->l.n = n2;
Denis Vlasenkob78c7822007-07-18 18:31:11 +00001336 if (!n2)
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001337 n->info = OC_EXEC;
1338 }
1339 break;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001340
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001341 case OC_PRINT:
1342 case OC_PRINTF:
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00001343 n = chain_node(t_info);
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001344 n->l.n = parse_expr(TC_OPTERM | TC_OUTRDR | TC_GRPTERM);
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00001345 if (t_tclass & TC_OUTRDR) {
1346 n->info |= t_info;
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001347 n->r.n = parse_expr(TC_OPTERM | TC_GRPTERM);
1348 }
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00001349 if (t_tclass & TC_GRPTERM)
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001350 rollback_token();
1351 break;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001352
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001353 case OC_BREAK:
1354 n = chain_node(OC_EXEC);
1355 n->a.n = break_ptr;
1356 break;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001357
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001358 case OC_CONTINUE:
1359 n = chain_node(OC_EXEC);
1360 n->a.n = continue_ptr;
1361 break;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001362
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001363 /* delete, next, nextfile, return, exit */
1364 default:
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00001365 chain_expr(t_info);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001366 }
1367 }
1368}
1369
Mike Frysinger10a11e22005-09-27 02:23:02 +00001370static void parse_program(char *p)
1371{
Mike Frysingerf87b3e32005-09-27 04:16:22 +00001372 uint32_t tclass;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001373 node *cn;
1374 func *f;
1375 var *v;
1376
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00001377 g_pos = p;
1378 t_lineno = 1;
Denis Vlasenkobf0a2012006-12-26 10:42:51 +00001379 while ((tclass = next_token(TC_EOF | TC_OPSEQ | TC_GRPSTART |
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001380 TC_OPTERM | TC_BEGIN | TC_END | TC_FUNCDECL)) != TC_EOF) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00001381
1382 if (tclass & TC_OPTERM)
1383 continue;
1384
1385 seq = &mainseq;
1386 if (tclass & TC_BEGIN) {
1387 seq = &beginseq;
1388 chain_group();
1389
1390 } else if (tclass & TC_END) {
1391 seq = &endseq;
1392 chain_group();
1393
1394 } else if (tclass & TC_FUNCDECL) {
1395 next_token(TC_FUNCTION);
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00001396 g_pos++;
1397 f = newfunc(t_string);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001398 f->body.first = NULL;
1399 f->nargs = 0;
Denis Vlasenkobf0a2012006-12-26 10:42:51 +00001400 while (next_token(TC_VARIABLE | TC_SEQTERM) & TC_VARIABLE) {
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00001401 v = findvar(ahash, t_string);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001402 v->x.aidx = (f->nargs)++;
1403
1404 if (next_token(TC_COMMA | TC_SEQTERM) & TC_SEQTERM)
1405 break;
1406 }
1407 seq = &(f->body);
1408 chain_group();
1409 clear_array(ahash);
1410
1411 } else if (tclass & TC_OPSEQ) {
1412 rollback_token();
1413 cn = chain_node(OC_TEST);
1414 cn->l.n = parse_expr(TC_OPTERM | TC_EOF | TC_GRPSTART);
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00001415 if (t_tclass & TC_GRPSTART) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00001416 rollback_token();
1417 chain_group();
1418 } else {
1419 chain_node(OC_PRINT);
1420 }
1421 cn->r.n = mainseq.last;
1422
1423 } else /* if (tclass & TC_GRPSTART) */ {
1424 rollback_token();
1425 chain_group();
1426 }
1427 }
1428}
1429
1430
1431/* -------- program execution part -------- */
1432
Denis Vlasenkoa41fdf32007-01-29 22:51:00 +00001433static node *mk_splitter(const char *s, tsplitter *spl)
Mike Frysinger10a11e22005-09-27 02:23:02 +00001434{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001435 regex_t *re, *ire;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001436 node *n;
1437
1438 re = &spl->re[0];
1439 ire = &spl->re[1];
1440 n = &spl->n;
Denis Vlasenko890ac9d2006-10-07 15:16:19 +00001441 if ((n->info & OPCLSMASK) == OC_REGEXP) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00001442 regfree(re);
Denis Vlasenkob78c7822007-07-18 18:31:11 +00001443 regfree(ire); // TODO: nuke ire, use re+1?
Glenn L McGrath545106f2002-11-11 06:21:00 +00001444 }
Rob Landleya3896512006-05-07 20:20:34 +00001445 if (strlen(s) > 1) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00001446 mk_re_node(s, n, re);
1447 } else {
Mike Frysingerf87b3e32005-09-27 04:16:22 +00001448 n->info = (uint32_t) *s;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001449 }
1450
1451 return n;
1452}
1453
1454/* use node as a regular expression. Supplied with node ptr and regex_t
Eric Andersenaff114c2004-04-14 17:51:38 +00001455 * storage space. Return ptr to regex (if result points to preg, it should
Glenn L McGrath545106f2002-11-11 06:21:00 +00001456 * be later regfree'd manually
1457 */
Mike Frysinger10a11e22005-09-27 02:23:02 +00001458static regex_t *as_regex(node *op, regex_t *preg)
1459{
Glenn L McGrath545106f2002-11-11 06:21:00 +00001460 var *v;
Denis Vlasenkoa41fdf32007-01-29 22:51:00 +00001461 const char *s;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001462
1463 if ((op->info & OPCLSMASK) == OC_REGEXP) {
1464 return icase ? op->r.ire : op->l.re;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001465 }
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001466 v = nvalloc(1);
1467 s = getvar_s(evaluate(op, v));
1468 xregcomp(preg, s, icase ? REG_EXTENDED | REG_ICASE : REG_EXTENDED);
1469 nvfree(v);
1470 return preg;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001471}
1472
1473/* gradually increasing buffer */
Mike Frysinger10a11e22005-09-27 02:23:02 +00001474static void qrealloc(char **b, int n, int *size)
1475{
Denis Vlasenkoe1d3e032007-01-01 23:53:52 +00001476 if (!*b || n >= *size)
Glenn L McGrath545106f2002-11-11 06:21:00 +00001477 *b = xrealloc(*b, *size = n + (n>>1) + 80);
1478}
1479
1480/* resize field storage space */
Mike Frysinger10a11e22005-09-27 02:23:02 +00001481static void fsrealloc(int size)
1482{
Glenn L McGrath545106f2002-11-11 06:21:00 +00001483 int i;
1484
1485 if (size >= maxfields) {
1486 i = maxfields;
1487 maxfields = size + 16;
Denis Vlasenkof782f522007-01-01 23:51:30 +00001488 Fields = xrealloc(Fields, maxfields * sizeof(var));
1489 for (; i < maxfields; i++) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00001490 Fields[i].type = VF_SPECIAL;
1491 Fields[i].string = NULL;
1492 }
1493 }
1494
1495 if (size < nfields) {
Denis Vlasenkoe1d3e032007-01-01 23:53:52 +00001496 for (i = size; i < nfields; i++) {
1497 clrvar(Fields + i);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001498 }
1499 }
1500 nfields = size;
1501}
1502
Denis Vlasenkoa41fdf32007-01-29 22:51:00 +00001503static int awk_split(const char *s, node *spl, char **slist)
Mike Frysinger10a11e22005-09-27 02:23:02 +00001504{
Denis Vlasenkof782f522007-01-01 23:51:30 +00001505 int l, n = 0;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001506 char c[4];
1507 char *s1;
Denis Vlasenkob78c7822007-07-18 18:31:11 +00001508 regmatch_t pmatch[2]; // TODO: why [2]? [1] is enough...
Glenn L McGrath545106f2002-11-11 06:21:00 +00001509
1510 /* in worst case, each char would be a separate field */
Denis Vlasenkoa41fdf32007-01-29 22:51:00 +00001511 *slist = s1 = xzalloc(strlen(s) * 2 + 3);
1512 strcpy(s1, s);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001513
1514 c[0] = c[1] = (char)spl->info;
1515 c[2] = c[3] = '\0';
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001516 if (*getvar_s(intvar[RS]) == '\0')
1517 c[2] = '\n';
Glenn L McGrath545106f2002-11-11 06:21:00 +00001518
Denis Vlasenkoaf1bd092007-07-18 18:32:25 +00001519 if ((spl->info & OPCLSMASK) == OC_REGEXP) { /* regex split */
1520 if (!*s)
1521 return n; /* "": zero fields */
1522 n++; /* at least one field will be there */
1523 do {
1524 l = strcspn(s, c+2); /* len till next NUL or \n */
Denis Vlasenkoa41fdf32007-01-29 22:51:00 +00001525 if (regexec(icase ? spl->r.ire : spl->l.re, s, 1, pmatch, 0) == 0
1526 && pmatch[0].rm_so <= l
1527 ) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00001528 l = pmatch[0].rm_so;
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001529 if (pmatch[0].rm_eo == 0) {
1530 l++;
1531 pmatch[0].rm_eo++;
1532 }
Denis Vlasenkoaf1bd092007-07-18 18:32:25 +00001533 n++; /* we saw yet another delimiter */
Glenn L McGrath545106f2002-11-11 06:21:00 +00001534 } else {
1535 pmatch[0].rm_eo = l;
Denis Vlasenkof782f522007-01-01 23:51:30 +00001536 if (s[l]) pmatch[0].rm_eo++;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001537 }
Glenn L McGrath545106f2002-11-11 06:21:00 +00001538 memcpy(s1, s, l);
Denis Vlasenkof782f522007-01-01 23:51:30 +00001539 s1[l] = '\0';
Glenn L McGrath545106f2002-11-11 06:21:00 +00001540 nextword(&s1);
1541 s += pmatch[0].rm_eo;
Denis Vlasenkoaf1bd092007-07-18 18:32:25 +00001542 } while (*s);
1543 return n;
1544 }
1545 if (c[0] == '\0') { /* null split */
Denis Vlasenkobf0a2012006-12-26 10:42:51 +00001546 while (*s) {
Denis Vlasenkoe1d3e032007-01-01 23:53:52 +00001547 *s1++ = *s++;
1548 *s1++ = '\0';
Glenn L McGrath545106f2002-11-11 06:21:00 +00001549 n++;
1550 }
Denis Vlasenkoaf1bd092007-07-18 18:32:25 +00001551 return n;
1552 }
1553 if (c[0] != ' ') { /* single-character split */
Glenn L McGrath545106f2002-11-11 06:21:00 +00001554 if (icase) {
1555 c[0] = toupper(c[0]);
1556 c[1] = tolower(c[1]);
1557 }
1558 if (*s1) n++;
1559 while ((s1 = strpbrk(s1, c))) {
Denis Vlasenkoe1d3e032007-01-01 23:53:52 +00001560 *s1++ = '\0';
Glenn L McGrath545106f2002-11-11 06:21:00 +00001561 n++;
1562 }
Denis Vlasenkoaf1bd092007-07-18 18:32:25 +00001563 return n;
1564 }
1565 /* space split */
1566 while (*s) {
1567 s = skip_whitespace(s);
1568 if (!*s) break;
1569 n++;
1570 while (*s && !isspace(*s))
1571 *s1++ = *s++;
1572 *s1++ = '\0';
Glenn L McGrath545106f2002-11-11 06:21:00 +00001573 }
1574 return n;
1575}
1576
Mike Frysinger10a11e22005-09-27 02:23:02 +00001577static void split_f0(void)
1578{
Denis Vlasenkoaf1bd092007-07-18 18:32:25 +00001579/* static char *fstrings; */
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00001580#define fstrings (G.split_f0__fstrings)
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001581
Glenn L McGrath545106f2002-11-11 06:21:00 +00001582 int i, n;
1583 char *s;
1584
1585 if (is_f0_split)
1586 return;
1587
1588 is_f0_split = TRUE;
Aaron Lehmanna170e1c2002-11-28 11:27:31 +00001589 free(fstrings);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001590 fsrealloc(0);
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001591 n = awk_split(getvar_s(intvar[F0]), &fsplitter.n, &fstrings);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001592 fsrealloc(n);
1593 s = fstrings;
Denis Vlasenkof782f522007-01-01 23:51:30 +00001594 for (i = 0; i < n; i++) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00001595 Fields[i].string = nextword(&s);
1596 Fields[i].type |= (VF_FSTR | VF_USER | VF_DIRTY);
1597 }
1598
1599 /* set NF manually to avoid side effects */
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001600 clrvar(intvar[NF]);
1601 intvar[NF]->type = VF_NUMBER | VF_SPECIAL;
1602 intvar[NF]->number = nfields;
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00001603#undef fstrings
Glenn L McGrath545106f2002-11-11 06:21:00 +00001604}
1605
1606/* perform additional actions when some internal variables changed */
Mike Frysinger10a11e22005-09-27 02:23:02 +00001607static void handle_special(var *v)
1608{
Glenn L McGrath545106f2002-11-11 06:21:00 +00001609 int n;
Denis Vlasenkoa41fdf32007-01-29 22:51:00 +00001610 char *b;
1611 const char *sep, *s;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001612 int sl, l, len, i, bsize;
1613
Denis Vlasenkoe1d3e032007-01-01 23:53:52 +00001614 if (!(v->type & VF_SPECIAL))
Glenn L McGrath545106f2002-11-11 06:21:00 +00001615 return;
1616
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001617 if (v == intvar[NF]) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00001618 n = (int)getvar_i(v);
1619 fsrealloc(n);
1620
1621 /* recalculate $0 */
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001622 sep = getvar_s(intvar[OFS]);
Rob Landleya3896512006-05-07 20:20:34 +00001623 sl = strlen(sep);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001624 b = NULL;
1625 len = 0;
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001626 for (i = 0; i < n; i++) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00001627 s = getvar_s(&Fields[i]);
Rob Landleya3896512006-05-07 20:20:34 +00001628 l = strlen(s);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001629 if (b) {
1630 memcpy(b+len, sep, sl);
1631 len += sl;
1632 }
1633 qrealloc(&b, len+l+sl, &bsize);
1634 memcpy(b+len, s, l);
1635 len += l;
1636 }
Denis Vlasenkoe1d3e032007-01-01 23:53:52 +00001637 if (b)
1638 b[len] = '\0';
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001639 setvar_p(intvar[F0], b);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001640 is_f0_split = TRUE;
1641
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001642 } else if (v == intvar[F0]) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00001643 is_f0_split = FALSE;
1644
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001645 } else if (v == intvar[FS]) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00001646 mk_splitter(getvar_s(v), &fsplitter);
1647
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001648 } else if (v == intvar[RS]) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00001649 mk_splitter(getvar_s(v), &rsplitter);
1650
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001651 } else if (v == intvar[IGNORECASE]) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00001652 icase = istrue(v);
1653
Denis Vlasenkoe1d3e032007-01-01 23:53:52 +00001654 } else { /* $n */
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001655 n = getvar_i(intvar[NF]);
1656 setvar_i(intvar[NF], n > v-Fields ? n : v-Fields+1);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001657 /* right here v is invalid. Just to note... */
1658 }
1659}
1660
1661/* step through func/builtin/etc arguments */
Mike Frysinger10a11e22005-09-27 02:23:02 +00001662static node *nextarg(node **pn)
1663{
Glenn L McGrath545106f2002-11-11 06:21:00 +00001664 node *n;
1665
1666 n = *pn;
1667 if (n && (n->info & OPCLSMASK) == OC_COMMA) {
1668 *pn = n->r.n;
1669 n = n->l.n;
1670 } else {
1671 *pn = NULL;
1672 }
1673 return n;
1674}
1675
Mike Frysinger10a11e22005-09-27 02:23:02 +00001676static void hashwalk_init(var *v, xhash *array)
1677{
Glenn L McGrath545106f2002-11-11 06:21:00 +00001678 char **w;
1679 hash_item *hi;
Denis Vlasenko77ad97f2008-05-13 02:27:31 +00001680 unsigned i;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001681
1682 if (v->type & VF_WALK)
1683 free(v->x.walker);
1684
1685 v->type |= VF_WALK;
Denis Vlasenko4cccc032006-12-22 18:37:07 +00001686 w = v->x.walker = xzalloc(2 + 2*sizeof(char *) + array->glen);
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001687 w[0] = w[1] = (char *)(w + 2);
1688 for (i = 0; i < array->csize; i++) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00001689 hi = array->items[i];
Denis Vlasenkobf0a2012006-12-26 10:42:51 +00001690 while (hi) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00001691 strcpy(*w, hi->name);
1692 nextword(w);
1693 hi = hi->next;
1694 }
1695 }
1696}
1697
Mike Frysinger10a11e22005-09-27 02:23:02 +00001698static int hashwalk_next(var *v)
1699{
Glenn L McGrath545106f2002-11-11 06:21:00 +00001700 char **w;
1701
1702 w = v->x.walker;
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001703 if (w[1] == w[0])
Glenn L McGrath545106f2002-11-11 06:21:00 +00001704 return FALSE;
1705
1706 setvar_s(v, nextword(w+1));
1707 return TRUE;
1708}
1709
1710/* evaluate node, return 1 when result is true, 0 otherwise */
Mike Frysinger10a11e22005-09-27 02:23:02 +00001711static int ptest(node *pattern)
1712{
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00001713 /* ptest__v is "static": to save stack space? */
1714 return istrue(evaluate(pattern, &G.ptest__v));
Glenn L McGrath545106f2002-11-11 06:21:00 +00001715}
1716
1717/* read next record from stream rsm into a variable v */
Mike Frysinger10a11e22005-09-27 02:23:02 +00001718static int awk_getline(rstream *rsm, var *v)
1719{
Glenn L McGrath545106f2002-11-11 06:21:00 +00001720 char *b;
1721 regmatch_t pmatch[2];
Glenn L McGrath00ed36f2003-10-30 13:36:39 +00001722 int a, p, pp=0, size;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001723 int fd, so, eo, r, rp;
Glenn L McGrath00ed36f2003-10-30 13:36:39 +00001724 char c, *m, *s;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001725
1726 /* we're using our own buffer since we need access to accumulating
1727 * characters
1728 */
1729 fd = fileno(rsm->F);
Glenn L McGrath00ed36f2003-10-30 13:36:39 +00001730 m = rsm->buffer;
1731 a = rsm->adv;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001732 p = rsm->pos;
1733 size = rsm->size;
1734 c = (char) rsplitter.n.info;
1735 rp = 0;
Glenn L McGrath00ed36f2003-10-30 13:36:39 +00001736
Denis Vlasenkob78c7822007-07-18 18:31:11 +00001737 if (!m) qrealloc(&m, 256, &size);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001738 do {
Glenn L McGrath00ed36f2003-10-30 13:36:39 +00001739 b = m + a;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001740 so = eo = p;
1741 r = 1;
1742 if (p > 0) {
1743 if ((rsplitter.n.info & OPCLSMASK) == OC_REGEXP) {
1744 if (regexec(icase ? rsplitter.n.r.ire : rsplitter.n.l.re,
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001745 b, 1, pmatch, 0) == 0) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00001746 so = pmatch[0].rm_so;
1747 eo = pmatch[0].rm_eo;
1748 if (b[eo] != '\0')
1749 break;
1750 }
1751 } else if (c != '\0') {
1752 s = strchr(b+pp, c);
Denis Vlasenkob78c7822007-07-18 18:31:11 +00001753 if (!s) s = memchr(b+pp, '\0', p - pp);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001754 if (s) {
1755 so = eo = s-b;
1756 eo++;
1757 break;
1758 }
1759 } else {
1760 while (b[rp] == '\n')
1761 rp++;
1762 s = strstr(b+rp, "\n\n");
1763 if (s) {
1764 so = eo = s-b;
1765 while (b[eo] == '\n') eo++;
1766 if (b[eo] != '\0')
1767 break;
1768 }
1769 }
1770 }
1771
Glenn L McGrath00ed36f2003-10-30 13:36:39 +00001772 if (a > 0) {
1773 memmove(m, (const void *)(m+a), p+1);
1774 b = m;
1775 a = 0;
1776 }
1777
1778 qrealloc(&m, a+p+128, &size);
1779 b = m + a;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001780 pp = p;
1781 p += safe_read(fd, b+p, size-p-1);
1782 if (p < pp) {
1783 p = 0;
1784 r = 0;
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001785 setvar_i(intvar[ERRNO], errno);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001786 }
1787 b[p] = '\0';
1788
1789 } while (p > pp);
1790
1791 if (p == 0) {
1792 r--;
1793 } else {
1794 c = b[so]; b[so] = '\0';
1795 setvar_s(v, b+rp);
1796 v->type |= VF_USER;
1797 b[so] = c;
1798 c = b[eo]; b[eo] = '\0';
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001799 setvar_s(intvar[RT], b+so);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001800 b[eo] = c;
1801 }
1802
Glenn L McGrath00ed36f2003-10-30 13:36:39 +00001803 rsm->buffer = m;
1804 rsm->adv = a + eo;
1805 rsm->pos = p - eo;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001806 rsm->size = size;
1807
1808 return r;
1809}
1810
"Vladimir N. Oleynik"5cf9a032005-10-19 09:21:51 +00001811static int fmt_num(char *b, int size, const char *format, double n, int int_as_int)
Mike Frysinger10a11e22005-09-27 02:23:02 +00001812{
Denis Vlasenkof782f522007-01-01 23:51:30 +00001813 int r = 0;
"Vladimir N. Oleynik"5cf9a032005-10-19 09:21:51 +00001814 char c;
Denis Vlasenkof782f522007-01-01 23:51:30 +00001815 const char *s = format;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001816
1817 if (int_as_int && n == (int)n) {
1818 r = snprintf(b, size, "%d", (int)n);
1819 } else {
Denis Vlasenkof782f522007-01-01 23:51:30 +00001820 do { c = *s; } while (c && *++s);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001821 if (strchr("diouxX", c)) {
1822 r = snprintf(b, size, format, (int)n);
1823 } else if (strchr("eEfgG", c)) {
1824 r = snprintf(b, size, format, n);
1825 } else {
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00001826 syntax_error(EMSG_INV_FMT);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001827 }
1828 }
1829 return r;
1830}
1831
1832
1833/* formatted output into an allocated buffer, return ptr to buffer */
Mike Frysinger10a11e22005-09-27 02:23:02 +00001834static char *awk_printf(node *n)
1835{
Glenn L McGrath545106f2002-11-11 06:21:00 +00001836 char *b = NULL;
Denis Vlasenkoa41fdf32007-01-29 22:51:00 +00001837 char *fmt, *s, *f;
1838 const char *s1;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001839 int i, j, incr, bsize;
1840 char c, c1;
1841 var *v, *arg;
1842
1843 v = nvalloc(1);
Rob Landleyd921b2e2006-08-03 15:41:12 +00001844 fmt = f = xstrdup(getvar_s(evaluate(nextarg(&n), v)));
Glenn L McGrath545106f2002-11-11 06:21:00 +00001845
1846 i = 0;
1847 while (*f) {
1848 s = f;
1849 while (*f && (*f != '%' || *(++f) == '%'))
1850 f++;
Denis Vlasenko389f9d52007-05-09 21:57:23 +00001851 while (*f && !isalpha(*f)) {
1852 if (*f == '*')
1853 syntax_error("%*x formats are not supported");
Glenn L McGrath545106f2002-11-11 06:21:00 +00001854 f++;
Denis Vlasenko389f9d52007-05-09 21:57:23 +00001855 }
Glenn L McGrath545106f2002-11-11 06:21:00 +00001856
1857 incr = (f - s) + MAXVARFMT;
Denis Vlasenkof782f522007-01-01 23:51:30 +00001858 qrealloc(&b, incr + i, &bsize);
1859 c = *f;
1860 if (c != '\0') f++;
1861 c1 = *f;
1862 *f = '\0';
Glenn L McGrath545106f2002-11-11 06:21:00 +00001863 arg = evaluate(nextarg(&n), v);
1864
1865 j = i;
1866 if (c == 'c' || !c) {
Denis Vlasenkof782f522007-01-01 23:51:30 +00001867 i += sprintf(b+i, s, is_numeric(arg) ?
1868 (char)getvar_i(arg) : *getvar_s(arg));
Glenn L McGrath545106f2002-11-11 06:21:00 +00001869 } else if (c == 's') {
Denis Vlasenko92758142006-10-03 19:56:34 +00001870 s1 = getvar_s(arg);
Rob Landleya3896512006-05-07 20:20:34 +00001871 qrealloc(&b, incr+i+strlen(s1), &bsize);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001872 i += sprintf(b+i, s, s1);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001873 } else {
1874 i += fmt_num(b+i, incr, s, getvar_i(arg), FALSE);
1875 }
1876 *f = c1;
1877
1878 /* if there was an error while sprintf, return value is negative */
1879 if (i < j) i = j;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001880 }
1881
Denis Vlasenkof782f522007-01-01 23:51:30 +00001882 b = xrealloc(b, i + 1);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001883 free(fmt);
1884 nvfree(v);
1885 b[i] = '\0';
1886 return b;
1887}
1888
1889/* common substitution routine
1890 * replace (nm) substring of (src) that match (n) with (repl), store
1891 * result into (dest), return number of substitutions. If nm=0, replace
1892 * all matches. If src or dst is NULL, use $0. If ex=TRUE, enable
1893 * subexpression matching (\1-\9)
1894 */
Denis Vlasenkoa41fdf32007-01-29 22:51:00 +00001895static int awk_sub(node *rn, const char *repl, int nm, var *src, var *dest, int ex)
Mike Frysinger10a11e22005-09-27 02:23:02 +00001896{
Glenn L McGrath545106f2002-11-11 06:21:00 +00001897 char *ds = NULL;
Denis Vlasenkoa41fdf32007-01-29 22:51:00 +00001898 const char *s;
1899 const char *sp;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001900 int c, i, j, di, rl, so, eo, nbs, n, dssize;
1901 regmatch_t pmatch[10];
1902 regex_t sreg, *re;
1903
1904 re = as_regex(rn, &sreg);
Denis Vlasenkob78c7822007-07-18 18:31:11 +00001905 if (!src) src = intvar[F0];
1906 if (!dest) dest = intvar[F0];
Glenn L McGrath545106f2002-11-11 06:21:00 +00001907
1908 i = di = 0;
1909 sp = getvar_s(src);
Rob Landleya3896512006-05-07 20:20:34 +00001910 rl = strlen(repl);
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001911 while (regexec(re, sp, 10, pmatch, sp==getvar_s(src) ? 0 : REG_NOTBOL) == 0) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00001912 so = pmatch[0].rm_so;
1913 eo = pmatch[0].rm_eo;
1914
1915 qrealloc(&ds, di + eo + rl, &dssize);
1916 memcpy(ds + di, sp, eo);
1917 di += eo;
1918 if (++i >= nm) {
1919 /* replace */
1920 di -= (eo - so);
1921 nbs = 0;
1922 for (s = repl; *s; s++) {
1923 ds[di++] = c = *s;
1924 if (c == '\\') {
1925 nbs++;
1926 continue;
1927 }
1928 if (c == '&' || (ex && c >= '0' && c <= '9')) {
1929 di -= ((nbs + 3) >> 1);
1930 j = 0;
1931 if (c != '&') {
1932 j = c - '0';
1933 nbs++;
1934 }
1935 if (nbs % 2) {
1936 ds[di++] = c;
1937 } else {
1938 n = pmatch[j].rm_eo - pmatch[j].rm_so;
1939 qrealloc(&ds, di + rl + n, &dssize);
1940 memcpy(ds + di, sp + pmatch[j].rm_so, n);
1941 di += n;
1942 }
1943 }
1944 nbs = 0;
1945 }
1946 }
1947
1948 sp += eo;
1949 if (i == nm) break;
1950 if (eo == so) {
Denis Vlasenkob78c7822007-07-18 18:31:11 +00001951 ds[di] = *sp++;
1952 if (!ds[di++]) break;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001953 }
1954 }
1955
1956 qrealloc(&ds, di + strlen(sp), &dssize);
1957 strcpy(ds + di, sp);
1958 setvar_p(dest, ds);
1959 if (re == &sreg) regfree(re);
1960 return i;
1961}
1962
Mike Frysinger10a11e22005-09-27 02:23:02 +00001963static var *exec_builtin(node *op, var *res)
1964{
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00001965#define tspl (G.exec_builtin__tspl)
1966
Glenn L McGrath545106f2002-11-11 06:21:00 +00001967 int (*to_xxx)(int);
1968 var *tv;
1969 node *an[4];
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001970 var *av[4];
Denis Vlasenkoa41fdf32007-01-29 22:51:00 +00001971 const char *as[4];
Glenn L McGrath545106f2002-11-11 06:21:00 +00001972 regmatch_t pmatch[2];
1973 regex_t sreg, *re;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001974 node *spl;
Mike Frysingerf87b3e32005-09-27 04:16:22 +00001975 uint32_t isr, info;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001976 int nargs;
1977 time_t tt;
1978 char *s, *s1;
1979 int i, l, ll, n;
1980
1981 tv = nvalloc(4);
1982 isr = info = op->info;
1983 op = op->l.n;
1984
1985 av[2] = av[3] = NULL;
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001986 for (i = 0; i < 4 && op; i++) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00001987 an[i] = nextarg(&op);
1988 if (isr & 0x09000000) av[i] = evaluate(an[i], &tv[i]);
1989 if (isr & 0x08000000) as[i] = getvar_s(av[i]);
1990 isr >>= 1;
1991 }
1992
1993 nargs = i;
Denis Vlasenko77ad97f2008-05-13 02:27:31 +00001994 if ((uint32_t)nargs < (info >> 30))
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00001995 syntax_error(EMSG_TOO_FEW_ARGS);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001996
1997 switch (info & OPNMASK) {
1998
Denis Vlasenkof782f522007-01-01 23:51:30 +00001999 case B_a2:
2000#if ENABLE_FEATURE_AWK_MATH
Glenn L McGrath545106f2002-11-11 06:21:00 +00002001 setvar_i(res, atan2(getvar_i(av[i]), getvar_i(av[1])));
2002#else
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002003 syntax_error(EMSG_NO_MATH);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002004#endif
2005 break;
2006
Denis Vlasenkof782f522007-01-01 23:51:30 +00002007 case B_sp:
Glenn L McGrath545106f2002-11-11 06:21:00 +00002008 if (nargs > 2) {
2009 spl = (an[2]->info & OPCLSMASK) == OC_REGEXP ?
2010 an[2] : mk_splitter(getvar_s(evaluate(an[2], &tv[2])), &tspl);
2011 } else {
2012 spl = &fsplitter.n;
2013 }
2014
2015 n = awk_split(as[0], spl, &s);
2016 s1 = s;
2017 clear_array(iamarray(av[1]));
2018 for (i=1; i<=n; i++)
2019 setari_u(av[1], i, nextword(&s1));
2020 free(s);
2021 setvar_i(res, n);
2022 break;
2023
Denis Vlasenkof782f522007-01-01 23:51:30 +00002024 case B_ss:
Rob Landleya3896512006-05-07 20:20:34 +00002025 l = strlen(as[0]);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002026 i = getvar_i(av[1]) - 1;
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002027 if (i > l) i = l;
2028 if (i < 0) i = 0;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002029 n = (nargs > 2) ? getvar_i(av[2]) : l-i;
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002030 if (n < 0) n = 0;
Denis Vlasenko8ae5b282008-07-02 22:47:49 +00002031 s = xstrndup(as[0]+i, n);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002032 setvar_p(res, s);
2033 break;
Denis Vlasenkof7996f32007-01-11 17:20:00 +00002034
Denis Vlasenkof782f522007-01-01 23:51:30 +00002035 case B_an:
Denis Vlasenkoe175ff22006-09-26 17:41:00 +00002036 setvar_i(res, (long)getvar_i(av[0]) & (long)getvar_i(av[1]));
2037 break;
Denis Vlasenkof7996f32007-01-11 17:20:00 +00002038
Denis Vlasenkof782f522007-01-01 23:51:30 +00002039 case B_co:
Denis Vlasenkoe175ff22006-09-26 17:41:00 +00002040 setvar_i(res, ~(long)getvar_i(av[0]));
2041 break;
2042
Denis Vlasenkof782f522007-01-01 23:51:30 +00002043 case B_ls:
Denis Vlasenkoe175ff22006-09-26 17:41:00 +00002044 setvar_i(res, (long)getvar_i(av[0]) << (long)getvar_i(av[1]));
2045 break;
2046
Denis Vlasenkof782f522007-01-01 23:51:30 +00002047 case B_or:
Denis Vlasenkoe175ff22006-09-26 17:41:00 +00002048 setvar_i(res, (long)getvar_i(av[0]) | (long)getvar_i(av[1]));
2049 break;
2050
Denis Vlasenkof782f522007-01-01 23:51:30 +00002051 case B_rs:
Denis Vlasenkoe175ff22006-09-26 17:41:00 +00002052 setvar_i(res, (long)((unsigned long)getvar_i(av[0]) >> (unsigned long)getvar_i(av[1])));
2053 break;
2054
Denis Vlasenkof782f522007-01-01 23:51:30 +00002055 case B_xo:
Denis Vlasenkoe175ff22006-09-26 17:41:00 +00002056 setvar_i(res, (long)getvar_i(av[0]) ^ (long)getvar_i(av[1]));
2057 break;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002058
Denis Vlasenkof782f522007-01-01 23:51:30 +00002059 case B_lo:
Glenn L McGrath545106f2002-11-11 06:21:00 +00002060 to_xxx = tolower;
2061 goto lo_cont;
2062
Denis Vlasenkof782f522007-01-01 23:51:30 +00002063 case B_up:
Glenn L McGrath545106f2002-11-11 06:21:00 +00002064 to_xxx = toupper;
Denis Vlasenkoe1d3e032007-01-01 23:53:52 +00002065 lo_cont:
Rob Landleyd921b2e2006-08-03 15:41:12 +00002066 s1 = s = xstrdup(as[0]);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002067 while (*s1) {
2068 *s1 = (*to_xxx)(*s1);
2069 s1++;
2070 }
2071 setvar_p(res, s);
2072 break;
2073
Denis Vlasenkof782f522007-01-01 23:51:30 +00002074 case B_ix:
Glenn L McGrath545106f2002-11-11 06:21:00 +00002075 n = 0;
Rob Landleya3896512006-05-07 20:20:34 +00002076 ll = strlen(as[1]);
2077 l = strlen(as[0]) - ll;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002078 if (ll > 0 && l >= 0) {
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002079 if (!icase) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00002080 s = strstr(as[0], as[1]);
2081 if (s) n = (s - as[0]) + 1;
2082 } else {
2083 /* this piece of code is terribly slow and
2084 * really should be rewritten
2085 */
2086 for (i=0; i<=l; i++) {
2087 if (strncasecmp(as[0]+i, as[1], ll) == 0) {
2088 n = i+1;
2089 break;
2090 }
2091 }
2092 }
2093 }
2094 setvar_i(res, n);
2095 break;
2096
Denis Vlasenkof782f522007-01-01 23:51:30 +00002097 case B_ti:
Glenn L McGrath545106f2002-11-11 06:21:00 +00002098 if (nargs > 1)
2099 tt = getvar_i(av[1]);
2100 else
2101 time(&tt);
Denis Vlasenkoa41fdf32007-01-29 22:51:00 +00002102 //s = (nargs > 0) ? as[0] : "%a %b %d %H:%M:%S %Z %Y";
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002103 i = strftime(g_buf, MAXVARFMT,
Denis Vlasenkoa41fdf32007-01-29 22:51:00 +00002104 ((nargs > 0) ? as[0] : "%a %b %d %H:%M:%S %Z %Y"),
2105 localtime(&tt));
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002106 g_buf[i] = '\0';
2107 setvar_s(res, g_buf);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002108 break;
2109
Denis Vlasenkof782f522007-01-01 23:51:30 +00002110 case B_ma:
Glenn L McGrath545106f2002-11-11 06:21:00 +00002111 re = as_regex(an[1], &sreg);
2112 n = regexec(re, as[0], 1, pmatch, 0);
2113 if (n == 0) {
2114 pmatch[0].rm_so++;
2115 pmatch[0].rm_eo++;
2116 } else {
2117 pmatch[0].rm_so = 0;
2118 pmatch[0].rm_eo = -1;
2119 }
2120 setvar_i(newvar("RSTART"), pmatch[0].rm_so);
2121 setvar_i(newvar("RLENGTH"), pmatch[0].rm_eo - pmatch[0].rm_so);
2122 setvar_i(res, pmatch[0].rm_so);
2123 if (re == &sreg) regfree(re);
2124 break;
2125
Denis Vlasenkof782f522007-01-01 23:51:30 +00002126 case B_ge:
Glenn L McGrath545106f2002-11-11 06:21:00 +00002127 awk_sub(an[0], as[1], getvar_i(av[2]), av[3], res, TRUE);
2128 break;
2129
Denis Vlasenkof782f522007-01-01 23:51:30 +00002130 case B_gs:
Glenn L McGrath545106f2002-11-11 06:21:00 +00002131 setvar_i(res, awk_sub(an[0], as[1], 0, av[2], av[2], FALSE));
2132 break;
2133
Denis Vlasenkof782f522007-01-01 23:51:30 +00002134 case B_su:
Glenn L McGrath545106f2002-11-11 06:21:00 +00002135 setvar_i(res, awk_sub(an[0], as[1], 1, av[2], av[2], FALSE));
2136 break;
2137 }
2138
2139 nvfree(tv);
2140 return res;
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002141#undef tspl
Glenn L McGrath545106f2002-11-11 06:21:00 +00002142}
2143
2144/*
2145 * Evaluate node - the heart of the program. Supplied with subtree
2146 * and place where to store result. returns ptr to result.
2147 */
2148#define XC(n) ((n) >> 8)
2149
Mike Frysinger10a11e22005-09-27 02:23:02 +00002150static var *evaluate(node *op, var *res)
2151{
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002152/* This procedure is recursive so we should count every byte */
2153#define fnargs (G.evaluate__fnargs)
2154/* seed is initialized to 1 */
2155#define seed (G.evaluate__seed)
2156#define sreg (G.evaluate__sreg)
Denis Vlasenkoe1d3e032007-01-01 23:53:52 +00002157
Glenn L McGrath545106f2002-11-11 06:21:00 +00002158 node *op1;
2159 var *v1;
2160 union {
2161 var *v;
Denis Vlasenkoa41fdf32007-01-29 22:51:00 +00002162 const char *s;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002163 double d;
2164 int i;
2165 } L, R;
Mike Frysingerf87b3e32005-09-27 04:16:22 +00002166 uint32_t opinfo;
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002167 int opn;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002168 union {
2169 char *s;
2170 rstream *rsm;
2171 FILE *F;
2172 var *v;
2173 regex_t *re;
Mike Frysingerf87b3e32005-09-27 04:16:22 +00002174 uint32_t info;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002175 } X;
2176
Denis Vlasenkoe1d3e032007-01-01 23:53:52 +00002177 if (!op)
Glenn L McGrath545106f2002-11-11 06:21:00 +00002178 return setvar_s(res, NULL);
2179
2180 v1 = nvalloc(2);
2181
2182 while (op) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00002183 opinfo = op->info;
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002184 opn = (opinfo & OPNMASK);
2185 g_lineno = op->lineno;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002186
Mike Frysingerde2b9382005-09-27 03:18:00 +00002187 /* execute inevitable things */
Glenn L McGrath545106f2002-11-11 06:21:00 +00002188 op1 = op->l.n;
2189 if (opinfo & OF_RES1) X.v = L.v = evaluate(op1, v1);
2190 if (opinfo & OF_RES2) R.v = evaluate(op->r.n, v1+1);
2191 if (opinfo & OF_STR1) L.s = getvar_s(L.v);
2192 if (opinfo & OF_STR2) R.s = getvar_s(R.v);
2193 if (opinfo & OF_NUM1) L.d = getvar_i(L.v);
2194
2195 switch (XC(opinfo & OPCLSMASK)) {
2196
Denis Vlasenkocd5c7862007-05-17 16:37:22 +00002197 /* -- iterative node type -- */
Glenn L McGrath545106f2002-11-11 06:21:00 +00002198
Denis Vlasenkocd5c7862007-05-17 16:37:22 +00002199 /* test pattern */
Denis Vlasenkof782f522007-01-01 23:51:30 +00002200 case XC( OC_TEST ):
Glenn L McGrath545106f2002-11-11 06:21:00 +00002201 if ((op1->info & OPCLSMASK) == OC_COMMA) {
2202 /* it's range pattern */
2203 if ((opinfo & OF_CHECKED) || ptest(op1->l.n)) {
2204 op->info |= OF_CHECKED;
2205 if (ptest(op1->r.n))
2206 op->info &= ~OF_CHECKED;
2207
2208 op = op->a.n;
2209 } else {
2210 op = op->r.n;
2211 }
2212 } else {
2213 op = (ptest(op1)) ? op->a.n : op->r.n;
2214 }
2215 break;
2216
Denis Vlasenkocd5c7862007-05-17 16:37:22 +00002217 /* just evaluate an expression, also used as unconditional jump */
Denis Vlasenkof782f522007-01-01 23:51:30 +00002218 case XC( OC_EXEC ):
Mike Frysingerde2b9382005-09-27 03:18:00 +00002219 break;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002220
Denis Vlasenkocd5c7862007-05-17 16:37:22 +00002221 /* branch, used in if-else and various loops */
Denis Vlasenkof782f522007-01-01 23:51:30 +00002222 case XC( OC_BR ):
Mike Frysingerde2b9382005-09-27 03:18:00 +00002223 op = istrue(L.v) ? op->a.n : op->r.n;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002224 break;
2225
Denis Vlasenkocd5c7862007-05-17 16:37:22 +00002226 /* initialize for-in loop */
Denis Vlasenkof782f522007-01-01 23:51:30 +00002227 case XC( OC_WALKINIT ):
Mike Frysingerde2b9382005-09-27 03:18:00 +00002228 hashwalk_init(L.v, iamarray(R.v));
Glenn L McGrath545106f2002-11-11 06:21:00 +00002229 break;
2230
Denis Vlasenkocd5c7862007-05-17 16:37:22 +00002231 /* get next array item */
Denis Vlasenkof782f522007-01-01 23:51:30 +00002232 case XC( OC_WALKNEXT ):
Glenn L McGrath545106f2002-11-11 06:21:00 +00002233 op = hashwalk_next(L.v) ? op->a.n : op->r.n;
2234 break;
2235
Denis Vlasenkof782f522007-01-01 23:51:30 +00002236 case XC( OC_PRINT ):
2237 case XC( OC_PRINTF ):
Glenn L McGrath545106f2002-11-11 06:21:00 +00002238 X.F = stdout;
Mike Frysingerde2b9382005-09-27 03:18:00 +00002239 if (op->r.n) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00002240 X.rsm = newfile(R.s);
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002241 if (!X.rsm->F) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00002242 if (opn == '|') {
Denis Vlasenko51742f42007-04-12 00:32:05 +00002243 X.rsm->F = popen(R.s, "w");
2244 if (X.rsm->F == NULL)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002245 bb_perror_msg_and_die("popen");
Glenn L McGrath545106f2002-11-11 06:21:00 +00002246 X.rsm->is_pipe = 1;
2247 } else {
Rob Landleyd921b2e2006-08-03 15:41:12 +00002248 X.rsm->F = xfopen(R.s, opn=='w' ? "w" : "a");
Glenn L McGrath545106f2002-11-11 06:21:00 +00002249 }
2250 }
2251 X.F = X.rsm->F;
2252 }
2253
2254 if ((opinfo & OPCLSMASK) == OC_PRINT) {
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002255 if (!op1) {
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002256 fputs(getvar_s(intvar[F0]), X.F);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002257 } else {
2258 while (op1) {
2259 L.v = evaluate(nextarg(&op1), v1);
2260 if (L.v->type & VF_NUMBER) {
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002261 fmt_num(g_buf, MAXVARFMT, getvar_s(intvar[OFMT]),
Denis Vlasenkob54b2082006-10-27 09:05:40 +00002262 getvar_i(L.v), TRUE);
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002263 fputs(g_buf, X.F);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002264 } else {
2265 fputs(getvar_s(L.v), X.F);
2266 }
2267
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002268 if (op1) fputs(getvar_s(intvar[OFS]), X.F);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002269 }
2270 }
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002271 fputs(getvar_s(intvar[ORS]), X.F);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002272
2273 } else { /* OC_PRINTF */
2274 L.s = awk_printf(op1);
2275 fputs(L.s, X.F);
Denis Vlasenkoa41fdf32007-01-29 22:51:00 +00002276 free((char*)L.s);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002277 }
2278 fflush(X.F);
2279 break;
2280
Denis Vlasenkof782f522007-01-01 23:51:30 +00002281 case XC( OC_DELETE ):
Mike Frysingerde2b9382005-09-27 03:18:00 +00002282 X.info = op1->info & OPCLSMASK;
2283 if (X.info == OC_VAR) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00002284 R.v = op1->l.v;
2285 } else if (X.info == OC_FNARG) {
2286 R.v = &fnargs[op1->l.i];
2287 } else {
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002288 syntax_error(EMSG_NOT_ARRAY);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002289 }
2290
Mike Frysingerde2b9382005-09-27 03:18:00 +00002291 if (op1->r.n) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00002292 clrvar(L.v);
2293 L.s = getvar_s(evaluate(op1->r.n, v1));
2294 hash_remove(iamarray(R.v), L.s);
2295 } else {
2296 clear_array(iamarray(R.v));
2297 }
2298 break;
2299
Denis Vlasenkof782f522007-01-01 23:51:30 +00002300 case XC( OC_NEWSOURCE ):
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002301 g_progname = op->l.s;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002302 break;
2303
Denis Vlasenkof782f522007-01-01 23:51:30 +00002304 case XC( OC_RETURN ):
Glenn L McGrath545106f2002-11-11 06:21:00 +00002305 copyvar(res, L.v);
2306 break;
2307
Denis Vlasenkof782f522007-01-01 23:51:30 +00002308 case XC( OC_NEXTFILE ):
Mike Frysingerde2b9382005-09-27 03:18:00 +00002309 nextfile = TRUE;
Denis Vlasenkof782f522007-01-01 23:51:30 +00002310 case XC( OC_NEXT ):
Mike Frysingerde2b9382005-09-27 03:18:00 +00002311 nextrec = TRUE;
Denis Vlasenkof782f522007-01-01 23:51:30 +00002312 case XC( OC_DONE ):
Glenn L McGrath545106f2002-11-11 06:21:00 +00002313 clrvar(res);
2314 break;
2315
Denis Vlasenkof782f522007-01-01 23:51:30 +00002316 case XC( OC_EXIT ):
Mike Frysingerde2b9382005-09-27 03:18:00 +00002317 awk_exit(L.d);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002318
Denis Vlasenkocd5c7862007-05-17 16:37:22 +00002319 /* -- recursive node type -- */
Glenn L McGrath545106f2002-11-11 06:21:00 +00002320
Denis Vlasenkof782f522007-01-01 23:51:30 +00002321 case XC( OC_VAR ):
Mike Frysingerde2b9382005-09-27 03:18:00 +00002322 L.v = op->l.v;
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002323 if (L.v == intvar[NF])
Glenn L McGrath545106f2002-11-11 06:21:00 +00002324 split_f0();
2325 goto v_cont;
2326
Denis Vlasenkof782f522007-01-01 23:51:30 +00002327 case XC( OC_FNARG ):
Mike Frysingerde2b9382005-09-27 03:18:00 +00002328 L.v = &fnargs[op->l.i];
Denis Vlasenkoe1d3e032007-01-01 23:53:52 +00002329 v_cont:
2330 res = op->r.n ? findvar(iamarray(L.v), R.s) : L.v;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002331 break;
2332
Denis Vlasenkof782f522007-01-01 23:51:30 +00002333 case XC( OC_IN ):
Glenn L McGrath545106f2002-11-11 06:21:00 +00002334 setvar_i(res, hash_search(iamarray(R.v), L.s) ? 1 : 0);
2335 break;
2336
Denis Vlasenkof782f522007-01-01 23:51:30 +00002337 case XC( OC_REGEXP ):
Mike Frysingerde2b9382005-09-27 03:18:00 +00002338 op1 = op;
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002339 L.s = getvar_s(intvar[F0]);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002340 goto re_cont;
2341
Denis Vlasenkof782f522007-01-01 23:51:30 +00002342 case XC( OC_MATCH ):
Mike Frysingerde2b9382005-09-27 03:18:00 +00002343 op1 = op->r.n;
Denis Vlasenkoe1d3e032007-01-01 23:53:52 +00002344 re_cont:
Glenn L McGrath545106f2002-11-11 06:21:00 +00002345 X.re = as_regex(op1, &sreg);
2346 R.i = regexec(X.re, L.s, 0, NULL, 0);
2347 if (X.re == &sreg) regfree(X.re);
2348 setvar_i(res, (R.i == 0 ? 1 : 0) ^ (opn == '!' ? 1 : 0));
2349 break;
2350
Denis Vlasenkof782f522007-01-01 23:51:30 +00002351 case XC( OC_MOVE ):
Mike Frysingerde2b9382005-09-27 03:18:00 +00002352 /* if source is a temporary string, jusk relink it to dest */
Glenn L McGrath545106f2002-11-11 06:21:00 +00002353 if (R.v == v1+1 && R.v->string) {
2354 res = setvar_p(L.v, R.v->string);
2355 R.v->string = NULL;
2356 } else {
Mike Frysingerde2b9382005-09-27 03:18:00 +00002357 res = copyvar(L.v, R.v);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002358 }
2359 break;
2360
Denis Vlasenkof782f522007-01-01 23:51:30 +00002361 case XC( OC_TERNARY ):
Mike Frysingerde2b9382005-09-27 03:18:00 +00002362 if ((op->r.n->info & OPCLSMASK) != OC_COLON)
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002363 syntax_error(EMSG_POSSIBLE_ERROR);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002364 res = evaluate(istrue(L.v) ? op->r.n->l.n : op->r.n->r.n, res);
2365 break;
2366
Denis Vlasenkof782f522007-01-01 23:51:30 +00002367 case XC( OC_FUNC ):
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002368 if (!op->r.f->body.first)
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002369 syntax_error(EMSG_UNDEF_FUNC);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002370
2371 X.v = R.v = nvalloc(op->r.f->nargs+1);
2372 while (op1) {
2373 L.v = evaluate(nextarg(&op1), v1);
2374 copyvar(R.v, L.v);
2375 R.v->type |= VF_CHILD;
2376 R.v->x.parent = L.v;
2377 if (++R.v - X.v >= op->r.f->nargs)
2378 break;
2379 }
2380
2381 R.v = fnargs;
2382 fnargs = X.v;
2383
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002384 L.s = g_progname;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002385 res = evaluate(op->r.f->body.first, res);
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002386 g_progname = L.s;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002387
2388 nvfree(fnargs);
2389 fnargs = R.v;
2390 break;
2391
Denis Vlasenkof782f522007-01-01 23:51:30 +00002392 case XC( OC_GETLINE ):
2393 case XC( OC_PGETLINE ):
Mike Frysingerde2b9382005-09-27 03:18:00 +00002394 if (op1) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00002395 X.rsm = newfile(L.s);
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002396 if (!X.rsm->F) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00002397 if ((opinfo & OPCLSMASK) == OC_PGETLINE) {
2398 X.rsm->F = popen(L.s, "r");
2399 X.rsm->is_pipe = TRUE;
2400 } else {
Rob Landleyd921b2e2006-08-03 15:41:12 +00002401 X.rsm->F = fopen(L.s, "r"); /* not xfopen! */
Glenn L McGrath545106f2002-11-11 06:21:00 +00002402 }
2403 }
2404 } else {
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002405 if (!iF) iF = next_input_file();
Glenn L McGrath545106f2002-11-11 06:21:00 +00002406 X.rsm = iF;
2407 }
2408
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002409 if (!X.rsm->F) {
2410 setvar_i(intvar[ERRNO], errno);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002411 setvar_i(res, -1);
2412 break;
2413 }
2414
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002415 if (!op->r.n)
2416 R.v = intvar[F0];
Glenn L McGrath545106f2002-11-11 06:21:00 +00002417
2418 L.i = awk_getline(X.rsm, R.v);
2419 if (L.i > 0) {
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002420 if (!op1) {
2421 incvar(intvar[FNR]);
2422 incvar(intvar[NR]);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002423 }
2424 }
2425 setvar_i(res, L.i);
2426 break;
2427
Denis Vlasenkocd5c7862007-05-17 16:37:22 +00002428 /* simple builtins */
Denis Vlasenkof782f522007-01-01 23:51:30 +00002429 case XC( OC_FBLTIN ):
Mike Frysingerde2b9382005-09-27 03:18:00 +00002430 switch (opn) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00002431
Denis Vlasenkof782f522007-01-01 23:51:30 +00002432 case F_in:
Mike Frysingerde2b9382005-09-27 03:18:00 +00002433 R.d = (int)L.d;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002434 break;
2435
Denis Vlasenkof782f522007-01-01 23:51:30 +00002436 case F_rn:
2437 R.d = (double)rand() / (double)RAND_MAX;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002438 break;
Denis Vlasenkof782f522007-01-01 23:51:30 +00002439#if ENABLE_FEATURE_AWK_MATH
2440 case F_co:
Mike Frysingerde2b9382005-09-27 03:18:00 +00002441 R.d = cos(L.d);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002442 break;
2443
Denis Vlasenkof782f522007-01-01 23:51:30 +00002444 case F_ex:
Mike Frysingerde2b9382005-09-27 03:18:00 +00002445 R.d = exp(L.d);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002446 break;
2447
Denis Vlasenkof782f522007-01-01 23:51:30 +00002448 case F_lg:
Mike Frysingerde2b9382005-09-27 03:18:00 +00002449 R.d = log(L.d);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002450 break;
2451
Denis Vlasenkof782f522007-01-01 23:51:30 +00002452 case F_si:
Mike Frysingerde2b9382005-09-27 03:18:00 +00002453 R.d = sin(L.d);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002454 break;
2455
Denis Vlasenkof782f522007-01-01 23:51:30 +00002456 case F_sq:
Mike Frysingerde2b9382005-09-27 03:18:00 +00002457 R.d = sqrt(L.d);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002458 break;
2459#else
Denis Vlasenkof782f522007-01-01 23:51:30 +00002460 case F_co:
2461 case F_ex:
2462 case F_lg:
2463 case F_si:
2464 case F_sq:
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002465 syntax_error(EMSG_NO_MATH);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002466 break;
2467#endif
Denis Vlasenkof782f522007-01-01 23:51:30 +00002468 case F_sr:
Glenn L McGrath545106f2002-11-11 06:21:00 +00002469 R.d = (double)seed;
Denis Vlasenkof782f522007-01-01 23:51:30 +00002470 seed = op1 ? (unsigned)L.d : (unsigned)time(NULL);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002471 srand(seed);
2472 break;
2473
Denis Vlasenkof782f522007-01-01 23:51:30 +00002474 case F_ti:
Glenn L McGrath545106f2002-11-11 06:21:00 +00002475 R.d = time(NULL);
2476 break;
2477
Denis Vlasenkof782f522007-01-01 23:51:30 +00002478 case F_le:
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002479 if (!op1)
2480 L.s = getvar_s(intvar[F0]);
Rob Landleya3896512006-05-07 20:20:34 +00002481 R.d = strlen(L.s);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002482 break;
2483
Denis Vlasenkof782f522007-01-01 23:51:30 +00002484 case F_sy:
Glenn L McGrath545106f2002-11-11 06:21:00 +00002485 fflush(NULL);
Denis Vlasenko249fabf2006-12-19 00:29:22 +00002486 R.d = (ENABLE_FEATURE_ALLOW_EXEC && L.s && *L.s)
2487 ? (system(L.s) >> 8) : 0;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002488 break;
2489
Denis Vlasenkof782f522007-01-01 23:51:30 +00002490 case F_ff:
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002491 if (!op1)
Glenn L McGrath545106f2002-11-11 06:21:00 +00002492 fflush(stdout);
2493 else {
2494 if (L.s && *L.s) {
2495 X.rsm = newfile(L.s);
2496 fflush(X.rsm->F);
2497 } else {
2498 fflush(NULL);
2499 }
2500 }
2501 break;
2502
Denis Vlasenkof782f522007-01-01 23:51:30 +00002503 case F_cl:
Glenn L McGrath545106f2002-11-11 06:21:00 +00002504 X.rsm = (rstream *)hash_search(fdhash, L.s);
2505 if (X.rsm) {
2506 R.i = X.rsm->is_pipe ? pclose(X.rsm->F) : fclose(X.rsm->F);
Aaron Lehmanna170e1c2002-11-28 11:27:31 +00002507 free(X.rsm->buffer);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002508 hash_remove(fdhash, L.s);
2509 }
2510 if (R.i != 0)
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002511 setvar_i(intvar[ERRNO], errno);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002512 R.d = (double)R.i;
2513 break;
2514 }
2515 setvar_i(res, R.d);
2516 break;
2517
Denis Vlasenkof782f522007-01-01 23:51:30 +00002518 case XC( OC_BUILTIN ):
Glenn L McGrath545106f2002-11-11 06:21:00 +00002519 res = exec_builtin(op, res);
2520 break;
2521
Denis Vlasenkof782f522007-01-01 23:51:30 +00002522 case XC( OC_SPRINTF ):
Mike Frysingerde2b9382005-09-27 03:18:00 +00002523 setvar_p(res, awk_printf(op1));
Glenn L McGrath545106f2002-11-11 06:21:00 +00002524 break;
2525
Denis Vlasenkof782f522007-01-01 23:51:30 +00002526 case XC( OC_UNARY ):
Mike Frysingerde2b9382005-09-27 03:18:00 +00002527 X.v = R.v;
2528 L.d = R.d = getvar_i(R.v);
2529 switch (opn) {
Denis Vlasenkof782f522007-01-01 23:51:30 +00002530 case 'P':
Mike Frysingerde2b9382005-09-27 03:18:00 +00002531 L.d = ++R.d;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002532 goto r_op_change;
Denis Vlasenkof782f522007-01-01 23:51:30 +00002533 case 'p':
Mike Frysingerde2b9382005-09-27 03:18:00 +00002534 R.d++;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002535 goto r_op_change;
Denis Vlasenkof782f522007-01-01 23:51:30 +00002536 case 'M':
Mike Frysingerde2b9382005-09-27 03:18:00 +00002537 L.d = --R.d;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002538 goto r_op_change;
Denis Vlasenkof782f522007-01-01 23:51:30 +00002539 case 'm':
Mike Frysingerde2b9382005-09-27 03:18:00 +00002540 R.d--;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002541 goto r_op_change;
Denis Vlasenkof782f522007-01-01 23:51:30 +00002542 case '!':
Denis Vlasenko92758142006-10-03 19:56:34 +00002543 L.d = istrue(X.v) ? 0 : 1;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002544 break;
Denis Vlasenkof782f522007-01-01 23:51:30 +00002545 case '-':
Mike Frysingerde2b9382005-09-27 03:18:00 +00002546 L.d = -R.d;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002547 break;
Denis Vlasenkof782f522007-01-01 23:51:30 +00002548 r_op_change:
Glenn L McGrath545106f2002-11-11 06:21:00 +00002549 setvar_i(X.v, R.d);
2550 }
2551 setvar_i(res, L.d);
2552 break;
2553
Denis Vlasenkof782f522007-01-01 23:51:30 +00002554 case XC( OC_FIELD ):
Mike Frysingerde2b9382005-09-27 03:18:00 +00002555 R.i = (int)getvar_i(R.v);
2556 if (R.i == 0) {
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002557 res = intvar[F0];
Glenn L McGrath545106f2002-11-11 06:21:00 +00002558 } else {
2559 split_f0();
2560 if (R.i > nfields)
2561 fsrealloc(R.i);
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002562 res = &Fields[R.i - 1];
Glenn L McGrath545106f2002-11-11 06:21:00 +00002563 }
2564 break;
2565
Denis Vlasenkocd5c7862007-05-17 16:37:22 +00002566 /* concatenation (" ") and index joining (",") */
Denis Vlasenkof782f522007-01-01 23:51:30 +00002567 case XC( OC_CONCAT ):
2568 case XC( OC_COMMA ):
Rob Landleya3896512006-05-07 20:20:34 +00002569 opn = strlen(L.s) + strlen(R.s) + 2;
Denis Vlasenkob95636c2006-12-19 23:36:04 +00002570 X.s = xmalloc(opn);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002571 strcpy(X.s, L.s);
2572 if ((opinfo & OPCLSMASK) == OC_COMMA) {
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002573 L.s = getvar_s(intvar[SUBSEP]);
Denis Vlasenkof782f522007-01-01 23:51:30 +00002574 X.s = xrealloc(X.s, opn + strlen(L.s));
Glenn L McGrath545106f2002-11-11 06:21:00 +00002575 strcat(X.s, L.s);
2576 }
2577 strcat(X.s, R.s);
2578 setvar_p(res, X.s);
2579 break;
2580
Denis Vlasenkof782f522007-01-01 23:51:30 +00002581 case XC( OC_LAND ):
Glenn L McGrath545106f2002-11-11 06:21:00 +00002582 setvar_i(res, istrue(L.v) ? ptest(op->r.n) : 0);
2583 break;
2584
Denis Vlasenkof782f522007-01-01 23:51:30 +00002585 case XC( OC_LOR ):
Glenn L McGrath545106f2002-11-11 06:21:00 +00002586 setvar_i(res, istrue(L.v) ? 1 : ptest(op->r.n));
2587 break;
2588
Denis Vlasenkof782f522007-01-01 23:51:30 +00002589 case XC( OC_BINARY ):
2590 case XC( OC_REPLACE ):
Mike Frysingerde2b9382005-09-27 03:18:00 +00002591 R.d = getvar_i(R.v);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002592 switch (opn) {
Denis Vlasenkof782f522007-01-01 23:51:30 +00002593 case '+':
Mike Frysingerde2b9382005-09-27 03:18:00 +00002594 L.d += R.d;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002595 break;
Denis Vlasenkof782f522007-01-01 23:51:30 +00002596 case '-':
Mike Frysingerde2b9382005-09-27 03:18:00 +00002597 L.d -= R.d;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002598 break;
Denis Vlasenkof782f522007-01-01 23:51:30 +00002599 case '*':
Mike Frysingerde2b9382005-09-27 03:18:00 +00002600 L.d *= R.d;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002601 break;
Denis Vlasenkof782f522007-01-01 23:51:30 +00002602 case '/':
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002603 if (R.d == 0) syntax_error(EMSG_DIV_BY_ZERO);
Mike Frysingerde2b9382005-09-27 03:18:00 +00002604 L.d /= R.d;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002605 break;
Denis Vlasenkof782f522007-01-01 23:51:30 +00002606 case '&':
2607#if ENABLE_FEATURE_AWK_MATH
Mike Frysingerde2b9382005-09-27 03:18:00 +00002608 L.d = pow(L.d, R.d);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002609#else
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002610 syntax_error(EMSG_NO_MATH);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002611#endif
2612 break;
Denis Vlasenkof782f522007-01-01 23:51:30 +00002613 case '%':
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002614 if (R.d == 0) syntax_error(EMSG_DIV_BY_ZERO);
Mike Frysingerde2b9382005-09-27 03:18:00 +00002615 L.d -= (int)(L.d / R.d) * R.d;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002616 break;
2617 }
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002618 res = setvar_i(((opinfo & OPCLSMASK) == OC_BINARY) ? res : X.v, L.d);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002619 break;
2620
Denis Vlasenkof782f522007-01-01 23:51:30 +00002621 case XC( OC_COMPARE ):
Glenn L McGrath545106f2002-11-11 06:21:00 +00002622 if (is_numeric(L.v) && is_numeric(R.v)) {
2623 L.d = getvar_i(L.v) - getvar_i(R.v);
2624 } else {
2625 L.s = getvar_s(L.v);
2626 R.s = getvar_s(R.v);
2627 L.d = icase ? strcasecmp(L.s, R.s) : strcmp(L.s, R.s);
2628 }
2629 switch (opn & 0xfe) {
Denis Vlasenkof782f522007-01-01 23:51:30 +00002630 case 0:
Mike Frysingerde2b9382005-09-27 03:18:00 +00002631 R.i = (L.d > 0);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002632 break;
Denis Vlasenkof782f522007-01-01 23:51:30 +00002633 case 2:
Mike Frysingerde2b9382005-09-27 03:18:00 +00002634 R.i = (L.d >= 0);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002635 break;
Denis Vlasenkof782f522007-01-01 23:51:30 +00002636 case 4:
Mike Frysingerde2b9382005-09-27 03:18:00 +00002637 R.i = (L.d == 0);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002638 break;
2639 }
2640 setvar_i(res, (opn & 0x1 ? R.i : !R.i) ? 1 : 0);
2641 break;
2642
Denis Vlasenkof782f522007-01-01 23:51:30 +00002643 default:
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002644 syntax_error(EMSG_POSSIBLE_ERROR);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002645 }
2646 if ((opinfo & OPCLSMASK) <= SHIFT_TIL_THIS)
2647 op = op->a.n;
2648 if ((opinfo & OPCLSMASK) >= RECUR_FROM_THIS)
2649 break;
2650 if (nextrec)
2651 break;
2652 }
2653 nvfree(v1);
2654 return res;
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002655#undef fnargs
2656#undef seed
2657#undef sreg
Glenn L McGrath545106f2002-11-11 06:21:00 +00002658}
2659
2660
2661/* -------- main & co. -------- */
2662
Mike Frysinger10a11e22005-09-27 02:23:02 +00002663static int awk_exit(int r)
2664{
Denis Vlasenkof782f522007-01-01 23:51:30 +00002665 var tv;
2666 unsigned i;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002667 hash_item *hi;
Glenn L McGrath00ed36f2003-10-30 13:36:39 +00002668
Denis Vlasenkof782f522007-01-01 23:51:30 +00002669 zero_out_var(&tv);
2670
2671 if (!exiting) {
Glenn L McGrath00ed36f2003-10-30 13:36:39 +00002672 exiting = TRUE;
Glenn L McGrathca29ffc2004-09-24 09:24:27 +00002673 nextrec = FALSE;
Glenn L McGrath00ed36f2003-10-30 13:36:39 +00002674 evaluate(endseq.first, &tv);
2675 }
Glenn L McGrath545106f2002-11-11 06:21:00 +00002676
2677 /* waiting for children */
Denis Vlasenkof782f522007-01-01 23:51:30 +00002678 for (i = 0; i < fdhash->csize; i++) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00002679 hi = fdhash->items[i];
Denis Vlasenkobf0a2012006-12-26 10:42:51 +00002680 while (hi) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00002681 if (hi->data.rs.F && hi->data.rs.is_pipe)
2682 pclose(hi->data.rs.F);
2683 hi = hi->next;
2684 }
2685 }
2686
2687 exit(r);
2688}
2689
2690/* if expr looks like "var=value", perform assignment and return 1,
2691 * otherwise return 0 */
"Vladimir N. Oleynik"5cf9a032005-10-19 09:21:51 +00002692static int is_assignment(const char *expr)
Mike Frysinger10a11e22005-09-27 02:23:02 +00002693{
Glenn L McGrath545106f2002-11-11 06:21:00 +00002694 char *exprc, *s, *s0, *s1;
2695
Rob Landleyd921b2e2006-08-03 15:41:12 +00002696 exprc = xstrdup(expr);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002697 if (!isalnum_(*exprc) || (s = strchr(exprc, '=')) == NULL) {
2698 free(exprc);
2699 return FALSE;
2700 }
2701
2702 *(s++) = '\0';
2703 s0 = s1 = s;
2704 while (*s)
2705 *(s1++) = nextchar(&s);
2706
2707 *s1 = '\0';
2708 setvar_u(newvar(exprc), s0);
2709 free(exprc);
2710 return TRUE;
2711}
2712
2713/* switch to next input file */
Mike Frysinger10a11e22005-09-27 02:23:02 +00002714static rstream *next_input_file(void)
2715{
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002716#define rsm (G.next_input_file__rsm)
2717#define files_happen (G.next_input_file__files_happen)
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002718
Glenn L McGrath545106f2002-11-11 06:21:00 +00002719 FILE *F = NULL;
Denis Vlasenkoa41fdf32007-01-29 22:51:00 +00002720 const char *fname, *ind;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002721
2722 if (rsm.F) fclose(rsm.F);
2723 rsm.F = NULL;
Glenn L McGrath00ed36f2003-10-30 13:36:39 +00002724 rsm.pos = rsm.adv = 0;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002725
2726 do {
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002727 if (getvar_i(intvar[ARGIND])+1 >= getvar_i(intvar[ARGC])) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00002728 if (files_happen)
2729 return NULL;
2730 fname = "-";
2731 F = stdin;
2732 } else {
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002733 ind = getvar_s(incvar(intvar[ARGIND]));
2734 fname = getvar_s(findvar(iamarray(intvar[ARGV]), ind));
Glenn L McGrath545106f2002-11-11 06:21:00 +00002735 if (fname && *fname && !is_assignment(fname))
Denis Vlasenko3bb2bbd2008-07-01 01:57:36 +00002736 F = xfopen_stdin(fname);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002737 }
2738 } while (!F);
2739
2740 files_happen = TRUE;
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002741 setvar_s(intvar[FILENAME], fname);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002742 rsm.F = F;
2743 return &rsm;
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002744#undef rsm
2745#undef files_happen
Glenn L McGrath545106f2002-11-11 06:21:00 +00002746}
2747
Denis Vlasenko9b49a5e2007-10-11 10:05:36 +00002748int awk_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
Rob Landleydfba7412006-03-06 20:47:33 +00002749int awk_main(int argc, char **argv)
Mike Frysinger10a11e22005-09-27 02:23:02 +00002750{
Denis Vlasenko67b23e62006-10-03 21:00:06 +00002751 unsigned opt;
Denis Vlasenkobe644a82007-03-10 17:22:14 +00002752 char *opt_F, *opt_W;
Denis Vlasenko3bb2bbd2008-07-01 01:57:36 +00002753 llist_t *list_v = NULL;
2754 llist_t *list_f = NULL;
2755 int i, j;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002756 var *v;
Denis Vlasenkof782f522007-01-01 23:51:30 +00002757 var tv;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002758 char **envp;
Denis Vlasenkof782f522007-01-01 23:51:30 +00002759 char *vnames = (char *)vNames; /* cheat */
2760 char *vvalues = (char *)vValues;
2761
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002762 INIT_G();
2763
Denis Vlasenko150f4022007-01-13 21:06:21 +00002764 /* Undo busybox.c, or else strtod may eat ','! This breaks parsing:
Denis Vlasenko6dc6ebb2007-01-01 23:53:12 +00002765 * $1,$2 == '$1,' '$2', NOT '$1' ',' '$2' */
2766 if (ENABLE_LOCALE_SUPPORT)
2767 setlocale(LC_NUMERIC, "C");
2768
Denis Vlasenkof782f522007-01-01 23:51:30 +00002769 zero_out_var(&tv);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002770
2771 /* allocate global buffer */
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002772 g_buf = xmalloc(MAXVARFMT + 1);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002773
2774 vhash = hash_init();
2775 ahash = hash_init();
2776 fdhash = hash_init();
2777 fnhash = hash_init();
2778
2779 /* initialize variables */
Denis Vlasenkof782f522007-01-01 23:51:30 +00002780 for (i = 0; *vnames; i++) {
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002781 intvar[i] = v = newvar(nextword(&vnames));
Denis Vlasenkof782f522007-01-01 23:51:30 +00002782 if (*vvalues != '\377')
2783 setvar_s(v, nextword(&vvalues));
Glenn L McGrath545106f2002-11-11 06:21:00 +00002784 else
2785 setvar_i(v, 0);
2786
Denis Vlasenkof782f522007-01-01 23:51:30 +00002787 if (*vnames == '*') {
Glenn L McGrath545106f2002-11-11 06:21:00 +00002788 v->type |= VF_SPECIAL;
Denis Vlasenkof782f522007-01-01 23:51:30 +00002789 vnames++;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002790 }
2791 }
2792
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002793 handle_special(intvar[FS]);
2794 handle_special(intvar[RS]);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002795
Denis Vlasenkof782f522007-01-01 23:51:30 +00002796 newfile("/dev/stdin")->F = stdin;
2797 newfile("/dev/stdout")->F = stdout;
2798 newfile("/dev/stderr")->F = stderr;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002799
Denis Vlasenkof71d9162007-05-03 22:57:56 +00002800 /* Huh, people report that sometimes environ is NULL. Oh well. */
2801 if (environ) for (envp = environ; *envp; envp++) {
Denis Vlasenkob78c7822007-07-18 18:31:11 +00002802 /* environ is writable, thus we don't strdup it needlessly */
2803 char *s = *envp;
Denis Vlasenkof782f522007-01-01 23:51:30 +00002804 char *s1 = strchr(s, '=');
2805 if (s1) {
Denis Vlasenkob78c7822007-07-18 18:31:11 +00002806 *s1 = '\0';
2807 /* Both findvar and setvar_u take const char*
2808 * as 2nd arg -> environment is not trashed */
2809 setvar_u(findvar(iamarray(intvar[ENVIRON]), s), s1 + 1);
2810 *s1 = '=';
Eric Andersen67776be2004-07-30 23:52:08 +00002811 }
Glenn L McGrath545106f2002-11-11 06:21:00 +00002812 }
Denis Vlasenko3bb2bbd2008-07-01 01:57:36 +00002813 opt_complementary = "v::f::"; /* -v and -f can occur multiple times */
2814 opt = getopt32(argv, "F:v:f:W:", &opt_F, &list_v, &list_f, &opt_W);
Denis Vlasenkof782f522007-01-01 23:51:30 +00002815 argv += optind;
2816 argc -= optind;
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002817 if (opt & 0x1)
2818 setvar_s(intvar[FS], opt_F); // -F
Denis Vlasenko3bb2bbd2008-07-01 01:57:36 +00002819 while (list_v) { /* -v */
2820 if (!is_assignment(llist_pop(&list_v)))
Denis Vlasenkobe644a82007-03-10 17:22:14 +00002821 bb_show_usage();
2822 }
Denis Vlasenko3bb2bbd2008-07-01 01:57:36 +00002823 if (list_f) { /* -f */
2824 do {
2825 char *s = NULL;
2826 FILE *from_file;
2827
2828 g_progname = llist_pop(&list_f);
2829 from_file = xfopen_stdin(g_progname);
2830 /* one byte is reserved for some trick in next_token */
Denis Vlasenkof782f522007-01-01 23:51:30 +00002831 for (i = j = 1; j > 0; i += j) {
2832 s = xrealloc(s, i + 4096);
2833 j = fread(s + i, 1, 4094, from_file);
Denis Vlasenko099efbf2006-09-22 09:02:30 +00002834 }
Denis Vlasenko3bb2bbd2008-07-01 01:57:36 +00002835 s[i] = '\0';
2836 fclose(from_file);
2837 parse_program(s + 1);
2838 free(s);
2839 } while (list_f);
Denis Vlasenkof782f522007-01-01 23:51:30 +00002840 } else { // no -f: take program from 1st parameter
2841 if (!argc)
2842 bb_show_usage();
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002843 g_progname = "cmd. line";
Denis Vlasenkof782f522007-01-01 23:51:30 +00002844 parse_program(*argv++);
2845 argc--;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002846 }
Denis Vlasenko099efbf2006-09-22 09:02:30 +00002847 if (opt & 0x8) // -W
Denis Vlasenkoe1a0d482006-10-20 13:28:22 +00002848 bb_error_msg("warning: unrecognized option '-W %s' ignored", opt_W);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002849
Glenn L McGrath545106f2002-11-11 06:21:00 +00002850 /* fill in ARGV array */
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002851 setvar_i(intvar[ARGC], argc + 1);
2852 setari_u(intvar[ARGV], 0, "awk");
Denis Vlasenkof782f522007-01-01 23:51:30 +00002853 i = 0;
2854 while (*argv)
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002855 setari_u(intvar[ARGV], ++i, *argv++);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002856
2857 evaluate(beginseq.first, &tv);
Denis Vlasenkof782f522007-01-01 23:51:30 +00002858 if (!mainseq.first && !endseq.first)
Glenn L McGrath545106f2002-11-11 06:21:00 +00002859 awk_exit(EXIT_SUCCESS);
2860
2861 /* input file could already be opened in BEGIN block */
Denis Vlasenkof782f522007-01-01 23:51:30 +00002862 if (!iF) iF = next_input_file();
Glenn L McGrath545106f2002-11-11 06:21:00 +00002863
2864 /* passing through input files */
2865 while (iF) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00002866 nextfile = FALSE;
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002867 setvar_i(intvar[FNR], 0);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002868
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002869 while ((i = awk_getline(iF, intvar[F0])) > 0) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00002870 nextrec = FALSE;
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002871 incvar(intvar[NR]);
2872 incvar(intvar[FNR]);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002873 evaluate(mainseq.first, &tv);
2874
2875 if (nextfile)
2876 break;
2877 }
2878
Denis Vlasenkof782f522007-01-01 23:51:30 +00002879 if (i < 0)
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002880 syntax_error(strerror(errno));
Glenn L McGrath545106f2002-11-11 06:21:00 +00002881
2882 iF = next_input_file();
Glenn L McGrath545106f2002-11-11 06:21:00 +00002883 }
2884
Glenn L McGrath545106f2002-11-11 06:21:00 +00002885 awk_exit(EXIT_SUCCESS);
Denis Vlasenkof782f522007-01-01 23:51:30 +00002886 /*return 0;*/
Glenn L McGrath545106f2002-11-11 06:21:00 +00002887}