diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-05-17 23:03:35 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-05-17 23:03:35 +0000 |
commit | ffba941d29afd609e0c7e39501a4542fac9a0ff0 (patch) | |
tree | 6de113dc1a2c433e8c885af23d4990ee72f71598 | |
parent | 5b340830045aa3dc6ca01cd1c6082b09161877d2 (diff) | |
download | busybox-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.c | 491 |
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 | ||
72 | typedef struct hash_item_s { | 72 | typedef 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 | ||
82 | typedef struct xhash_s { | 82 | typedef 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 | ||
224 | enum { | 224 | enum { |
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 */ |
247 | enum { | 247 | enum { |
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 */ |
253 | enum { | 253 | enum { |
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 */ |
367 | enum { | 367 | enum { |
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 | ||
376 | static const char vNames[] = | 376 | static 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; |
392 | static const unsigned PRIMES[] = { 251, 1021, 4093, 16381, 65521 }; | 392 | static const unsigned PRIMES[] = { 251, 1021, 4093, 16381, 65521 }; |
393 | enum { NPRIMES = sizeof(PRIMES) / sizeof(unsigned) }; | 393 | enum { NPRIMES = sizeof(PRIMES) / sizeof(PRIMES[0]) }; |
394 | 394 | ||
395 | /* globals */ | 395 | /* globals */ |
396 | 396 | ||
397 | static var * V[_intvarcount_]; | 397 | static var *intvar[NUM_INTERNAL_VARS]; |
398 | static chain beginseq, mainseq, endseq, *seq; | 398 | static chain beginseq, mainseq, endseq, *seq; |
399 | static int nextrec, nextfile; | 399 | static int nextrec, nextfile; |
400 | static node *break_ptr, *continue_ptr; | 400 | static 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 */ |
426 | static void handle_special(var *); | 427 | static 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 | ||
556 | static void hash_remove(xhash *hash, const char *name) | 557 | static 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 */ |
693 | static void setari_u(var *a, int idx, const char *s) | 693 | static 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) | |||
1495 | static void split_f0(void) | 1505 | static 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) | |||
2627 | static rstream *next_input_file(void) | 2636 | static 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) |