Commit 407f4247 407f42472b53d5452c780e0a39b6975c4d841fec by Sam Roberts

argcv_get() now (optionally) strips comments while parsing. Its the right

place because it tokenizes, and whether a char is a comment or not depends
on whether its in the middle of a token or not:  "hi # there"  # comment.
1 parent de82eae6
......@@ -367,7 +367,7 @@ run_user_action (FILE *tty, const char *cr, message_t msg)
str = expand_line (stmt, msg);
if (!str)
continue;
if (argcv_get (str, "", &argc, &argv)
if (argcv_get (str, "", NULL, &argc, &argv)
|| argc == 0
|| argv[0][0] == '#')
{
......
......@@ -161,7 +161,7 @@ read_config (const char *config_file)
if (!*ptr || *ptr == '#')
continue;
argcv_get (ptr, "", &argc, &argv);
argcv_get (ptr, "", NULL, &argc, &argv);
if (argc < 2)
{
syslog (LOG_ERR, "%s:%d: too few fields", config_file, line);
......
......@@ -19,6 +19,8 @@
#include "argcv.h"
char srtime[] = __TIME__;
/*
* takes a string and splits it into several strings, breaking at ' '
* command is the string to split
......@@ -27,47 +29,71 @@
* returns 0 on success, nonzero on failure
*/
#define isws(c) ((c)==' '||(c)=='\t')
#define isws(c) ((c)==' '||(c)=='\t'||(c)=='\n')
#define isdelim(c,delim) ((c)=='"'||strchr(delim,(c))!=NULL)
static int
argcv_scan (int len, const char *command, const char *delim,
argcv_scan (int len, const char *command, const char *delim, const char* cmnt,
int *start, int *end, int *save)
{
int i = *save;
/* Skip initial whitespace */
while (i < len && isws (command[i]))
i++;
*start = i;
int i = 0;
switch (command[i])
for (;;)
{
case '"':
case '\'':
while (++i < len && command[i] != command[*start])
;
if (i < len) /* found matching quote */
break;
/*FALLTHRU*/
default:
if (isdelim (command [i], delim))
break;
/* Skip until next whitespace character or end of line */
while (++i < len &&
!(isws (command [i]) || isdelim (command [i], delim)))
;
i--;
i = *save;
if (i >= len)
return i;
/* Skip initial whitespace */
while (i < len && isws (command[i]))
i++;
*start = i;
switch (command[i])
{
case '"':
case '\'':
while (++i < len && command[i] != command[*start])
;
if (i < len) /* found matching quote */
break;
/*FALLTHRU*/ default:
if (isdelim (command[i], delim))
break;
/* Skip until next whitespace character or end of line */
while (++i < len &&
!(isws (command[i]) || isdelim (command[i], delim)))
;
i--;
break;
}
*end = i;
*save = i + 1;
/* If we have a token, and it starts with a comment character, skip
to the newline and restart the token search. */
if (*save < len)
{
if (cmnt && strchr (cmnt, command[*start]) != NULL)
{
i = *save;
while (i < len && command[i] != '\n')
i++;
*save = i;
continue;
}
}
break;
}
*end = i;
*save = i+1;
return *save;
}
int
argcv_get (const char *command, const char *delim, int *argc, char ***argv)
argcv_get (const char *command, const char *delim, const char* cmnt,
int *argc, char ***argv)
{
int len = strlen (command);
int i = 0;
......@@ -76,15 +102,10 @@ argcv_get (const char *command, const char *delim, int *argc, char ***argv)
*argc = 0;
*argv = NULL;
while (len > 0 && isspace (command[len-1]))
len--;
if (len < 1)
return 1;
/* Count number of arguments */
*argc = 1;
save = 0;
while (argcv_scan (len, command, delim, &start, &end, &save) < len)
while (argcv_scan (len, command, delim, cmnt, &start, &end, &save) < len)
(*argc)++;
*argv = calloc ((*argc + 1), sizeof (char *));
......@@ -94,8 +115,10 @@ argcv_get (const char *command, const char *delim, int *argc, char ***argv)
for (i = 0; i < *argc; i++)
{
int n;
argcv_scan (len, command, delim, &start, &end, &save);
argcv_scan (len, command, delim, cmnt, &start, &end, &save);
/* FIXME: this is the right place to do unescaping as well
as stripping of quotes. */
if (command[start] == '"' && command[end] == '"')
{
start++;
......@@ -182,7 +205,7 @@ main()
int i, argc;
char **argv;
argcv_get (command, "=", &argc, &argv);
argcv_get (command, "=", NULL, &argc, &argv);
printf ("%d args:\n", argc);
for (i = 0; i < argc; i++)
printf ("%s\n", argv[i]);
......
......@@ -36,6 +36,7 @@ extern "C" {
#endif /*__P */
extern int argcv_get __P ((const char *command, const char *delim,
const char* cmnt,
int *argc, char ***argv));
extern int argcv_string __P ((int argc, char **argv, char **string));
extern int argcv_free __P ((int argc, char **argv));
......
......@@ -387,7 +387,7 @@ mu_create_argcv (int argc, char **argv, int *p_argc, char ***p_argv)
int n_argc = 0;
char **n_argv;
if (argcv_get (p, "", &n_argc, &n_argv))
if (argcv_get (p, "", NULL, &n_argc, &n_argv))
{
argcv_free (n_argc, n_argv);
if (linebuf)
......
......@@ -210,7 +210,7 @@ mail_send0 (struct send_environ *env, int save_to)
ofile = env->file;
if (argcv_get (buf+1, "", &argc, &argv) == 0)
if (argcv_get (buf+1, "", NULL, &argc, &argv) == 0)
{
struct mail_command_entry entry;
entry = util_find_entry (mail_escape_table, argv[0]);
......
......@@ -100,7 +100,7 @@ util_do_command (const char *c, ...)
if (cmd[0] == '#')
return 0;
if (argcv_get (cmd, delim, &argc, &argv) != 0)
if (argcv_get (cmd, delim, NULL, &argc, &argv) != 0)
return argcv_free (argc, argv);
entry = util_find_entry (mail_command_table, argv[0]);
......
......@@ -103,7 +103,7 @@ mh_argp_parse (int argc, char **argv,
char **xargv;
int i;
argcv_get (p, "", &xargc, &xargv);
argcv_get (p, "", NULL, &xargc, &xargv);
_argc = argc + xargc;
_argv = calloc (_argc+1, sizeof *_argv);
......
......@@ -308,7 +308,7 @@ action_create (struct action_data *ap)
buf[--len] = 0;
line++;
if (argcv_get (buf, ":", &argc, &argv))
if (argcv_get (buf, ":", NULL, &argc, &argv))
{
argcv_free (argc, argv);
continue;
......