diff options
author | Andrew Burgess <aburgess@redhat.com> | 2024-08-20 17:42:46 +0100 |
---|---|---|
committer | Andrew Burgess <aburgess@redhat.com> | 2024-09-04 15:35:42 +0100 |
commit | 0121d70b233cd2c472a4447478f557ea9e6126c1 (patch) | |
tree | fa736481c2a9c7025ac709281cd253f21ae9f929 /libiberty | |
parent | a92e943014f5e8d6a2eaccaf8a725941ac47a121 (diff) | |
download | fsf-binutils-gdb-0121d70b233cd2c472a4447478f557ea9e6126c1.zip fsf-binutils-gdb-0121d70b233cd2c472a4447478f557ea9e6126c1.tar.gz fsf-binutils-gdb-0121d70b233cd2c472a4447478f557ea9e6126c1.tar.bz2 |
libiberty: sync with gcc
This syncs binutils-gdb/libiberty with gcc/libiberty up to GCC commit
64028d626a50410dbf29. This picks up the follow 3 GCC commits:
ea238096883 (gcc-delete-unused-func) libiberty/argv.c: remove only_whitespace
5e1d530da87 (gcc-buildargv) libiberty/buildargv: handle input consisting of only white space
a87954610f5 libiberty/buildargv: POSIX behaviour for backslash handling
Diffstat (limited to 'libiberty')
-rw-r--r-- | libiberty/ChangeLog | 21 | ||||
-rw-r--r-- | libiberty/argv.c | 113 | ||||
-rw-r--r-- | libiberty/testsuite/test-expandargv.c | 170 |
3 files changed, 221 insertions, 83 deletions
diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog index cdcd4b3..949fec6 100644 --- a/libiberty/ChangeLog +++ b/libiberty/ChangeLog @@ -1,3 +1,24 @@ +2024-08-05 Andrew Burgess <aburgess@redhat.com> + + * argv.c (only_whitespace): Delete. + +2024-07-16 Andrew Burgess <aburgess@redhat.com> + + * argv.c (buildargv): Treat input of only whitespace as an empty + argument list. + (expandargv): Remove work around for intput that is only + whitespace. + * testsuite/test-expandargv.c: Add new tests 10, 11, and 12. + Extend testing to call buildargv in more cases. + +2024-07-16 Andrew Burgess <aburgess@redhat.com> + + * argv.c (buildargv): Backslashes within single quotes are + literal, backslashes only escape POSIX defined special characters + within double quotes, and backslashed newlines should act as line + continuations. + * testsuite/test-expandargv.c: Add new tests 7, 8, and 9. + 2024-04-02 Tom Tromey <tom@tromey.com> * cplus-dem.c (cplus_demangle): Try the D demangler with diff --git a/libiberty/argv.c b/libiberty/argv.c index 45f1685..f889432 100644 --- a/libiberty/argv.c +++ b/libiberty/argv.c @@ -124,15 +124,6 @@ consume_whitespace (const char **input) } } -static int -only_whitespace (const char* input) -{ - while (*input != EOS && ISSPACE (*input)) - input++; - - return (*input == EOS); -} - /* @deftypefn Extension char** buildargv (char *@var{sp}) @@ -212,67 +203,74 @@ char **buildargv (const char *input) argv[argc] = NULL; } /* Begin scanning arg */ - arg = copybuf; - while (*input != EOS) + if (*input != EOS) { - if (ISSPACE (*input) && !squote && !dquote && !bsquote) - { - break; - } - else + arg = copybuf; + while (*input != EOS) { - if (bsquote) - { - bsquote = 0; - *arg++ = *input; - } - else if (*input == '\\') + if (ISSPACE (*input) && !squote && !dquote && !bsquote) { - bsquote = 1; - } - else if (squote) - { - if (*input == '\'') - { - squote = 0; - } - else - { - *arg++ = *input; - } + break; } - else if (dquote) + else { - if (*input == '"') + if (bsquote) { - dquote = 0; + bsquote = 0; + if (*input != '\n') + *arg++ = *input; } - else + else if (*input == '\\' + && !squote + && (!dquote + || strchr ("$`\"\\\n", *(input + 1)) != NULL)) { - *arg++ = *input; + bsquote = 1; } - } - else - { - if (*input == '\'') + else if (squote) { - squote = 1; + if (*input == '\'') + { + squote = 0; + } + else + { + *arg++ = *input; + } } - else if (*input == '"') + else if (dquote) { - dquote = 1; + if (*input == '"') + { + dquote = 0; + } + else + { + *arg++ = *input; + } } else { - *arg++ = *input; + if (*input == '\'') + { + squote = 1; + } + else if (*input == '"') + { + dquote = 1; + } + else + { + *arg++ = *input; + } } + input++; } - input++; } + *arg = EOS; + argv[argc] = xstrdup (copybuf); + argc++; } - *arg = EOS; - argv[argc] = xstrdup (copybuf); - argc++; argv[argc] = NULL; consume_whitespace (&input); @@ -435,17 +433,8 @@ expandargv (int *argcp, char ***argvp) } /* Add a NUL terminator. */ buffer[len] = '\0'; - /* If the file is empty or contains only whitespace, buildargv would - return a single empty argument. In this context we want no arguments, - instead. */ - if (only_whitespace (buffer)) - { - file_argv = (char **) xmalloc (sizeof (char *)); - file_argv[0] = NULL; - } - else - /* Parse the string. */ - file_argv = buildargv (buffer); + /* Parse the string. */ + file_argv = buildargv (buffer); /* If *ARGVP is not already dynamically allocated, copy it. */ if (*argvp == original_argv) *argvp = dupargv (*argvp); diff --git a/libiberty/testsuite/test-expandargv.c b/libiberty/testsuite/test-expandargv.c index 1e9cb0a..ca7031e 100644 --- a/libiberty/testsuite/test-expandargv.c +++ b/libiberty/testsuite/test-expandargv.c @@ -142,6 +142,64 @@ const char *test_data[] = { "b", 0, + /* Test 7 - No backslash removal within single quotes. */ + "'a\\$VAR' '\\\"'", /* Test 7 data */ + ARGV0, + "@test-expandargv-7.lst", + 0, + ARGV0, + "a\\$VAR", + "\\\"", + 0, + + /* Test 8 - Remove backslash / newline pairs. */ + "\"ab\\\ncd\" ef\\\ngh", /* Test 8 data */ + ARGV0, + "@test-expandargv-8.lst", + 0, + ARGV0, + "abcd", + "efgh", + 0, + + /* Test 9 - Backslash within double quotes. */ + "\"\\$VAR\" \"\\`\" \"\\\"\" \"\\\\\" \"\\n\" \"\\t\"", /* Test 9 data */ + ARGV0, + "@test-expandargv-9.lst", + 0, + ARGV0, + "$VAR", + "`", + "\"", + "\\", + "\\n", + "\\t", + 0, + + /* Test 10 - Mixed white space characters. */ + "\t \n \t ", /* Test 10 data */ + ARGV0, + "@test-expandargv-10.lst", + 0, + ARGV0, + 0, + + /* Test 11 - Single ' ' character. */ + " ", /* Test 11 data */ + ARGV0, + "@test-expandargv-11.lst", + 0, + ARGV0, + 0, + + /* Test 12 - Multiple ' ' characters. */ + " ", /* Test 12 data */ + ARGV0, + "@test-expandargv-12.lst", + 0, + ARGV0, + 0, + 0 /* Test done marker, don't remove. */ }; @@ -231,6 +289,78 @@ erase_test (int test) fatal_error (__LINE__, "Failed to erase test file.", errno); } +/* compare_argv: + TEST is the current test number, and NAME is a short string to identify + which libibery function is being tested. ARGC_A and ARGV_A describe an + argument array, and this is compared to ARGC_B and ARGV_B, return 0 if + the two arrays match, otherwise return 1. */ + +static int +compare_argv (int test, const char *name, int argc_a, char *argv_a[], + int argc_b, char *argv_b[]) +{ + int failed = 0, k; + + if (argc_a != argc_b) + { + printf ("FAIL: test-%s-%d. Argument count didn't match\n", name, test); + failed = 1; + } + /* Compare each of the argv's ... */ + else + for (k = 0; k < argc_a; k++) + if (strcmp (argv_a[k], argv_b[k]) != 0) + { + printf ("FAIL: test-%s-%d. Arguments don't match.\n", name, test); + failed = 1; + break; + } + + if (!failed) + printf ("PASS: test-%s-%d.\n", name, test); + + return failed; +} + +/* test_buildargv + Test the buildargv function from libiberty. TEST is the current test + number and TEST_INPUT is the string to pass to buildargv (after calling + run_replaces on it). ARGC_AFTER and ARGV_AFTER are the expected + results. Return 0 if the test passes, otherwise return 1. */ + +static int +test_buildargv (int test, const char * test_input, int argc_after, + char *argv_after[]) +{ + char * input, ** argv; + size_t len; + int argc, failed; + + /* Generate RW copy of data for replaces */ + len = strlen (test_input); + input = malloc (sizeof (char) * (len + 1)); + if (input == NULL) + fatal_error (__LINE__, "Failed to malloc buildargv input buffer.", errno); + + memcpy (input, test_input, sizeof (char) * (len + 1)); + /* Run all possible replaces */ + run_replaces (input); + + /* Split INPUT into separate arguments. */ + argv = buildargv (input); + + /* Count the arguments we got back. */ + argc = 0; + while (argv[argc]) + ++argc; + + failed = compare_argv (test, "buildargv", argc_after, argv_after, argc, argv); + + free (input); + freeargv (argv); + + return failed; +} /* run_tests: Run expandargv @@ -242,12 +372,16 @@ run_tests (const char **test_data) { int argc_after, argc_before; char ** argv_before, ** argv_after; - int i, j, k, fails, failed; + int i, j, k, fails; + const char * input_str; i = j = fails = 0; /* Loop over all the tests */ while (test_data[j]) { + /* Save original input in case we run a buildargv test. */ + input_str = test_data[j]; + /* Write test data */ writeout_test (i, test_data[j++]); /* Copy argv before */ @@ -271,29 +405,23 @@ run_tests (const char **test_data) for (k = 0; k < argc_after; k++) run_replaces (argv_after[k]); + /* If the test input is just a file to expand then we can also test + calling buildargv directly as the expected output is equivalent to + calling buildargv on the contents of the file. + + The results of calling buildargv will not include the ARGV0 constant, + which is why we pass 'argc_after - 1' and 'argv_after + 1', this skips + over the ARGV0 in the expected results. */ + if (argc_before == 2) + fails += test_buildargv (i, input_str, argc_after - 1, argv_after + 1); + else + printf ("SKIP: test-buildargv-%d. This test isn't for buildargv\n", i); + /* Run test: Expand arguments */ expandargv (&argc_before, &argv_before); - failed = 0; - /* Compare size first */ - if (argc_before != argc_after) - { - printf ("FAIL: test-expandargv-%d. Number of arguments don't match.\n", i); - failed++; - } - /* Compare each of the argv's ... */ - else - for (k = 0; k < argc_after; k++) - if (strcmp (argv_before[k], argv_after[k]) != 0) - { - printf ("FAIL: test-expandargv-%d. Arguments don't match.\n", i); - failed++; - } - - if (!failed) - printf ("PASS: test-expandargv-%d.\n", i); - else - fails++; + fails += compare_argv (i, "expandargv", argc_before, argv_before, + argc_after, argv_after); freeargv (argv_before); freeargv (argv_after); |