aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-05-17 23:03:35 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-05-17 23:03:35 +0000
commitffba941d29afd609e0c7e39501a4542fac9a0ff0 (patch)
tree6de113dc1a2c433e8c885af23d4990ee72f71598
parent5b340830045aa3dc6ca01cd1c6082b09161877d2 (diff)
downloadbusybox-w32-ffba941d29afd609e0c7e39501a4542fac9a0ff0.tar.gz
busybox-w32-ffba941d29afd609e0c7e39501a4542fac9a0ff0.tar.bz2
busybox-w32-ffba941d29afd609e0c7e39501a4542fac9a0ff0.zip
awk: make code a bit less obfuscated
-rw-r--r--editors/awk.c491
1 files changed, 251 insertions, 240 deletions
diff --git a/editors/awk.c b/editors/awk.c
index 76ebe0fb9..d0a8846b9 100644
--- a/editors/awk.c
+++ b/editors/awk.c
@@ -71,19 +71,19 @@ typedef struct rstream_s {
71 71
72typedef struct hash_item_s { 72typedef struct hash_item_s {
73 union { 73 union {
74 struct var_s v; /* variable/array hash */ 74 struct var_s v; /* variable/array hash */
75 struct rstream_s rs; /* redirect streams hash */ 75 struct rstream_s rs; /* redirect streams hash */
76 struct func_s f; /* functions hash */ 76 struct func_s f; /* functions hash */
77 } data; 77 } data;
78 struct hash_item_s *next; /* next in chain */ 78 struct hash_item_s *next; /* next in chain */
79 char name[1]; /* really it's longer */ 79 char name[1]; /* really it's longer */
80} hash_item; 80} hash_item;
81 81
82typedef struct xhash_s { 82typedef struct xhash_s {
83 unsigned nel; /* num of elements */ 83 unsigned nel; /* num of elements */
84 unsigned csize; /* current hash size */ 84 unsigned csize; /* current hash size */
85 unsigned nprime; /* next hash size in PRIMES[] */ 85 unsigned nprime; /* next hash size in PRIMES[] */
86 unsigned glen; /* summary length of item names */ 86 unsigned glen; /* summary length of item names */
87 struct hash_item_s **items; 87 struct hash_item_s **items;
88} xhash; 88} xhash;
89 89
@@ -156,42 +156,42 @@ typedef struct tsplitter_s {
156#define TC_STRING (1 << 28) 156#define TC_STRING (1 << 28)
157#define TC_NUMBER (1 << 29) 157#define TC_NUMBER (1 << 29)
158 158
159#define TC_UOPPRE (TC_UOPPRE1 | TC_UOPPRE2) 159#define TC_UOPPRE (TC_UOPPRE1 | TC_UOPPRE2)
160 160
161/* combined token classes */ 161/* combined token classes */
162#define TC_BINOP (TC_BINOPX | TC_COMMA | TC_PIPE | TC_IN) 162#define TC_BINOP (TC_BINOPX | TC_COMMA | TC_PIPE | TC_IN)
163#define TC_UNARYOP (TC_UOPPRE | TC_UOPPOST) 163#define TC_UNARYOP (TC_UOPPRE | TC_UOPPOST)
164#define TC_OPERAND (TC_VARIABLE | TC_ARRAY | TC_FUNCTION | \ 164#define TC_OPERAND (TC_VARIABLE | TC_ARRAY | TC_FUNCTION \
165 TC_BUILTIN | TC_GETLINE | TC_SEQSTART | TC_STRING | TC_NUMBER) 165 | TC_BUILTIN | TC_GETLINE | TC_SEQSTART | TC_STRING | TC_NUMBER)
166 166
167#define TC_STATEMNT (TC_STATX | TC_WHILE) 167#define TC_STATEMNT (TC_STATX | TC_WHILE)
168#define TC_OPTERM (TC_SEMICOL | TC_NEWLINE) 168#define TC_OPTERM (TC_SEMICOL | TC_NEWLINE)
169 169
170/* word tokens, cannot mean something else if not expected */ 170/* word tokens, cannot mean something else if not expected */
171#define TC_WORD (TC_IN | TC_STATEMNT | TC_ELSE | TC_BUILTIN | \ 171#define TC_WORD (TC_IN | TC_STATEMNT | TC_ELSE | TC_BUILTIN \
172 TC_GETLINE | TC_FUNCDECL | TC_BEGIN | TC_END) 172 | TC_GETLINE | TC_FUNCDECL | TC_BEGIN | TC_END)
173 173
174/* discard newlines after these */ 174/* discard newlines after these */
175#define TC_NOTERM (TC_COMMA | TC_GRPSTART | TC_GRPTERM | \ 175#define TC_NOTERM (TC_COMMA | TC_GRPSTART | TC_GRPTERM \
176 TC_BINOP | TC_OPTERM) 176 | TC_BINOP | TC_OPTERM)
177 177
178/* what can expression begin with */ 178/* what can expression begin with */
179#define TC_OPSEQ (TC_OPERAND | TC_UOPPRE | TC_REGEXP) 179#define TC_OPSEQ (TC_OPERAND | TC_UOPPRE | TC_REGEXP)
180/* what can group begin with */ 180/* what can group begin with */
181#define TC_GRPSEQ (TC_OPSEQ | TC_OPTERM | TC_STATEMNT | TC_GRPSTART) 181#define TC_GRPSEQ (TC_OPSEQ | TC_OPTERM | TC_STATEMNT | TC_GRPSTART)
182 182
183/* if previous token class is CONCAT1 and next is CONCAT2, concatenation */ 183/* if previous token class is CONCAT1 and next is CONCAT2, concatenation */
184/* operator is inserted between them */ 184/* operator is inserted between them */
185#define TC_CONCAT1 (TC_VARIABLE | TC_ARRTERM | TC_SEQTERM | \ 185#define TC_CONCAT1 (TC_VARIABLE | TC_ARRTERM | TC_SEQTERM \
186 TC_STRING | TC_NUMBER | TC_UOPPOST) 186 | TC_STRING | TC_NUMBER | TC_UOPPOST)
187#define TC_CONCAT2 (TC_OPERAND | TC_UOPPRE) 187#define TC_CONCAT2 (TC_OPERAND | TC_UOPPRE)
188 188
189#define OF_RES1 0x010000 189#define OF_RES1 0x010000
190#define OF_RES2 0x020000 190#define OF_RES2 0x020000
191#define OF_STR1 0x040000 191#define OF_STR1 0x040000
192#define OF_STR2 0x080000 192#define OF_STR2 0x080000
193#define OF_NUM1 0x100000 193#define OF_NUM1 0x100000
194#define OF_CHECKED 0x200000 194#define OF_CHECKED 0x200000
195 195
196/* combined operator flags */ 196/* combined operator flags */
197#define xx 0 197#define xx 0
@@ -205,16 +205,16 @@ typedef struct tsplitter_s {
205#define SV (OF_RES1 | OF_STR1 | OF_RES2) 205#define SV (OF_RES1 | OF_STR1 | OF_RES2)
206#define SS (OF_RES1 | OF_STR1 | OF_RES2 | OF_STR2) 206#define SS (OF_RES1 | OF_STR1 | OF_RES2 | OF_STR2)
207 207
208#define OPCLSMASK 0xFF00 208#define OPCLSMASK 0xFF00
209#define OPNMASK 0x007F 209#define OPNMASK 0x007F
210 210
211/* operator priority is a highest byte (even: r->l, odd: l->r grouping) 211/* operator priority is a highest byte (even: r->l, odd: l->r grouping)
212 * For builtins it has different meaning: n n s3 s2 s1 v3 v2 v1, 212 * For builtins it has different meaning: n n s3 s2 s1 v3 v2 v1,
213 * n - min. number of args, vN - resolve Nth arg to var, sN - resolve to string 213 * n - min. number of args, vN - resolve Nth arg to var, sN - resolve to string
214 */ 214 */
215#define P(x) (x << 24) 215#define P(x) (x << 24)
216#define PRIMASK 0x7F000000 216#define PRIMASK 0x7F000000
217#define PRIMASK2 0x7E000000 217#define PRIMASK2 0x7E000000
218 218
219/* Operation classes */ 219/* Operation classes */
220 220
@@ -222,44 +222,44 @@ typedef struct tsplitter_s {
222#define RECUR_FROM_THIS 0x1000 222#define RECUR_FROM_THIS 0x1000
223 223
224enum { 224enum {
225 OC_DELETE=0x0100, OC_EXEC=0x0200, OC_NEWSOURCE=0x0300, 225 OC_DELETE = 0x0100, OC_EXEC = 0x0200, OC_NEWSOURCE = 0x0300,
226 OC_PRINT=0x0400, OC_PRINTF=0x0500, OC_WALKINIT=0x0600, 226 OC_PRINT = 0x0400, OC_PRINTF = 0x0500, OC_WALKINIT = 0x0600,
227 227
228 OC_BR=0x0700, OC_BREAK=0x0800, OC_CONTINUE=0x0900, 228 OC_BR = 0x0700, OC_BREAK = 0x0800, OC_CONTINUE = 0x0900,
229 OC_EXIT=0x0a00, OC_NEXT=0x0b00, OC_NEXTFILE=0x0c00, 229 OC_EXIT = 0x0a00, OC_NEXT = 0x0b00, OC_NEXTFILE = 0x0c00,
230 OC_TEST=0x0d00, OC_WALKNEXT=0x0e00, 230 OC_TEST = 0x0d00, OC_WALKNEXT = 0x0e00,
231 231
232 OC_BINARY=0x1000, OC_BUILTIN=0x1100, OC_COLON=0x1200, 232 OC_BINARY = 0x1000, OC_BUILTIN = 0x1100, OC_COLON = 0x1200,
233 OC_COMMA=0x1300, OC_COMPARE=0x1400, OC_CONCAT=0x1500, 233 OC_COMMA = 0x1300, OC_COMPARE = 0x1400, OC_CONCAT = 0x1500,
234 OC_FBLTIN=0x1600, OC_FIELD=0x1700, OC_FNARG=0x1800, 234 OC_FBLTIN = 0x1600, OC_FIELD = 0x1700, OC_FNARG = 0x1800,
235 OC_FUNC=0x1900, OC_GETLINE=0x1a00, OC_IN=0x1b00, 235 OC_FUNC = 0x1900, OC_GETLINE = 0x1a00, OC_IN = 0x1b00,
236 OC_LAND=0x1c00, OC_LOR=0x1d00, OC_MATCH=0x1e00, 236 OC_LAND = 0x1c00, OC_LOR = 0x1d00, OC_MATCH = 0x1e00,
237 OC_MOVE=0x1f00, OC_PGETLINE=0x2000, OC_REGEXP=0x2100, 237 OC_MOVE = 0x1f00, OC_PGETLINE = 0x2000, OC_REGEXP = 0x2100,
238 OC_REPLACE=0x2200, OC_RETURN=0x2300, OC_SPRINTF=0x2400, 238 OC_REPLACE = 0x2200, OC_RETURN = 0x2300, OC_SPRINTF = 0x2400,
239 OC_TERNARY=0x2500, OC_UNARY=0x2600, OC_VAR=0x2700, 239 OC_TERNARY = 0x2500, OC_UNARY = 0x2600, OC_VAR = 0x2700,
240 OC_DONE=0x2800, 240 OC_DONE = 0x2800,
241 241
242 ST_IF=0x3000, ST_DO=0x3100, ST_FOR=0x3200, 242 ST_IF = 0x3000, ST_DO = 0x3100, ST_FOR = 0x3200,
243 ST_WHILE=0x3300 243 ST_WHILE = 0x3300
244}; 244};
245 245
246/* simple builtins */ 246/* simple builtins */
247enum { 247enum {
248 F_in=0, F_rn, F_co, F_ex, F_lg, F_si, F_sq, F_sr, 248 F_in, F_rn, F_co, F_ex, F_lg, F_si, F_sq, F_sr,
249 F_ti, F_le, F_sy, F_ff, F_cl 249 F_ti, F_le, F_sy, F_ff, F_cl
250}; 250};
251 251
252/* builtins */ 252/* builtins */
253enum { 253enum {
254 B_a2=0, B_ix, B_ma, B_sp, B_ss, B_ti, B_lo, B_up, 254 B_a2, B_ix, B_ma, B_sp, B_ss, B_ti, B_lo, B_up,
255 B_ge, B_gs, B_su, 255 B_ge, B_gs, B_su,
256 B_an, B_co, B_ls, B_or, B_rs, B_xo, 256 B_an, B_co, B_ls, B_or, B_rs, B_xo,
257}; 257};
258 258
259/* tokens and their corresponding info values */ 259/* tokens and their corresponding info values */
260 260
261#define NTC "\377" /* switch to next token class (tc<<1) */ 261#define NTC "\377" /* switch to next token class (tc<<1) */
262#define NTCC '\377' 262#define NTCC '\377'
263 263
264#define OC_B OC_BUILTIN 264#define OC_B OC_BUILTIN
265 265
@@ -365,12 +365,12 @@ static const uint32_t tokeninfo[] = {
365/* internal variable names and their initial values */ 365/* internal variable names and their initial values */
366/* asterisk marks SPECIAL vars; $ is just no-named Field0 */ 366/* asterisk marks SPECIAL vars; $ is just no-named Field0 */
367enum { 367enum {
368 CONVFMT=0, OFMT, FS, OFS, 368 CONVFMT, OFMT, FS, OFS,
369 ORS, RS, RT, FILENAME, 369 ORS, RS, RT, FILENAME,
370 SUBSEP, ARGIND, ARGC, ARGV, 370 SUBSEP, ARGIND, ARGC, ARGV,
371 ERRNO, FNR, 371 ERRNO, FNR,
372 NR, NF, IGNORECASE, 372 NR, NF, IGNORECASE,
373 ENVIRON, F0, _intvarcount_ 373 ENVIRON, F0, NUM_INTERNAL_VARS
374}; 374};
375 375
376static const char vNames[] = 376static const char vNames[] =
@@ -390,11 +390,11 @@ static const char vValues[] =
390/* hash size may grow to these values */ 390/* hash size may grow to these values */
391#define FIRST_PRIME 61; 391#define FIRST_PRIME 61;
392static const unsigned PRIMES[] = { 251, 1021, 4093, 16381, 65521 }; 392static const unsigned PRIMES[] = { 251, 1021, 4093, 16381, 65521 };
393enum { NPRIMES = sizeof(PRIMES) / sizeof(unsigned) }; 393enum { NPRIMES = sizeof(PRIMES) / sizeof(PRIMES[0]) };
394 394
395/* globals */ 395/* globals */
396 396
397static var * V[_intvarcount_]; 397static var *intvar[NUM_INTERNAL_VARS];
398static chain beginseq, mainseq, endseq, *seq; 398static chain beginseq, mainseq, endseq, *seq;
399static int nextrec, nextfile; 399static int nextrec, nextfile;
400static node *break_ptr, *continue_ptr; 400static node *break_ptr, *continue_ptr;
@@ -421,6 +421,7 @@ static struct {
421 int rollback; 421 int rollback;
422} ttt; 422} ttt;
423/* It had even better name: 't'. Whoever knows what is it, please rename! */ 423/* It had even better name: 't'. Whoever knows what is it, please rename! */
424/* (actually it looks like unrelated stuff lumped together...) */
424 425
425/* function prototypes */ 426/* function prototypes */
426static void handle_special(var *); 427static void handle_special(var *);
@@ -508,7 +509,7 @@ static void hash_rebuild(xhash *hash)
508 newsize = PRIMES[hash->nprime++]; 509 newsize = PRIMES[hash->nprime++];
509 newitems = xzalloc(newsize * sizeof(hash_item *)); 510 newitems = xzalloc(newsize * sizeof(hash_item *));
510 511
511 for (i=0; i<hash->csize; i++) { 512 for (i = 0; i < hash->csize; i++) {
512 hi = hash->items[i]; 513 hi = hash->items[i];
513 while (hi) { 514 while (hi) {
514 thi = hi; 515 thi = hi;
@@ -548,16 +549,16 @@ static void *hash_find(xhash *hash, const char *name)
548 return &(hi->data); 549 return &(hi->data);
549} 550}
550 551
551#define findvar(hash, name) ((var*) hash_find((hash) , (name))) 552#define findvar(hash, name) ((var*) hash_find((hash), (name)))
552#define newvar(name) ((var*) hash_find(vhash , (name))) 553#define newvar(name) ((var*) hash_find(vhash, (name)))
553#define newfile(name) ((rstream*)hash_find(fdhash ,(name))) 554#define newfile(name) ((rstream*)hash_find(fdhash, (name)))
554#define newfunc(name) ((func*) hash_find(fnhash , (name))) 555#define newfunc(name) ((func*) hash_find(fnhash, (name)))
555 556
556static void hash_remove(xhash *hash, const char *name) 557static void hash_remove(xhash *hash, const char *name)
557{ 558{
558 hash_item *hi, **phi; 559 hash_item *hi, **phi;
559 560
560 phi = &(hash->items[ hashidx(name) % hash->csize ]); 561 phi = &(hash->items[hashidx(name) % hash->csize]);
561 while (*phi) { 562 while (*phi) {
562 hi = *phi; 563 hi = *phi;
563 if (strcmp(hi->name, name) == 0) { 564 if (strcmp(hi->name, name) == 0) {
@@ -671,7 +672,6 @@ static var *setvar_p(var *v, char *value)
671 clrvar(v); 672 clrvar(v);
672 v->string = value; 673 v->string = value;
673 handle_special(v); 674 handle_special(v);
674
675 return v; 675 return v;
676} 676}
677 677
@@ -692,8 +692,8 @@ static var *setvar_u(var *v, const char *value)
692/* set array element to user string */ 692/* set array element to user string */
693static void setari_u(var *a, int idx, const char *s) 693static void setari_u(var *a, int idx, const char *s)
694{ 694{
695 char sidx[sizeof(int)*3 + 1];
695 var *v; 696 var *v;
696 static char sidx[12];
697 697
698 sprintf(sidx, "%d", idx); 698 sprintf(sidx, "%d", idx);
699 v = findvar(iamarray(a), sidx); 699 v = findvar(iamarray(a), sidx);
@@ -714,7 +714,7 @@ static const char *getvar_s(var *v)
714{ 714{
715 /* if v is numeric and has no cached string, convert it to string */ 715 /* if v is numeric and has no cached string, convert it to string */
716 if ((v->type & (VF_NUMBER | VF_CACHED)) == VF_NUMBER) { 716 if ((v->type & (VF_NUMBER | VF_CACHED)) == VF_NUMBER) {
717 fmt_num(buf, MAXVARFMT, getvar_s(V[CONVFMT]), v->number, TRUE); 717 fmt_num(buf, MAXVARFMT, getvar_s(intvar[CONVFMT]), v->number, TRUE);
718 v->string = xstrdup(buf); 718 v->string = xstrdup(buf);
719 v->type |= VF_CACHED; 719 v->type |= VF_CACHED;
720 } 720 }
@@ -819,8 +819,8 @@ static void nvfree(var *v)
819 if (v < cb->nv || v >= cb->pos) 819 if (v < cb->nv || v >= cb->pos)
820 runtime_error(EMSG_INTERNAL_ERROR); 820 runtime_error(EMSG_INTERNAL_ERROR);
821 821
822 for (p=v; p<cb->pos; p++) { 822 for (p = v; p < cb->pos; p++) {
823 if ((p->type & (VF_ARRAY|VF_CHILD)) == VF_ARRAY) { 823 if ((p->type & (VF_ARRAY | VF_CHILD)) == VF_ARRAY) {
824 clear_array(iamarray(p)); 824 clear_array(iamarray(p));
825 free(p->x.array->items); 825 free(p->x.array->items);
826 free(p->x.array); 826 free(p->x.array);
@@ -868,7 +868,8 @@ static uint32_t next_token(uint32_t expected)
868 skip_spaces(&p); 868 skip_spaces(&p);
869 lineno = ttt.lineno; 869 lineno = ttt.lineno;
870 if (*p == '#') 870 if (*p == '#')
871 while (*p != '\n' && *p != '\0') p++; 871 while (*p != '\n' && *p != '\0')
872 p++;
872 873
873 if (*p == '\n') 874 if (*p == '\n')
874 ttt.lineno++; 875 ttt.lineno++;
@@ -894,11 +895,14 @@ static uint32_t next_token(uint32_t expected)
894 while (*p != '/') { 895 while (*p != '/') {
895 if (*p == '\0' || *p == '\n') 896 if (*p == '\0' || *p == '\n')
896 syntax_error(EMSG_UNEXP_EOS); 897 syntax_error(EMSG_UNEXP_EOS);
897 if ((*s++ = *p++) == '\\') { 898 *s++ = *p++;
899 if (*s++ == '\\') {
898 pp = p; 900 pp = p;
899 *(s-1) = bb_process_escape_sequence((const char **)&p); 901 *(s-1) = bb_process_escape_sequence((const char **)&p);
900 if (*pp == '\\') *s++ = '\\'; 902 if (*pp == '\\')
901 if (p == pp) *s++ = *p++; 903 *s++ = '\\';
904 if (p == pp)
905 *s++ = *p++;
902 } 906 }
903 } 907 }
904 p++; 908 p++;
@@ -927,9 +931,10 @@ static uint32_t next_token(uint32_t expected)
927 * matches and it's not a longer word, 931 * matches and it's not a longer word,
928 * then this is what we are looking for 932 * then this is what we are looking for
929 */ 933 */
930 if ((tc & (expected | TC_WORD | TC_NEWLINE)) && 934 if ((tc & (expected | TC_WORD | TC_NEWLINE))
931 *tl == *p && strncmp(p, tl, l) == 0 && 935 && *tl == *p && strncmp(p, tl, l) == 0
932 !((tc & TC_WORD) && isalnum_(*(p + l)))) { 936 && !((tc & TC_WORD) && isalnum_(p[l]))
937 ) {
933 ttt.info = *ti; 938 ttt.info = *ti;
934 p += l; 939 p += l;
935 break; 940 break;
@@ -952,7 +957,8 @@ static uint32_t next_token(uint32_t expected)
952 *(p-1) = '\0'; 957 *(p-1) = '\0';
953 tc = TC_VARIABLE; 958 tc = TC_VARIABLE;
954 /* also consume whitespace between functionname and bracket */ 959 /* also consume whitespace between functionname and bracket */
955 if (!(expected & TC_VARIABLE)) skip_spaces(&p); 960 if (!(expected & TC_VARIABLE))
961 skip_spaces(&p);
956 if (*p == '(') { 962 if (*p == '(') {
957 tc = TC_FUNCTION; 963 tc = TC_FUNCTION;
958 } else { 964 } else {
@@ -970,7 +976,7 @@ static uint32_t next_token(uint32_t expected)
970 goto readnext; 976 goto readnext;
971 977
972 /* insert concatenation operator when needed */ 978 /* insert concatenation operator when needed */
973 if ((ltclass&TC_CONCAT1) && (tc&TC_CONCAT2) && (expected&TC_BINOP)) { 979 if ((ltclass & TC_CONCAT1) && (tc & TC_CONCAT2) && (expected & TC_BINOP)) {
974 concat_inserted = TRUE; 980 concat_inserted = TRUE;
975 save_tclass = tc; 981 save_tclass = tc;
976 save_info = ttt.info; 982 save_info = ttt.info;
@@ -983,9 +989,9 @@ static uint32_t next_token(uint32_t expected)
983 ltclass = ttt.tclass; 989 ltclass = ttt.tclass;
984 990
985 /* Are we ready for this? */ 991 /* Are we ready for this? */
986 if (! (ltclass & expected)) 992 if (!(ltclass & expected))
987 syntax_error((ltclass & (TC_NEWLINE | TC_EOF)) ? 993 syntax_error((ltclass & (TC_NEWLINE | TC_EOF)) ?
988 EMSG_UNEXP_EOS : EMSG_UNEXP_TOKEN); 994 EMSG_UNEXP_EOS : EMSG_UNEXP_TOKEN);
989 995
990 return ltclass; 996 return ltclass;
991} 997}
@@ -1011,7 +1017,7 @@ static node *mk_re_node(const char *s, node *n, regex_t *re)
1011 n->l.re = re; 1017 n->l.re = re;
1012 n->r.ire = re + 1; 1018 n->r.ire = re + 1;
1013 xregcomp(re, s, REG_EXTENDED); 1019 xregcomp(re, s, REG_EXTENDED);
1014 xregcomp(re+1, s, REG_EXTENDED | REG_ICASE); 1020 xregcomp(re + 1, s, REG_EXTENDED | REG_ICASE);
1015 1021
1016 return n; 1022 return n;
1017} 1023}
@@ -1037,9 +1043,9 @@ static node *parse_expr(uint32_t iexp)
1037 xtc = TC_OPERAND | TC_UOPPRE | TC_REGEXP | iexp; 1043 xtc = TC_OPERAND | TC_UOPPRE | TC_REGEXP | iexp;
1038 1044
1039 while (!((tc = next_token(xtc)) & iexp)) { 1045 while (!((tc = next_token(xtc)) & iexp)) {
1040 if (glptr && (ttt.info == (OC_COMPARE|VV|P(39)|2))) { 1046 if (glptr && (ttt.info == (OC_COMPARE | VV | P(39) | 2))) {
1041 /* input redirection (<) attached to glptr node */ 1047 /* input redirection (<) attached to glptr node */
1042 cn = glptr->l.n = new_node(OC_CONCAT|SS|P(37)); 1048 cn = glptr->l.n = new_node(OC_CONCAT | SS | P(37));
1043 cn->a.n = glptr; 1049 cn->a.n = glptr;
1044 xtc = TC_OPERAND | TC_UOPPRE; 1050 xtc = TC_OPERAND | TC_UOPPRE;
1045 glptr = NULL; 1051 glptr = NULL;
@@ -1048,8 +1054,8 @@ static node *parse_expr(uint32_t iexp)
1048 /* for binary and postfix-unary operators, jump back over 1054 /* for binary and postfix-unary operators, jump back over
1049 * previous operators with higher priority */ 1055 * previous operators with higher priority */
1050 vn = cn; 1056 vn = cn;
1051 while ( ((ttt.info & PRIMASK) > (vn->a.n->info & PRIMASK2)) || 1057 while ( ((ttt.info & PRIMASK) > (vn->a.n->info & PRIMASK2))
1052 ((ttt.info == vn->info) && ((ttt.info & OPCLSMASK) == OC_COLON)) ) 1058 || ((ttt.info == vn->info) && ((ttt.info & OPCLSMASK) == OC_COLON)) )
1053 vn = vn->a.n; 1059 vn = vn->a.n;
1054 if ((ttt.info & OPCLSMASK) == OC_TERNARY) 1060 if ((ttt.info & OPCLSMASK) == OC_TERNARY)
1055 ttt.info += P(6); 1061 ttt.info += P(6);
@@ -1086,7 +1092,8 @@ static node *parse_expr(uint32_t iexp)
1086 case TC_VARIABLE: 1092 case TC_VARIABLE:
1087 case TC_ARRAY: 1093 case TC_ARRAY:
1088 cn->info = OC_VAR; 1094 cn->info = OC_VAR;
1089 if ((v = hash_search(ahash, ttt.string)) != NULL) { 1095 v = hash_search(ahash, ttt.string);
1096 if (v != NULL) {
1090 cn->info = OC_FNARG; 1097 cn->info = OC_FNARG;
1091 cn->l.i = v->x.aidx; 1098 cn->l.i = v->x.aidx;
1092 } else { 1099 } else {
@@ -1213,83 +1220,83 @@ static void chain_group(void)
1213 chain_expr(OC_EXEC | Vx); 1220 chain_expr(OC_EXEC | Vx);
1214 } else { /* TC_STATEMNT */ 1221 } else { /* TC_STATEMNT */
1215 switch (ttt.info & OPCLSMASK) { 1222 switch (ttt.info & OPCLSMASK) {
1216 case ST_IF: 1223 case ST_IF:
1217 n = chain_node(OC_BR | Vx); 1224 n = chain_node(OC_BR | Vx);
1218 n->l.n = condition(); 1225 n->l.n = condition();
1226 chain_group();
1227 n2 = chain_node(OC_EXEC);
1228 n->r.n = seq->last;
1229 if (next_token(TC_GRPSEQ | TC_GRPTERM | TC_ELSE) == TC_ELSE) {
1219 chain_group(); 1230 chain_group();
1220 n2 = chain_node(OC_EXEC); 1231 n2->a.n = seq->last;
1221 n->r.n = seq->last; 1232 } else {
1222 if (next_token(TC_GRPSEQ | TC_GRPTERM | TC_ELSE)==TC_ELSE) { 1233 rollback_token();
1223 chain_group(); 1234 }
1224 n2->a.n = seq->last; 1235 break;
1225 } else {
1226 rollback_token();
1227 }
1228 break;
1229 1236
1230 case ST_WHILE: 1237 case ST_WHILE:
1231 n2 = condition(); 1238 n2 = condition();
1232 n = chain_loop(NULL); 1239 n = chain_loop(NULL);
1233 n->l.n = n2; 1240 n->l.n = n2;
1234 break; 1241 break;
1235 1242
1236 case ST_DO: 1243 case ST_DO:
1237 n2 = chain_node(OC_EXEC); 1244 n2 = chain_node(OC_EXEC);
1238 n = chain_loop(NULL); 1245 n = chain_loop(NULL);
1239 n2->a.n = n->a.n; 1246 n2->a.n = n->a.n;
1240 next_token(TC_WHILE); 1247 next_token(TC_WHILE);
1241 n->l.n = condition(); 1248 n->l.n = condition();
1242 break; 1249 break;
1243 1250
1244 case ST_FOR: 1251 case ST_FOR:
1245 next_token(TC_SEQSTART); 1252 next_token(TC_SEQSTART);
1246 n2 = parse_expr(TC_SEMICOL | TC_SEQTERM); 1253 n2 = parse_expr(TC_SEMICOL | TC_SEQTERM);
1247 if (ttt.tclass & TC_SEQTERM) { /* for-in */ 1254 if (ttt.tclass & TC_SEQTERM) { /* for-in */
1248 if ((n2->info & OPCLSMASK) != OC_IN) 1255 if ((n2->info & OPCLSMASK) != OC_IN)
1249 syntax_error(EMSG_UNEXP_TOKEN); 1256 syntax_error(EMSG_UNEXP_TOKEN);
1250 n = chain_node(OC_WALKINIT | VV); 1257 n = chain_node(OC_WALKINIT | VV);
1251 n->l.n = n2->l.n; 1258 n->l.n = n2->l.n;
1252 n->r.n = n2->r.n; 1259 n->r.n = n2->r.n;
1253 n = chain_loop(NULL); 1260 n = chain_loop(NULL);
1254 n->info = OC_WALKNEXT | Vx; 1261 n->info = OC_WALKNEXT | Vx;
1255 n->l.n = n2->l.n; 1262 n->l.n = n2->l.n;
1256 } else { /* for (;;) */ 1263 } else { /* for (;;) */
1257 n = chain_node(OC_EXEC | Vx); 1264 n = chain_node(OC_EXEC | Vx);
1258 n->l.n = n2; 1265 n->l.n = n2;
1259 n2 = parse_expr(TC_SEMICOL); 1266 n2 = parse_expr(TC_SEMICOL);
1260 n3 = parse_expr(TC_SEQTERM); 1267 n3 = parse_expr(TC_SEQTERM);
1261 n = chain_loop(n3); 1268 n = chain_loop(n3);
1262 n->l.n = n2; 1269 n->l.n = n2;
1263 if (! n2) 1270 if (! n2)
1264 n->info = OC_EXEC; 1271 n->info = OC_EXEC;
1265 } 1272 }
1266 break; 1273 break;
1267 1274
1268 case OC_PRINT: 1275 case OC_PRINT:
1269 case OC_PRINTF: 1276 case OC_PRINTF:
1270 n = chain_node(ttt.info); 1277 n = chain_node(ttt.info);
1271 n->l.n = parse_expr(TC_OPTERM | TC_OUTRDR | TC_GRPTERM); 1278 n->l.n = parse_expr(TC_OPTERM | TC_OUTRDR | TC_GRPTERM);
1272 if (ttt.tclass & TC_OUTRDR) { 1279 if (ttt.tclass & TC_OUTRDR) {
1273 n->info |= ttt.info; 1280 n->info |= ttt.info;
1274 n->r.n = parse_expr(TC_OPTERM | TC_GRPTERM); 1281 n->r.n = parse_expr(TC_OPTERM | TC_GRPTERM);
1275 } 1282 }
1276 if (ttt.tclass & TC_GRPTERM) 1283 if (ttt.tclass & TC_GRPTERM)
1277 rollback_token(); 1284 rollback_token();
1278 break; 1285 break;
1279 1286
1280 case OC_BREAK: 1287 case OC_BREAK:
1281 n = chain_node(OC_EXEC); 1288 n = chain_node(OC_EXEC);
1282 n->a.n = break_ptr; 1289 n->a.n = break_ptr;
1283 break; 1290 break;
1284 1291
1285 case OC_CONTINUE: 1292 case OC_CONTINUE:
1286 n = chain_node(OC_EXEC); 1293 n = chain_node(OC_EXEC);
1287 n->a.n = continue_ptr; 1294 n->a.n = continue_ptr;
1288 break; 1295 break;
1289 1296
1290 /* delete, next, nextfile, return, exit */ 1297 /* delete, next, nextfile, return, exit */
1291 default: 1298 default:
1292 chain_expr(ttt.info); 1299 chain_expr(ttt.info);
1293 } 1300 }
1294 } 1301 }
1295} 1302}
@@ -1304,7 +1311,7 @@ static void parse_program(char *p)
1304 pos = p; 1311 pos = p;
1305 ttt.lineno = 1; 1312 ttt.lineno = 1;
1306 while ((tclass = next_token(TC_EOF | TC_OPSEQ | TC_GRPSTART | 1313 while ((tclass = next_token(TC_EOF | TC_OPSEQ | TC_GRPSTART |
1307 TC_OPTERM | TC_BEGIN | TC_END | TC_FUNCDECL)) != TC_EOF) { 1314 TC_OPTERM | TC_BEGIN | TC_END | TC_FUNCDECL)) != TC_EOF) {
1308 1315
1309 if (tclass & TC_OPTERM) 1316 if (tclass & TC_OPTERM)
1310 continue; 1317 continue;
@@ -1389,13 +1396,12 @@ static regex_t *as_regex(node *op, regex_t *preg)
1389 1396
1390 if ((op->info & OPCLSMASK) == OC_REGEXP) { 1397 if ((op->info & OPCLSMASK) == OC_REGEXP) {
1391 return icase ? op->r.ire : op->l.re; 1398 return icase ? op->r.ire : op->l.re;
1392 } else {
1393 v = nvalloc(1);
1394 s = getvar_s(evaluate(op, v));
1395 xregcomp(preg, s, icase ? REG_EXTENDED | REG_ICASE : REG_EXTENDED);
1396 nvfree(v);
1397 return preg;
1398 } 1399 }
1400 v = nvalloc(1);
1401 s = getvar_s(evaluate(op, v));
1402 xregcomp(preg, s, icase ? REG_EXTENDED | REG_ICASE : REG_EXTENDED);
1403 nvfree(v);
1404 return preg;
1399} 1405}
1400 1406
1401/* gradually increasing buffer */ 1407/* gradually increasing buffer */
@@ -1442,7 +1448,8 @@ static int awk_split(const char *s, node *spl, char **slist)
1442 1448
1443 c[0] = c[1] = (char)spl->info; 1449 c[0] = c[1] = (char)spl->info;
1444 c[2] = c[3] = '\0'; 1450 c[2] = c[3] = '\0';
1445 if (*getvar_s(V[RS]) == '\0') c[2] = '\n'; 1451 if (*getvar_s(intvar[RS]) == '\0')
1452 c[2] = '\n';
1446 1453
1447 if ((spl->info & OPCLSMASK) == OC_REGEXP) { /* regex split */ 1454 if ((spl->info & OPCLSMASK) == OC_REGEXP) { /* regex split */
1448 while (*s) { 1455 while (*s) {
@@ -1451,7 +1458,10 @@ static int awk_split(const char *s, node *spl, char **slist)
1451 && pmatch[0].rm_so <= l 1458 && pmatch[0].rm_so <= l
1452 ) { 1459 ) {
1453 l = pmatch[0].rm_so; 1460 l = pmatch[0].rm_so;
1454 if (pmatch[0].rm_eo == 0) { l++; pmatch[0].rm_eo++; } 1461 if (pmatch[0].rm_eo == 0) {
1462 l++;
1463 pmatch[0].rm_eo++;
1464 }
1455 } else { 1465 } else {
1456 pmatch[0].rm_eo = l; 1466 pmatch[0].rm_eo = l;
1457 if (s[l]) pmatch[0].rm_eo++; 1467 if (s[l]) pmatch[0].rm_eo++;
@@ -1495,6 +1505,7 @@ static int awk_split(const char *s, node *spl, char **slist)
1495static void split_f0(void) 1505static void split_f0(void)
1496{ 1506{
1497 static char *fstrings = NULL; 1507 static char *fstrings = NULL;
1508
1498 int i, n; 1509 int i, n;
1499 char *s; 1510 char *s;
1500 1511
@@ -1504,7 +1515,7 @@ static void split_f0(void)
1504 is_f0_split = TRUE; 1515 is_f0_split = TRUE;
1505 free(fstrings); 1516 free(fstrings);
1506 fsrealloc(0); 1517 fsrealloc(0);
1507 n = awk_split(getvar_s(V[F0]), &fsplitter.n, &fstrings); 1518 n = awk_split(getvar_s(intvar[F0]), &fsplitter.n, &fstrings);
1508 fsrealloc(n); 1519 fsrealloc(n);
1509 s = fstrings; 1520 s = fstrings;
1510 for (i = 0; i < n; i++) { 1521 for (i = 0; i < n; i++) {
@@ -1513,9 +1524,9 @@ static void split_f0(void)
1513 } 1524 }
1514 1525
1515 /* set NF manually to avoid side effects */ 1526 /* set NF manually to avoid side effects */
1516 clrvar(V[NF]); 1527 clrvar(intvar[NF]);
1517 V[NF]->type = VF_NUMBER | VF_SPECIAL; 1528 intvar[NF]->type = VF_NUMBER | VF_SPECIAL;
1518 V[NF]->number = nfields; 1529 intvar[NF]->number = nfields;
1519} 1530}
1520 1531
1521/* perform additional actions when some internal variables changed */ 1532/* perform additional actions when some internal variables changed */
@@ -1529,16 +1540,16 @@ static void handle_special(var *v)
1529 if (!(v->type & VF_SPECIAL)) 1540 if (!(v->type & VF_SPECIAL))
1530 return; 1541 return;
1531 1542
1532 if (v == V[NF]) { 1543 if (v == intvar[NF]) {
1533 n = (int)getvar_i(v); 1544 n = (int)getvar_i(v);
1534 fsrealloc(n); 1545 fsrealloc(n);
1535 1546
1536 /* recalculate $0 */ 1547 /* recalculate $0 */
1537 sep = getvar_s(V[OFS]); 1548 sep = getvar_s(intvar[OFS]);
1538 sl = strlen(sep); 1549 sl = strlen(sep);
1539 b = NULL; 1550 b = NULL;
1540 len = 0; 1551 len = 0;
1541 for (i=0; i<n; i++) { 1552 for (i = 0; i < n; i++) {
1542 s = getvar_s(&Fields[i]); 1553 s = getvar_s(&Fields[i]);
1543 l = strlen(s); 1554 l = strlen(s);
1544 if (b) { 1555 if (b) {
@@ -1551,24 +1562,24 @@ static void handle_special(var *v)
1551 } 1562 }
1552 if (b) 1563 if (b)
1553 b[len] = '\0'; 1564 b[len] = '\0';
1554 setvar_p(V[F0], b); 1565 setvar_p(intvar[F0], b);
1555 is_f0_split = TRUE; 1566 is_f0_split = TRUE;
1556 1567
1557 } else if (v == V[F0]) { 1568 } else if (v == intvar[F0]) {
1558 is_f0_split = FALSE; 1569 is_f0_split = FALSE;
1559 1570
1560 } else if (v == V[FS]) { 1571 } else if (v == intvar[FS]) {
1561 mk_splitter(getvar_s(v), &fsplitter); 1572 mk_splitter(getvar_s(v), &fsplitter);
1562 1573
1563 } else if (v == V[RS]) { 1574 } else if (v == intvar[RS]) {
1564 mk_splitter(getvar_s(v), &rsplitter); 1575 mk_splitter(getvar_s(v), &rsplitter);
1565 1576
1566 } else if (v == V[IGNORECASE]) { 1577 } else if (v == intvar[IGNORECASE]) {
1567 icase = istrue(v); 1578 icase = istrue(v);
1568 1579
1569 } else { /* $n */ 1580 } else { /* $n */
1570 n = getvar_i(V[NF]); 1581 n = getvar_i(intvar[NF]);
1571 setvar_i(V[NF], n > v-Fields ? n : v-Fields+1); 1582 setvar_i(intvar[NF], n > v-Fields ? n : v-Fields+1);
1572 /* right here v is invalid. Just to note... */ 1583 /* right here v is invalid. Just to note... */
1573 } 1584 }
1574} 1585}
@@ -1599,8 +1610,8 @@ static void hashwalk_init(var *v, xhash *array)
1599 1610
1600 v->type |= VF_WALK; 1611 v->type |= VF_WALK;
1601 w = v->x.walker = xzalloc(2 + 2*sizeof(char *) + array->glen); 1612 w = v->x.walker = xzalloc(2 + 2*sizeof(char *) + array->glen);
1602 *w = *(w+1) = (char *)(w + 2); 1613 w[0] = w[1] = (char *)(w + 2);
1603 for (i=0; i<array->csize; i++) { 1614 for (i = 0; i < array->csize; i++) {
1604 hi = array->items[i]; 1615 hi = array->items[i];
1605 while (hi) { 1616 while (hi) {
1606 strcpy(*w, hi->name); 1617 strcpy(*w, hi->name);
@@ -1615,7 +1626,7 @@ static int hashwalk_next(var *v)
1615 char **w; 1626 char **w;
1616 1627
1617 w = v->x.walker; 1628 w = v->x.walker;
1618 if (*(w+1) == *w) 1629 if (w[1] == w[0])
1619 return FALSE; 1630 return FALSE;
1620 1631
1621 setvar_s(v, nextword(w+1)); 1632 setvar_s(v, nextword(w+1));
@@ -1658,7 +1669,7 @@ static int awk_getline(rstream *rsm, var *v)
1658 if (p > 0) { 1669 if (p > 0) {
1659 if ((rsplitter.n.info & OPCLSMASK) == OC_REGEXP) { 1670 if ((rsplitter.n.info & OPCLSMASK) == OC_REGEXP) {
1660 if (regexec(icase ? rsplitter.n.r.ire : rsplitter.n.l.re, 1671 if (regexec(icase ? rsplitter.n.r.ire : rsplitter.n.l.re,
1661 b, 1, pmatch, 0) == 0) { 1672 b, 1, pmatch, 0) == 0) {
1662 so = pmatch[0].rm_so; 1673 so = pmatch[0].rm_so;
1663 eo = pmatch[0].rm_eo; 1674 eo = pmatch[0].rm_eo;
1664 if (b[eo] != '\0') 1675 if (b[eo] != '\0')
@@ -1698,7 +1709,7 @@ static int awk_getline(rstream *rsm, var *v)
1698 if (p < pp) { 1709 if (p < pp) {
1699 p = 0; 1710 p = 0;
1700 r = 0; 1711 r = 0;
1701 setvar_i(V[ERRNO], errno); 1712 setvar_i(intvar[ERRNO], errno);
1702 } 1713 }
1703 b[p] = '\0'; 1714 b[p] = '\0';
1704 1715
@@ -1712,7 +1723,7 @@ static int awk_getline(rstream *rsm, var *v)
1712 v->type |= VF_USER; 1723 v->type |= VF_USER;
1713 b[so] = c; 1724 b[so] = c;
1714 c = b[eo]; b[eo] = '\0'; 1725 c = b[eo]; b[eo] = '\0';
1715 setvar_s(V[RT], b+so); 1726 setvar_s(intvar[RT], b+so);
1716 b[eo] = c; 1727 b[eo] = c;
1717 } 1728 }
1718 1729
@@ -1782,12 +1793,10 @@ static char *awk_printf(node *n)
1782 if (c == 'c' || !c) { 1793 if (c == 'c' || !c) {
1783 i += sprintf(b+i, s, is_numeric(arg) ? 1794 i += sprintf(b+i, s, is_numeric(arg) ?
1784 (char)getvar_i(arg) : *getvar_s(arg)); 1795 (char)getvar_i(arg) : *getvar_s(arg));
1785
1786 } else if (c == 's') { 1796 } else if (c == 's') {
1787 s1 = getvar_s(arg); 1797 s1 = getvar_s(arg);
1788 qrealloc(&b, incr+i+strlen(s1), &bsize); 1798 qrealloc(&b, incr+i+strlen(s1), &bsize);
1789 i += sprintf(b+i, s, s1); 1799 i += sprintf(b+i, s, s1);
1790
1791 } else { 1800 } else {
1792 i += fmt_num(b+i, incr, s, getvar_i(arg), FALSE); 1801 i += fmt_num(b+i, incr, s, getvar_i(arg), FALSE);
1793 } 1802 }
@@ -1820,13 +1829,13 @@ static int awk_sub(node *rn, const char *repl, int nm, var *src, var *dest, int
1820 regex_t sreg, *re; 1829 regex_t sreg, *re;
1821 1830
1822 re = as_regex(rn, &sreg); 1831 re = as_regex(rn, &sreg);
1823 if (! src) src = V[F0]; 1832 if (! src) src = intvar[F0];
1824 if (! dest) dest = V[F0]; 1833 if (! dest) dest = intvar[F0];
1825 1834
1826 i = di = 0; 1835 i = di = 0;
1827 sp = getvar_s(src); 1836 sp = getvar_s(src);
1828 rl = strlen(repl); 1837 rl = strlen(repl);
1829 while (regexec(re, sp, 10, pmatch, sp==getvar_s(src) ? 0:REG_NOTBOL) == 0) { 1838 while (regexec(re, sp, 10, pmatch, sp==getvar_s(src) ? 0 : REG_NOTBOL) == 0) {
1830 so = pmatch[0].rm_so; 1839 so = pmatch[0].rm_so;
1831 eo = pmatch[0].rm_eo; 1840 eo = pmatch[0].rm_eo;
1832 1841
@@ -1882,7 +1891,7 @@ static var *exec_builtin(node *op, var *res)
1882 int (*to_xxx)(int); 1891 int (*to_xxx)(int);
1883 var *tv; 1892 var *tv;
1884 node *an[4]; 1893 node *an[4];
1885 var *av[4]; 1894 var *av[4];
1886 const char *as[4]; 1895 const char *as[4];
1887 regmatch_t pmatch[2]; 1896 regmatch_t pmatch[2];
1888 regex_t sreg, *re; 1897 regex_t sreg, *re;
@@ -1899,7 +1908,7 @@ static var *exec_builtin(node *op, var *res)
1899 op = op->l.n; 1908 op = op->l.n;
1900 1909
1901 av[2] = av[3] = NULL; 1910 av[2] = av[3] = NULL;
1902 for (i=0 ; i<4 && op ; i++) { 1911 for (i = 0; i < 4 && op; i++) {
1903 an[i] = nextarg(&op); 1912 an[i] = nextarg(&op);
1904 if (isr & 0x09000000) av[i] = evaluate(an[i], &tv[i]); 1913 if (isr & 0x09000000) av[i] = evaluate(an[i], &tv[i]);
1905 if (isr & 0x08000000) as[i] = getvar_s(av[i]); 1914 if (isr & 0x08000000) as[i] = getvar_s(av[i]);
@@ -1940,9 +1949,10 @@ static var *exec_builtin(node *op, var *res)
1940 case B_ss: 1949 case B_ss:
1941 l = strlen(as[0]); 1950 l = strlen(as[0]);
1942 i = getvar_i(av[1]) - 1; 1951 i = getvar_i(av[1]) - 1;
1943 if (i>l) i=l; if (i<0) i=0; 1952 if (i > l) i = l;
1953 if (i < 0) i = 0;
1944 n = (nargs > 2) ? getvar_i(av[2]) : l-i; 1954 n = (nargs > 2) ? getvar_i(av[2]) : l-i;
1945 if (n<0) n=0; 1955 if (n < 0) n = 0;
1946 s = xmalloc(n+1); 1956 s = xmalloc(n+1);
1947 strncpy(s, as[0]+i, n); 1957 strncpy(s, as[0]+i, n);
1948 s[n] = '\0'; 1958 s[n] = '\0';
@@ -2168,22 +2178,22 @@ static var *evaluate(node *op, var *res)
2168 2178
2169 if ((opinfo & OPCLSMASK) == OC_PRINT) { 2179 if ((opinfo & OPCLSMASK) == OC_PRINT) {
2170 if (! op1) { 2180 if (! op1) {
2171 fputs(getvar_s(V[F0]), X.F); 2181 fputs(getvar_s(intvar[F0]), X.F);
2172 } else { 2182 } else {
2173 while (op1) { 2183 while (op1) {
2174 L.v = evaluate(nextarg(&op1), v1); 2184 L.v = evaluate(nextarg(&op1), v1);
2175 if (L.v->type & VF_NUMBER) { 2185 if (L.v->type & VF_NUMBER) {
2176 fmt_num(buf, MAXVARFMT, getvar_s(V[OFMT]), 2186 fmt_num(buf, MAXVARFMT, getvar_s(intvar[OFMT]),
2177 getvar_i(L.v), TRUE); 2187 getvar_i(L.v), TRUE);
2178 fputs(buf, X.F); 2188 fputs(buf, X.F);
2179 } else { 2189 } else {
2180 fputs(getvar_s(L.v), X.F); 2190 fputs(getvar_s(L.v), X.F);
2181 } 2191 }
2182 2192
2183 if (op1) fputs(getvar_s(V[OFS]), X.F); 2193 if (op1) fputs(getvar_s(intvar[OFS]), X.F);
2184 } 2194 }
2185 } 2195 }
2186 fputs(getvar_s(V[ORS]), X.F); 2196 fputs(getvar_s(intvar[ORS]), X.F);
2187 2197
2188 } else { /* OC_PRINTF */ 2198 } else { /* OC_PRINTF */
2189 L.s = awk_printf(op1); 2199 L.s = awk_printf(op1);
@@ -2235,7 +2245,7 @@ static var *evaluate(node *op, var *res)
2235 2245
2236 case XC( OC_VAR ): 2246 case XC( OC_VAR ):
2237 L.v = op->l.v; 2247 L.v = op->l.v;
2238 if (L.v == V[NF]) 2248 if (L.v == intvar[NF])
2239 split_f0(); 2249 split_f0();
2240 goto v_cont; 2250 goto v_cont;
2241 2251
@@ -2251,7 +2261,7 @@ static var *evaluate(node *op, var *res)
2251 2261
2252 case XC( OC_REGEXP ): 2262 case XC( OC_REGEXP ):
2253 op1 = op; 2263 op1 = op;
2254 L.s = getvar_s(V[F0]); 2264 L.s = getvar_s(intvar[F0]);
2255 goto re_cont; 2265 goto re_cont;
2256 2266
2257 case XC( OC_MATCH ): 2267 case XC( OC_MATCH ):
@@ -2280,7 +2290,7 @@ static var *evaluate(node *op, var *res)
2280 break; 2290 break;
2281 2291
2282 case XC( OC_FUNC ): 2292 case XC( OC_FUNC ):
2283 if (! op->r.f->body.first) 2293 if (!op->r.f->body.first)
2284 runtime_error(EMSG_UNDEF_FUNC); 2294 runtime_error(EMSG_UNDEF_FUNC);
2285 2295
2286 X.v = R.v = nvalloc(op->r.f->nargs+1); 2296 X.v = R.v = nvalloc(op->r.f->nargs+1);
@@ -2308,7 +2318,7 @@ static var *evaluate(node *op, var *res)
2308 case XC( OC_PGETLINE ): 2318 case XC( OC_PGETLINE ):
2309 if (op1) { 2319 if (op1) {
2310 X.rsm = newfile(L.s); 2320 X.rsm = newfile(L.s);
2311 if (! X.rsm->F) { 2321 if (!X.rsm->F) {
2312 if ((opinfo & OPCLSMASK) == OC_PGETLINE) { 2322 if ((opinfo & OPCLSMASK) == OC_PGETLINE) {
2313 X.rsm->F = popen(L.s, "r"); 2323 X.rsm->F = popen(L.s, "r");
2314 X.rsm->is_pipe = TRUE; 2324 X.rsm->is_pipe = TRUE;
@@ -2317,24 +2327,24 @@ static var *evaluate(node *op, var *res)
2317 } 2327 }
2318 } 2328 }
2319 } else { 2329 } else {
2320 if (! iF) iF = next_input_file(); 2330 if (!iF) iF = next_input_file();
2321 X.rsm = iF; 2331 X.rsm = iF;
2322 } 2332 }
2323 2333
2324 if (! X.rsm->F) { 2334 if (!X.rsm->F) {
2325 setvar_i(V[ERRNO], errno); 2335 setvar_i(intvar[ERRNO], errno);
2326 setvar_i(res, -1); 2336 setvar_i(res, -1);
2327 break; 2337 break;
2328 } 2338 }
2329 2339
2330 if (! op->r.n) 2340 if (!op->r.n)
2331 R.v = V[F0]; 2341 R.v = intvar[F0];
2332 2342
2333 L.i = awk_getline(X.rsm, R.v); 2343 L.i = awk_getline(X.rsm, R.v);
2334 if (L.i > 0) { 2344 if (L.i > 0) {
2335 if (! op1) { 2345 if (!op1) {
2336 incvar(V[FNR]); 2346 incvar(intvar[FNR]);
2337 incvar(V[NR]); 2347 incvar(intvar[NR]);
2338 } 2348 }
2339 } 2349 }
2340 setvar_i(res, L.i); 2350 setvar_i(res, L.i);
@@ -2391,8 +2401,8 @@ static var *evaluate(node *op, var *res)
2391 break; 2401 break;
2392 2402
2393 case F_le: 2403 case F_le:
2394 if (! op1) 2404 if (!op1)
2395 L.s = getvar_s(V[F0]); 2405 L.s = getvar_s(intvar[F0]);
2396 R.d = strlen(L.s); 2406 R.d = strlen(L.s);
2397 break; 2407 break;
2398 2408
@@ -2403,7 +2413,7 @@ static var *evaluate(node *op, var *res)
2403 break; 2413 break;
2404 2414
2405 case F_ff: 2415 case F_ff:
2406 if (! op1) 2416 if (!op1)
2407 fflush(stdout); 2417 fflush(stdout);
2408 else { 2418 else {
2409 if (L.s && *L.s) { 2419 if (L.s && *L.s) {
@@ -2423,7 +2433,7 @@ static var *evaluate(node *op, var *res)
2423 hash_remove(fdhash, L.s); 2433 hash_remove(fdhash, L.s);
2424 } 2434 }
2425 if (R.i != 0) 2435 if (R.i != 0)
2426 setvar_i(V[ERRNO], errno); 2436 setvar_i(intvar[ERRNO], errno);
2427 R.d = (double)R.i; 2437 R.d = (double)R.i;
2428 break; 2438 break;
2429 } 2439 }
@@ -2469,13 +2479,12 @@ static var *evaluate(node *op, var *res)
2469 case XC( OC_FIELD ): 2479 case XC( OC_FIELD ):
2470 R.i = (int)getvar_i(R.v); 2480 R.i = (int)getvar_i(R.v);
2471 if (R.i == 0) { 2481 if (R.i == 0) {
2472 res = V[F0]; 2482 res = intvar[F0];
2473 } else { 2483 } else {
2474 split_f0(); 2484 split_f0();
2475 if (R.i > nfields) 2485 if (R.i > nfields)
2476 fsrealloc(R.i); 2486 fsrealloc(R.i);
2477 2487 res = &Fields[R.i - 1];
2478 res = &Fields[R.i-1];
2479 } 2488 }
2480 break; 2489 break;
2481 2490
@@ -2486,7 +2495,7 @@ static var *evaluate(node *op, var *res)
2486 X.s = xmalloc(opn); 2495 X.s = xmalloc(opn);
2487 strcpy(X.s, L.s); 2496 strcpy(X.s, L.s);
2488 if ((opinfo & OPCLSMASK) == OC_COMMA) { 2497 if ((opinfo & OPCLSMASK) == OC_COMMA) {
2489 L.s = getvar_s(V[SUBSEP]); 2498 L.s = getvar_s(intvar[SUBSEP]);
2490 X.s = xrealloc(X.s, opn + strlen(L.s)); 2499 X.s = xrealloc(X.s, opn + strlen(L.s));
2491 strcat(X.s, L.s); 2500 strcat(X.s, L.s);
2492 } 2501 }
@@ -2531,7 +2540,7 @@ static var *evaluate(node *op, var *res)
2531 L.d -= (int)(L.d / R.d) * R.d; 2540 L.d -= (int)(L.d / R.d) * R.d;
2532 break; 2541 break;
2533 } 2542 }
2534 res = setvar_i(((opinfo&OPCLSMASK) == OC_BINARY) ? res : X.v, L.d); 2543 res = setvar_i(((opinfo & OPCLSMASK) == OC_BINARY) ? res : X.v, L.d);
2535 break; 2544 break;
2536 2545
2537 case XC( OC_COMPARE ): 2546 case XC( OC_COMPARE ):
@@ -2627,30 +2636,31 @@ static int is_assignment(const char *expr)
2627static rstream *next_input_file(void) 2636static rstream *next_input_file(void)
2628{ 2637{
2629 static rstream rsm; 2638 static rstream rsm;
2639 static int files_happen = FALSE;
2640
2630 FILE *F = NULL; 2641 FILE *F = NULL;
2631 const char *fname, *ind; 2642 const char *fname, *ind;
2632 static int files_happen = FALSE;
2633 2643
2634 if (rsm.F) fclose(rsm.F); 2644 if (rsm.F) fclose(rsm.F);
2635 rsm.F = NULL; 2645 rsm.F = NULL;
2636 rsm.pos = rsm.adv = 0; 2646 rsm.pos = rsm.adv = 0;
2637 2647
2638 do { 2648 do {
2639 if (getvar_i(V[ARGIND])+1 >= getvar_i(V[ARGC])) { 2649 if (getvar_i(intvar[ARGIND])+1 >= getvar_i(intvar[ARGC])) {
2640 if (files_happen) 2650 if (files_happen)
2641 return NULL; 2651 return NULL;
2642 fname = "-"; 2652 fname = "-";
2643 F = stdin; 2653 F = stdin;
2644 } else { 2654 } else {
2645 ind = getvar_s(incvar(V[ARGIND])); 2655 ind = getvar_s(incvar(intvar[ARGIND]));
2646 fname = getvar_s(findvar(iamarray(V[ARGV]), ind)); 2656 fname = getvar_s(findvar(iamarray(intvar[ARGV]), ind));
2647 if (fname && *fname && !is_assignment(fname)) 2657 if (fname && *fname && !is_assignment(fname))
2648 F = afopen(fname, "r"); 2658 F = afopen(fname, "r");
2649 } 2659 }
2650 } while (!F); 2660 } while (!F);
2651 2661
2652 files_happen = TRUE; 2662 files_happen = TRUE;
2653 setvar_s(V[FILENAME], fname); 2663 setvar_s(intvar[FILENAME], fname);
2654 rsm.F = F; 2664 rsm.F = F;
2655 return &rsm; 2665 return &rsm;
2656} 2666}
@@ -2685,7 +2695,7 @@ int awk_main(int argc, char **argv)
2685 2695
2686 /* initialize variables */ 2696 /* initialize variables */
2687 for (i = 0; *vnames; i++) { 2697 for (i = 0; *vnames; i++) {
2688 V[i] = v = newvar(nextword(&vnames)); 2698 intvar[i] = v = newvar(nextword(&vnames));
2689 if (*vvalues != '\377') 2699 if (*vvalues != '\377')
2690 setvar_s(v, nextword(&vvalues)); 2700 setvar_s(v, nextword(&vvalues));
2691 else 2701 else
@@ -2697,8 +2707,8 @@ int awk_main(int argc, char **argv)
2697 } 2707 }
2698 } 2708 }
2699 2709
2700 handle_special(V[FS]); 2710 handle_special(intvar[FS]);
2701 handle_special(V[RS]); 2711 handle_special(intvar[RS]);
2702 2712
2703 newfile("/dev/stdin")->F = stdin; 2713 newfile("/dev/stdin")->F = stdin;
2704 newfile("/dev/stdout")->F = stdout; 2714 newfile("/dev/stdout")->F = stdout;
@@ -2710,7 +2720,7 @@ int awk_main(int argc, char **argv)
2710 char *s1 = strchr(s, '='); 2720 char *s1 = strchr(s, '=');
2711 if (s1) { 2721 if (s1) {
2712 *s1++ = '\0'; 2722 *s1++ = '\0';
2713 setvar_u(findvar(iamarray(V[ENVIRON]), s), s1); 2723 setvar_u(findvar(iamarray(intvar[ENVIRON]), s), s1);
2714 } 2724 }
2715 free(s); 2725 free(s);
2716 } 2726 }
@@ -2718,7 +2728,8 @@ int awk_main(int argc, char **argv)
2718 opt = getopt32(argc, argv, "F:v:f:W:", &opt_F, &opt_v, &programname, &opt_W); 2728 opt = getopt32(argc, argv, "F:v:f:W:", &opt_F, &opt_v, &programname, &opt_W);
2719 argv += optind; 2729 argv += optind;
2720 argc -= optind; 2730 argc -= optind;
2721 if (opt & 0x1) setvar_s(V[FS], opt_F); // -F 2731 if (opt & 0x1)
2732 setvar_s(intvar[FS], opt_F); // -F
2722 while (opt_v) { /* -v */ 2733 while (opt_v) { /* -v */
2723 if (!is_assignment(llist_pop(&opt_v))) 2734 if (!is_assignment(llist_pop(&opt_v)))
2724 bb_show_usage(); 2735 bb_show_usage();
@@ -2753,11 +2764,11 @@ int awk_main(int argc, char **argv)
2753 bb_error_msg("warning: unrecognized option '-W %s' ignored", opt_W); 2764 bb_error_msg("warning: unrecognized option '-W %s' ignored", opt_W);
2754 2765
2755 /* fill in ARGV array */ 2766 /* fill in ARGV array */
2756 setvar_i(V[ARGC], argc + 1); 2767 setvar_i(intvar[ARGC], argc + 1);
2757 setari_u(V[ARGV], 0, "awk"); 2768 setari_u(intvar[ARGV], 0, "awk");
2758 i = 0; 2769 i = 0;
2759 while (*argv) 2770 while (*argv)
2760 setari_u(V[ARGV], ++i, *argv++); 2771 setari_u(intvar[ARGV], ++i, *argv++);
2761 2772
2762 evaluate(beginseq.first, &tv); 2773 evaluate(beginseq.first, &tv);
2763 if (!mainseq.first && !endseq.first) 2774 if (!mainseq.first && !endseq.first)
@@ -2769,12 +2780,12 @@ int awk_main(int argc, char **argv)
2769 /* passing through input files */ 2780 /* passing through input files */
2770 while (iF) { 2781 while (iF) {
2771 nextfile = FALSE; 2782 nextfile = FALSE;
2772 setvar_i(V[FNR], 0); 2783 setvar_i(intvar[FNR], 0);
2773 2784
2774 while ((i = awk_getline(iF, V[F0])) > 0) { 2785 while ((i = awk_getline(iF, intvar[F0])) > 0) {
2775 nextrec = FALSE; 2786 nextrec = FALSE;
2776 incvar(V[NR]); 2787 incvar(intvar[NR]);
2777 incvar(V[FNR]); 2788 incvar(intvar[FNR]);
2778 evaluate(mainseq.first, &tv); 2789 evaluate(mainseq.first, &tv);
2779 2790
2780 if (nextfile) 2791 if (nextfile)