aboutsummaryrefslogtreecommitdiff
path: root/editors/awk.c
diff options
context:
space:
mode:
Diffstat (limited to 'editors/awk.c')
-rw-r--r--editors/awk.c41
1 files changed, 31 insertions, 10 deletions
diff --git a/editors/awk.c b/editors/awk.c
index 86cd9a289..dbb26068d 100644
--- a/editors/awk.c
+++ b/editors/awk.c
@@ -275,18 +275,21 @@ typedef struct tsplitter_s {
275 | TC_STRING | TC_NUMBER | TC_UOPPOST) 275 | TC_STRING | TC_NUMBER | TC_UOPPOST)
276#define TC_CONCAT2 (TC_OPERAND | TC_UOPPRE) 276#define TC_CONCAT2 (TC_OPERAND | TC_UOPPRE)
277 277
278#define OF_RES1 0x010000 278#define OF_RES1 0x010000
279#define OF_RES2 0x020000 279#define OF_RES2 0x020000
280#define OF_STR1 0x040000 280#define OF_STR1 0x040000
281#define OF_STR2 0x080000 281#define OF_STR2 0x080000
282#define OF_NUM1 0x100000 282#define OF_NUM1 0x100000
283#define OF_CHECKED 0x200000 283#define OF_CHECKED 0x200000
284#define OF_REQUIRED 0x400000
285
284 286
285/* combined operator flags */ 287/* combined operator flags */
286#define xx 0 288#define xx 0
287#define xV OF_RES2 289#define xV OF_RES2
288#define xS (OF_RES2 | OF_STR2) 290#define xS (OF_RES2 | OF_STR2)
289#define Vx OF_RES1 291#define Vx OF_RES1
292#define Rx (OF_RES1 | OF_NUM1 | OF_REQUIRED)
290#define VV (OF_RES1 | OF_RES2) 293#define VV (OF_RES1 | OF_RES2)
291#define Nx (OF_RES1 | OF_NUM1) 294#define Nx (OF_RES1 | OF_NUM1)
292#define NV (OF_RES1 | OF_NUM1 | OF_RES2) 295#define NV (OF_RES1 | OF_NUM1 | OF_RES2)
@@ -425,7 +428,7 @@ static const uint32_t tokeninfo[] = {
425 0, 428 0,
426 0, /* \n */ 429 0, /* \n */
427 ST_IF, ST_DO, ST_FOR, OC_BREAK, 430 ST_IF, ST_DO, ST_FOR, OC_BREAK,
428 OC_CONTINUE, OC_DELETE|Vx, OC_PRINT, 431 OC_CONTINUE, OC_DELETE|Rx, OC_PRINT,
429 OC_PRINTF, OC_NEXT, OC_NEXTFILE, 432 OC_PRINTF, OC_NEXT, OC_NEXTFILE,
430 OC_RETURN|Vx, OC_EXIT|Nx, 433 OC_RETURN|Vx, OC_EXIT|Nx,
431 ST_WHILE, 434 ST_WHILE,
@@ -593,7 +596,7 @@ static const char EMSG_UNEXP_EOS[] ALIGN1 = "Unexpected end of string";
593static const char EMSG_UNEXP_TOKEN[] ALIGN1 = "Unexpected token"; 596static const char EMSG_UNEXP_TOKEN[] ALIGN1 = "Unexpected token";
594static const char EMSG_DIV_BY_ZERO[] ALIGN1 = "Division by zero"; 597static const char EMSG_DIV_BY_ZERO[] ALIGN1 = "Division by zero";
595static const char EMSG_INV_FMT[] ALIGN1 = "Invalid format specifier"; 598static const char EMSG_INV_FMT[] ALIGN1 = "Invalid format specifier";
596static const char EMSG_TOO_FEW_ARGS[] ALIGN1 = "Too few arguments for builtin"; 599static const char EMSG_TOO_FEW_ARGS[] ALIGN1 = "Too few arguments";
597static const char EMSG_NOT_ARRAY[] ALIGN1 = "Not an array"; 600static const char EMSG_NOT_ARRAY[] ALIGN1 = "Not an array";
598static const char EMSG_POSSIBLE_ERROR[] ALIGN1 = "Possible syntax error"; 601static const char EMSG_POSSIBLE_ERROR[] ALIGN1 = "Possible syntax error";
599static const char EMSG_UNDEF_FUNC[] ALIGN1 = "Call to undefined function"; 602static const char EMSG_UNDEF_FUNC[] ALIGN1 = "Call to undefined function";
@@ -1269,7 +1272,7 @@ static node *parse_expr(uint32_t iexp)
1269 debug_printf_parse("%s(%x)\n", __func__, iexp); 1272 debug_printf_parse("%s(%x)\n", __func__, iexp);
1270 1273
1271 sn.info = PRIMASK; 1274 sn.info = PRIMASK;
1272 sn.r.n = glptr = NULL; 1275 sn.r.n = sn.a.n = glptr = NULL;
1273 xtc = TC_OPERAND | TC_UOPPRE | TC_REGEXP | iexp; 1276 xtc = TC_OPERAND | TC_UOPPRE | TC_REGEXP | iexp;
1274 1277
1275 while (!((tc = next_token(xtc)) & iexp)) { 1278 while (!((tc = next_token(xtc)) & iexp)) {
@@ -1291,6 +1294,7 @@ static node *parse_expr(uint32_t iexp)
1291 || ((t_info == vn->info) && ((t_info & OPCLSMASK) == OC_COLON)) 1294 || ((t_info == vn->info) && ((t_info & OPCLSMASK) == OC_COLON))
1292 ) { 1295 ) {
1293 vn = vn->a.n; 1296 vn = vn->a.n;
1297 if (!vn->a.n) syntax_error(EMSG_UNEXP_TOKEN);
1294 } 1298 }
1295 if ((t_info & OPCLSMASK) == OC_TERNARY) 1299 if ((t_info & OPCLSMASK) == OC_TERNARY)
1296 t_info += P(6); 1300 t_info += P(6);
@@ -1429,7 +1433,11 @@ static void chain_expr(uint32_t info)
1429 node *n; 1433 node *n;
1430 1434
1431 n = chain_node(info); 1435 n = chain_node(info);
1436
1432 n->l.n = parse_expr(TC_OPTERM | TC_GRPTERM); 1437 n->l.n = parse_expr(TC_OPTERM | TC_GRPTERM);
1438 if ((info & OF_REQUIRED) && !n->l.n)
1439 syntax_error(EMSG_TOO_FEW_ARGS);
1440
1433 if (t_tclass & TC_GRPTERM) 1441 if (t_tclass & TC_GRPTERM)
1434 rollback_token(); 1442 rollback_token();
1435} 1443}
@@ -1609,12 +1617,25 @@ static void parse_program(char *p)
1609 f = newfunc(t_string); 1617 f = newfunc(t_string);
1610 f->body.first = NULL; 1618 f->body.first = NULL;
1611 f->nargs = 0; 1619 f->nargs = 0;
1612 while (next_token(TC_VARIABLE | TC_SEQTERM) & TC_VARIABLE) { 1620 /* Match func arg list: a comma sep list of >= 0 args, and a close paren */
1621 while (next_token(TC_VARIABLE | TC_SEQTERM | TC_COMMA)) {
1622 /* Either an empty arg list, or trailing comma from prev iter
1623 * must be followed by an arg */
1624 if (f->nargs == 0 && t_tclass == TC_SEQTERM)
1625 break;
1626
1627 /* TC_SEQSTART/TC_COMMA must be followed by TC_VARIABLE */
1628 if (t_tclass != TC_VARIABLE)
1629 syntax_error(EMSG_UNEXP_TOKEN);
1630
1613 v = findvar(ahash, t_string); 1631 v = findvar(ahash, t_string);
1614 v->x.aidx = f->nargs++; 1632 v->x.aidx = f->nargs++;
1615 1633
1634 /* Arg followed either by end of arg list or 1 comma */
1616 if (next_token(TC_COMMA | TC_SEQTERM) & TC_SEQTERM) 1635 if (next_token(TC_COMMA | TC_SEQTERM) & TC_SEQTERM)
1617 break; 1636 break;
1637 if (t_tclass != TC_COMMA)
1638 syntax_error(EMSG_UNEXP_TOKEN);
1618 } 1639 }
1619 seq = &f->body; 1640 seq = &f->body;
1620 chain_group(); 1641 chain_group();