forked from ariadne/pkgconf
argvsplit: refactor splitting state machine
parent
a3fa9732b3
commit
ae42261c3f
|
@ -2,7 +2,7 @@
|
||||||
* argvsplit.c
|
* argvsplit.c
|
||||||
* argv_split() routine
|
* argv_split() routine
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012 pkgconf authors (see AUTHORS).
|
* Copyright (c) 2012, 2017 pkgconf authors (see AUTHORS).
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and/or distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -64,7 +64,7 @@ pkgconf_argv_split(const char *src, int *argc, char ***argv)
|
||||||
int argc_count = 0;
|
int argc_count = 0;
|
||||||
int argv_size = 5;
|
int argv_size = 5;
|
||||||
char quote = 0;
|
char quote = 0;
|
||||||
bool in_single_quotes = false;
|
bool escaped = false;
|
||||||
|
|
||||||
src_iter = src;
|
src_iter = src;
|
||||||
dst_iter = buf;
|
dst_iter = buf;
|
||||||
|
@ -76,23 +76,31 @@ pkgconf_argv_split(const char *src, int *argc, char ***argv)
|
||||||
|
|
||||||
while (*src_iter)
|
while (*src_iter)
|
||||||
{
|
{
|
||||||
if (quote == *src_iter)
|
if (escaped)
|
||||||
quote = 0;
|
|
||||||
else if (quote)
|
|
||||||
{
|
{
|
||||||
if (*src_iter == '\\')
|
/* POSIX: only \CHAR is special inside a double quote if CHAR is {$, `, ", \, newline}. */
|
||||||
|
if (quote == '\"')
|
||||||
{
|
{
|
||||||
src_iter++;
|
if (!(*src_iter == '$' || *src_iter == '`' || *src_iter == '"' || *src_iter == '\\'))
|
||||||
if (!*src_iter)
|
*dst_iter++ = '\\';
|
||||||
|
|
||||||
|
*dst_iter++ = *src_iter;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
free(*argv);
|
if (!isspace((unsigned int) *src_iter))
|
||||||
free(buf);
|
*dst_iter++ = *src_iter;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*src_iter != quote)
|
escaped = false;
|
||||||
*dst_iter++ = '\\';
|
|
||||||
}
|
}
|
||||||
|
else if (quote)
|
||||||
|
{
|
||||||
|
if (*src_iter == quote)
|
||||||
|
quote = 0;
|
||||||
|
else if (*src_iter == '\\')
|
||||||
|
escaped = true;
|
||||||
|
else
|
||||||
*dst_iter++ = *src_iter;
|
*dst_iter++ = *src_iter;
|
||||||
}
|
}
|
||||||
else if (isspace((unsigned int)*src_iter))
|
else if (isspace((unsigned int)*src_iter))
|
||||||
|
@ -112,32 +120,15 @@ pkgconf_argv_split(const char *src, int *argc, char ***argv)
|
||||||
}
|
}
|
||||||
else switch(*src_iter)
|
else switch(*src_iter)
|
||||||
{
|
{
|
||||||
case '\"':
|
|
||||||
if (in_single_quotes)
|
|
||||||
*dst_iter++ = *src_iter;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '\'':
|
|
||||||
in_single_quotes ^= true;
|
|
||||||
*dst_iter++ = *src_iter;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '\\':
|
case '\\':
|
||||||
src_iter++;
|
escaped = true;
|
||||||
|
|
||||||
if (!*src_iter)
|
|
||||||
{
|
|
||||||
free(argv);
|
|
||||||
free(buf);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*dst_iter++ = '\\';
|
|
||||||
*dst_iter++ = *src_iter;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case '\"':
|
||||||
|
case '\'':
|
||||||
|
quote = *src_iter;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
*dst_iter++ = *src_iter;
|
*dst_iter++ = *src_iter;
|
||||||
break;
|
break;
|
||||||
|
@ -146,7 +137,15 @@ pkgconf_argv_split(const char *src, int *argc, char ***argv)
|
||||||
src_iter++;
|
src_iter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strlen((*argv)[argc_count])) {
|
if (escaped || quote)
|
||||||
|
{
|
||||||
|
free(*argv);
|
||||||
|
free(buf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strlen((*argv)[argc_count]))
|
||||||
|
{
|
||||||
argc_count++;
|
argc_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue