blob: 571d68193a6d9cf88395400e1ac76fba75214a98 [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 Vlasenkodeeed592008-07-08 05:14:36 +00001476 if (!*b || n >= *size) {
1477 *size = n + (n>>1) + 80;
1478 *b = xrealloc(*b, *size);
1479 }
Glenn L McGrath545106f2002-11-11 06:21:00 +00001480}
1481
1482/* resize field storage space */
Mike Frysinger10a11e22005-09-27 02:23:02 +00001483static void fsrealloc(int size)
1484{
Glenn L McGrath545106f2002-11-11 06:21:00 +00001485 int i;
1486
1487 if (size >= maxfields) {
1488 i = maxfields;
1489 maxfields = size + 16;
Denis Vlasenkof782f522007-01-01 23:51:30 +00001490 Fields = xrealloc(Fields, maxfields * sizeof(var));
1491 for (; i < maxfields; i++) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00001492 Fields[i].type = VF_SPECIAL;
1493 Fields[i].string = NULL;
1494 }
1495 }
1496
1497 if (size < nfields) {
Denis Vlasenkoe1d3e032007-01-01 23:53:52 +00001498 for (i = size; i < nfields; i++) {
1499 clrvar(Fields + i);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001500 }
1501 }
1502 nfields = size;
1503}
1504
Denis Vlasenkoa41fdf32007-01-29 22:51:00 +00001505static int awk_split(const char *s, node *spl, char **slist)
Mike Frysinger10a11e22005-09-27 02:23:02 +00001506{
Denis Vlasenkof782f522007-01-01 23:51:30 +00001507 int l, n = 0;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001508 char c[4];
1509 char *s1;
Denis Vlasenkob78c7822007-07-18 18:31:11 +00001510 regmatch_t pmatch[2]; // TODO: why [2]? [1] is enough...
Glenn L McGrath545106f2002-11-11 06:21:00 +00001511
1512 /* in worst case, each char would be a separate field */
Denis Vlasenkoa41fdf32007-01-29 22:51:00 +00001513 *slist = s1 = xzalloc(strlen(s) * 2 + 3);
1514 strcpy(s1, s);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001515
1516 c[0] = c[1] = (char)spl->info;
1517 c[2] = c[3] = '\0';
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001518 if (*getvar_s(intvar[RS]) == '\0')
1519 c[2] = '\n';
Glenn L McGrath545106f2002-11-11 06:21:00 +00001520
Denis Vlasenkoaf1bd092007-07-18 18:32:25 +00001521 if ((spl->info & OPCLSMASK) == OC_REGEXP) { /* regex split */
1522 if (!*s)
1523 return n; /* "": zero fields */
1524 n++; /* at least one field will be there */
1525 do {
1526 l = strcspn(s, c+2); /* len till next NUL or \n */
Denis Vlasenkoa41fdf32007-01-29 22:51:00 +00001527 if (regexec(icase ? spl->r.ire : spl->l.re, s, 1, pmatch, 0) == 0
1528 && pmatch[0].rm_so <= l
1529 ) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00001530 l = pmatch[0].rm_so;
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001531 if (pmatch[0].rm_eo == 0) {
1532 l++;
1533 pmatch[0].rm_eo++;
1534 }
Denis Vlasenkoaf1bd092007-07-18 18:32:25 +00001535 n++; /* we saw yet another delimiter */
Glenn L McGrath545106f2002-11-11 06:21:00 +00001536 } else {
1537 pmatch[0].rm_eo = l;
Denis Vlasenkof782f522007-01-01 23:51:30 +00001538 if (s[l]) pmatch[0].rm_eo++;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001539 }
Glenn L McGrath545106f2002-11-11 06:21:00 +00001540 memcpy(s1, s, l);
Denis Vlasenkof782f522007-01-01 23:51:30 +00001541 s1[l] = '\0';
Glenn L McGrath545106f2002-11-11 06:21:00 +00001542 nextword(&s1);
1543 s += pmatch[0].rm_eo;
Denis Vlasenkoaf1bd092007-07-18 18:32:25 +00001544 } while (*s);
1545 return n;
1546 }
1547 if (c[0] == '\0') { /* null split */
Denis Vlasenkobf0a2012006-12-26 10:42:51 +00001548 while (*s) {
Denis Vlasenkoe1d3e032007-01-01 23:53:52 +00001549 *s1++ = *s++;
1550 *s1++ = '\0';
Glenn L McGrath545106f2002-11-11 06:21:00 +00001551 n++;
1552 }
Denis Vlasenkoaf1bd092007-07-18 18:32:25 +00001553 return n;
1554 }
1555 if (c[0] != ' ') { /* single-character split */
Glenn L McGrath545106f2002-11-11 06:21:00 +00001556 if (icase) {
1557 c[0] = toupper(c[0]);
1558 c[1] = tolower(c[1]);
1559 }
1560 if (*s1) n++;
1561 while ((s1 = strpbrk(s1, c))) {
Denis Vlasenkoe1d3e032007-01-01 23:53:52 +00001562 *s1++ = '\0';
Glenn L McGrath545106f2002-11-11 06:21:00 +00001563 n++;
1564 }
Denis Vlasenkoaf1bd092007-07-18 18:32:25 +00001565 return n;
1566 }
1567 /* space split */
1568 while (*s) {
1569 s = skip_whitespace(s);
1570 if (!*s) break;
1571 n++;
1572 while (*s && !isspace(*s))
1573 *s1++ = *s++;
1574 *s1++ = '\0';
Glenn L McGrath545106f2002-11-11 06:21:00 +00001575 }
1576 return n;
1577}
1578
Mike Frysinger10a11e22005-09-27 02:23:02 +00001579static void split_f0(void)
1580{
Denis Vlasenkoaf1bd092007-07-18 18:32:25 +00001581/* static char *fstrings; */
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00001582#define fstrings (G.split_f0__fstrings)
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001583
Glenn L McGrath545106f2002-11-11 06:21:00 +00001584 int i, n;
1585 char *s;
1586
1587 if (is_f0_split)
1588 return;
1589
1590 is_f0_split = TRUE;
Aaron Lehmanna170e1c2002-11-28 11:27:31 +00001591 free(fstrings);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001592 fsrealloc(0);
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001593 n = awk_split(getvar_s(intvar[F0]), &fsplitter.n, &fstrings);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001594 fsrealloc(n);
1595 s = fstrings;
Denis Vlasenkof782f522007-01-01 23:51:30 +00001596 for (i = 0; i < n; i++) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00001597 Fields[i].string = nextword(&s);
1598 Fields[i].type |= (VF_FSTR | VF_USER | VF_DIRTY);
1599 }
1600
1601 /* set NF manually to avoid side effects */
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001602 clrvar(intvar[NF]);
1603 intvar[NF]->type = VF_NUMBER | VF_SPECIAL;
1604 intvar[NF]->number = nfields;
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00001605#undef fstrings
Glenn L McGrath545106f2002-11-11 06:21:00 +00001606}
1607
1608/* perform additional actions when some internal variables changed */
Mike Frysinger10a11e22005-09-27 02:23:02 +00001609static void handle_special(var *v)
1610{
Glenn L McGrath545106f2002-11-11 06:21:00 +00001611 int n;
Denis Vlasenkoa41fdf32007-01-29 22:51:00 +00001612 char *b;
1613 const char *sep, *s;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001614 int sl, l, len, i, bsize;
1615
Denis Vlasenkoe1d3e032007-01-01 23:53:52 +00001616 if (!(v->type & VF_SPECIAL))
Glenn L McGrath545106f2002-11-11 06:21:00 +00001617 return;
1618
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001619 if (v == intvar[NF]) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00001620 n = (int)getvar_i(v);
1621 fsrealloc(n);
1622
1623 /* recalculate $0 */
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001624 sep = getvar_s(intvar[OFS]);
Rob Landleya3896512006-05-07 20:20:34 +00001625 sl = strlen(sep);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001626 b = NULL;
1627 len = 0;
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001628 for (i = 0; i < n; i++) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00001629 s = getvar_s(&Fields[i]);
Rob Landleya3896512006-05-07 20:20:34 +00001630 l = strlen(s);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001631 if (b) {
1632 memcpy(b+len, sep, sl);
1633 len += sl;
1634 }
1635 qrealloc(&b, len+l+sl, &bsize);
1636 memcpy(b+len, s, l);
1637 len += l;
1638 }
Denis Vlasenkoe1d3e032007-01-01 23:53:52 +00001639 if (b)
1640 b[len] = '\0';
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001641 setvar_p(intvar[F0], b);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001642 is_f0_split = TRUE;
1643
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001644 } else if (v == intvar[F0]) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00001645 is_f0_split = FALSE;
1646
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001647 } else if (v == intvar[FS]) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00001648 mk_splitter(getvar_s(v), &fsplitter);
1649
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001650 } else if (v == intvar[RS]) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00001651 mk_splitter(getvar_s(v), &rsplitter);
1652
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001653 } else if (v == intvar[IGNORECASE]) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00001654 icase = istrue(v);
1655
Denis Vlasenkoe1d3e032007-01-01 23:53:52 +00001656 } else { /* $n */
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001657 n = getvar_i(intvar[NF]);
1658 setvar_i(intvar[NF], n > v-Fields ? n : v-Fields+1);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001659 /* right here v is invalid. Just to note... */
1660 }
1661}
1662
1663/* step through func/builtin/etc arguments */
Mike Frysinger10a11e22005-09-27 02:23:02 +00001664static node *nextarg(node **pn)
1665{
Glenn L McGrath545106f2002-11-11 06:21:00 +00001666 node *n;
1667
1668 n = *pn;
1669 if (n && (n->info & OPCLSMASK) == OC_COMMA) {
1670 *pn = n->r.n;
1671 n = n->l.n;
1672 } else {
1673 *pn = NULL;
1674 }
1675 return n;
1676}
1677
Mike Frysinger10a11e22005-09-27 02:23:02 +00001678static void hashwalk_init(var *v, xhash *array)
1679{
Glenn L McGrath545106f2002-11-11 06:21:00 +00001680 char **w;
1681 hash_item *hi;
Denis Vlasenko77ad97f2008-05-13 02:27:31 +00001682 unsigned i;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001683
1684 if (v->type & VF_WALK)
1685 free(v->x.walker);
1686
1687 v->type |= VF_WALK;
Denis Vlasenko4cccc032006-12-22 18:37:07 +00001688 w = v->x.walker = xzalloc(2 + 2*sizeof(char *) + array->glen);
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001689 w[0] = w[1] = (char *)(w + 2);
1690 for (i = 0; i < array->csize; i++) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00001691 hi = array->items[i];
Denis Vlasenkobf0a2012006-12-26 10:42:51 +00001692 while (hi) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00001693 strcpy(*w, hi->name);
1694 nextword(w);
1695 hi = hi->next;
1696 }
1697 }
1698}
1699
Mike Frysinger10a11e22005-09-27 02:23:02 +00001700static int hashwalk_next(var *v)
1701{
Glenn L McGrath545106f2002-11-11 06:21:00 +00001702 char **w;
1703
1704 w = v->x.walker;
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001705 if (w[1] == w[0])
Glenn L McGrath545106f2002-11-11 06:21:00 +00001706 return FALSE;
1707
1708 setvar_s(v, nextword(w+1));
1709 return TRUE;
1710}
1711
1712/* evaluate node, return 1 when result is true, 0 otherwise */
Mike Frysinger10a11e22005-09-27 02:23:02 +00001713static int ptest(node *pattern)
1714{
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00001715 /* ptest__v is "static": to save stack space? */
1716 return istrue(evaluate(pattern, &G.ptest__v));
Glenn L McGrath545106f2002-11-11 06:21:00 +00001717}
1718
1719/* read next record from stream rsm into a variable v */
Mike Frysinger10a11e22005-09-27 02:23:02 +00001720static int awk_getline(rstream *rsm, var *v)
1721{
Glenn L McGrath545106f2002-11-11 06:21:00 +00001722 char *b;
1723 regmatch_t pmatch[2];
Glenn L McGrath00ed36f2003-10-30 13:36:39 +00001724 int a, p, pp=0, size;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001725 int fd, so, eo, r, rp;
Glenn L McGrath00ed36f2003-10-30 13:36:39 +00001726 char c, *m, *s;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001727
1728 /* we're using our own buffer since we need access to accumulating
1729 * characters
1730 */
1731 fd = fileno(rsm->F);
Glenn L McGrath00ed36f2003-10-30 13:36:39 +00001732 m = rsm->buffer;
1733 a = rsm->adv;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001734 p = rsm->pos;
1735 size = rsm->size;
1736 c = (char) rsplitter.n.info;
1737 rp = 0;
Glenn L McGrath00ed36f2003-10-30 13:36:39 +00001738
Denis Vlasenkob78c7822007-07-18 18:31:11 +00001739 if (!m) qrealloc(&m, 256, &size);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001740 do {
Glenn L McGrath00ed36f2003-10-30 13:36:39 +00001741 b = m + a;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001742 so = eo = p;
1743 r = 1;
1744 if (p > 0) {
1745 if ((rsplitter.n.info & OPCLSMASK) == OC_REGEXP) {
1746 if (regexec(icase ? rsplitter.n.r.ire : rsplitter.n.l.re,
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001747 b, 1, pmatch, 0) == 0) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00001748 so = pmatch[0].rm_so;
1749 eo = pmatch[0].rm_eo;
1750 if (b[eo] != '\0')
1751 break;
1752 }
1753 } else if (c != '\0') {
1754 s = strchr(b+pp, c);
Denis Vlasenkob78c7822007-07-18 18:31:11 +00001755 if (!s) s = memchr(b+pp, '\0', p - pp);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001756 if (s) {
1757 so = eo = s-b;
1758 eo++;
1759 break;
1760 }
1761 } else {
1762 while (b[rp] == '\n')
1763 rp++;
1764 s = strstr(b+rp, "\n\n");
1765 if (s) {
1766 so = eo = s-b;
1767 while (b[eo] == '\n') eo++;
1768 if (b[eo] != '\0')
1769 break;
1770 }
1771 }
1772 }
1773
Glenn L McGrath00ed36f2003-10-30 13:36:39 +00001774 if (a > 0) {
1775 memmove(m, (const void *)(m+a), p+1);
1776 b = m;
1777 a = 0;
1778 }
1779
1780 qrealloc(&m, a+p+128, &size);
1781 b = m + a;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001782 pp = p;
1783 p += safe_read(fd, b+p, size-p-1);
1784 if (p < pp) {
1785 p = 0;
1786 r = 0;
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001787 setvar_i(intvar[ERRNO], errno);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001788 }
1789 b[p] = '\0';
1790
1791 } while (p > pp);
1792
1793 if (p == 0) {
1794 r--;
1795 } else {
1796 c = b[so]; b[so] = '\0';
1797 setvar_s(v, b+rp);
1798 v->type |= VF_USER;
1799 b[so] = c;
1800 c = b[eo]; b[eo] = '\0';
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001801 setvar_s(intvar[RT], b+so);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001802 b[eo] = c;
1803 }
1804
Glenn L McGrath00ed36f2003-10-30 13:36:39 +00001805 rsm->buffer = m;
1806 rsm->adv = a + eo;
1807 rsm->pos = p - eo;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001808 rsm->size = size;
1809
1810 return r;
1811}
1812
"Vladimir N. Oleynik"5cf9a032005-10-19 09:21:51 +00001813static int fmt_num(char *b, int size, const char *format, double n, int int_as_int)
Mike Frysinger10a11e22005-09-27 02:23:02 +00001814{
Denis Vlasenkof782f522007-01-01 23:51:30 +00001815 int r = 0;
"Vladimir N. Oleynik"5cf9a032005-10-19 09:21:51 +00001816 char c;
Denis Vlasenkof782f522007-01-01 23:51:30 +00001817 const char *s = format;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001818
1819 if (int_as_int && n == (int)n) {
1820 r = snprintf(b, size, "%d", (int)n);
1821 } else {
Denis Vlasenkof782f522007-01-01 23:51:30 +00001822 do { c = *s; } while (c && *++s);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001823 if (strchr("diouxX", c)) {
1824 r = snprintf(b, size, format, (int)n);
1825 } else if (strchr("eEfgG", c)) {
1826 r = snprintf(b, size, format, n);
1827 } else {
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00001828 syntax_error(EMSG_INV_FMT);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001829 }
1830 }
1831 return r;
1832}
1833
1834
1835/* formatted output into an allocated buffer, return ptr to buffer */
Mike Frysinger10a11e22005-09-27 02:23:02 +00001836static char *awk_printf(node *n)
1837{
Glenn L McGrath545106f2002-11-11 06:21:00 +00001838 char *b = NULL;
Denis Vlasenkoa41fdf32007-01-29 22:51:00 +00001839 char *fmt, *s, *f;
1840 const char *s1;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001841 int i, j, incr, bsize;
1842 char c, c1;
1843 var *v, *arg;
1844
1845 v = nvalloc(1);
Rob Landleyd921b2e2006-08-03 15:41:12 +00001846 fmt = f = xstrdup(getvar_s(evaluate(nextarg(&n), v)));
Glenn L McGrath545106f2002-11-11 06:21:00 +00001847
1848 i = 0;
1849 while (*f) {
1850 s = f;
1851 while (*f && (*f != '%' || *(++f) == '%'))
1852 f++;
Denis Vlasenko389f9d52007-05-09 21:57:23 +00001853 while (*f && !isalpha(*f)) {
1854 if (*f == '*')
1855 syntax_error("%*x formats are not supported");
Glenn L McGrath545106f2002-11-11 06:21:00 +00001856 f++;
Denis Vlasenko389f9d52007-05-09 21:57:23 +00001857 }
Glenn L McGrath545106f2002-11-11 06:21:00 +00001858
1859 incr = (f - s) + MAXVARFMT;
Denis Vlasenkof782f522007-01-01 23:51:30 +00001860 qrealloc(&b, incr + i, &bsize);
1861 c = *f;
1862 if (c != '\0') f++;
1863 c1 = *f;
1864 *f = '\0';
Glenn L McGrath545106f2002-11-11 06:21:00 +00001865 arg = evaluate(nextarg(&n), v);
1866
1867 j = i;
1868 if (c == 'c' || !c) {
Denis Vlasenkof782f522007-01-01 23:51:30 +00001869 i += sprintf(b+i, s, is_numeric(arg) ?
1870 (char)getvar_i(arg) : *getvar_s(arg));
Glenn L McGrath545106f2002-11-11 06:21:00 +00001871 } else if (c == 's') {
Denis Vlasenko92758142006-10-03 19:56:34 +00001872 s1 = getvar_s(arg);
Rob Landleya3896512006-05-07 20:20:34 +00001873 qrealloc(&b, incr+i+strlen(s1), &bsize);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001874 i += sprintf(b+i, s, s1);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001875 } else {
1876 i += fmt_num(b+i, incr, s, getvar_i(arg), FALSE);
1877 }
1878 *f = c1;
1879
1880 /* if there was an error while sprintf, return value is negative */
1881 if (i < j) i = j;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001882 }
1883
Denis Vlasenkof782f522007-01-01 23:51:30 +00001884 b = xrealloc(b, i + 1);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001885 free(fmt);
1886 nvfree(v);
1887 b[i] = '\0';
1888 return b;
1889}
1890
1891/* common substitution routine
1892 * replace (nm) substring of (src) that match (n) with (repl), store
1893 * result into (dest), return number of substitutions. If nm=0, replace
1894 * all matches. If src or dst is NULL, use $0. If ex=TRUE, enable
1895 * subexpression matching (\1-\9)
1896 */
Denis Vlasenkoa41fdf32007-01-29 22:51:00 +00001897static int awk_sub(node *rn, const char *repl, int nm, var *src, var *dest, int ex)
Mike Frysinger10a11e22005-09-27 02:23:02 +00001898{
Glenn L McGrath545106f2002-11-11 06:21:00 +00001899 char *ds = NULL;
Denis Vlasenkoa41fdf32007-01-29 22:51:00 +00001900 const char *s;
1901 const char *sp;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001902 int c, i, j, di, rl, so, eo, nbs, n, dssize;
1903 regmatch_t pmatch[10];
1904 regex_t sreg, *re;
1905
1906 re = as_regex(rn, &sreg);
Denis Vlasenkob78c7822007-07-18 18:31:11 +00001907 if (!src) src = intvar[F0];
1908 if (!dest) dest = intvar[F0];
Glenn L McGrath545106f2002-11-11 06:21:00 +00001909
1910 i = di = 0;
1911 sp = getvar_s(src);
Rob Landleya3896512006-05-07 20:20:34 +00001912 rl = strlen(repl);
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001913 while (regexec(re, sp, 10, pmatch, sp==getvar_s(src) ? 0 : REG_NOTBOL) == 0) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00001914 so = pmatch[0].rm_so;
1915 eo = pmatch[0].rm_eo;
1916
1917 qrealloc(&ds, di + eo + rl, &dssize);
1918 memcpy(ds + di, sp, eo);
1919 di += eo;
1920 if (++i >= nm) {
1921 /* replace */
1922 di -= (eo - so);
1923 nbs = 0;
1924 for (s = repl; *s; s++) {
1925 ds[di++] = c = *s;
1926 if (c == '\\') {
1927 nbs++;
1928 continue;
1929 }
1930 if (c == '&' || (ex && c >= '0' && c <= '9')) {
1931 di -= ((nbs + 3) >> 1);
1932 j = 0;
1933 if (c != '&') {
1934 j = c - '0';
1935 nbs++;
1936 }
1937 if (nbs % 2) {
1938 ds[di++] = c;
1939 } else {
1940 n = pmatch[j].rm_eo - pmatch[j].rm_so;
1941 qrealloc(&ds, di + rl + n, &dssize);
1942 memcpy(ds + di, sp + pmatch[j].rm_so, n);
1943 di += n;
1944 }
1945 }
1946 nbs = 0;
1947 }
1948 }
1949
1950 sp += eo;
1951 if (i == nm) break;
1952 if (eo == so) {
Denis Vlasenkob78c7822007-07-18 18:31:11 +00001953 ds[di] = *sp++;
1954 if (!ds[di++]) break;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001955 }
1956 }
1957
1958 qrealloc(&ds, di + strlen(sp), &dssize);
1959 strcpy(ds + di, sp);
1960 setvar_p(dest, ds);
1961 if (re == &sreg) regfree(re);
1962 return i;
1963}
1964
Mike Frysinger10a11e22005-09-27 02:23:02 +00001965static var *exec_builtin(node *op, var *res)
1966{
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00001967#define tspl (G.exec_builtin__tspl)
1968
Glenn L McGrath545106f2002-11-11 06:21:00 +00001969 int (*to_xxx)(int);
1970 var *tv;
1971 node *an[4];
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001972 var *av[4];
Denis Vlasenkoa41fdf32007-01-29 22:51:00 +00001973 const char *as[4];
Glenn L McGrath545106f2002-11-11 06:21:00 +00001974 regmatch_t pmatch[2];
1975 regex_t sreg, *re;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001976 node *spl;
Mike Frysingerf87b3e32005-09-27 04:16:22 +00001977 uint32_t isr, info;
Glenn L McGrath545106f2002-11-11 06:21:00 +00001978 int nargs;
1979 time_t tt;
1980 char *s, *s1;
1981 int i, l, ll, n;
1982
1983 tv = nvalloc(4);
1984 isr = info = op->info;
1985 op = op->l.n;
1986
1987 av[2] = av[3] = NULL;
Denis Vlasenkoffba9412007-05-17 23:03:35 +00001988 for (i = 0; i < 4 && op; i++) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00001989 an[i] = nextarg(&op);
1990 if (isr & 0x09000000) av[i] = evaluate(an[i], &tv[i]);
1991 if (isr & 0x08000000) as[i] = getvar_s(av[i]);
1992 isr >>= 1;
1993 }
1994
1995 nargs = i;
Denis Vlasenko77ad97f2008-05-13 02:27:31 +00001996 if ((uint32_t)nargs < (info >> 30))
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00001997 syntax_error(EMSG_TOO_FEW_ARGS);
Glenn L McGrath545106f2002-11-11 06:21:00 +00001998
1999 switch (info & OPNMASK) {
2000
Denis Vlasenkof782f522007-01-01 23:51:30 +00002001 case B_a2:
2002#if ENABLE_FEATURE_AWK_MATH
Glenn L McGrath545106f2002-11-11 06:21:00 +00002003 setvar_i(res, atan2(getvar_i(av[i]), getvar_i(av[1])));
2004#else
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002005 syntax_error(EMSG_NO_MATH);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002006#endif
2007 break;
2008
Denis Vlasenkof782f522007-01-01 23:51:30 +00002009 case B_sp:
Glenn L McGrath545106f2002-11-11 06:21:00 +00002010 if (nargs > 2) {
2011 spl = (an[2]->info & OPCLSMASK) == OC_REGEXP ?
2012 an[2] : mk_splitter(getvar_s(evaluate(an[2], &tv[2])), &tspl);
2013 } else {
2014 spl = &fsplitter.n;
2015 }
2016
2017 n = awk_split(as[0], spl, &s);
2018 s1 = s;
2019 clear_array(iamarray(av[1]));
2020 for (i=1; i<=n; i++)
2021 setari_u(av[1], i, nextword(&s1));
2022 free(s);
2023 setvar_i(res, n);
2024 break;
2025
Denis Vlasenkof782f522007-01-01 23:51:30 +00002026 case B_ss:
Rob Landleya3896512006-05-07 20:20:34 +00002027 l = strlen(as[0]);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002028 i = getvar_i(av[1]) - 1;
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002029 if (i > l) i = l;
2030 if (i < 0) i = 0;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002031 n = (nargs > 2) ? getvar_i(av[2]) : l-i;
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002032 if (n < 0) n = 0;
Denis Vlasenko8ae5b282008-07-02 22:47:49 +00002033 s = xstrndup(as[0]+i, n);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002034 setvar_p(res, s);
2035 break;
Denis Vlasenkof7996f32007-01-11 17:20:00 +00002036
Denis Vlasenkof782f522007-01-01 23:51:30 +00002037 case B_an:
Denis Vlasenkoe175ff22006-09-26 17:41:00 +00002038 setvar_i(res, (long)getvar_i(av[0]) & (long)getvar_i(av[1]));
2039 break;
Denis Vlasenkof7996f32007-01-11 17:20:00 +00002040
Denis Vlasenkof782f522007-01-01 23:51:30 +00002041 case B_co:
Denis Vlasenkoe175ff22006-09-26 17:41:00 +00002042 setvar_i(res, ~(long)getvar_i(av[0]));
2043 break;
2044
Denis Vlasenkof782f522007-01-01 23:51:30 +00002045 case B_ls:
Denis Vlasenkoe175ff22006-09-26 17:41:00 +00002046 setvar_i(res, (long)getvar_i(av[0]) << (long)getvar_i(av[1]));
2047 break;
2048
Denis Vlasenkof782f522007-01-01 23:51:30 +00002049 case B_or:
Denis Vlasenkoe175ff22006-09-26 17:41:00 +00002050 setvar_i(res, (long)getvar_i(av[0]) | (long)getvar_i(av[1]));
2051 break;
2052
Denis Vlasenkof782f522007-01-01 23:51:30 +00002053 case B_rs:
Denis Vlasenkoe175ff22006-09-26 17:41:00 +00002054 setvar_i(res, (long)((unsigned long)getvar_i(av[0]) >> (unsigned long)getvar_i(av[1])));
2055 break;
2056
Denis Vlasenkof782f522007-01-01 23:51:30 +00002057 case B_xo:
Denis Vlasenkoe175ff22006-09-26 17:41:00 +00002058 setvar_i(res, (long)getvar_i(av[0]) ^ (long)getvar_i(av[1]));
2059 break;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002060
Denis Vlasenkof782f522007-01-01 23:51:30 +00002061 case B_lo:
Glenn L McGrath545106f2002-11-11 06:21:00 +00002062 to_xxx = tolower;
2063 goto lo_cont;
2064
Denis Vlasenkof782f522007-01-01 23:51:30 +00002065 case B_up:
Glenn L McGrath545106f2002-11-11 06:21:00 +00002066 to_xxx = toupper;
Denis Vlasenkoe1d3e032007-01-01 23:53:52 +00002067 lo_cont:
Rob Landleyd921b2e2006-08-03 15:41:12 +00002068 s1 = s = xstrdup(as[0]);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002069 while (*s1) {
2070 *s1 = (*to_xxx)(*s1);
2071 s1++;
2072 }
2073 setvar_p(res, s);
2074 break;
2075
Denis Vlasenkof782f522007-01-01 23:51:30 +00002076 case B_ix:
Glenn L McGrath545106f2002-11-11 06:21:00 +00002077 n = 0;
Rob Landleya3896512006-05-07 20:20:34 +00002078 ll = strlen(as[1]);
2079 l = strlen(as[0]) - ll;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002080 if (ll > 0 && l >= 0) {
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002081 if (!icase) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00002082 s = strstr(as[0], as[1]);
2083 if (s) n = (s - as[0]) + 1;
2084 } else {
2085 /* this piece of code is terribly slow and
2086 * really should be rewritten
2087 */
2088 for (i=0; i<=l; i++) {
2089 if (strncasecmp(as[0]+i, as[1], ll) == 0) {
2090 n = i+1;
2091 break;
2092 }
2093 }
2094 }
2095 }
2096 setvar_i(res, n);
2097 break;
2098
Denis Vlasenkof782f522007-01-01 23:51:30 +00002099 case B_ti:
Glenn L McGrath545106f2002-11-11 06:21:00 +00002100 if (nargs > 1)
2101 tt = getvar_i(av[1]);
2102 else
2103 time(&tt);
Denis Vlasenkoa41fdf32007-01-29 22:51:00 +00002104 //s = (nargs > 0) ? as[0] : "%a %b %d %H:%M:%S %Z %Y";
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002105 i = strftime(g_buf, MAXVARFMT,
Denis Vlasenkoa41fdf32007-01-29 22:51:00 +00002106 ((nargs > 0) ? as[0] : "%a %b %d %H:%M:%S %Z %Y"),
2107 localtime(&tt));
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002108 g_buf[i] = '\0';
2109 setvar_s(res, g_buf);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002110 break;
2111
Denis Vlasenkof782f522007-01-01 23:51:30 +00002112 case B_ma:
Glenn L McGrath545106f2002-11-11 06:21:00 +00002113 re = as_regex(an[1], &sreg);
2114 n = regexec(re, as[0], 1, pmatch, 0);
2115 if (n == 0) {
2116 pmatch[0].rm_so++;
2117 pmatch[0].rm_eo++;
2118 } else {
2119 pmatch[0].rm_so = 0;
2120 pmatch[0].rm_eo = -1;
2121 }
2122 setvar_i(newvar("RSTART"), pmatch[0].rm_so);
2123 setvar_i(newvar("RLENGTH"), pmatch[0].rm_eo - pmatch[0].rm_so);
2124 setvar_i(res, pmatch[0].rm_so);
2125 if (re == &sreg) regfree(re);
2126 break;
2127
Denis Vlasenkof782f522007-01-01 23:51:30 +00002128 case B_ge:
Glenn L McGrath545106f2002-11-11 06:21:00 +00002129 awk_sub(an[0], as[1], getvar_i(av[2]), av[3], res, TRUE);
2130 break;
2131
Denis Vlasenkof782f522007-01-01 23:51:30 +00002132 case B_gs:
Glenn L McGrath545106f2002-11-11 06:21:00 +00002133 setvar_i(res, awk_sub(an[0], as[1], 0, av[2], av[2], FALSE));
2134 break;
2135
Denis Vlasenkof782f522007-01-01 23:51:30 +00002136 case B_su:
Glenn L McGrath545106f2002-11-11 06:21:00 +00002137 setvar_i(res, awk_sub(an[0], as[1], 1, av[2], av[2], FALSE));
2138 break;
2139 }
2140
2141 nvfree(tv);
2142 return res;
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002143#undef tspl
Glenn L McGrath545106f2002-11-11 06:21:00 +00002144}
2145
2146/*
2147 * Evaluate node - the heart of the program. Supplied with subtree
2148 * and place where to store result. returns ptr to result.
2149 */
2150#define XC(n) ((n) >> 8)
2151
Mike Frysinger10a11e22005-09-27 02:23:02 +00002152static var *evaluate(node *op, var *res)
2153{
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002154/* This procedure is recursive so we should count every byte */
2155#define fnargs (G.evaluate__fnargs)
2156/* seed is initialized to 1 */
2157#define seed (G.evaluate__seed)
2158#define sreg (G.evaluate__sreg)
Denis Vlasenkoe1d3e032007-01-01 23:53:52 +00002159
Glenn L McGrath545106f2002-11-11 06:21:00 +00002160 node *op1;
2161 var *v1;
2162 union {
2163 var *v;
Denis Vlasenkoa41fdf32007-01-29 22:51:00 +00002164 const char *s;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002165 double d;
2166 int i;
2167 } L, R;
Mike Frysingerf87b3e32005-09-27 04:16:22 +00002168 uint32_t opinfo;
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002169 int opn;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002170 union {
2171 char *s;
2172 rstream *rsm;
2173 FILE *F;
2174 var *v;
2175 regex_t *re;
Mike Frysingerf87b3e32005-09-27 04:16:22 +00002176 uint32_t info;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002177 } X;
2178
Denis Vlasenkoe1d3e032007-01-01 23:53:52 +00002179 if (!op)
Glenn L McGrath545106f2002-11-11 06:21:00 +00002180 return setvar_s(res, NULL);
2181
2182 v1 = nvalloc(2);
2183
2184 while (op) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00002185 opinfo = op->info;
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002186 opn = (opinfo & OPNMASK);
2187 g_lineno = op->lineno;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002188
Mike Frysingerde2b9382005-09-27 03:18:00 +00002189 /* execute inevitable things */
Glenn L McGrath545106f2002-11-11 06:21:00 +00002190 op1 = op->l.n;
2191 if (opinfo & OF_RES1) X.v = L.v = evaluate(op1, v1);
2192 if (opinfo & OF_RES2) R.v = evaluate(op->r.n, v1+1);
2193 if (opinfo & OF_STR1) L.s = getvar_s(L.v);
2194 if (opinfo & OF_STR2) R.s = getvar_s(R.v);
2195 if (opinfo & OF_NUM1) L.d = getvar_i(L.v);
2196
2197 switch (XC(opinfo & OPCLSMASK)) {
2198
Denis Vlasenkocd5c7862007-05-17 16:37:22 +00002199 /* -- iterative node type -- */
Glenn L McGrath545106f2002-11-11 06:21:00 +00002200
Denis Vlasenkocd5c7862007-05-17 16:37:22 +00002201 /* test pattern */
Denis Vlasenkof782f522007-01-01 23:51:30 +00002202 case XC( OC_TEST ):
Glenn L McGrath545106f2002-11-11 06:21:00 +00002203 if ((op1->info & OPCLSMASK) == OC_COMMA) {
2204 /* it's range pattern */
2205 if ((opinfo & OF_CHECKED) || ptest(op1->l.n)) {
2206 op->info |= OF_CHECKED;
2207 if (ptest(op1->r.n))
2208 op->info &= ~OF_CHECKED;
2209
2210 op = op->a.n;
2211 } else {
2212 op = op->r.n;
2213 }
2214 } else {
2215 op = (ptest(op1)) ? op->a.n : op->r.n;
2216 }
2217 break;
2218
Denis Vlasenkocd5c7862007-05-17 16:37:22 +00002219 /* just evaluate an expression, also used as unconditional jump */
Denis Vlasenkof782f522007-01-01 23:51:30 +00002220 case XC( OC_EXEC ):
Mike Frysingerde2b9382005-09-27 03:18:00 +00002221 break;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002222
Denis Vlasenkocd5c7862007-05-17 16:37:22 +00002223 /* branch, used in if-else and various loops */
Denis Vlasenkof782f522007-01-01 23:51:30 +00002224 case XC( OC_BR ):
Mike Frysingerde2b9382005-09-27 03:18:00 +00002225 op = istrue(L.v) ? op->a.n : op->r.n;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002226 break;
2227
Denis Vlasenkocd5c7862007-05-17 16:37:22 +00002228 /* initialize for-in loop */
Denis Vlasenkof782f522007-01-01 23:51:30 +00002229 case XC( OC_WALKINIT ):
Mike Frysingerde2b9382005-09-27 03:18:00 +00002230 hashwalk_init(L.v, iamarray(R.v));
Glenn L McGrath545106f2002-11-11 06:21:00 +00002231 break;
2232
Denis Vlasenkocd5c7862007-05-17 16:37:22 +00002233 /* get next array item */
Denis Vlasenkof782f522007-01-01 23:51:30 +00002234 case XC( OC_WALKNEXT ):
Glenn L McGrath545106f2002-11-11 06:21:00 +00002235 op = hashwalk_next(L.v) ? op->a.n : op->r.n;
2236 break;
2237
Denis Vlasenkof782f522007-01-01 23:51:30 +00002238 case XC( OC_PRINT ):
2239 case XC( OC_PRINTF ):
Glenn L McGrath545106f2002-11-11 06:21:00 +00002240 X.F = stdout;
Mike Frysingerde2b9382005-09-27 03:18:00 +00002241 if (op->r.n) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00002242 X.rsm = newfile(R.s);
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002243 if (!X.rsm->F) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00002244 if (opn == '|') {
Denis Vlasenko51742f42007-04-12 00:32:05 +00002245 X.rsm->F = popen(R.s, "w");
2246 if (X.rsm->F == NULL)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002247 bb_perror_msg_and_die("popen");
Glenn L McGrath545106f2002-11-11 06:21:00 +00002248 X.rsm->is_pipe = 1;
2249 } else {
Rob Landleyd921b2e2006-08-03 15:41:12 +00002250 X.rsm->F = xfopen(R.s, opn=='w' ? "w" : "a");
Glenn L McGrath545106f2002-11-11 06:21:00 +00002251 }
2252 }
2253 X.F = X.rsm->F;
2254 }
2255
2256 if ((opinfo & OPCLSMASK) == OC_PRINT) {
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002257 if (!op1) {
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002258 fputs(getvar_s(intvar[F0]), X.F);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002259 } else {
2260 while (op1) {
2261 L.v = evaluate(nextarg(&op1), v1);
2262 if (L.v->type & VF_NUMBER) {
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002263 fmt_num(g_buf, MAXVARFMT, getvar_s(intvar[OFMT]),
Denis Vlasenkob54b2082006-10-27 09:05:40 +00002264 getvar_i(L.v), TRUE);
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002265 fputs(g_buf, X.F);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002266 } else {
2267 fputs(getvar_s(L.v), X.F);
2268 }
2269
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002270 if (op1) fputs(getvar_s(intvar[OFS]), X.F);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002271 }
2272 }
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002273 fputs(getvar_s(intvar[ORS]), X.F);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002274
2275 } else { /* OC_PRINTF */
2276 L.s = awk_printf(op1);
2277 fputs(L.s, X.F);
Denis Vlasenkoa41fdf32007-01-29 22:51:00 +00002278 free((char*)L.s);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002279 }
2280 fflush(X.F);
2281 break;
2282
Denis Vlasenkof782f522007-01-01 23:51:30 +00002283 case XC( OC_DELETE ):
Mike Frysingerde2b9382005-09-27 03:18:00 +00002284 X.info = op1->info & OPCLSMASK;
2285 if (X.info == OC_VAR) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00002286 R.v = op1->l.v;
2287 } else if (X.info == OC_FNARG) {
2288 R.v = &fnargs[op1->l.i];
2289 } else {
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002290 syntax_error(EMSG_NOT_ARRAY);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002291 }
2292
Mike Frysingerde2b9382005-09-27 03:18:00 +00002293 if (op1->r.n) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00002294 clrvar(L.v);
2295 L.s = getvar_s(evaluate(op1->r.n, v1));
2296 hash_remove(iamarray(R.v), L.s);
2297 } else {
2298 clear_array(iamarray(R.v));
2299 }
2300 break;
2301
Denis Vlasenkof782f522007-01-01 23:51:30 +00002302 case XC( OC_NEWSOURCE ):
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002303 g_progname = op->l.s;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002304 break;
2305
Denis Vlasenkof782f522007-01-01 23:51:30 +00002306 case XC( OC_RETURN ):
Glenn L McGrath545106f2002-11-11 06:21:00 +00002307 copyvar(res, L.v);
2308 break;
2309
Denis Vlasenkof782f522007-01-01 23:51:30 +00002310 case XC( OC_NEXTFILE ):
Mike Frysingerde2b9382005-09-27 03:18:00 +00002311 nextfile = TRUE;
Denis Vlasenkof782f522007-01-01 23:51:30 +00002312 case XC( OC_NEXT ):
Mike Frysingerde2b9382005-09-27 03:18:00 +00002313 nextrec = TRUE;
Denis Vlasenkof782f522007-01-01 23:51:30 +00002314 case XC( OC_DONE ):
Glenn L McGrath545106f2002-11-11 06:21:00 +00002315 clrvar(res);
2316 break;
2317
Denis Vlasenkof782f522007-01-01 23:51:30 +00002318 case XC( OC_EXIT ):
Mike Frysingerde2b9382005-09-27 03:18:00 +00002319 awk_exit(L.d);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002320
Denis Vlasenkocd5c7862007-05-17 16:37:22 +00002321 /* -- recursive node type -- */
Glenn L McGrath545106f2002-11-11 06:21:00 +00002322
Denis Vlasenkof782f522007-01-01 23:51:30 +00002323 case XC( OC_VAR ):
Mike Frysingerde2b9382005-09-27 03:18:00 +00002324 L.v = op->l.v;
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002325 if (L.v == intvar[NF])
Glenn L McGrath545106f2002-11-11 06:21:00 +00002326 split_f0();
2327 goto v_cont;
2328
Denis Vlasenkof782f522007-01-01 23:51:30 +00002329 case XC( OC_FNARG ):
Mike Frysingerde2b9382005-09-27 03:18:00 +00002330 L.v = &fnargs[op->l.i];
Denis Vlasenkoe1d3e032007-01-01 23:53:52 +00002331 v_cont:
2332 res = op->r.n ? findvar(iamarray(L.v), R.s) : L.v;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002333 break;
2334
Denis Vlasenkof782f522007-01-01 23:51:30 +00002335 case XC( OC_IN ):
Glenn L McGrath545106f2002-11-11 06:21:00 +00002336 setvar_i(res, hash_search(iamarray(R.v), L.s) ? 1 : 0);
2337 break;
2338
Denis Vlasenkof782f522007-01-01 23:51:30 +00002339 case XC( OC_REGEXP ):
Mike Frysingerde2b9382005-09-27 03:18:00 +00002340 op1 = op;
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002341 L.s = getvar_s(intvar[F0]);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002342 goto re_cont;
2343
Denis Vlasenkof782f522007-01-01 23:51:30 +00002344 case XC( OC_MATCH ):
Mike Frysingerde2b9382005-09-27 03:18:00 +00002345 op1 = op->r.n;
Denis Vlasenkoe1d3e032007-01-01 23:53:52 +00002346 re_cont:
Glenn L McGrath545106f2002-11-11 06:21:00 +00002347 X.re = as_regex(op1, &sreg);
2348 R.i = regexec(X.re, L.s, 0, NULL, 0);
2349 if (X.re == &sreg) regfree(X.re);
2350 setvar_i(res, (R.i == 0 ? 1 : 0) ^ (opn == '!' ? 1 : 0));
2351 break;
2352
Denis Vlasenkof782f522007-01-01 23:51:30 +00002353 case XC( OC_MOVE ):
Mike Frysingerde2b9382005-09-27 03:18:00 +00002354 /* if source is a temporary string, jusk relink it to dest */
Glenn L McGrath545106f2002-11-11 06:21:00 +00002355 if (R.v == v1+1 && R.v->string) {
2356 res = setvar_p(L.v, R.v->string);
2357 R.v->string = NULL;
2358 } else {
Mike Frysingerde2b9382005-09-27 03:18:00 +00002359 res = copyvar(L.v, R.v);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002360 }
2361 break;
2362
Denis Vlasenkof782f522007-01-01 23:51:30 +00002363 case XC( OC_TERNARY ):
Mike Frysingerde2b9382005-09-27 03:18:00 +00002364 if ((op->r.n->info & OPCLSMASK) != OC_COLON)
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002365 syntax_error(EMSG_POSSIBLE_ERROR);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002366 res = evaluate(istrue(L.v) ? op->r.n->l.n : op->r.n->r.n, res);
2367 break;
2368
Denis Vlasenkof782f522007-01-01 23:51:30 +00002369 case XC( OC_FUNC ):
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002370 if (!op->r.f->body.first)
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002371 syntax_error(EMSG_UNDEF_FUNC);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002372
2373 X.v = R.v = nvalloc(op->r.f->nargs+1);
2374 while (op1) {
2375 L.v = evaluate(nextarg(&op1), v1);
2376 copyvar(R.v, L.v);
2377 R.v->type |= VF_CHILD;
2378 R.v->x.parent = L.v;
2379 if (++R.v - X.v >= op->r.f->nargs)
2380 break;
2381 }
2382
2383 R.v = fnargs;
2384 fnargs = X.v;
2385
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002386 L.s = g_progname;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002387 res = evaluate(op->r.f->body.first, res);
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002388 g_progname = L.s;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002389
2390 nvfree(fnargs);
2391 fnargs = R.v;
2392 break;
2393
Denis Vlasenkof782f522007-01-01 23:51:30 +00002394 case XC( OC_GETLINE ):
2395 case XC( OC_PGETLINE ):
Mike Frysingerde2b9382005-09-27 03:18:00 +00002396 if (op1) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00002397 X.rsm = newfile(L.s);
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002398 if (!X.rsm->F) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00002399 if ((opinfo & OPCLSMASK) == OC_PGETLINE) {
2400 X.rsm->F = popen(L.s, "r");
2401 X.rsm->is_pipe = TRUE;
2402 } else {
Denis Vlasenko5415c852008-07-21 23:05:26 +00002403 X.rsm->F = fopen_for_read(L.s); /* not xfopen! */
Glenn L McGrath545106f2002-11-11 06:21:00 +00002404 }
2405 }
2406 } else {
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002407 if (!iF) iF = next_input_file();
Glenn L McGrath545106f2002-11-11 06:21:00 +00002408 X.rsm = iF;
2409 }
2410
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002411 if (!X.rsm->F) {
2412 setvar_i(intvar[ERRNO], errno);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002413 setvar_i(res, -1);
2414 break;
2415 }
2416
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002417 if (!op->r.n)
2418 R.v = intvar[F0];
Glenn L McGrath545106f2002-11-11 06:21:00 +00002419
2420 L.i = awk_getline(X.rsm, R.v);
2421 if (L.i > 0) {
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002422 if (!op1) {
2423 incvar(intvar[FNR]);
2424 incvar(intvar[NR]);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002425 }
2426 }
2427 setvar_i(res, L.i);
2428 break;
2429
Denis Vlasenkocd5c7862007-05-17 16:37:22 +00002430 /* simple builtins */
Denis Vlasenkof782f522007-01-01 23:51:30 +00002431 case XC( OC_FBLTIN ):
Mike Frysingerde2b9382005-09-27 03:18:00 +00002432 switch (opn) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00002433
Denis Vlasenkof782f522007-01-01 23:51:30 +00002434 case F_in:
Mike Frysingerde2b9382005-09-27 03:18:00 +00002435 R.d = (int)L.d;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002436 break;
2437
Denis Vlasenkof782f522007-01-01 23:51:30 +00002438 case F_rn:
2439 R.d = (double)rand() / (double)RAND_MAX;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002440 break;
Denis Vlasenkof782f522007-01-01 23:51:30 +00002441#if ENABLE_FEATURE_AWK_MATH
2442 case F_co:
Mike Frysingerde2b9382005-09-27 03:18:00 +00002443 R.d = cos(L.d);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002444 break;
2445
Denis Vlasenkof782f522007-01-01 23:51:30 +00002446 case F_ex:
Mike Frysingerde2b9382005-09-27 03:18:00 +00002447 R.d = exp(L.d);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002448 break;
2449
Denis Vlasenkof782f522007-01-01 23:51:30 +00002450 case F_lg:
Mike Frysingerde2b9382005-09-27 03:18:00 +00002451 R.d = log(L.d);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002452 break;
2453
Denis Vlasenkof782f522007-01-01 23:51:30 +00002454 case F_si:
Mike Frysingerde2b9382005-09-27 03:18:00 +00002455 R.d = sin(L.d);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002456 break;
2457
Denis Vlasenkof782f522007-01-01 23:51:30 +00002458 case F_sq:
Mike Frysingerde2b9382005-09-27 03:18:00 +00002459 R.d = sqrt(L.d);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002460 break;
2461#else
Denis Vlasenkof782f522007-01-01 23:51:30 +00002462 case F_co:
2463 case F_ex:
2464 case F_lg:
2465 case F_si:
2466 case F_sq:
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002467 syntax_error(EMSG_NO_MATH);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002468 break;
2469#endif
Denis Vlasenkof782f522007-01-01 23:51:30 +00002470 case F_sr:
Glenn L McGrath545106f2002-11-11 06:21:00 +00002471 R.d = (double)seed;
Denis Vlasenkof782f522007-01-01 23:51:30 +00002472 seed = op1 ? (unsigned)L.d : (unsigned)time(NULL);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002473 srand(seed);
2474 break;
2475
Denis Vlasenkof782f522007-01-01 23:51:30 +00002476 case F_ti:
Glenn L McGrath545106f2002-11-11 06:21:00 +00002477 R.d = time(NULL);
2478 break;
2479
Denis Vlasenkof782f522007-01-01 23:51:30 +00002480 case F_le:
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002481 if (!op1)
2482 L.s = getvar_s(intvar[F0]);
Rob Landleya3896512006-05-07 20:20:34 +00002483 R.d = strlen(L.s);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002484 break;
2485
Denis Vlasenkof782f522007-01-01 23:51:30 +00002486 case F_sy:
Glenn L McGrath545106f2002-11-11 06:21:00 +00002487 fflush(NULL);
Denis Vlasenko249fabf2006-12-19 00:29:22 +00002488 R.d = (ENABLE_FEATURE_ALLOW_EXEC && L.s && *L.s)
2489 ? (system(L.s) >> 8) : 0;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002490 break;
2491
Denis Vlasenkof782f522007-01-01 23:51:30 +00002492 case F_ff:
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002493 if (!op1)
Glenn L McGrath545106f2002-11-11 06:21:00 +00002494 fflush(stdout);
2495 else {
2496 if (L.s && *L.s) {
2497 X.rsm = newfile(L.s);
2498 fflush(X.rsm->F);
2499 } else {
2500 fflush(NULL);
2501 }
2502 }
2503 break;
2504
Denis Vlasenkof782f522007-01-01 23:51:30 +00002505 case F_cl:
Glenn L McGrath545106f2002-11-11 06:21:00 +00002506 X.rsm = (rstream *)hash_search(fdhash, L.s);
2507 if (X.rsm) {
2508 R.i = X.rsm->is_pipe ? pclose(X.rsm->F) : fclose(X.rsm->F);
Aaron Lehmanna170e1c2002-11-28 11:27:31 +00002509 free(X.rsm->buffer);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002510 hash_remove(fdhash, L.s);
2511 }
2512 if (R.i != 0)
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002513 setvar_i(intvar[ERRNO], errno);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002514 R.d = (double)R.i;
2515 break;
2516 }
2517 setvar_i(res, R.d);
2518 break;
2519
Denis Vlasenkof782f522007-01-01 23:51:30 +00002520 case XC( OC_BUILTIN ):
Glenn L McGrath545106f2002-11-11 06:21:00 +00002521 res = exec_builtin(op, res);
2522 break;
2523
Denis Vlasenkof782f522007-01-01 23:51:30 +00002524 case XC( OC_SPRINTF ):
Mike Frysingerde2b9382005-09-27 03:18:00 +00002525 setvar_p(res, awk_printf(op1));
Glenn L McGrath545106f2002-11-11 06:21:00 +00002526 break;
2527
Denis Vlasenkof782f522007-01-01 23:51:30 +00002528 case XC( OC_UNARY ):
Mike Frysingerde2b9382005-09-27 03:18:00 +00002529 X.v = R.v;
2530 L.d = R.d = getvar_i(R.v);
2531 switch (opn) {
Denis Vlasenkof782f522007-01-01 23:51:30 +00002532 case 'P':
Mike Frysingerde2b9382005-09-27 03:18:00 +00002533 L.d = ++R.d;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002534 goto r_op_change;
Denis Vlasenkof782f522007-01-01 23:51:30 +00002535 case 'p':
Mike Frysingerde2b9382005-09-27 03:18:00 +00002536 R.d++;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002537 goto r_op_change;
Denis Vlasenkof782f522007-01-01 23:51:30 +00002538 case 'M':
Mike Frysingerde2b9382005-09-27 03:18:00 +00002539 L.d = --R.d;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002540 goto r_op_change;
Denis Vlasenkof782f522007-01-01 23:51:30 +00002541 case 'm':
Mike Frysingerde2b9382005-09-27 03:18:00 +00002542 R.d--;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002543 goto r_op_change;
Denis Vlasenkof782f522007-01-01 23:51:30 +00002544 case '!':
Denis Vlasenko92758142006-10-03 19:56:34 +00002545 L.d = istrue(X.v) ? 0 : 1;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002546 break;
Denis Vlasenkof782f522007-01-01 23:51:30 +00002547 case '-':
Mike Frysingerde2b9382005-09-27 03:18:00 +00002548 L.d = -R.d;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002549 break;
Denis Vlasenkof782f522007-01-01 23:51:30 +00002550 r_op_change:
Glenn L McGrath545106f2002-11-11 06:21:00 +00002551 setvar_i(X.v, R.d);
2552 }
2553 setvar_i(res, L.d);
2554 break;
2555
Denis Vlasenkof782f522007-01-01 23:51:30 +00002556 case XC( OC_FIELD ):
Mike Frysingerde2b9382005-09-27 03:18:00 +00002557 R.i = (int)getvar_i(R.v);
2558 if (R.i == 0) {
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002559 res = intvar[F0];
Glenn L McGrath545106f2002-11-11 06:21:00 +00002560 } else {
2561 split_f0();
2562 if (R.i > nfields)
2563 fsrealloc(R.i);
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002564 res = &Fields[R.i - 1];
Glenn L McGrath545106f2002-11-11 06:21:00 +00002565 }
2566 break;
2567
Denis Vlasenkocd5c7862007-05-17 16:37:22 +00002568 /* concatenation (" ") and index joining (",") */
Denis Vlasenkof782f522007-01-01 23:51:30 +00002569 case XC( OC_CONCAT ):
2570 case XC( OC_COMMA ):
Rob Landleya3896512006-05-07 20:20:34 +00002571 opn = strlen(L.s) + strlen(R.s) + 2;
Denis Vlasenkob95636c2006-12-19 23:36:04 +00002572 X.s = xmalloc(opn);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002573 strcpy(X.s, L.s);
2574 if ((opinfo & OPCLSMASK) == OC_COMMA) {
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002575 L.s = getvar_s(intvar[SUBSEP]);
Denis Vlasenkof782f522007-01-01 23:51:30 +00002576 X.s = xrealloc(X.s, opn + strlen(L.s));
Glenn L McGrath545106f2002-11-11 06:21:00 +00002577 strcat(X.s, L.s);
2578 }
2579 strcat(X.s, R.s);
2580 setvar_p(res, X.s);
2581 break;
2582
Denis Vlasenkof782f522007-01-01 23:51:30 +00002583 case XC( OC_LAND ):
Glenn L McGrath545106f2002-11-11 06:21:00 +00002584 setvar_i(res, istrue(L.v) ? ptest(op->r.n) : 0);
2585 break;
2586
Denis Vlasenkof782f522007-01-01 23:51:30 +00002587 case XC( OC_LOR ):
Glenn L McGrath545106f2002-11-11 06:21:00 +00002588 setvar_i(res, istrue(L.v) ? 1 : ptest(op->r.n));
2589 break;
2590
Denis Vlasenkof782f522007-01-01 23:51:30 +00002591 case XC( OC_BINARY ):
2592 case XC( OC_REPLACE ):
Mike Frysingerde2b9382005-09-27 03:18:00 +00002593 R.d = getvar_i(R.v);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002594 switch (opn) {
Denis Vlasenkof782f522007-01-01 23:51:30 +00002595 case '+':
Mike Frysingerde2b9382005-09-27 03:18:00 +00002596 L.d += R.d;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002597 break;
Denis Vlasenkof782f522007-01-01 23:51:30 +00002598 case '-':
Mike Frysingerde2b9382005-09-27 03:18:00 +00002599 L.d -= R.d;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002600 break;
Denis Vlasenkof782f522007-01-01 23:51:30 +00002601 case '*':
Mike Frysingerde2b9382005-09-27 03:18:00 +00002602 L.d *= R.d;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002603 break;
Denis Vlasenkof782f522007-01-01 23:51:30 +00002604 case '/':
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002605 if (R.d == 0) syntax_error(EMSG_DIV_BY_ZERO);
Mike Frysingerde2b9382005-09-27 03:18:00 +00002606 L.d /= R.d;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002607 break;
Denis Vlasenkof782f522007-01-01 23:51:30 +00002608 case '&':
2609#if ENABLE_FEATURE_AWK_MATH
Mike Frysingerde2b9382005-09-27 03:18:00 +00002610 L.d = pow(L.d, R.d);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002611#else
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002612 syntax_error(EMSG_NO_MATH);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002613#endif
2614 break;
Denis Vlasenkof782f522007-01-01 23:51:30 +00002615 case '%':
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002616 if (R.d == 0) syntax_error(EMSG_DIV_BY_ZERO);
Mike Frysingerde2b9382005-09-27 03:18:00 +00002617 L.d -= (int)(L.d / R.d) * R.d;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002618 break;
2619 }
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002620 res = setvar_i(((opinfo & OPCLSMASK) == OC_BINARY) ? res : X.v, L.d);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002621 break;
2622
Denis Vlasenkof782f522007-01-01 23:51:30 +00002623 case XC( OC_COMPARE ):
Glenn L McGrath545106f2002-11-11 06:21:00 +00002624 if (is_numeric(L.v) && is_numeric(R.v)) {
2625 L.d = getvar_i(L.v) - getvar_i(R.v);
2626 } else {
2627 L.s = getvar_s(L.v);
2628 R.s = getvar_s(R.v);
2629 L.d = icase ? strcasecmp(L.s, R.s) : strcmp(L.s, R.s);
2630 }
2631 switch (opn & 0xfe) {
Denis Vlasenkof782f522007-01-01 23:51:30 +00002632 case 0:
Mike Frysingerde2b9382005-09-27 03:18:00 +00002633 R.i = (L.d > 0);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002634 break;
Denis Vlasenkof782f522007-01-01 23:51:30 +00002635 case 2:
Mike Frysingerde2b9382005-09-27 03:18:00 +00002636 R.i = (L.d >= 0);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002637 break;
Denis Vlasenkof782f522007-01-01 23:51:30 +00002638 case 4:
Mike Frysingerde2b9382005-09-27 03:18:00 +00002639 R.i = (L.d == 0);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002640 break;
2641 }
2642 setvar_i(res, (opn & 0x1 ? R.i : !R.i) ? 1 : 0);
2643 break;
2644
Denis Vlasenkof782f522007-01-01 23:51:30 +00002645 default:
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002646 syntax_error(EMSG_POSSIBLE_ERROR);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002647 }
2648 if ((opinfo & OPCLSMASK) <= SHIFT_TIL_THIS)
2649 op = op->a.n;
2650 if ((opinfo & OPCLSMASK) >= RECUR_FROM_THIS)
2651 break;
2652 if (nextrec)
2653 break;
2654 }
2655 nvfree(v1);
2656 return res;
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002657#undef fnargs
2658#undef seed
2659#undef sreg
Glenn L McGrath545106f2002-11-11 06:21:00 +00002660}
2661
2662
2663/* -------- main & co. -------- */
2664
Mike Frysinger10a11e22005-09-27 02:23:02 +00002665static int awk_exit(int r)
2666{
Denis Vlasenkof782f522007-01-01 23:51:30 +00002667 var tv;
2668 unsigned i;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002669 hash_item *hi;
Glenn L McGrath00ed36f2003-10-30 13:36:39 +00002670
Denis Vlasenkof782f522007-01-01 23:51:30 +00002671 zero_out_var(&tv);
2672
2673 if (!exiting) {
Glenn L McGrath00ed36f2003-10-30 13:36:39 +00002674 exiting = TRUE;
Glenn L McGrathca29ffc2004-09-24 09:24:27 +00002675 nextrec = FALSE;
Glenn L McGrath00ed36f2003-10-30 13:36:39 +00002676 evaluate(endseq.first, &tv);
2677 }
Glenn L McGrath545106f2002-11-11 06:21:00 +00002678
2679 /* waiting for children */
Denis Vlasenkof782f522007-01-01 23:51:30 +00002680 for (i = 0; i < fdhash->csize; i++) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00002681 hi = fdhash->items[i];
Denis Vlasenkobf0a2012006-12-26 10:42:51 +00002682 while (hi) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00002683 if (hi->data.rs.F && hi->data.rs.is_pipe)
2684 pclose(hi->data.rs.F);
2685 hi = hi->next;
2686 }
2687 }
2688
2689 exit(r);
2690}
2691
2692/* if expr looks like "var=value", perform assignment and return 1,
2693 * otherwise return 0 */
"Vladimir N. Oleynik"5cf9a032005-10-19 09:21:51 +00002694static int is_assignment(const char *expr)
Mike Frysinger10a11e22005-09-27 02:23:02 +00002695{
Glenn L McGrath545106f2002-11-11 06:21:00 +00002696 char *exprc, *s, *s0, *s1;
2697
Rob Landleyd921b2e2006-08-03 15:41:12 +00002698 exprc = xstrdup(expr);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002699 if (!isalnum_(*exprc) || (s = strchr(exprc, '=')) == NULL) {
2700 free(exprc);
2701 return FALSE;
2702 }
2703
2704 *(s++) = '\0';
2705 s0 = s1 = s;
2706 while (*s)
2707 *(s1++) = nextchar(&s);
2708
2709 *s1 = '\0';
2710 setvar_u(newvar(exprc), s0);
2711 free(exprc);
2712 return TRUE;
2713}
2714
2715/* switch to next input file */
Mike Frysinger10a11e22005-09-27 02:23:02 +00002716static rstream *next_input_file(void)
2717{
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002718#define rsm (G.next_input_file__rsm)
2719#define files_happen (G.next_input_file__files_happen)
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002720
Glenn L McGrath545106f2002-11-11 06:21:00 +00002721 FILE *F = NULL;
Denis Vlasenkoa41fdf32007-01-29 22:51:00 +00002722 const char *fname, *ind;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002723
2724 if (rsm.F) fclose(rsm.F);
2725 rsm.F = NULL;
Glenn L McGrath00ed36f2003-10-30 13:36:39 +00002726 rsm.pos = rsm.adv = 0;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002727
2728 do {
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002729 if (getvar_i(intvar[ARGIND])+1 >= getvar_i(intvar[ARGC])) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00002730 if (files_happen)
2731 return NULL;
2732 fname = "-";
2733 F = stdin;
2734 } else {
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002735 ind = getvar_s(incvar(intvar[ARGIND]));
2736 fname = getvar_s(findvar(iamarray(intvar[ARGV]), ind));
Glenn L McGrath545106f2002-11-11 06:21:00 +00002737 if (fname && *fname && !is_assignment(fname))
Denis Vlasenko3bb2bbd2008-07-01 01:57:36 +00002738 F = xfopen_stdin(fname);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002739 }
2740 } while (!F);
2741
2742 files_happen = TRUE;
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002743 setvar_s(intvar[FILENAME], fname);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002744 rsm.F = F;
2745 return &rsm;
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002746#undef rsm
2747#undef files_happen
Glenn L McGrath545106f2002-11-11 06:21:00 +00002748}
2749
Denis Vlasenko9b49a5e2007-10-11 10:05:36 +00002750int awk_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
Rob Landleydfba7412006-03-06 20:47:33 +00002751int awk_main(int argc, char **argv)
Mike Frysinger10a11e22005-09-27 02:23:02 +00002752{
Denis Vlasenko67b23e62006-10-03 21:00:06 +00002753 unsigned opt;
Denis Vlasenkobe644a82007-03-10 17:22:14 +00002754 char *opt_F, *opt_W;
Denis Vlasenko3bb2bbd2008-07-01 01:57:36 +00002755 llist_t *list_v = NULL;
2756 llist_t *list_f = NULL;
2757 int i, j;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002758 var *v;
Denis Vlasenkof782f522007-01-01 23:51:30 +00002759 var tv;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002760 char **envp;
Denis Vlasenkof782f522007-01-01 23:51:30 +00002761 char *vnames = (char *)vNames; /* cheat */
2762 char *vvalues = (char *)vValues;
2763
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002764 INIT_G();
2765
Denis Vlasenko150f4022007-01-13 21:06:21 +00002766 /* Undo busybox.c, or else strtod may eat ','! This breaks parsing:
Denis Vlasenko6dc6ebb2007-01-01 23:53:12 +00002767 * $1,$2 == '$1,' '$2', NOT '$1' ',' '$2' */
2768 if (ENABLE_LOCALE_SUPPORT)
2769 setlocale(LC_NUMERIC, "C");
2770
Denis Vlasenkof782f522007-01-01 23:51:30 +00002771 zero_out_var(&tv);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002772
2773 /* allocate global buffer */
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002774 g_buf = xmalloc(MAXVARFMT + 1);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002775
2776 vhash = hash_init();
2777 ahash = hash_init();
2778 fdhash = hash_init();
2779 fnhash = hash_init();
2780
2781 /* initialize variables */
Denis Vlasenkof782f522007-01-01 23:51:30 +00002782 for (i = 0; *vnames; i++) {
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002783 intvar[i] = v = newvar(nextword(&vnames));
Denis Vlasenkof782f522007-01-01 23:51:30 +00002784 if (*vvalues != '\377')
2785 setvar_s(v, nextword(&vvalues));
Glenn L McGrath545106f2002-11-11 06:21:00 +00002786 else
2787 setvar_i(v, 0);
2788
Denis Vlasenkof782f522007-01-01 23:51:30 +00002789 if (*vnames == '*') {
Glenn L McGrath545106f2002-11-11 06:21:00 +00002790 v->type |= VF_SPECIAL;
Denis Vlasenkof782f522007-01-01 23:51:30 +00002791 vnames++;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002792 }
2793 }
2794
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002795 handle_special(intvar[FS]);
2796 handle_special(intvar[RS]);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002797
Denis Vlasenkof782f522007-01-01 23:51:30 +00002798 newfile("/dev/stdin")->F = stdin;
2799 newfile("/dev/stdout")->F = stdout;
2800 newfile("/dev/stderr")->F = stderr;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002801
Denis Vlasenkof71d9162007-05-03 22:57:56 +00002802 /* Huh, people report that sometimes environ is NULL. Oh well. */
2803 if (environ) for (envp = environ; *envp; envp++) {
Denis Vlasenkob78c7822007-07-18 18:31:11 +00002804 /* environ is writable, thus we don't strdup it needlessly */
2805 char *s = *envp;
Denis Vlasenkof782f522007-01-01 23:51:30 +00002806 char *s1 = strchr(s, '=');
2807 if (s1) {
Denis Vlasenkob78c7822007-07-18 18:31:11 +00002808 *s1 = '\0';
2809 /* Both findvar and setvar_u take const char*
2810 * as 2nd arg -> environment is not trashed */
2811 setvar_u(findvar(iamarray(intvar[ENVIRON]), s), s1 + 1);
2812 *s1 = '=';
Eric Andersen67776be2004-07-30 23:52:08 +00002813 }
Glenn L McGrath545106f2002-11-11 06:21:00 +00002814 }
Denis Vlasenko3bb2bbd2008-07-01 01:57:36 +00002815 opt_complementary = "v::f::"; /* -v and -f can occur multiple times */
2816 opt = getopt32(argv, "F:v:f:W:", &opt_F, &list_v, &list_f, &opt_W);
Denis Vlasenkof782f522007-01-01 23:51:30 +00002817 argv += optind;
2818 argc -= optind;
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002819 if (opt & 0x1)
2820 setvar_s(intvar[FS], opt_F); // -F
Denis Vlasenko3bb2bbd2008-07-01 01:57:36 +00002821 while (list_v) { /* -v */
2822 if (!is_assignment(llist_pop(&list_v)))
Denis Vlasenkobe644a82007-03-10 17:22:14 +00002823 bb_show_usage();
2824 }
Denis Vlasenko3bb2bbd2008-07-01 01:57:36 +00002825 if (list_f) { /* -f */
2826 do {
2827 char *s = NULL;
2828 FILE *from_file;
2829
2830 g_progname = llist_pop(&list_f);
2831 from_file = xfopen_stdin(g_progname);
2832 /* one byte is reserved for some trick in next_token */
Denis Vlasenkof782f522007-01-01 23:51:30 +00002833 for (i = j = 1; j > 0; i += j) {
2834 s = xrealloc(s, i + 4096);
2835 j = fread(s + i, 1, 4094, from_file);
Denis Vlasenko099efbf2006-09-22 09:02:30 +00002836 }
Denis Vlasenko3bb2bbd2008-07-01 01:57:36 +00002837 s[i] = '\0';
2838 fclose(from_file);
2839 parse_program(s + 1);
2840 free(s);
2841 } while (list_f);
Denis Vlasenkof782f522007-01-01 23:51:30 +00002842 } else { // no -f: take program from 1st parameter
2843 if (!argc)
2844 bb_show_usage();
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002845 g_progname = "cmd. line";
Denis Vlasenkof782f522007-01-01 23:51:30 +00002846 parse_program(*argv++);
2847 argc--;
Glenn L McGrath545106f2002-11-11 06:21:00 +00002848 }
Denis Vlasenko099efbf2006-09-22 09:02:30 +00002849 if (opt & 0x8) // -W
Denis Vlasenkoe1a0d482006-10-20 13:28:22 +00002850 bb_error_msg("warning: unrecognized option '-W %s' ignored", opt_W);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002851
Glenn L McGrath545106f2002-11-11 06:21:00 +00002852 /* fill in ARGV array */
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002853 setvar_i(intvar[ARGC], argc + 1);
2854 setari_u(intvar[ARGV], 0, "awk");
Denis Vlasenkof782f522007-01-01 23:51:30 +00002855 i = 0;
2856 while (*argv)
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002857 setari_u(intvar[ARGV], ++i, *argv++);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002858
2859 evaluate(beginseq.first, &tv);
Denis Vlasenkof782f522007-01-01 23:51:30 +00002860 if (!mainseq.first && !endseq.first)
Glenn L McGrath545106f2002-11-11 06:21:00 +00002861 awk_exit(EXIT_SUCCESS);
2862
2863 /* input file could already be opened in BEGIN block */
Denis Vlasenkof782f522007-01-01 23:51:30 +00002864 if (!iF) iF = next_input_file();
Glenn L McGrath545106f2002-11-11 06:21:00 +00002865
2866 /* passing through input files */
2867 while (iF) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00002868 nextfile = FALSE;
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002869 setvar_i(intvar[FNR], 0);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002870
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002871 while ((i = awk_getline(iF, intvar[F0])) > 0) {
Glenn L McGrath545106f2002-11-11 06:21:00 +00002872 nextrec = FALSE;
Denis Vlasenkoffba9412007-05-17 23:03:35 +00002873 incvar(intvar[NR]);
2874 incvar(intvar[FNR]);
Glenn L McGrath545106f2002-11-11 06:21:00 +00002875 evaluate(mainseq.first, &tv);
2876
2877 if (nextfile)
2878 break;
2879 }
2880
Denis Vlasenkof782f522007-01-01 23:51:30 +00002881 if (i < 0)
Denis Vlasenkoae5a8aa2007-06-06 17:01:00 +00002882 syntax_error(strerror(errno));
Glenn L McGrath545106f2002-11-11 06:21:00 +00002883
2884 iF = next_input_file();
Glenn L McGrath545106f2002-11-11 06:21:00 +00002885 }
2886
Glenn L McGrath545106f2002-11-11 06:21:00 +00002887 awk_exit(EXIT_SUCCESS);
Denis Vlasenkof782f522007-01-01 23:51:30 +00002888 /*return 0;*/
Glenn L McGrath545106f2002-11-11 06:21:00 +00002889}