aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2011-09-11 00:30:56 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2011-09-11 00:30:56 +0200
commit7b46d11582047d0dd21b547ff4a913defe646d40 (patch)
treef4f6787860df6536bd1e22deba6ddec41a0e3fa1
parentd48fdde3704f453014404fca321e08238dc4acc4 (diff)
downloadbusybox-w32-7b46d11582047d0dd21b547ff4a913defe646d40.tar.gz
busybox-w32-7b46d11582047d0dd21b547ff4a913defe646d40.tar.bz2
busybox-w32-7b46d11582047d0dd21b547ff4a913defe646d40.zip
awk: fix a SEGV
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--editors/awk.c71
-rwxr-xr-xtestsuite/awk.tests3
2 files changed, 65 insertions, 9 deletions
diff --git a/editors/awk.c b/editors/awk.c
index 8117cab54..71abca215 100644
--- a/editors/awk.c
+++ b/editors/awk.c
@@ -25,6 +25,7 @@
25 * to perform debug printfs to stderr: */ 25 * to perform debug printfs to stderr: */
26#define debug_printf_walker(...) do {} while (0) 26#define debug_printf_walker(...) do {} while (0)
27#define debug_printf_eval(...) do {} while (0) 27#define debug_printf_eval(...) do {} while (0)
28#define debug_printf_parse(...) do {} while (0)
28 29
29#ifndef debug_printf_walker 30#ifndef debug_printf_walker
30# define debug_printf_walker(...) (fprintf(stderr, __VA_ARGS__)) 31# define debug_printf_walker(...) (fprintf(stderr, __VA_ARGS__))
@@ -32,6 +33,9 @@
32#ifndef debug_printf_eval 33#ifndef debug_printf_eval
33# define debug_printf_eval(...) (fprintf(stderr, __VA_ARGS__)) 34# define debug_printf_eval(...) (fprintf(stderr, __VA_ARGS__))
34#endif 35#endif
36#ifndef debug_printf_parse
37# define debug_printf_parse(...) (fprintf(stderr, __VA_ARGS__))
38#endif
35 39
36 40
37 41
@@ -435,13 +439,13 @@ struct globals {
435 smallint nextrec; 439 smallint nextrec;
436 smallint nextfile; 440 smallint nextfile;
437 smallint is_f0_split; 441 smallint is_f0_split;
442 smallint t_rollback;
438}; 443};
439struct globals2 { 444struct globals2 {
440 uint32_t t_info; /* often used */ 445 uint32_t t_info; /* often used */
441 uint32_t t_tclass; 446 uint32_t t_tclass;
442 char *t_string; 447 char *t_string;
443 int t_lineno; 448 int t_lineno;
444 int t_rollback;
445 449
446 var *intvar[NUM_INTERNAL_VARS]; /* often used */ 450 var *intvar[NUM_INTERNAL_VARS]; /* often used */
447 451
@@ -499,11 +503,11 @@ struct globals2 {
499#define nextrec (G1.nextrec ) 503#define nextrec (G1.nextrec )
500#define nextfile (G1.nextfile ) 504#define nextfile (G1.nextfile )
501#define is_f0_split (G1.is_f0_split ) 505#define is_f0_split (G1.is_f0_split )
506#define t_rollback (G1.t_rollback )
502#define t_info (G.t_info ) 507#define t_info (G.t_info )
503#define t_tclass (G.t_tclass ) 508#define t_tclass (G.t_tclass )
504#define t_string (G.t_string ) 509#define t_string (G.t_string )
505#define t_lineno (G.t_lineno ) 510#define t_lineno (G.t_lineno )
506#define t_rollback (G.t_rollback )
507#define intvar (G.intvar ) 511#define intvar (G.intvar )
508#define fsplitter (G.fsplitter ) 512#define fsplitter (G.fsplitter )
509#define rsplitter (G.rsplitter ) 513#define rsplitter (G.rsplitter )
@@ -1011,6 +1015,7 @@ static uint32_t next_token(uint32_t expected)
1011 1015
1012 if (*p == '\0') { 1016 if (*p == '\0') {
1013 tc = TC_EOF; 1017 tc = TC_EOF;
1018 debug_printf_parse("%s: token found: TC_EOF\n", __func__);
1014 1019
1015 } else if (*p == '\"') { 1020 } else if (*p == '\"') {
1016 /* it's a string */ 1021 /* it's a string */
@@ -1026,6 +1031,7 @@ static uint32_t next_token(uint32_t expected)
1026 p++; 1031 p++;
1027 *s = '\0'; 1032 *s = '\0';
1028 tc = TC_STRING; 1033 tc = TC_STRING;
1034 debug_printf_parse("%s: token found:'%s' TC_STRING\n", __func__, t_string);
1029 1035
1030 } else if ((expected & TC_REGEXP) && *p == '/') { 1036 } else if ((expected & TC_REGEXP) && *p == '/') {
1031 /* it's regexp */ 1037 /* it's regexp */
@@ -1048,6 +1054,7 @@ static uint32_t next_token(uint32_t expected)
1048 p++; 1054 p++;
1049 *s = '\0'; 1055 *s = '\0';
1050 tc = TC_REGEXP; 1056 tc = TC_REGEXP;
1057 debug_printf_parse("%s: token found:'%s' TC_REGEXP\n", __func__, t_string);
1051 1058
1052 } else if (*p == '.' || isdigit(*p)) { 1059 } else if (*p == '.' || isdigit(*p)) {
1053 /* it's a number */ 1060 /* it's a number */
@@ -1057,6 +1064,7 @@ static uint32_t next_token(uint32_t expected)
1057 if (*p == '.') 1064 if (*p == '.')
1058 syntax_error(EMSG_UNEXP_TOKEN); 1065 syntax_error(EMSG_UNEXP_TOKEN);
1059 tc = TC_NUMBER; 1066 tc = TC_NUMBER;
1067 debug_printf_parse("%s: token found:%f TC_NUMBER\n", __func__, t_double);
1060 1068
1061 } else { 1069 } else {
1062 /* search for something known */ 1070 /* search for something known */
@@ -1079,6 +1087,7 @@ static uint32_t next_token(uint32_t expected)
1079 ) { 1087 ) {
1080 /* then this is what we are looking for */ 1088 /* then this is what we are looking for */
1081 t_info = *ti; 1089 t_info = *ti;
1090 debug_printf_parse("%s: token found:'%.*s' t_info:%x\n", __func__, l, p, t_info);
1082 p += l; 1091 p += l;
1083 goto token_found; 1092 goto token_found;
1084 } 1093 }
@@ -1102,14 +1111,17 @@ static uint32_t next_token(uint32_t expected)
1102 p = skip_spaces(p); 1111 p = skip_spaces(p);
1103 if (*p == '(') { 1112 if (*p == '(') {
1104 tc = TC_FUNCTION; 1113 tc = TC_FUNCTION;
1114 debug_printf_parse("%s: token found:'%s' TC_FUNCTION\n", __func__, t_string);
1105 } else { 1115 } else {
1106 if (*p == '[') { 1116 if (*p == '[') {
1107 p++; 1117 p++;
1108 tc = TC_ARRAY; 1118 tc = TC_ARRAY;
1109 } 1119 debug_printf_parse("%s: token found:'%s' TC_ARRAY\n", __func__, t_string);
1120 } else
1121 debug_printf_parse("%s: token found:'%s' TC_VARIABLE\n", __func__, t_string);
1110 } 1122 }
1111 token_found: ;
1112 } 1123 }
1124 token_found:
1113 g_pos = p; 1125 g_pos = p;
1114 1126
1115 /* skipping newlines in some cases */ 1127 /* skipping newlines in some cases */
@@ -1181,6 +1193,8 @@ static node *parse_expr(uint32_t iexp)
1181 uint32_t tc, xtc; 1193 uint32_t tc, xtc;
1182 var *v; 1194 var *v;
1183 1195
1196 debug_printf_parse("%s(%x)\n", __func__, iexp);
1197
1184 sn.info = PRIMASK; 1198 sn.info = PRIMASK;
1185 sn.r.n = glptr = NULL; 1199 sn.r.n = glptr = NULL;
1186 xtc = TC_OPERAND | TC_UOPPRE | TC_REGEXP | iexp; 1200 xtc = TC_OPERAND | TC_UOPPRE | TC_REGEXP | iexp;
@@ -1189,12 +1203,14 @@ static node *parse_expr(uint32_t iexp)
1189 1203
1190 if (glptr && (t_info == (OC_COMPARE | VV | P(39) | 2))) { 1204 if (glptr && (t_info == (OC_COMPARE | VV | P(39) | 2))) {
1191 /* input redirection (<) attached to glptr node */ 1205 /* input redirection (<) attached to glptr node */
1206 debug_printf_parse("%s: input redir\n", __func__);
1192 cn = glptr->l.n = new_node(OC_CONCAT | SS | P(37)); 1207 cn = glptr->l.n = new_node(OC_CONCAT | SS | P(37));
1193 cn->a.n = glptr; 1208 cn->a.n = glptr;
1194 xtc = TC_OPERAND | TC_UOPPRE; 1209 xtc = TC_OPERAND | TC_UOPPRE;
1195 glptr = NULL; 1210 glptr = NULL;
1196 1211
1197 } else if (tc & (TC_BINOP | TC_UOPPOST)) { 1212 } else if (tc & (TC_BINOP | TC_UOPPOST)) {
1213 debug_printf_parse("%s: TC_BINOP | TC_UOPPOST\n", __func__);
1198 /* for binary and postfix-unary operators, jump back over 1214 /* for binary and postfix-unary operators, jump back over
1199 * previous operators with higher priority */ 1215 * previous operators with higher priority */
1200 vn = cn; 1216 vn = cn;
@@ -1224,6 +1240,7 @@ static node *parse_expr(uint32_t iexp)
1224 vn->a.n = cn; 1240 vn->a.n = cn;
1225 1241
1226 } else { 1242 } else {
1243 debug_printf_parse("%s: other\n", __func__);
1227 /* for operands and prefix-unary operators, attach them 1244 /* for operands and prefix-unary operators, attach them
1228 * to last node */ 1245 * to last node */
1229 vn = cn; 1246 vn = cn;
@@ -1231,12 +1248,14 @@ static node *parse_expr(uint32_t iexp)
1231 cn->a.n = vn; 1248 cn->a.n = vn;
1232 xtc = TC_OPERAND | TC_UOPPRE | TC_REGEXP; 1249 xtc = TC_OPERAND | TC_UOPPRE | TC_REGEXP;
1233 if (tc & (TC_OPERAND | TC_REGEXP)) { 1250 if (tc & (TC_OPERAND | TC_REGEXP)) {
1251 debug_printf_parse("%s: TC_OPERAND | TC_REGEXP\n", __func__);
1234 xtc = TC_UOPPRE | TC_UOPPOST | TC_BINOP | TC_OPERAND | iexp; 1252 xtc = TC_UOPPRE | TC_UOPPOST | TC_BINOP | TC_OPERAND | iexp;
1235 /* one should be very careful with switch on tclass - 1253 /* one should be very careful with switch on tclass -
1236 * only simple tclasses should be used! */ 1254 * only simple tclasses should be used! */
1237 switch (tc) { 1255 switch (tc) {
1238 case TC_VARIABLE: 1256 case TC_VARIABLE:
1239 case TC_ARRAY: 1257 case TC_ARRAY:
1258 debug_printf_parse("%s: TC_VARIABLE | TC_ARRAY\n", __func__);
1240 cn->info = OC_VAR; 1259 cn->info = OC_VAR;
1241 v = hash_search(ahash, t_string); 1260 v = hash_search(ahash, t_string);
1242 if (v != NULL) { 1261 if (v != NULL) {
@@ -1253,6 +1272,7 @@ static node *parse_expr(uint32_t iexp)
1253 1272
1254 case TC_NUMBER: 1273 case TC_NUMBER:
1255 case TC_STRING: 1274 case TC_STRING:
1275 debug_printf_parse("%s: TC_NUMBER | TC_STRING\n", __func__);
1256 cn->info = OC_VAR; 1276 cn->info = OC_VAR;
1257 v = cn->l.v = xzalloc(sizeof(var)); 1277 v = cn->l.v = xzalloc(sizeof(var));
1258 if (tc & TC_NUMBER) 1278 if (tc & TC_NUMBER)
@@ -1262,32 +1282,41 @@ static node *parse_expr(uint32_t iexp)
1262 break; 1282 break;
1263 1283
1264 case TC_REGEXP: 1284 case TC_REGEXP:
1285 debug_printf_parse("%s: TC_REGEXP\n", __func__);
1265 mk_re_node(t_string, cn, xzalloc(sizeof(regex_t)*2)); 1286 mk_re_node(t_string, cn, xzalloc(sizeof(regex_t)*2));
1266 break; 1287 break;
1267 1288
1268 case TC_FUNCTION: 1289 case TC_FUNCTION:
1290 debug_printf_parse("%s: TC_FUNCTION\n", __func__);
1269 cn->info = OC_FUNC; 1291 cn->info = OC_FUNC;
1270 cn->r.f = newfunc(t_string); 1292 cn->r.f = newfunc(t_string);
1271 cn->l.n = condition(); 1293 cn->l.n = condition();
1272 break; 1294 break;
1273 1295
1274 case TC_SEQSTART: 1296 case TC_SEQSTART:
1297 debug_printf_parse("%s: TC_SEQSTART\n", __func__);
1275 cn = vn->r.n = parse_expr(TC_SEQTERM); 1298 cn = vn->r.n = parse_expr(TC_SEQTERM);
1299 if (!cn)
1300 syntax_error("Empty sequence");
1276 cn->a.n = vn; 1301 cn->a.n = vn;
1277 break; 1302 break;
1278 1303
1279 case TC_GETLINE: 1304 case TC_GETLINE:
1305 debug_printf_parse("%s: TC_GETLINE\n", __func__);
1280 glptr = cn; 1306 glptr = cn;
1281 xtc = TC_OPERAND | TC_UOPPRE | TC_BINOP | iexp; 1307 xtc = TC_OPERAND | TC_UOPPRE | TC_BINOP | iexp;
1282 break; 1308 break;
1283 1309
1284 case TC_BUILTIN: 1310 case TC_BUILTIN:
1311 debug_printf_parse("%s: TC_BUILTIN\n", __func__);
1285 cn->l.n = condition(); 1312 cn->l.n = condition();
1286 break; 1313 break;
1287 } 1314 }
1288 } 1315 }
1289 } 1316 }
1290 } 1317 }
1318
1319 debug_printf_parse("%s() returns %p\n", __func__, sn.r.n);
1291 return sn.r.n; 1320 return sn.r.n;
1292} 1321}
1293 1322
@@ -1356,18 +1385,25 @@ static void chain_group(void)
1356 } while (c & TC_NEWLINE); 1385 } while (c & TC_NEWLINE);
1357 1386
1358 if (c & TC_GRPSTART) { 1387 if (c & TC_GRPSTART) {
1388 debug_printf_parse("%s: TC_GRPSTART\n", __func__);
1359 while (next_token(TC_GRPSEQ | TC_GRPTERM) != TC_GRPTERM) { 1389 while (next_token(TC_GRPSEQ | TC_GRPTERM) != TC_GRPTERM) {
1390 debug_printf_parse("%s: !TC_GRPTERM\n", __func__);
1360 if (t_tclass & TC_NEWLINE) 1391 if (t_tclass & TC_NEWLINE)
1361 continue; 1392 continue;
1362 rollback_token(); 1393 rollback_token();
1363 chain_group(); 1394 chain_group();
1364 } 1395 }
1396 debug_printf_parse("%s: TC_GRPTERM\n", __func__);
1365 } else if (c & (TC_OPSEQ | TC_OPTERM)) { 1397 } else if (c & (TC_OPSEQ | TC_OPTERM)) {
1398 debug_printf_parse("%s: TC_OPSEQ | TC_OPTERM\n", __func__);
1366 rollback_token(); 1399 rollback_token();
1367 chain_expr(OC_EXEC | Vx); 1400 chain_expr(OC_EXEC | Vx);
1368 } else { /* TC_STATEMNT */ 1401 } else {
1402 /* TC_STATEMNT */
1403 debug_printf_parse("%s: TC_STATEMNT(?)\n", __func__);
1369 switch (t_info & OPCLSMASK) { 1404 switch (t_info & OPCLSMASK) {
1370 case ST_IF: 1405 case ST_IF:
1406 debug_printf_parse("%s: ST_IF\n", __func__);
1371 n = chain_node(OC_BR | Vx); 1407 n = chain_node(OC_BR | Vx);
1372 n->l.n = condition(); 1408 n->l.n = condition();
1373 chain_group(); 1409 chain_group();
@@ -1382,12 +1418,14 @@ static void chain_group(void)
1382 break; 1418 break;
1383 1419
1384 case ST_WHILE: 1420 case ST_WHILE:
1421 debug_printf_parse("%s: ST_WHILE\n", __func__);
1385 n2 = condition(); 1422 n2 = condition();
1386 n = chain_loop(NULL); 1423 n = chain_loop(NULL);
1387 n->l.n = n2; 1424 n->l.n = n2;
1388 break; 1425 break;
1389 1426
1390 case ST_DO: 1427 case ST_DO:
1428 debug_printf_parse("%s: ST_DO\n", __func__);
1391 n2 = chain_node(OC_EXEC); 1429 n2 = chain_node(OC_EXEC);
1392 n = chain_loop(NULL); 1430 n = chain_loop(NULL);
1393 n2->a.n = n->a.n; 1431 n2->a.n = n->a.n;
@@ -1396,6 +1434,7 @@ static void chain_group(void)
1396 break; 1434 break;
1397 1435
1398 case ST_FOR: 1436 case ST_FOR:
1437 debug_printf_parse("%s: ST_FOR\n", __func__);
1399 next_token(TC_SEQSTART); 1438 next_token(TC_SEQSTART);
1400 n2 = parse_expr(TC_SEMICOL | TC_SEQTERM); 1439 n2 = parse_expr(TC_SEMICOL | TC_SEQTERM);
1401 if (t_tclass & TC_SEQTERM) { /* for-in */ 1440 if (t_tclass & TC_SEQTERM) { /* for-in */
@@ -1421,6 +1460,7 @@ static void chain_group(void)
1421 1460
1422 case OC_PRINT: 1461 case OC_PRINT:
1423 case OC_PRINTF: 1462 case OC_PRINTF:
1463 debug_printf_parse("%s: OC_PRINT[F]\n", __func__);
1424 n = chain_node(t_info); 1464 n = chain_node(t_info);
1425 n->l.n = parse_expr(TC_OPTERM | TC_OUTRDR | TC_GRPTERM); 1465 n->l.n = parse_expr(TC_OPTERM | TC_OUTRDR | TC_GRPTERM);
1426 if (t_tclass & TC_OUTRDR) { 1466 if (t_tclass & TC_OUTRDR) {
@@ -1432,17 +1472,20 @@ static void chain_group(void)
1432 break; 1472 break;
1433 1473
1434 case OC_BREAK: 1474 case OC_BREAK:
1475 debug_printf_parse("%s: OC_BREAK\n", __func__);
1435 n = chain_node(OC_EXEC); 1476 n = chain_node(OC_EXEC);
1436 n->a.n = break_ptr; 1477 n->a.n = break_ptr;
1437 break; 1478 break;
1438 1479
1439 case OC_CONTINUE: 1480 case OC_CONTINUE:
1481 debug_printf_parse("%s: OC_CONTINUE\n", __func__);
1440 n = chain_node(OC_EXEC); 1482 n = chain_node(OC_EXEC);
1441 n->a.n = continue_ptr; 1483 n->a.n = continue_ptr;
1442 break; 1484 break;
1443 1485
1444 /* delete, next, nextfile, return, exit */ 1486 /* delete, next, nextfile, return, exit */
1445 default: 1487 default:
1488 debug_printf_parse("%s: default\n", __func__);
1446 chain_expr(t_info); 1489 chain_expr(t_info);
1447 } 1490 }
1448 } 1491 }
@@ -1460,19 +1503,24 @@ static void parse_program(char *p)
1460 while ((tclass = next_token(TC_EOF | TC_OPSEQ | TC_GRPSTART | 1503 while ((tclass = next_token(TC_EOF | TC_OPSEQ | TC_GRPSTART |
1461 TC_OPTERM | TC_BEGIN | TC_END | TC_FUNCDECL)) != TC_EOF) { 1504 TC_OPTERM | TC_BEGIN | TC_END | TC_FUNCDECL)) != TC_EOF) {
1462 1505
1463 if (tclass & TC_OPTERM) 1506 if (tclass & TC_OPTERM) {
1507 debug_printf_parse("%s: TC_OPTERM\n", __func__);
1464 continue; 1508 continue;
1509 }
1465 1510
1466 seq = &mainseq; 1511 seq = &mainseq;
1467 if (tclass & TC_BEGIN) { 1512 if (tclass & TC_BEGIN) {
1513 debug_printf_parse("%s: TC_BEGIN\n", __func__);
1468 seq = &beginseq; 1514 seq = &beginseq;
1469 chain_group(); 1515 chain_group();
1470 1516
1471 } else if (tclass & TC_END) { 1517 } else if (tclass & TC_END) {
1518 debug_printf_parse("%s: TC_END\n", __func__);
1472 seq = &endseq; 1519 seq = &endseq;
1473 chain_group(); 1520 chain_group();
1474 1521
1475 } else if (tclass & TC_FUNCDECL) { 1522 } else if (tclass & TC_FUNCDECL) {
1523 debug_printf_parse("%s: TC_FUNCDECL\n", __func__);
1476 next_token(TC_FUNCTION); 1524 next_token(TC_FUNCTION);
1477 g_pos++; 1525 g_pos++;
1478 f = newfunc(t_string); 1526 f = newfunc(t_string);
@@ -1490,22 +1538,27 @@ static void parse_program(char *p)
1490 clear_array(ahash); 1538 clear_array(ahash);
1491 1539
1492 } else if (tclass & TC_OPSEQ) { 1540 } else if (tclass & TC_OPSEQ) {
1541 debug_printf_parse("%s: TC_OPSEQ\n", __func__);
1493 rollback_token(); 1542 rollback_token();
1494 cn = chain_node(OC_TEST); 1543 cn = chain_node(OC_TEST);
1495 cn->l.n = parse_expr(TC_OPTERM | TC_EOF | TC_GRPSTART); 1544 cn->l.n = parse_expr(TC_OPTERM | TC_EOF | TC_GRPSTART);
1496 if (t_tclass & TC_GRPSTART) { 1545 if (t_tclass & TC_GRPSTART) {
1546 debug_printf_parse("%s: TC_GRPSTART\n", __func__);
1497 rollback_token(); 1547 rollback_token();
1498 chain_group(); 1548 chain_group();
1499 } else { 1549 } else {
1550 debug_printf_parse("%s: !TC_GRPSTART\n", __func__);
1500 chain_node(OC_PRINT); 1551 chain_node(OC_PRINT);
1501 } 1552 }
1502 cn->r.n = mainseq.last; 1553 cn->r.n = mainseq.last;
1503 1554
1504 } else /* if (tclass & TC_GRPSTART) */ { 1555 } else /* if (tclass & TC_GRPSTART) */ {
1556 debug_printf_parse("%s: TC_GRPSTART(?)\n", __func__);
1505 rollback_token(); 1557 rollback_token();
1506 chain_group(); 1558 chain_group();
1507 } 1559 }
1508 } 1560 }
1561 debug_printf_parse("%s: TC_EOF\n", __func__);
1509} 1562}
1510 1563
1511 1564
@@ -3000,7 +3053,7 @@ int awk_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
3000int awk_main(int argc, char **argv) 3053int awk_main(int argc, char **argv)
3001{ 3054{
3002 unsigned opt; 3055 unsigned opt;
3003 char *opt_F, *opt_W; 3056 char *opt_F;
3004 llist_t *list_v = NULL; 3057 llist_t *list_v = NULL;
3005 llist_t *list_f = NULL; 3058 llist_t *list_f = NULL;
3006 int i, j; 3059 int i, j;
@@ -3062,7 +3115,7 @@ int awk_main(int argc, char **argv)
3062 } 3115 }
3063 } 3116 }
3064 opt_complementary = "v::f::"; /* -v and -f can occur multiple times */ 3117 opt_complementary = "v::f::"; /* -v and -f can occur multiple times */
3065 opt = getopt32(argv, "F:v:f:W:", &opt_F, &list_v, &list_f, &opt_W); 3118 opt = getopt32(argv, "F:v:f:W:", &opt_F, &list_v, &list_f, NULL);
3066 argv += optind; 3119 argv += optind;
3067 argc -= optind; 3120 argc -= optind;
3068 if (opt & 0x1) 3121 if (opt & 0x1)
@@ -3096,7 +3149,7 @@ int awk_main(int argc, char **argv)
3096 parse_program(*argv++); 3149 parse_program(*argv++);
3097 } 3150 }
3098 if (opt & 0x8) // -W 3151 if (opt & 0x8) // -W
3099 bb_error_msg("warning: unrecognized option '-W %s' ignored", opt_W); 3152 bb_error_msg("warning: option -W is ignored");
3100 3153
3101 /* fill in ARGV array */ 3154 /* fill in ARGV array */
3102 setvar_i(intvar[ARGC], argc); 3155 setvar_i(intvar[ARGC], argc);
diff --git a/testsuite/awk.tests b/testsuite/awk.tests
index 0afe9b9e7..5a323047d 100755
--- a/testsuite/awk.tests
+++ b/testsuite/awk.tests
@@ -202,4 +202,7 @@ end d
202" \ 202" \
203 "" "" 203 "" ""
204 204
205testing "awk handles empty ()" \
206 "awk 'BEGIN {print()}' 2>&1" "awk: cmd. line:1: Empty sequence\n" "" ""
207
205exit $FAILCOUNT 208exit $FAILCOUNT