aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-01-01 23:51:30 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-01-01 23:51:30 +0000
commitf782f52c8cab1457d9e912b8bf2afdde6d170816 (patch)
tree232224d85ecc50c7204fa96f0fce43eb70bca586
parentb2abef3e54de606ced5082d82e381dbafef1bf72 (diff)
downloadbusybox-w32-f782f52c8cab1457d9e912b8bf2afdde6d170816.tar.gz
busybox-w32-f782f52c8cab1457d9e912b8bf2afdde6d170816.tar.bz2
busybox-w32-f782f52c8cab1457d9e912b8bf2afdde6d170816.zip
awk: style cleanup. A lot of rw data moved to ro
(still has quite a lot of statics etc...). getopt32-ification.
-rw-r--r--editors/awk.c587
1 files changed, 293 insertions, 294 deletions
diff --git a/editors/awk.c b/editors/awk.c
index 5a500aa83..97e78163c 100644
--- a/editors/awk.c
+++ b/editors/awk.c
@@ -77,10 +77,10 @@ typedef struct hash_item_s {
77} hash_item; 77} hash_item;
78 78
79typedef struct xhash_s { 79typedef struct xhash_s {
80 unsigned int nel; /* num of elements */ 80 unsigned nel; /* num of elements */
81 unsigned int csize; /* current hash size */ 81 unsigned csize; /* current hash size */
82 unsigned int nprime; /* next hash size in PRIMES[] */ 82 unsigned nprime; /* next hash size in PRIMES[] */
83 unsigned int glen; /* summary length of item names */ 83 unsigned glen; /* summary length of item names */
84 struct hash_item_s **items; 84 struct hash_item_s **items;
85} xhash; 85} xhash;
86 86
@@ -260,88 +260,87 @@ enum {
260 260
261#define OC_B OC_BUILTIN 261#define OC_B OC_BUILTIN
262 262
263static char * const tokenlist = 263static const char tokenlist[] =
264 "\1(" NTC 264 "\1(" NTC
265 "\1)" NTC 265 "\1)" NTC
266 "\1/" NTC /* REGEXP */ 266 "\1/" NTC /* REGEXP */
267 "\2>>" "\1>" "\1|" NTC /* OUTRDR */ 267 "\2>>" "\1>" "\1|" NTC /* OUTRDR */
268 "\2++" "\2--" NTC /* UOPPOST */ 268 "\2++" "\2--" NTC /* UOPPOST */
269 "\2++" "\2--" "\1$" NTC /* UOPPRE1 */ 269 "\2++" "\2--" "\1$" NTC /* UOPPRE1 */
270 "\2==" "\1=" "\2+=" "\2-=" /* BINOPX */ 270 "\2==" "\1=" "\2+=" "\2-=" /* BINOPX */
271 "\2*=" "\2/=" "\2%=" "\2^=" 271 "\2*=" "\2/=" "\2%=" "\2^="
272 "\1+" "\1-" "\3**=" "\2**" 272 "\1+" "\1-" "\3**=" "\2**"
273 "\1/" "\1%" "\1^" "\1*" 273 "\1/" "\1%" "\1^" "\1*"
274 "\2!=" "\2>=" "\2<=" "\1>" 274 "\2!=" "\2>=" "\2<=" "\1>"
275 "\1<" "\2!~" "\1~" "\2&&" 275 "\1<" "\2!~" "\1~" "\2&&"
276 "\2||" "\1?" "\1:" NTC 276 "\2||" "\1?" "\1:" NTC
277 "\2in" NTC 277 "\2in" NTC
278 "\1," NTC 278 "\1," NTC
279 "\1|" NTC 279 "\1|" NTC
280 "\1+" "\1-" "\1!" NTC /* UOPPRE2 */ 280 "\1+" "\1-" "\1!" NTC /* UOPPRE2 */
281 "\1]" NTC 281 "\1]" NTC
282 "\1{" NTC 282 "\1{" NTC
283 "\1}" NTC 283 "\1}" NTC
284 "\1;" NTC 284 "\1;" NTC
285 "\1\n" NTC 285 "\1\n" NTC
286 "\2if" "\2do" "\3for" "\5break" /* STATX */ 286 "\2if" "\2do" "\3for" "\5break" /* STATX */
287 "\10continue" "\6delete" "\5print" 287 "\10continue" "\6delete" "\5print"
288 "\6printf" "\4next" "\10nextfile" 288 "\6printf" "\4next" "\10nextfile"
289 "\6return" "\4exit" NTC 289 "\6return" "\4exit" NTC
290 "\5while" NTC 290 "\5while" NTC
291 "\4else" NTC 291 "\4else" NTC
292 292
293 "\3and" "\5compl" "\6lshift" "\2or" 293 "\3and" "\5compl" "\6lshift" "\2or"
294 "\6rshift" "\3xor" 294 "\6rshift" "\3xor"
295 "\5close" "\6system" "\6fflush" "\5atan2" /* BUILTIN */ 295 "\5close" "\6system" "\6fflush" "\5atan2" /* BUILTIN */
296 "\3cos" "\3exp" "\3int" "\3log" 296 "\3cos" "\3exp" "\3int" "\3log"
297 "\4rand" "\3sin" "\4sqrt" "\5srand" 297 "\4rand" "\3sin" "\4sqrt" "\5srand"
298 "\6gensub" "\4gsub" "\5index" "\6length" 298 "\6gensub" "\4gsub" "\5index" "\6length"
299 "\5match" "\5split" "\7sprintf" "\3sub" 299 "\5match" "\5split" "\7sprintf" "\3sub"
300 "\6substr" "\7systime" "\10strftime" 300 "\6substr" "\7systime" "\10strftime"
301 "\7tolower" "\7toupper" NTC 301 "\7tolower" "\7toupper" NTC
302 "\7getline" NTC 302 "\7getline" NTC
303 "\4func" "\10function" NTC 303 "\4func" "\10function" NTC
304 "\5BEGIN" NTC 304 "\5BEGIN" NTC
305 "\3END" "\0" 305 "\3END" "\0"
306 ; 306 ;
307 307
308static const uint32_t tokeninfo[] = { 308static const uint32_t tokeninfo[] = {
309
310 0, 309 0,
311 0, 310 0,
312 OC_REGEXP, 311 OC_REGEXP,
313 xS|'a', xS|'w', xS|'|', 312 xS|'a', xS|'w', xS|'|',
314 OC_UNARY|xV|P(9)|'p', OC_UNARY|xV|P(9)|'m', 313 OC_UNARY|xV|P(9)|'p', OC_UNARY|xV|P(9)|'m',
315 OC_UNARY|xV|P(9)|'P', OC_UNARY|xV|P(9)|'M', 314 OC_UNARY|xV|P(9)|'P', OC_UNARY|xV|P(9)|'M',
316 OC_FIELD|xV|P(5), 315 OC_FIELD|xV|P(5),
317 OC_COMPARE|VV|P(39)|5, OC_MOVE|VV|P(74), 316 OC_COMPARE|VV|P(39)|5, OC_MOVE|VV|P(74),
318 OC_REPLACE|NV|P(74)|'+', OC_REPLACE|NV|P(74)|'-', 317 OC_REPLACE|NV|P(74)|'+', OC_REPLACE|NV|P(74)|'-',
319 OC_REPLACE|NV|P(74)|'*', OC_REPLACE|NV|P(74)|'/', 318 OC_REPLACE|NV|P(74)|'*', OC_REPLACE|NV|P(74)|'/',
320 OC_REPLACE|NV|P(74)|'%', OC_REPLACE|NV|P(74)|'&', 319 OC_REPLACE|NV|P(74)|'%', OC_REPLACE|NV|P(74)|'&',
321 OC_BINARY|NV|P(29)|'+', OC_BINARY|NV|P(29)|'-', 320 OC_BINARY|NV|P(29)|'+', OC_BINARY|NV|P(29)|'-',
322 OC_REPLACE|NV|P(74)|'&', OC_BINARY|NV|P(15)|'&', 321 OC_REPLACE|NV|P(74)|'&', OC_BINARY|NV|P(15)|'&',
323 OC_BINARY|NV|P(25)|'/', OC_BINARY|NV|P(25)|'%', 322 OC_BINARY|NV|P(25)|'/', OC_BINARY|NV|P(25)|'%',
324 OC_BINARY|NV|P(15)|'&', OC_BINARY|NV|P(25)|'*', 323 OC_BINARY|NV|P(15)|'&', OC_BINARY|NV|P(25)|'*',
325 OC_COMPARE|VV|P(39)|4, OC_COMPARE|VV|P(39)|3, 324 OC_COMPARE|VV|P(39)|4, OC_COMPARE|VV|P(39)|3,
326 OC_COMPARE|VV|P(39)|0, OC_COMPARE|VV|P(39)|1, 325 OC_COMPARE|VV|P(39)|0, OC_COMPARE|VV|P(39)|1,
327 OC_COMPARE|VV|P(39)|2, OC_MATCH|Sx|P(45)|'!', 326 OC_COMPARE|VV|P(39)|2, OC_MATCH|Sx|P(45)|'!',
328 OC_MATCH|Sx|P(45)|'~', OC_LAND|Vx|P(55), 327 OC_MATCH|Sx|P(45)|'~', OC_LAND|Vx|P(55),
329 OC_LOR|Vx|P(59), OC_TERNARY|Vx|P(64)|'?', 328 OC_LOR|Vx|P(59), OC_TERNARY|Vx|P(64)|'?',
330 OC_COLON|xx|P(67)|':', 329 OC_COLON|xx|P(67)|':',
331 OC_IN|SV|P(49), 330 OC_IN|SV|P(49),
332 OC_COMMA|SS|P(80), 331 OC_COMMA|SS|P(80),
333 OC_PGETLINE|SV|P(37), 332 OC_PGETLINE|SV|P(37),
334 OC_UNARY|xV|P(19)|'+', OC_UNARY|xV|P(19)|'-', 333 OC_UNARY|xV|P(19)|'+', OC_UNARY|xV|P(19)|'-',
335 OC_UNARY|xV|P(19)|'!', 334 OC_UNARY|xV|P(19)|'!',
336 0, 335 0,
337 0, 336 0,
338 0, 337 0,
339 0, 338 0,
340 0, 339 0,
341 ST_IF, ST_DO, ST_FOR, OC_BREAK, 340 ST_IF, ST_DO, ST_FOR, OC_BREAK,
342 OC_CONTINUE, OC_DELETE|Vx, OC_PRINT, 341 OC_CONTINUE, OC_DELETE|Vx, OC_PRINT,
343 OC_PRINTF, OC_NEXT, OC_NEXTFILE, 342 OC_PRINTF, OC_NEXT, OC_NEXTFILE,
344 OC_RETURN|Vx, OC_EXIT|Nx, 343 OC_RETURN|Vx, OC_EXIT|Nx,
345 ST_WHILE, 344 ST_WHILE,
346 0, 345 0,
347 346
@@ -363,32 +362,32 @@ static const uint32_t tokeninfo[] = {
363/* internal variable names and their initial values */ 362/* internal variable names and their initial values */
364/* asterisk marks SPECIAL vars; $ is just no-named Field0 */ 363/* asterisk marks SPECIAL vars; $ is just no-named Field0 */
365enum { 364enum {
366 CONVFMT=0, OFMT, FS, OFS, 365 CONVFMT=0, OFMT, FS, OFS,
367 ORS, RS, RT, FILENAME, 366 ORS, RS, RT, FILENAME,
368 SUBSEP, ARGIND, ARGC, ARGV, 367 SUBSEP, ARGIND, ARGC, ARGV,
369 ERRNO, FNR, 368 ERRNO, FNR,
370 NR, NF, IGNORECASE, 369 NR, NF, IGNORECASE,
371 ENVIRON, F0, _intvarcount_ 370 ENVIRON, F0, _intvarcount_
372}; 371};
373 372
374static char * vNames = 373static const char vNames[] =
375 "CONVFMT\0" "OFMT\0" "FS\0*" "OFS\0" 374 "CONVFMT\0" "OFMT\0" "FS\0*" "OFS\0"
376 "ORS\0" "RS\0*" "RT\0" "FILENAME\0" 375 "ORS\0" "RS\0*" "RT\0" "FILENAME\0"
377 "SUBSEP\0" "ARGIND\0" "ARGC\0" "ARGV\0" 376 "SUBSEP\0" "ARGIND\0" "ARGC\0" "ARGV\0"
378 "ERRNO\0" "FNR\0" 377 "ERRNO\0" "FNR\0"
379 "NR\0" "NF\0*" "IGNORECASE\0*" 378 "NR\0" "NF\0*" "IGNORECASE\0*"
380 "ENVIRON\0" "$\0*" "\0"; 379 "ENVIRON\0" "$\0*" "\0";
381 380
382static char * vValues = 381static const char vValues[] =
383 "%.6g\0" "%.6g\0" " \0" " \0" 382 "%.6g\0" "%.6g\0" " \0" " \0"
384 "\n\0" "\n\0" "\0" "\0" 383 "\n\0" "\n\0" "\0" "\0"
385 "\034\0" 384 "\034\0"
386 "\377"; 385 "\377";
387 386
388/* hash size may grow to these values */ 387/* hash size may grow to these values */
389#define FIRST_PRIME 61; 388#define FIRST_PRIME 61;
390static const unsigned int PRIMES[] = { 251, 1021, 4093, 16381, 65521 }; 389static const unsigned PRIMES[] = { 251, 1021, 4093, 16381, 65521 };
391enum { NPRIMES = sizeof(PRIMES) / sizeof(unsigned int) }; 390enum { NPRIMES = sizeof(PRIMES) / sizeof(unsigned) };
392 391
393/* globals */ 392/* globals */
394 393
@@ -441,10 +440,15 @@ static const char EMSG_TOO_FEW_ARGS[] = "Too few arguments for builtin";
441static const char EMSG_NOT_ARRAY[] = "Not an array"; 440static const char EMSG_NOT_ARRAY[] = "Not an array";
442static const char EMSG_POSSIBLE_ERROR[] = "Possible syntax error"; 441static const char EMSG_POSSIBLE_ERROR[] = "Possible syntax error";
443static const char EMSG_UNDEF_FUNC[] = "Call to undefined function"; 442static const char EMSG_UNDEF_FUNC[] = "Call to undefined function";
444#ifndef CONFIG_FEATURE_AWK_MATH 443#if !ENABLE_FEATURE_AWK_MATH
445static const char EMSG_NO_MATH[] = "Math support is not compiled in"; 444static const char EMSG_NO_MATH[] = "Math support is not compiled in";
446#endif 445#endif
447 446
447static void zero_out_var(var * vp)
448{
449 memset(vp, 0, sizeof(*vp));
450}
451
448static void syntax_error(const char * const message) ATTRIBUTE_NORETURN; 452static void syntax_error(const char * const message) ATTRIBUTE_NORETURN;
449static void syntax_error(const char * const message) 453static void syntax_error(const char * const message)
450{ 454{
@@ -456,11 +460,11 @@ static void syntax_error(const char * const message)
456 460
457/* ---- hash stuff ---- */ 461/* ---- hash stuff ---- */
458 462
459static unsigned int hashidx(const char *name) 463static unsigned hashidx(const char *name)
460{ 464{
461 unsigned int idx=0; 465 unsigned idx = 0;
462 466
463 while (*name) idx = *name++ + (idx << 6) - idx; 467 while (*name) idx = *name++ + (idx << 6) - idx;
464 return idx; 468 return idx;
465} 469}
466 470
@@ -493,7 +497,7 @@ static void *hash_search(xhash *hash, const char *name)
493/* grow hash if it becomes too big */ 497/* grow hash if it becomes too big */
494static void hash_rebuild(xhash *hash) 498static void hash_rebuild(xhash *hash)
495{ 499{
496 unsigned int newsize, i, idx; 500 unsigned newsize, i, idx;
497 hash_item **newitems, *hi, *thi; 501 hash_item **newitems, *hi, *thi;
498 502
499 if (hash->nprime == NPRIMES) 503 if (hash->nprime == NPRIMES)
@@ -522,7 +526,7 @@ static void hash_rebuild(xhash *hash)
522static void *hash_find(xhash *hash, const char *name) 526static void *hash_find(xhash *hash, const char *name)
523{ 527{
524 hash_item *hi; 528 hash_item *hi;
525 unsigned int idx; 529 unsigned idx;
526 int l; 530 int l;
527 531
528 hi = hash_search(hash, name); 532 hi = hash_search(hash, name);
@@ -542,10 +546,10 @@ static void *hash_find(xhash *hash, const char *name)
542 return &(hi->data); 546 return &(hi->data);
543} 547}
544 548
545#define findvar(hash, name) (var *) hash_find ( (hash) , (name) ) 549#define findvar(hash, name) ((var*) hash_find((hash) , (name)))
546#define newvar(name) (var *) hash_find ( vhash , (name) ) 550#define newvar(name) ((var*) hash_find(vhash , (name)))
547#define newfile(name) (rstream *) hash_find ( fdhash , (name) ) 551#define newfile(name) ((rstream*)hash_find(fdhash ,(name)))
548#define newfunc(name) (func *) hash_find ( fnhash , (name) ) 552#define newfunc(name) ((func*) hash_find(fnhash , (name)))
549 553
550static void hash_remove(xhash *hash, const char *name) 554static void hash_remove(xhash *hash, const char *name)
551{ 555{
@@ -582,7 +586,7 @@ static char *nextword(char **s)
582{ 586{
583 char *p = *s; 587 char *p = *s;
584 588
585 while (*(*s)++) ; 589 while (*(*s)++) /* */;
586 590
587 return p; 591 return p;
588} 592}
@@ -626,7 +630,7 @@ static xhash *iamarray(var *v)
626 630
627static void clear_array(xhash *array) 631static void clear_array(xhash *array)
628{ 632{
629 unsigned int i; 633 unsigned i;
630 hash_item *hi, *thi; 634 hash_item *hi, *thi;
631 635
632 for (i=0; i<array->csize; i++) { 636 for (i=0; i<array->csize; i++) {
@@ -833,14 +837,15 @@ static void nvfree(var *v)
833 */ 837 */
834static uint32_t next_token(uint32_t expected) 838static uint32_t next_token(uint32_t expected)
835{ 839{
840 static int concat_inserted;
841 static uint32_t save_tclass, save_info;
842 static uint32_t ltclass = TC_OPTERM;
843
836 char *p, *pp, *s; 844 char *p, *pp, *s;
837 char *tl; 845 const char *tl;
838 uint32_t tc; 846 uint32_t tc;
839 const uint32_t *ti; 847 const uint32_t *ti;
840 int l; 848 int l;
841 static int concat_inserted;
842 static uint32_t save_tclass, save_info;
843 static uint32_t ltclass = TC_OPTERM;
844 849
845 if (t.rollback) { 850 if (t.rollback) {
846 851
@@ -930,7 +935,7 @@ static uint32_t next_token(uint32_t expected)
930 tl += l; 935 tl += l;
931 } 936 }
932 937
933 if (! *tl) { 938 if (!*tl) {
934 /* it's a name (var/array/function), 939 /* it's a name (var/array/function),
935 * otherwise it's something wrong 940 * otherwise it's something wrong
936 */ 941 */
@@ -1072,8 +1077,8 @@ static node *parse_expr(uint32_t iexp)
1072 /* one should be very careful with switch on tclass - 1077 /* one should be very careful with switch on tclass -
1073 * only simple tclasses should be used! */ 1078 * only simple tclasses should be used! */
1074 switch (tc) { 1079 switch (tc) {
1075 case TC_VARIABLE: 1080 case TC_VARIABLE:
1076 case TC_ARRAY: 1081 case TC_ARRAY:
1077 cn->info = OC_VAR; 1082 cn->info = OC_VAR;
1078 if ((v = hash_search(ahash, t.string)) != NULL) { 1083 if ((v = hash_search(ahash, t.string)) != NULL) {
1079 cn->info = OC_FNARG; 1084 cn->info = OC_FNARG;
@@ -1087,8 +1092,8 @@ static node *parse_expr(uint32_t iexp)
1087 } 1092 }
1088 break; 1093 break;
1089 1094
1090 case TC_NUMBER: 1095 case TC_NUMBER:
1091 case TC_STRING: 1096 case TC_STRING:
1092 cn->info = OC_VAR; 1097 cn->info = OC_VAR;
1093 v = cn->l.v = xzalloc(sizeof(var)); 1098 v = cn->l.v = xzalloc(sizeof(var));
1094 if (tc & TC_NUMBER) 1099 if (tc & TC_NUMBER)
@@ -1097,27 +1102,27 @@ static node *parse_expr(uint32_t iexp)
1097 setvar_s(v, t.string); 1102 setvar_s(v, t.string);
1098 break; 1103 break;
1099 1104
1100 case TC_REGEXP: 1105 case TC_REGEXP:
1101 mk_re_node(t.string, cn, xzalloc(sizeof(regex_t)*2)); 1106 mk_re_node(t.string, cn, xzalloc(sizeof(regex_t)*2));
1102 break; 1107 break;
1103 1108
1104 case TC_FUNCTION: 1109 case TC_FUNCTION:
1105 cn->info = OC_FUNC; 1110 cn->info = OC_FUNC;
1106 cn->r.f = newfunc(t.string); 1111 cn->r.f = newfunc(t.string);
1107 cn->l.n = condition(); 1112 cn->l.n = condition();
1108 break; 1113 break;
1109 1114
1110 case TC_SEQSTART: 1115 case TC_SEQSTART:
1111 cn = vn->r.n = parse_expr(TC_SEQTERM); 1116 cn = vn->r.n = parse_expr(TC_SEQTERM);
1112 cn->a.n = vn; 1117 cn->a.n = vn;
1113 break; 1118 break;
1114 1119
1115 case TC_GETLINE: 1120 case TC_GETLINE:
1116 glptr = cn; 1121 glptr = cn;
1117 xtc = TC_OPERAND | TC_UOPPRE | TC_BINOP | iexp; 1122 xtc = TC_OPERAND | TC_UOPPRE | TC_BINOP | iexp;
1118 break; 1123 break;
1119 1124
1120 case TC_BUILTIN: 1125 case TC_BUILTIN:
1121 cn->l.n = condition(); 1126 cn->l.n = condition();
1122 break; 1127 break;
1123 } 1128 }
@@ -1403,8 +1408,8 @@ static void fsrealloc(int size)
1403 if (size >= maxfields) { 1408 if (size >= maxfields) {
1404 i = maxfields; 1409 i = maxfields;
1405 maxfields = size + 16; 1410 maxfields = size + 16;
1406 Fields = (var *)xrealloc(Fields, maxfields * sizeof(var)); 1411 Fields = xrealloc(Fields, maxfields * sizeof(var));
1407 for (; i<maxfields; i++) { 1412 for (; i < maxfields; i++) {
1408 Fields[i].type = VF_SPECIAL; 1413 Fields[i].type = VF_SPECIAL;
1409 Fields[i].string = NULL; 1414 Fields[i].string = NULL;
1410 } 1415 }
@@ -1420,7 +1425,7 @@ static void fsrealloc(int size)
1420 1425
1421static int awk_split(char *s, node *spl, char **slist) 1426static int awk_split(char *s, node *spl, char **slist)
1422{ 1427{
1423 int l, n=0; 1428 int l, n = 0;
1424 char c[4]; 1429 char c[4];
1425 char *s1; 1430 char *s1;
1426 regmatch_t pmatch[2]; 1431 regmatch_t pmatch[2];
@@ -1441,11 +1446,11 @@ static int awk_split(char *s, node *spl, char **slist)
1441 if (pmatch[0].rm_eo == 0) { l++; pmatch[0].rm_eo++; } 1446 if (pmatch[0].rm_eo == 0) { l++; pmatch[0].rm_eo++; }
1442 } else { 1447 } else {
1443 pmatch[0].rm_eo = l; 1448 pmatch[0].rm_eo = l;
1444 if (*(s+l)) pmatch[0].rm_eo++; 1449 if (s[l]) pmatch[0].rm_eo++;
1445 } 1450 }
1446 1451
1447 memcpy(s1, s, l); 1452 memcpy(s1, s, l);
1448 *(s1+l) = '\0'; 1453 s1[l] = '\0';
1449 nextword(&s1); 1454 nextword(&s1);
1450 s += pmatch[0].rm_eo; 1455 s += pmatch[0].rm_eo;
1451 n++; 1456 n++;
@@ -1494,7 +1499,7 @@ static void split_f0(void)
1494 n = awk_split(getvar_s(V[F0]), &fsplitter.n, &fstrings); 1499 n = awk_split(getvar_s(V[F0]), &fsplitter.n, &fstrings);
1495 fsrealloc(n); 1500 fsrealloc(n);
1496 s = fstrings; 1501 s = fstrings;
1497 for (i=0; i<n; i++) { 1502 for (i = 0; i < n; i++) {
1498 Fields[i].string = nextword(&s); 1503 Fields[i].string = nextword(&s);
1499 Fields[i].type |= (VF_FSTR | VF_USER | VF_DIRTY); 1504 Fields[i].type |= (VF_FSTR | VF_USER | VF_DIRTY);
1500 } 1505 }
@@ -1610,7 +1615,8 @@ static int hashwalk_next(var *v)
1610/* evaluate node, return 1 when result is true, 0 otherwise */ 1615/* evaluate node, return 1 when result is true, 0 otherwise */
1611static int ptest(node *pattern) 1616static int ptest(node *pattern)
1612{ 1617{
1613 static var v; 1618 static var v; /* static: to save stack space? */
1619
1614 return istrue(evaluate(pattern, &v)); 1620 return istrue(evaluate(pattern, &v));
1615} 1621}
1616 1622
@@ -1710,14 +1716,14 @@ static int awk_getline(rstream *rsm, var *v)
1710 1716
1711static int fmt_num(char *b, int size, const char *format, double n, int int_as_int) 1717static int fmt_num(char *b, int size, const char *format, double n, int int_as_int)
1712{ 1718{
1713 int r=0; 1719 int r = 0;
1714 char c; 1720 char c;
1715 const char *s=format; 1721 const char *s = format;
1716 1722
1717 if (int_as_int && n == (int)n) { 1723 if (int_as_int && n == (int)n) {
1718 r = snprintf(b, size, "%d", (int)n); 1724 r = snprintf(b, size, "%d", (int)n);
1719 } else { 1725 } else {
1720 do { c = *s; } while (*s && *++s); 1726 do { c = *s; } while (c && *++s);
1721 if (strchr("diouxX", c)) { 1727 if (strchr("diouxX", c)) {
1722 r = snprintf(b, size, format, (int)n); 1728 r = snprintf(b, size, format, (int)n);
1723 } else if (strchr("eEfgG", c)) { 1729 } else if (strchr("eEfgG", c)) {
@@ -1751,15 +1757,17 @@ static char *awk_printf(node *n)
1751 f++; 1757 f++;
1752 1758
1753 incr = (f - s) + MAXVARFMT; 1759 incr = (f - s) + MAXVARFMT;
1754 qrealloc(&b, incr+i, &bsize); 1760 qrealloc(&b, incr + i, &bsize);
1755 c = *f; if (c != '\0') f++; 1761 c = *f;
1756 c1 = *f ; *f = '\0'; 1762 if (c != '\0') f++;
1763 c1 = *f;
1764 *f = '\0';
1757 arg = evaluate(nextarg(&n), v); 1765 arg = evaluate(nextarg(&n), v);
1758 1766
1759 j = i; 1767 j = i;
1760 if (c == 'c' || !c) { 1768 if (c == 'c' || !c) {
1761 i += sprintf(b+i, s, 1769 i += sprintf(b+i, s, is_numeric(arg) ?
1762 is_numeric(arg) ? (char)getvar_i(arg) : *getvar_s(arg)); 1770 (char)getvar_i(arg) : *getvar_s(arg));
1763 1771
1764 } else if (c == 's') { 1772 } else if (c == 's') {
1765 s1 = getvar_s(arg); 1773 s1 = getvar_s(arg);
@@ -1776,7 +1784,7 @@ static char *awk_printf(node *n)
1776 1784
1777 } 1785 }
1778 1786
1779 b = xrealloc(b, i+1); 1787 b = xrealloc(b, i + 1);
1780 free(fmt); 1788 free(fmt);
1781 nvfree(v); 1789 nvfree(v);
1782 b[i] = '\0'; 1790 b[i] = '\0';
@@ -1890,15 +1898,15 @@ static var *exec_builtin(node *op, var *res)
1890 1898
1891 switch (info & OPNMASK) { 1899 switch (info & OPNMASK) {
1892 1900
1893 case B_a2: 1901 case B_a2:
1894#ifdef CONFIG_FEATURE_AWK_MATH 1902#if ENABLE_FEATURE_AWK_MATH
1895 setvar_i(res, atan2(getvar_i(av[i]), getvar_i(av[1]))); 1903 setvar_i(res, atan2(getvar_i(av[i]), getvar_i(av[1])));
1896#else 1904#else
1897 runtime_error(EMSG_NO_MATH); 1905 runtime_error(EMSG_NO_MATH);
1898#endif 1906#endif
1899 break; 1907 break;
1900 1908
1901 case B_sp: 1909 case B_sp:
1902 if (nargs > 2) { 1910 if (nargs > 2) {
1903 spl = (an[2]->info & OPCLSMASK) == OC_REGEXP ? 1911 spl = (an[2]->info & OPCLSMASK) == OC_REGEXP ?
1904 an[2] : mk_splitter(getvar_s(evaluate(an[2], &tv[2])), &tspl); 1912 an[2] : mk_splitter(getvar_s(evaluate(an[2], &tv[2])), &tspl);
@@ -1915,7 +1923,7 @@ static var *exec_builtin(node *op, var *res)
1915 setvar_i(res, n); 1923 setvar_i(res, n);
1916 break; 1924 break;
1917 1925
1918 case B_ss: 1926 case B_ss:
1919 l = strlen(as[0]); 1927 l = strlen(as[0]);
1920 i = getvar_i(av[1]) - 1; 1928 i = getvar_i(av[1]) - 1;
1921 if (i>l) i=l; if (i<0) i=0; 1929 if (i>l) i=l; if (i<0) i=0;
@@ -1927,35 +1935,35 @@ static var *exec_builtin(node *op, var *res)
1927 setvar_p(res, s); 1935 setvar_p(res, s);
1928 break; 1936 break;
1929 1937
1930 case B_an: 1938 case B_an:
1931 setvar_i(res, (long)getvar_i(av[0]) & (long)getvar_i(av[1])); 1939 setvar_i(res, (long)getvar_i(av[0]) & (long)getvar_i(av[1]));
1932 break; 1940 break;
1933 1941
1934 case B_co: 1942 case B_co:
1935 setvar_i(res, ~(long)getvar_i(av[0])); 1943 setvar_i(res, ~(long)getvar_i(av[0]));
1936 break; 1944 break;
1937 1945
1938 case B_ls: 1946 case B_ls:
1939 setvar_i(res, (long)getvar_i(av[0]) << (long)getvar_i(av[1])); 1947 setvar_i(res, (long)getvar_i(av[0]) << (long)getvar_i(av[1]));
1940 break; 1948 break;
1941 1949
1942 case B_or: 1950 case B_or:
1943 setvar_i(res, (long)getvar_i(av[0]) | (long)getvar_i(av[1])); 1951 setvar_i(res, (long)getvar_i(av[0]) | (long)getvar_i(av[1]));
1944 break; 1952 break;
1945 1953
1946 case B_rs: 1954 case B_rs:
1947 setvar_i(res, (long)((unsigned long)getvar_i(av[0]) >> (unsigned long)getvar_i(av[1]))); 1955 setvar_i(res, (long)((unsigned long)getvar_i(av[0]) >> (unsigned long)getvar_i(av[1])));
1948 break; 1956 break;
1949 1957
1950 case B_xo: 1958 case B_xo:
1951 setvar_i(res, (long)getvar_i(av[0]) ^ (long)getvar_i(av[1])); 1959 setvar_i(res, (long)getvar_i(av[0]) ^ (long)getvar_i(av[1]));
1952 break; 1960 break;
1953 1961
1954 case B_lo: 1962 case B_lo:
1955 to_xxx = tolower; 1963 to_xxx = tolower;
1956 goto lo_cont; 1964 goto lo_cont;
1957 1965
1958 case B_up: 1966 case B_up:
1959 to_xxx = toupper; 1967 to_xxx = toupper;
1960lo_cont: 1968lo_cont:
1961 s1 = s = xstrdup(as[0]); 1969 s1 = s = xstrdup(as[0]);
@@ -1966,7 +1974,7 @@ lo_cont:
1966 setvar_p(res, s); 1974 setvar_p(res, s);
1967 break; 1975 break;
1968 1976
1969 case B_ix: 1977 case B_ix:
1970 n = 0; 1978 n = 0;
1971 ll = strlen(as[1]); 1979 ll = strlen(as[1]);
1972 l = strlen(as[0]) - ll; 1980 l = strlen(as[0]) - ll;
@@ -1989,7 +1997,7 @@ lo_cont:
1989 setvar_i(res, n); 1997 setvar_i(res, n);
1990 break; 1998 break;
1991 1999
1992 case B_ti: 2000 case B_ti:
1993 if (nargs > 1) 2001 if (nargs > 1)
1994 tt = getvar_i(av[1]); 2002 tt = getvar_i(av[1]);
1995 else 2003 else
@@ -2000,7 +2008,7 @@ lo_cont:
2000 setvar_s(res, buf); 2008 setvar_s(res, buf);
2001 break; 2009 break;
2002 2010
2003 case B_ma: 2011 case B_ma:
2004 re = as_regex(an[1], &sreg); 2012 re = as_regex(an[1], &sreg);
2005 n = regexec(re, as[0], 1, pmatch, 0); 2013 n = regexec(re, as[0], 1, pmatch, 0);
2006 if (n == 0) { 2014 if (n == 0) {
@@ -2016,15 +2024,15 @@ lo_cont:
2016 if (re == &sreg) regfree(re); 2024 if (re == &sreg) regfree(re);
2017 break; 2025 break;
2018 2026
2019 case B_ge: 2027 case B_ge:
2020 awk_sub(an[0], as[1], getvar_i(av[2]), av[3], res, TRUE); 2028 awk_sub(an[0], as[1], getvar_i(av[2]), av[3], res, TRUE);
2021 break; 2029 break;
2022 2030
2023 case B_gs: 2031 case B_gs:
2024 setvar_i(res, awk_sub(an[0], as[1], 0, av[2], av[2], FALSE)); 2032 setvar_i(res, awk_sub(an[0], as[1], 0, av[2], av[2], FALSE));
2025 break; 2033 break;
2026 2034
2027 case B_su: 2035 case B_su:
2028 setvar_i(res, awk_sub(an[0], as[1], 1, av[2], av[2], FALSE)); 2036 setvar_i(res, awk_sub(an[0], as[1], 1, av[2], av[2], FALSE));
2029 break; 2037 break;
2030 } 2038 }
@@ -2043,7 +2051,7 @@ static var *evaluate(node *op, var *res)
2043{ 2051{
2044 /* This procedure is recursive so we should count every byte */ 2052 /* This procedure is recursive so we should count every byte */
2045 static var *fnargs = NULL; 2053 static var *fnargs = NULL;
2046 static unsigned int seed = 1; 2054 static unsigned seed = 1;
2047 static regex_t sreg; 2055 static regex_t sreg;
2048 node *op1; 2056 node *op1;
2049 var *v1; 2057 var *v1;
@@ -2088,7 +2096,7 @@ static var *evaluate(node *op, var *res)
2088 /* -- iterative node type -- */ 2096 /* -- iterative node type -- */
2089 2097
2090 /* test pattern */ 2098 /* test pattern */
2091 case XC( OC_TEST ): 2099 case XC( OC_TEST ):
2092 if ((op1->info & OPCLSMASK) == OC_COMMA) { 2100 if ((op1->info & OPCLSMASK) == OC_COMMA) {
2093 /* it's range pattern */ 2101 /* it's range pattern */
2094 if ((opinfo & OF_CHECKED) || ptest(op1->l.n)) { 2102 if ((opinfo & OF_CHECKED) || ptest(op1->l.n)) {
@@ -2106,26 +2114,26 @@ static var *evaluate(node *op, var *res)
2106 break; 2114 break;
2107 2115
2108 /* just evaluate an expression, also used as unconditional jump */ 2116 /* just evaluate an expression, also used as unconditional jump */
2109 case XC( OC_EXEC ): 2117 case XC( OC_EXEC ):
2110 break; 2118 break;
2111 2119
2112 /* branch, used in if-else and various loops */ 2120 /* branch, used in if-else and various loops */
2113 case XC( OC_BR ): 2121 case XC( OC_BR ):
2114 op = istrue(L.v) ? op->a.n : op->r.n; 2122 op = istrue(L.v) ? op->a.n : op->r.n;
2115 break; 2123 break;
2116 2124
2117 /* initialize for-in loop */ 2125 /* initialize for-in loop */
2118 case XC( OC_WALKINIT ): 2126 case XC( OC_WALKINIT ):
2119 hashwalk_init(L.v, iamarray(R.v)); 2127 hashwalk_init(L.v, iamarray(R.v));
2120 break; 2128 break;
2121 2129
2122 /* get next array item */ 2130 /* get next array item */
2123 case XC( OC_WALKNEXT ): 2131 case XC( OC_WALKNEXT ):
2124 op = hashwalk_next(L.v) ? op->a.n : op->r.n; 2132 op = hashwalk_next(L.v) ? op->a.n : op->r.n;
2125 break; 2133 break;
2126 2134
2127 case XC( OC_PRINT ): 2135 case XC( OC_PRINT ):
2128 case XC( OC_PRINTF ): 2136 case XC( OC_PRINTF ):
2129 X.F = stdout; 2137 X.F = stdout;
2130 if (op->r.n) { 2138 if (op->r.n) {
2131 X.rsm = newfile(R.s); 2139 X.rsm = newfile(R.s);
@@ -2168,7 +2176,7 @@ static var *evaluate(node *op, var *res)
2168 fflush(X.F); 2176 fflush(X.F);
2169 break; 2177 break;
2170 2178
2171 case XC( OC_DELETE ): 2179 case XC( OC_DELETE ):
2172 X.info = op1->info & OPCLSMASK; 2180 X.info = op1->info & OPCLSMASK;
2173 if (X.info == OC_VAR) { 2181 if (X.info == OC_VAR) {
2174 R.v = op1->l.v; 2182 R.v = op1->l.v;
@@ -2187,50 +2195,50 @@ static var *evaluate(node *op, var *res)
2187 } 2195 }
2188 break; 2196 break;
2189 2197
2190 case XC( OC_NEWSOURCE ): 2198 case XC( OC_NEWSOURCE ):
2191 programname = op->l.s; 2199 programname = op->l.s;
2192 break; 2200 break;
2193 2201
2194 case XC( OC_RETURN ): 2202 case XC( OC_RETURN ):
2195 copyvar(res, L.v); 2203 copyvar(res, L.v);
2196 break; 2204 break;
2197 2205
2198 case XC( OC_NEXTFILE ): 2206 case XC( OC_NEXTFILE ):
2199 nextfile = TRUE; 2207 nextfile = TRUE;
2200 case XC( OC_NEXT ): 2208 case XC( OC_NEXT ):
2201 nextrec = TRUE; 2209 nextrec = TRUE;
2202 case XC( OC_DONE ): 2210 case XC( OC_DONE ):
2203 clrvar(res); 2211 clrvar(res);
2204 break; 2212 break;
2205 2213
2206 case XC( OC_EXIT ): 2214 case XC( OC_EXIT ):
2207 awk_exit(L.d); 2215 awk_exit(L.d);
2208 2216
2209 /* -- recursive node type -- */ 2217 /* -- recursive node type -- */
2210 2218
2211 case XC( OC_VAR ): 2219 case XC( OC_VAR ):
2212 L.v = op->l.v; 2220 L.v = op->l.v;
2213 if (L.v == V[NF]) 2221 if (L.v == V[NF])
2214 split_f0(); 2222 split_f0();
2215 goto v_cont; 2223 goto v_cont;
2216 2224
2217 case XC( OC_FNARG ): 2225 case XC( OC_FNARG ):
2218 L.v = &fnargs[op->l.i]; 2226 L.v = &fnargs[op->l.i];
2219 2227
2220v_cont: 2228v_cont:
2221 res = (op->r.n) ? findvar(iamarray(L.v), R.s) : L.v; 2229 res = (op->r.n) ? findvar(iamarray(L.v), R.s) : L.v;
2222 break; 2230 break;
2223 2231
2224 case XC( OC_IN ): 2232 case XC( OC_IN ):
2225 setvar_i(res, hash_search(iamarray(R.v), L.s) ? 1 : 0); 2233 setvar_i(res, hash_search(iamarray(R.v), L.s) ? 1 : 0);
2226 break; 2234 break;
2227 2235
2228 case XC( OC_REGEXP ): 2236 case XC( OC_REGEXP ):
2229 op1 = op; 2237 op1 = op;
2230 L.s = getvar_s(V[F0]); 2238 L.s = getvar_s(V[F0]);
2231 goto re_cont; 2239 goto re_cont;
2232 2240
2233 case XC( OC_MATCH ): 2241 case XC( OC_MATCH ):
2234 op1 = op->r.n; 2242 op1 = op->r.n;
2235re_cont: 2243re_cont:
2236 X.re = as_regex(op1, &sreg); 2244 X.re = as_regex(op1, &sreg);
@@ -2239,7 +2247,7 @@ re_cont:
2239 setvar_i(res, (R.i == 0 ? 1 : 0) ^ (opn == '!' ? 1 : 0)); 2247 setvar_i(res, (R.i == 0 ? 1 : 0) ^ (opn == '!' ? 1 : 0));
2240 break; 2248 break;
2241 2249
2242 case XC( OC_MOVE ): 2250 case XC( OC_MOVE ):
2243 /* if source is a temporary string, jusk relink it to dest */ 2251 /* if source is a temporary string, jusk relink it to dest */
2244 if (R.v == v1+1 && R.v->string) { 2252 if (R.v == v1+1 && R.v->string) {
2245 res = setvar_p(L.v, R.v->string); 2253 res = setvar_p(L.v, R.v->string);
@@ -2249,13 +2257,13 @@ re_cont:
2249 } 2257 }
2250 break; 2258 break;
2251 2259
2252 case XC( OC_TERNARY ): 2260 case XC( OC_TERNARY ):
2253 if ((op->r.n->info & OPCLSMASK) != OC_COLON) 2261 if ((op->r.n->info & OPCLSMASK) != OC_COLON)
2254 runtime_error(EMSG_POSSIBLE_ERROR); 2262 runtime_error(EMSG_POSSIBLE_ERROR);
2255 res = evaluate(istrue(L.v) ? op->r.n->l.n : op->r.n->r.n, res); 2263 res = evaluate(istrue(L.v) ? op->r.n->l.n : op->r.n->r.n, res);
2256 break; 2264 break;
2257 2265
2258 case XC( OC_FUNC ): 2266 case XC( OC_FUNC ):
2259 if (! op->r.f->body.first) 2267 if (! op->r.f->body.first)
2260 runtime_error(EMSG_UNDEF_FUNC); 2268 runtime_error(EMSG_UNDEF_FUNC);
2261 2269
@@ -2280,8 +2288,8 @@ re_cont:
2280 fnargs = R.v; 2288 fnargs = R.v;
2281 break; 2289 break;
2282 2290
2283 case XC( OC_GETLINE ): 2291 case XC( OC_GETLINE ):
2284 case XC( OC_PGETLINE ): 2292 case XC( OC_PGETLINE ):
2285 if (op1) { 2293 if (op1) {
2286 X.rsm = newfile(L.s); 2294 X.rsm = newfile(L.s);
2287 if (! X.rsm->F) { 2295 if (! X.rsm->F) {
@@ -2317,70 +2325,70 @@ re_cont:
2317 break; 2325 break;
2318 2326
2319 /* simple builtins */ 2327 /* simple builtins */
2320 case XC( OC_FBLTIN ): 2328 case XC( OC_FBLTIN ):
2321 switch (opn) { 2329 switch (opn) {
2322 2330
2323 case F_in: 2331 case F_in:
2324 R.d = (int)L.d; 2332 R.d = (int)L.d;
2325 break; 2333 break;
2326 2334
2327 case F_rn: 2335 case F_rn:
2328 R.d = (double)rand() / (double)RAND_MAX; 2336 R.d = (double)rand() / (double)RAND_MAX;
2329 break; 2337 break;
2330 2338
2331#ifdef CONFIG_FEATURE_AWK_MATH 2339#if ENABLE_FEATURE_AWK_MATH
2332 case F_co: 2340 case F_co:
2333 R.d = cos(L.d); 2341 R.d = cos(L.d);
2334 break; 2342 break;
2335 2343
2336 case F_ex: 2344 case F_ex:
2337 R.d = exp(L.d); 2345 R.d = exp(L.d);
2338 break; 2346 break;
2339 2347
2340 case F_lg: 2348 case F_lg:
2341 R.d = log(L.d); 2349 R.d = log(L.d);
2342 break; 2350 break;
2343 2351
2344 case F_si: 2352 case F_si:
2345 R.d = sin(L.d); 2353 R.d = sin(L.d);
2346 break; 2354 break;
2347 2355
2348 case F_sq: 2356 case F_sq:
2349 R.d = sqrt(L.d); 2357 R.d = sqrt(L.d);
2350 break; 2358 break;
2351#else 2359#else
2352 case F_co: 2360 case F_co:
2353 case F_ex: 2361 case F_ex:
2354 case F_lg: 2362 case F_lg:
2355 case F_si: 2363 case F_si:
2356 case F_sq: 2364 case F_sq:
2357 runtime_error(EMSG_NO_MATH); 2365 runtime_error(EMSG_NO_MATH);
2358 break; 2366 break;
2359#endif 2367#endif
2360 2368
2361 case F_sr: 2369 case F_sr:
2362 R.d = (double)seed; 2370 R.d = (double)seed;
2363 seed = op1 ? (unsigned int)L.d : (unsigned int)time(NULL); 2371 seed = op1 ? (unsigned)L.d : (unsigned)time(NULL);
2364 srand(seed); 2372 srand(seed);
2365 break; 2373 break;
2366 2374
2367 case F_ti: 2375 case F_ti:
2368 R.d = time(NULL); 2376 R.d = time(NULL);
2369 break; 2377 break;
2370 2378
2371 case F_le: 2379 case F_le:
2372 if (! op1) 2380 if (! op1)
2373 L.s = getvar_s(V[F0]); 2381 L.s = getvar_s(V[F0]);
2374 R.d = strlen(L.s); 2382 R.d = strlen(L.s);
2375 break; 2383 break;
2376 2384
2377 case F_sy: 2385 case F_sy:
2378 fflush(NULL); 2386 fflush(NULL);
2379 R.d = (ENABLE_FEATURE_ALLOW_EXEC && L.s && *L.s) 2387 R.d = (ENABLE_FEATURE_ALLOW_EXEC && L.s && *L.s)
2380 ? (system(L.s) >> 8) : 0; 2388 ? (system(L.s) >> 8) : 0;
2381 break; 2389 break;
2382 2390
2383 case F_ff: 2391 case F_ff:
2384 if (! op1) 2392 if (! op1)
2385 fflush(stdout); 2393 fflush(stdout);
2386 else { 2394 else {
@@ -2393,7 +2401,7 @@ re_cont:
2393 } 2401 }
2394 break; 2402 break;
2395 2403
2396 case F_cl: 2404 case F_cl:
2397 X.rsm = (rstream *)hash_search(fdhash, L.s); 2405 X.rsm = (rstream *)hash_search(fdhash, L.s);
2398 if (X.rsm) { 2406 if (X.rsm) {
2399 R.i = X.rsm->is_pipe ? pclose(X.rsm->F) : fclose(X.rsm->F); 2407 R.i = X.rsm->is_pipe ? pclose(X.rsm->F) : fclose(X.rsm->F);
@@ -2408,43 +2416,43 @@ re_cont:
2408 setvar_i(res, R.d); 2416 setvar_i(res, R.d);
2409 break; 2417 break;
2410 2418
2411 case XC( OC_BUILTIN ): 2419 case XC( OC_BUILTIN ):
2412 res = exec_builtin(op, res); 2420 res = exec_builtin(op, res);
2413 break; 2421 break;
2414 2422
2415 case XC( OC_SPRINTF ): 2423 case XC( OC_SPRINTF ):
2416 setvar_p(res, awk_printf(op1)); 2424 setvar_p(res, awk_printf(op1));
2417 break; 2425 break;
2418 2426
2419 case XC( OC_UNARY ): 2427 case XC( OC_UNARY ):
2420 X.v = R.v; 2428 X.v = R.v;
2421 L.d = R.d = getvar_i(R.v); 2429 L.d = R.d = getvar_i(R.v);
2422 switch (opn) { 2430 switch (opn) {
2423 case 'P': 2431 case 'P':
2424 L.d = ++R.d; 2432 L.d = ++R.d;
2425 goto r_op_change; 2433 goto r_op_change;
2426 case 'p': 2434 case 'p':
2427 R.d++; 2435 R.d++;
2428 goto r_op_change; 2436 goto r_op_change;
2429 case 'M': 2437 case 'M':
2430 L.d = --R.d; 2438 L.d = --R.d;
2431 goto r_op_change; 2439 goto r_op_change;
2432 case 'm': 2440 case 'm':
2433 R.d--; 2441 R.d--;
2434 goto r_op_change; 2442 goto r_op_change;
2435 case '!': 2443 case '!':
2436 L.d = istrue(X.v) ? 0 : 1; 2444 L.d = istrue(X.v) ? 0 : 1;
2437 break; 2445 break;
2438 case '-': 2446 case '-':
2439 L.d = -R.d; 2447 L.d = -R.d;
2440 break; 2448 break;
2441 r_op_change: 2449 r_op_change:
2442 setvar_i(X.v, R.d); 2450 setvar_i(X.v, R.d);
2443 } 2451 }
2444 setvar_i(res, L.d); 2452 setvar_i(res, L.d);
2445 break; 2453 break;
2446 2454
2447 case XC( OC_FIELD ): 2455 case XC( OC_FIELD ):
2448 R.i = (int)getvar_i(R.v); 2456 R.i = (int)getvar_i(R.v);
2449 if (R.i == 0) { 2457 if (R.i == 0) {
2450 res = V[F0]; 2458 res = V[F0];
@@ -2458,53 +2466,53 @@ re_cont:
2458 break; 2466 break;
2459 2467
2460 /* concatenation (" ") and index joining (",") */ 2468 /* concatenation (" ") and index joining (",") */
2461 case XC( OC_CONCAT ): 2469 case XC( OC_CONCAT ):
2462 case XC( OC_COMMA ): 2470 case XC( OC_COMMA ):
2463 opn = strlen(L.s) + strlen(R.s) + 2; 2471 opn = strlen(L.s) + strlen(R.s) + 2;
2464 X.s = xmalloc(opn); 2472 X.s = xmalloc(opn);
2465 strcpy(X.s, L.s); 2473 strcpy(X.s, L.s);
2466 if ((opinfo & OPCLSMASK) == OC_COMMA) { 2474 if ((opinfo & OPCLSMASK) == OC_COMMA) {
2467 L.s = getvar_s(V[SUBSEP]); 2475 L.s = getvar_s(V[SUBSEP]);
2468 X.s = (char *)xrealloc(X.s, opn + strlen(L.s)); 2476 X.s = xrealloc(X.s, opn + strlen(L.s));
2469 strcat(X.s, L.s); 2477 strcat(X.s, L.s);
2470 } 2478 }
2471 strcat(X.s, R.s); 2479 strcat(X.s, R.s);
2472 setvar_p(res, X.s); 2480 setvar_p(res, X.s);
2473 break; 2481 break;
2474 2482
2475 case XC( OC_LAND ): 2483 case XC( OC_LAND ):
2476 setvar_i(res, istrue(L.v) ? ptest(op->r.n) : 0); 2484 setvar_i(res, istrue(L.v) ? ptest(op->r.n) : 0);
2477 break; 2485 break;
2478 2486
2479 case XC( OC_LOR ): 2487 case XC( OC_LOR ):
2480 setvar_i(res, istrue(L.v) ? 1 : ptest(op->r.n)); 2488 setvar_i(res, istrue(L.v) ? 1 : ptest(op->r.n));
2481 break; 2489 break;
2482 2490
2483 case XC( OC_BINARY ): 2491 case XC( OC_BINARY ):
2484 case XC( OC_REPLACE ): 2492 case XC( OC_REPLACE ):
2485 R.d = getvar_i(R.v); 2493 R.d = getvar_i(R.v);
2486 switch (opn) { 2494 switch (opn) {
2487 case '+': 2495 case '+':
2488 L.d += R.d; 2496 L.d += R.d;
2489 break; 2497 break;
2490 case '-': 2498 case '-':
2491 L.d -= R.d; 2499 L.d -= R.d;
2492 break; 2500 break;
2493 case '*': 2501 case '*':
2494 L.d *= R.d; 2502 L.d *= R.d;
2495 break; 2503 break;
2496 case '/': 2504 case '/':
2497 if (R.d == 0) runtime_error(EMSG_DIV_BY_ZERO); 2505 if (R.d == 0) runtime_error(EMSG_DIV_BY_ZERO);
2498 L.d /= R.d; 2506 L.d /= R.d;
2499 break; 2507 break;
2500 case '&': 2508 case '&':
2501#ifdef CONFIG_FEATURE_AWK_MATH 2509#if ENABLE_FEATURE_AWK_MATH
2502 L.d = pow(L.d, R.d); 2510 L.d = pow(L.d, R.d);
2503#else 2511#else
2504 runtime_error(EMSG_NO_MATH); 2512 runtime_error(EMSG_NO_MATH);
2505#endif 2513#endif
2506 break; 2514 break;
2507 case '%': 2515 case '%':
2508 if (R.d == 0) runtime_error(EMSG_DIV_BY_ZERO); 2516 if (R.d == 0) runtime_error(EMSG_DIV_BY_ZERO);
2509 L.d -= (int)(L.d / R.d) * R.d; 2517 L.d -= (int)(L.d / R.d) * R.d;
2510 break; 2518 break;
@@ -2512,7 +2520,7 @@ re_cont:
2512 res = setvar_i(((opinfo&OPCLSMASK) == OC_BINARY) ? res : X.v, L.d); 2520 res = setvar_i(((opinfo&OPCLSMASK) == OC_BINARY) ? res : X.v, L.d);
2513 break; 2521 break;
2514 2522
2515 case XC( OC_COMPARE ): 2523 case XC( OC_COMPARE ):
2516 if (is_numeric(L.v) && is_numeric(R.v)) { 2524 if (is_numeric(L.v) && is_numeric(R.v)) {
2517 L.d = getvar_i(L.v) - getvar_i(R.v); 2525 L.d = getvar_i(L.v) - getvar_i(R.v);
2518 } else { 2526 } else {
@@ -2521,20 +2529,20 @@ re_cont:
2521 L.d = icase ? strcasecmp(L.s, R.s) : strcmp(L.s, R.s); 2529 L.d = icase ? strcasecmp(L.s, R.s) : strcmp(L.s, R.s);
2522 } 2530 }
2523 switch (opn & 0xfe) { 2531 switch (opn & 0xfe) {
2524 case 0: 2532 case 0:
2525 R.i = (L.d > 0); 2533 R.i = (L.d > 0);
2526 break; 2534 break;
2527 case 2: 2535 case 2:
2528 R.i = (L.d >= 0); 2536 R.i = (L.d >= 0);
2529 break; 2537 break;
2530 case 4: 2538 case 4:
2531 R.i = (L.d == 0); 2539 R.i = (L.d == 0);
2532 break; 2540 break;
2533 } 2541 }
2534 setvar_i(res, (opn & 0x1 ? R.i : !R.i) ? 1 : 0); 2542 setvar_i(res, (opn & 0x1 ? R.i : !R.i) ? 1 : 0);
2535 break; 2543 break;
2536 2544
2537 default: 2545 default:
2538 runtime_error(EMSG_POSSIBLE_ERROR); 2546 runtime_error(EMSG_POSSIBLE_ERROR);
2539 } 2547 }
2540 if ((opinfo & OPCLSMASK) <= SHIFT_TIL_THIS) 2548 if ((opinfo & OPCLSMASK) <= SHIFT_TIL_THIS)
@@ -2553,18 +2561,20 @@ re_cont:
2553 2561
2554static int awk_exit(int r) 2562static int awk_exit(int r)
2555{ 2563{
2556 unsigned int i; 2564 var tv;
2565 unsigned i;
2557 hash_item *hi; 2566 hash_item *hi;
2558 static var tv;
2559 2567
2560 if (! exiting) { 2568 zero_out_var(&tv);
2569
2570 if (!exiting) {
2561 exiting = TRUE; 2571 exiting = TRUE;
2562 nextrec = FALSE; 2572 nextrec = FALSE;
2563 evaluate(endseq.first, &tv); 2573 evaluate(endseq.first, &tv);
2564 } 2574 }
2565 2575
2566 /* waiting for children */ 2576 /* waiting for children */
2567 for (i=0; i<fdhash->csize; i++) { 2577 for (i = 0; i < fdhash->csize; i++) {
2568 hi = fdhash->items[i]; 2578 hi = fdhash->items[i];
2569 while (hi) { 2579 while (hi) {
2570 if (hi->data.rs.F && hi->data.rs.is_pipe) 2580 if (hi->data.rs.F && hi->data.rs.is_pipe)
@@ -2635,18 +2645,17 @@ int awk_main(int argc, char **argv)
2635{ 2645{
2636 unsigned opt; 2646 unsigned opt;
2637 char *opt_F, *opt_v, *opt_W; 2647 char *opt_F, *opt_v, *opt_W;
2638 char *s, *s1; 2648 int i, j, flen;
2639 int i, j, c, flen;
2640 var *v; 2649 var *v;
2641 static var tv; 2650 var tv;
2642 char **envp; 2651 char **envp;
2643 static int from_file = FALSE; 2652 char *vnames = (char *)vNames; /* cheat */
2644 rstream *rsm; 2653 char *vvalues = (char *)vValues;
2645 FILE *F, *stdfiles[3]; 2654
2646 static char * stdnames = "/dev/stdin\0/dev/stdout\0/dev/stderr"; 2655 zero_out_var(&tv);
2647 2656
2648 /* allocate global buffer */ 2657 /* allocate global buffer */
2649 buf = xmalloc(MAXVARFMT+1); 2658 buf = xmalloc(MAXVARFMT + 1);
2650 2659
2651 vhash = hash_init(); 2660 vhash = hash_init();
2652 ahash = hash_init(); 2661 ahash = hash_init();
@@ -2654,98 +2663,90 @@ int awk_main(int argc, char **argv)
2654 fnhash = hash_init(); 2663 fnhash = hash_init();
2655 2664
2656 /* initialize variables */ 2665 /* initialize variables */
2657 for (i=0; *vNames; i++) { 2666 for (i = 0; *vnames; i++) {
2658 V[i] = v = newvar(nextword(&vNames)); 2667 V[i] = v = newvar(nextword(&vnames));
2659 if (*vValues != '\377') 2668 if (*vvalues != '\377')
2660 setvar_s(v, nextword(&vValues)); 2669 setvar_s(v, nextword(&vvalues));
2661 else 2670 else
2662 setvar_i(v, 0); 2671 setvar_i(v, 0);
2663 2672
2664 if (*vNames == '*') { 2673 if (*vnames == '*') {
2665 v->type |= VF_SPECIAL; 2674 v->type |= VF_SPECIAL;
2666 vNames++; 2675 vnames++;
2667 } 2676 }
2668 } 2677 }
2669 2678
2670 handle_special(V[FS]); 2679 handle_special(V[FS]);
2671 handle_special(V[RS]); 2680 handle_special(V[RS]);
2672 2681
2673 stdfiles[0] = stdin; 2682 newfile("/dev/stdin")->F = stdin;
2674 stdfiles[1] = stdout; 2683 newfile("/dev/stdout")->F = stdout;
2675 stdfiles[2] = stderr; 2684 newfile("/dev/stderr")->F = stderr;
2676 for (i=0; i<3; i++) {
2677 rsm = newfile(nextword(&stdnames));
2678 rsm->F = stdfiles[i];
2679 }
2680 2685
2681 for (envp=environ; *envp; envp++) { 2686 for (envp = environ; *envp; envp++) {
2682 s = xstrdup(*envp); 2687 char *s = xstrdup(*envp);
2683 s1 = strchr(s, '='); 2688 char *s1 = strchr(s, '=');
2684 if (!s1) { 2689 if (s1) {
2685 goto keep_going; 2690 *s1++ = '\0';
2691 setvar_u(findvar(iamarray(V[ENVIRON]), s), s1);
2686 } 2692 }
2687 *(s1++) = '\0';
2688 setvar_u(findvar(iamarray(V[ENVIRON]), s), s1);
2689keep_going:
2690 free(s); 2693 free(s);
2691 } 2694 }
2692 2695
2693 opt = getopt32(argc, argv, "F:v:f:W:", &opt_F, &opt_v, &programname, &opt_W); 2696 opt = getopt32(argc, argv, "F:v:f:W:", &opt_F, &opt_v, &programname, &opt_W);
2697 argv += optind;
2698 argc -= optind;
2694 if (opt & 0x1) setvar_s(V[FS], opt_F); // -F 2699 if (opt & 0x1) setvar_s(V[FS], opt_F); // -F
2695 if (opt & 0x2) if (!is_assignment(opt_v)) bb_show_usage(); // -v 2700 if (opt & 0x2) if (!is_assignment(opt_v)) bb_show_usage(); // -v
2696 if (opt & 0x4) { // -f 2701 if (opt & 0x4) { // -f
2697 from_file = TRUE; 2702 char *s = s; /* die, gcc, die */
2698 F = afopen(programname, "r"); 2703 FILE *from_file = afopen(programname, "r");
2699 s = NULL;
2700 /* one byte is reserved for some trick in next_token */ 2704 /* one byte is reserved for some trick in next_token */
2701 if (fseek(F, 0, SEEK_END) == 0) { 2705 if (fseek(from_file, 0, SEEK_END) == 0) {
2702 flen = ftell(F); 2706 flen = ftell(from_file);
2703 s = xmalloc(flen+4); 2707 s = xmalloc(flen + 4);
2704 fseek(F, 0, SEEK_SET); 2708 fseek(from_file, 0, SEEK_SET);
2705 i = 1 + fread(s+1, 1, flen, F); 2709 i = 1 + fread(s + 1, 1, flen, from_file);
2706 } else { 2710 } else {
2707 for (i=j=1; j>0; i+=j) { 2711 for (i = j = 1; j > 0; i += j) {
2708 s = (char *)xrealloc(s, i+4096); 2712 s = xrealloc(s, i + 4096);
2709 j = fread(s+i, 1, 4094, F); 2713 j = fread(s + i, 1, 4094, from_file);
2710 } 2714 }
2711 } 2715 }
2712 s[i] = '\0'; 2716 s[i] = '\0';
2713 fclose(F); 2717 fclose(from_file);
2714 parse_program(s+1); 2718 parse_program(s + 1);
2715 free(s); 2719 free(s);
2716 } 2720 } else { // no -f: take program from 1st parameter
2717 if (opt & 0x8) // -W 2721 if (!argc)
2718 bb_error_msg("warning: unrecognized option '-W %s' ignored", opt_W);
2719
2720 if (!from_file) {
2721 if (argc == optind)
2722 bb_show_usage(); 2722 bb_show_usage();
2723 programname = "cmd. line"; 2723 programname = "cmd. line";
2724 parse_program(argv[optind++]); 2724 parse_program(*argv++);
2725 2725 argc--;
2726 } 2726 }
2727 if (opt & 0x8) // -W
2728 bb_error_msg("warning: unrecognized option '-W %s' ignored", opt_W);
2727 2729
2728 /* fill in ARGV array */ 2730 /* fill in ARGV array */
2729 setvar_i(V[ARGC], argc - optind + 1); 2731 setvar_i(V[ARGC], argc + 1);
2730 setari_u(V[ARGV], 0, "awk"); 2732 setari_u(V[ARGV], 0, "awk");
2731 for (i = optind; i < argc; i++) 2733 i = 0;
2732 setari_u(V[ARGV], i+1-optind, argv[i]); 2734 while (*argv)
2735 setari_u(V[ARGV], ++i, *argv++);
2733 2736
2734 evaluate(beginseq.first, &tv); 2737 evaluate(beginseq.first, &tv);
2735 if (! mainseq.first && ! endseq.first) 2738 if (!mainseq.first && !endseq.first)
2736 awk_exit(EXIT_SUCCESS); 2739 awk_exit(EXIT_SUCCESS);
2737 2740
2738 /* input file could already be opened in BEGIN block */ 2741 /* input file could already be opened in BEGIN block */
2739 if (! iF) iF = next_input_file(); 2742 if (!iF) iF = next_input_file();
2740 2743
2741 /* passing through input files */ 2744 /* passing through input files */
2742 while (iF) { 2745 while (iF) {
2743
2744 nextfile = FALSE; 2746 nextfile = FALSE;
2745 setvar_i(V[FNR], 0); 2747 setvar_i(V[FNR], 0);
2746 2748
2747 while ((c = awk_getline(iF, V[F0])) > 0) { 2749 while ((i = awk_getline(iF, V[F0])) > 0) {
2748
2749 nextrec = FALSE; 2750 nextrec = FALSE;
2750 incvar(V[NR]); 2751 incvar(V[NR]);
2751 incvar(V[FNR]); 2752 incvar(V[FNR]);
@@ -2755,14 +2756,12 @@ keep_going:
2755 break; 2756 break;
2756 } 2757 }
2757 2758
2758 if (c < 0) 2759 if (i < 0)
2759 runtime_error(strerror(errno)); 2760 runtime_error(strerror(errno));
2760 2761
2761 iF = next_input_file(); 2762 iF = next_input_file();
2762
2763 } 2763 }
2764 2764
2765 awk_exit(EXIT_SUCCESS); 2765 awk_exit(EXIT_SUCCESS);
2766 2766 /*return 0;*/
2767 return 0;
2768} 2767}