/* SPDX-License-Identifier: BSD-3-Clause */
/*
- * Authors: Simon Kuenzer <simon.kuenzer@neclab.eu>
+ * Authors: Simon Kuenzer <simon@unikraft.io>
*
*
* Copyright (c) 2017, NEC Europe Ltd., NEC Corporation. All rights reserved.
+ * Copyright (c) 2023, Unikraft GmbH. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
{
int argc = 0;
int prev_wspace = 1;
+ int prev_escape = 0;
char in_quote = '\0';
__sz i;
case '\n':
case '\t':
case '\v':
- if (!in_quote) {
+ if (!in_quote && !prev_escape) {
argb[i] = '\0';
prev_wspace = 1;
break;
/* quotes */
case '\'':
case '"':
+ if (prev_escape) {
+ if (!in_quote) {
+ /* escaping removes special meaning */
+ goto regularchar;
+ } else if (argb[i] == '"') {
+ /* \" -> " */
+ left_shift(argb, i - 1, maxlen + 1);
+ --i;
+ prev_escape = 0;
+ goto regularchar;
+ }
+ }
if (!in_quote) {
in_quote = argb[i];
left_shift(argb, i, maxlen);
if (prev_wspace) {
argv[argc++] = &argb[i];
prev_wspace = 0;
+ prev_escape = 0;
+ }
+
+ /* escape character handling */
+ if (argb[i] == '\\' && in_quote != '\'') {
+ if (prev_escape) {
+ /* double escape: \\ -> \ */
+ left_shift(argb, i, maxlen);
+ --i;
+ prev_escape = 0;
+ } else {
+ prev_escape = 1;
+ }
+ } else if (prev_escape) {
+ /* any character after escape symbol */
+ if (!in_quote) {
+ /* remove escape symbol */
+ left_shift(argb, i - 1, maxlen + 1);
+ --i;
+ }
+ prev_escape = 0;
}
break;
}
UK_TEST_EXPECT_SNUM_EQ(strcmp(arg_ex[i], arg_out[i]), 0);
}
+UK_TESTCASE(ukargparse, parse_quotes_escaped)
+{
+ int argc, i;
+ char *arg_vec[0x10] = { NULL };
+ char arg_str[] =
+ "\\'"
+ " \\\""
+ " \"arg0\\\"\""
+ " \"\\\"arg1 '-'\\\"\"-\" \\\\ arg2\\\"\""
+ " '\" \\\\ \\\" \\''\"'"
+ " \\a\\b\\\"\\c\\\""
+ " \"\\a\\b\\\"\\c\\\"\""
+ " '\\a\\b\\\"\\c\\\"'"
+ " '\\'a\\'"
+ " a\\ b"
+ " \\";
+ static const char * const arg_exp[] = {
+ "'",
+ "\"",
+ "arg0\"",
+ "\"arg1 '-'\"- \\ arg2\"",
+ "\" \\\\ \\\" \\\"",
+ "ab\"c\"",
+ "\\a\\b\"\\c\"",
+ "\\a\\b\\\"\\c\\\"",
+ "\\a'",
+ "a b",
+ "\\"
+ };
+
+ argc = uk_argparse(arg_str, arg_vec, ARRAY_SIZE(arg_vec) - 1);
+ UK_TEST_EXPECT_SNUM_EQ(argc, ARRAY_SIZE(arg_exp));
+ if (argc != ARRAY_SIZE(arg_exp))
+ return;
+
+ for (i = 0; i < (int) ARRAY_SIZE(arg_exp); ++i)
+ UK_TEST_EXPECT_SNUM_EQ(strcmp(arg_exp[i], arg_vec[i]), 0);
+}
+
uk_testsuite_register(ukargparse, NULL);