#include <libpkgconf/stdinc.h>
#include <libpkgconf/libpkgconf.h>
void
pkgconf_argv_free(char **argv)
{
free(argv[0]);
free(argv);
}
int
pkgconf_argv_split(const char *src, int *argc, char ***argv)
{
char *buf = malloc(strlen(src) + 1);
const char *src_iter;
char *dst_iter;
int argc_count = 0;
int argv_size = 5;
char quote = 0;
bool escaped = false;
src_iter = src;
dst_iter = buf;
memset(buf, 0, strlen(src) + 1);
*argv = calloc(argv_size, sizeof (void *));
(*argv)[argc_count] = dst_iter;
while (*src_iter)
{
if (escaped)
{
if (quote == '"')
{
if (!(*src_iter == '$' || *src_iter == '`' || *src_iter == '"' || *src_iter == '\\'))
*dst_iter++ = '\\';
*dst_iter++ = *src_iter;
}
else
{
*dst_iter++ = *src_iter;
}
escaped = false;
}
else if (quote)
{
if (*src_iter == quote)
quote = 0;
else if (*src_iter == '\\' && quote != '\'')
escaped = true;
else
*dst_iter++ = *src_iter;
}
else if (isspace((unsigned char)*src_iter))
{
if ((*argv)[argc_count] != NULL)
{
argc_count++, dst_iter++;
if (argc_count == argv_size)
{
argv_size += 5;
*argv = realloc(*argv, sizeof(void *) * argv_size);
}
(*argv)[argc_count] = dst_iter;
}
}
else switch(*src_iter)
{
case '\\':
escaped = true;
break;
case '\"':
case '\'':
quote = *src_iter;
break;
default:
*dst_iter++ = *src_iter;
break;
}
src_iter++;
}
if (escaped || quote)
{
free(*argv);
free(buf);
return -1;
}
if (strlen((*argv)[argc_count]))
{
argc_count++;
}
*argc = argc_count;
return 0;
}