aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--miscutils/make.c98
-rwxr-xr-xtestsuite/make.tests14
2 files changed, 96 insertions, 16 deletions
diff --git a/miscutils/make.c b/miscutils/make.c
index c69dcec8a..063d0662d 100644
--- a/miscutils/make.c
+++ b/miscutils/make.c
@@ -1419,17 +1419,74 @@ enum {
1419 1419
1420#define IFDEF 0 1420#define IFDEF 0
1421#define IFNDEF 1 1421#define IFNDEF 1
1422#define IFEQ 2
1423#define IFNEQ 3
1422#define ELSE 0 1424#define ELSE 0
1423#define ENDIF 1 1425#define ENDIF 1
1424 1426
1425/* 1427/*
1428 * Extract strings following ifeq/ifneq and compare them.
1429 * Return -1 on error.
1430 */
1431static int
1432compare_strings(char *arg1)
1433{
1434 char *arg2, *end, term, *t1, *t2;
1435 int ret;
1436
1437 // Get first string terminator.
1438 if (arg1[0] == '(')
1439 term = ',';
1440 else if (arg1[0] == '"' || arg1[0] == '\'')
1441 term = arg1[0];
1442 else
1443 return -1;
1444
1445 arg2 = find_char(++arg1, term);
1446 if (arg2 == NULL)
1447 return -1;
1448 *arg2++ = '\0';
1449
1450 // Get second string terminator.
1451 if (term == ',') {
1452 term = ')';
1453 } else {
1454 // Skip spaces between quoted strings.
1455 while (isspace(arg2[0]))
1456 arg2++;
1457 if (arg2[0] == '"' || arg2[0] == '\'')
1458 term = arg2[0];
1459 else
1460 return -1;
1461 ++arg2;
1462 }
1463
1464 end = find_char(arg2, term);
1465 if (end == NULL)
1466 return -1;
1467 *end++ = '\0';
1468
1469 if (gettok(&end) != NULL) {
1470 warning("unexpected text");
1471 }
1472
1473 t1 = expand_macros(arg1, FALSE);
1474 t2 = expand_macros(arg2, FALSE);
1475
1476 ret = strcmp(t1, t2) == 0;
1477 free(t1);
1478 free(t2);
1479 return ret;
1480}
1481
1482/*
1426 * Process conditional directives and return TRUE if the current line 1483 * Process conditional directives and return TRUE if the current line
1427 * should be skipped. 1484 * should be skipped.
1428 */ 1485 */
1429static int 1486static int
1430skip_line(const char *str1) 1487skip_line(const char *str1)
1431{ 1488{
1432 char *copy, *q, *token, *next_token; 1489 char *copy, *q, *token;
1433 bool new_level = TRUE; 1490 bool new_level = TRUE;
1434 // Default is to return skip flag for current level 1491 // Default is to return skip flag for current level
1435 int ret = cstate[clevel] & SKIP_LINE; 1492 int ret = cstate[clevel] & SKIP_LINE;
@@ -1441,11 +1498,9 @@ skip_line(const char *str1)
1441 copy = xstrdup(str1); 1498 copy = xstrdup(str1);
1442 q = process_line(copy); 1499 q = process_line(copy);
1443 if ((token = gettok(&q)) != NULL) { 1500 if ((token = gettok(&q)) != NULL) {
1444 next_token = gettok(&q);
1445
1446 switch (index_in_strings("else\0endif\0", token)) { 1501 switch (index_in_strings("else\0endif\0", token)) {
1447 case ENDIF: 1502 case ENDIF:
1448 if (next_token != NULL) 1503 if (gettok(&q) != NULL)
1449 error_unexpected("text"); 1504 error_unexpected("text");
1450 if (clevel == 0) 1505 if (clevel == 0)
1451 error_unexpected(token); 1506 error_unexpected(token);
@@ -1463,23 +1518,39 @@ skip_line(const char *str1)
1463 else 1518 else
1464 cstate[clevel] &= ~SKIP_LINE; 1519 cstate[clevel] &= ~SKIP_LINE;
1465 1520
1466 if (next_token == NULL) { 1521 token = gettok(&q);
1522 if (token == NULL) {
1467 // Simple else with no conditional directive 1523 // Simple else with no conditional directive
1468 cstate[clevel] &= ~EXPECT_ELSE; 1524 cstate[clevel] &= ~EXPECT_ELSE;
1469 ret = TRUE; 1525 ret = TRUE;
1470 goto end; 1526 goto end;
1471 } else { 1527 } else {
1472 // A conditional directive is now required ('else if'). 1528 // A conditional directive is now required ('else if').
1473 token = next_token;
1474 next_token = gettok(&q);
1475 new_level = FALSE; 1529 new_level = FALSE;
1476 } 1530 }
1477 break;
1478 } 1531 }
1479 1532
1480 key = index_in_strings("ifdef\0ifndef\0", token); 1533 key = index_in_strings("ifdef\0ifndef\0ifeq\0ifneq\0", token);
1481 if (key != -1) { 1534 if (key != -1) {
1482 if (next_token != NULL && gettok(&q) == NULL) { 1535 int match;
1536
1537 if (key == IFDEF || key == IFNDEF) {
1538 // ifdef/ifndef: find out if macro is defined.
1539 char *name = gettok(&q);
1540 if (name != NULL && gettok(&q) == NULL) {
1541 char *t = expand_macros(name, FALSE);
1542 struct macro *mp = getmp(t);
1543 match = mp != NULL && mp->m_val[0] != '\0';
1544 free(t);
1545 } else {
1546 match = -1;
1547 }
1548 } else {
1549 // ifeq/ifneq: compare strings.
1550 match = compare_strings(q);
1551 }
1552
1553 if (match >= 0) {
1483 if (new_level) { 1554 if (new_level) {
1484 // Start a new level. 1555 // Start a new level.
1485 if (clevel == IF_MAX) 1556 if (clevel == IF_MAX)
@@ -1494,17 +1565,12 @@ skip_line(const char *str1)
1494 } 1565 }
1495 1566
1496 if (!(cstate[clevel] & GOT_MATCH)) { 1567 if (!(cstate[clevel] & GOT_MATCH)) {
1497 char *t = expand_macros(next_token, FALSE); 1568 if (key == IFNDEF || key == IFNEQ)
1498 struct macro *mp = getmp(t);
1499 int match = mp != NULL && mp->m_val[0] != '\0';
1500
1501 if (key == IFNDEF)
1502 match = !match; 1569 match = !match;
1503 if (match) { 1570 if (match) {
1504 cstate[clevel] &= ~SKIP_LINE; 1571 cstate[clevel] &= ~SKIP_LINE;
1505 cstate[clevel] |= GOT_MATCH; 1572 cstate[clevel] |= GOT_MATCH;
1506 } 1573 }
1507 free(t);
1508 } 1574 }
1509 } else { 1575 } else {
1510 error("invalid condition"); 1576 error("invalid condition");
diff --git a/testsuite/make.tests b/testsuite/make.tests
index 5119a77d3..ba3855973 100755
--- a/testsuite/make.tests
+++ b/testsuite/make.tests
@@ -553,6 +553,20 @@ src.o: src.c src.h
553' 553'
554cd .. || exit 1; rm -rf make.tempdir 2>/dev/null 554cd .. || exit 1; rm -rf make.tempdir 2>/dev/null
555 555
556# ifeq/ifneq conditionals are supported
557testing 'make support ifeq and ifneq conditionals' \
558 "make -f -" "A OK\nB OK\n" "" '
559A = a
560B = b
561target:
562ifeq ($(A),a)
563 @echo A OK
564endif
565ifneq "a" "$B"
566 @echo B OK
567endif
568'
569
556# An empty original suffix indicates that every word should have 570# An empty original suffix indicates that every word should have
557# the new suffix added. If neither suffix is provided the words 571# the new suffix added. If neither suffix is provided the words
558# remain unchanged. 572# remain unchanged.