aboutsummaryrefslogtreecommitdiff
path: root/tests/wsp.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/wsp.c')
-rw-r--r--tests/wsp.c756
1 files changed, 0 insertions, 756 deletions
diff --git a/tests/wsp.c b/tests/wsp.c
deleted file mode 100644
index 958d01f..0000000
--- a/tests/wsp.c
+++ /dev/null
@@ -1,756 +0,0 @@
-/* grecs - Gray's Extensible Configuration System
- Copyright (C) 2014-2019 Sergey Poznyakoff
-
- Grecs is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 3 of the License, or (at your
- option) any later version.
-
- Grecs is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along
- with Grecs. If not, see <http://www.gnu.org/licenses/>. */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-#include <errno.h>
-#include "grecs.h"
-#include "wordsplit.h"
-
-extern char **environ;
-
-char *progname;
-
-/* Global options */
-enum
- {
- TRIMNL_OPTION = 0x01, /* Remove trailing newline */
- PLAINTEXT_OPTION = 0x02 /* Print intput verbatim (no escapes) */
- };
-
-/* Environment types */
-enum env_type
- {
- env_none, /* No environment */
- env_null, /* Null environment */
- env_sys /* Use system environment */
- };
-
-struct wsclosure
-{
- int options; /* Global options */
- struct wordsplit ws; /* The wordsplit structure */
- int wsflags; /* Wordsplit flags */
- enum env_type env_type; /* Environment type */
- int offarg; /* Index of the first of the initial words in
- the argv array. The ws.ws_dooffs field gives
- the number of such variables. Forces the
- WRDSF_DOOFFS flag. */
- char **fenvbase; /* Environment for testing the ws_getenv function */
- int fenvidx; /* Number of variables in fenvbase */
- int fenvmax; /* Size of fenbase (entries) */
- int append_start; /* First argument to append (index in argv) */
- int append_count; /* Number of arguments to append */
-};
-
-/* Command line option types */
-enum
- {
- ws_no_argument, /* Option requires no arguments */
- ws_boolean, /* Option is boolean (can be prefixed with -no) */
- ws_required_argument, /* Option requires one argument */
- ws_multiple_arguments /* Option takes multiple arguments, terminated with
- "--" or end of argument list */
- };
-
-/* Structure describing a single command-line option */
-struct wsopt
-{
- const char *name; /* Option name */
- int tok; /* Corresponding flag */
- int arg; /* Option type (see the enum above) */
- void (*setfn) (int tok, int neg, char *arg, struct wsclosure *wsc);
- /* Setter function */
-};
-
-/* Index of the next argument in the argv */
-static int wsoptind = -1;
-
-/* Parse next argument from the command line. Return EOF on end of arguments
- or when the "--" argument is seen. */
-static int
-getwsopt (int argc, char **argv, struct wsopt *wso, struct wsclosure *wsc)
-{
- int negate = 0;
- char *opt;
-
- if (wsoptind == -1)
- wsoptind = 1;
- if (wsoptind == argc)
- return EOF;
-
- opt = argv[wsoptind++];
- if (strcmp (opt, "--") == 0)
- return EOF;
- if (*opt != '-')
- {
- if (strchr (opt, '='))
- {
- assert (wsc->fenvidx < wsc->fenvmax - 1);
- wsc->fenvbase[wsc->fenvidx++] = opt;
- return 0;
- }
- wsoptind--;
- return EOF;
- }
- opt++; /* skip past initial dash */
- if (strncmp (opt, "no-", 3) == 0)
- {
- negate = 1;
- opt += 3;
- }
- else if (strncmp (opt, "no", 2) == 0)
- {
- negate = 1;
- opt += 2;
- }
-
- for (; wso->name; wso++)
- {
- if (wso->arg == ws_boolean && wso->name[0] == 'n' && wso->name[1] == 'o'
- && strcmp (wso->name + 2, opt) == 0)
- {
- negate ^= 1;
- break;
- }
- if (strcmp (wso->name, opt) == 0)
- break;
- }
-
- if (wso->name)
- {
- char *arg;
- if (wso->arg == ws_multiple_arguments)
- {
- while (1)
- {
- if (wsoptind == argc)
- break;
- arg = argv[wsoptind++];
- if (strcmp (arg, "--") == 0)
- break;
- wso->setfn (wso->tok, negate, arg, wsc);
- }
- }
- else
- {
- if (wso->arg == ws_required_argument)
- {
- if (wsoptind == argc)
- {
- fprintf (stderr, "%s: missing arguments for -%s\n",
- progname, opt);
- exit (1);
- }
- arg = argv[wsoptind++];
- }
- wso->setfn (wso->tok, negate, arg, wsc);
- }
- return 0;
- }
-
- fprintf (stderr, "%s: unrecognized option: -%s\n",
- progname, opt);
- fprintf (stderr, "%s: try %s -help for more detail\n",
- progname, progname);
- exit (1);
-}
-
-/* Setter functions for various options */
-
-static void
-setfn_flag (int flag, int neg, char *arg, struct wsclosure *wsc)
-{
- if (neg)
- wsc->wsflags &= ~flag;
- else
- wsc->wsflags |= flag;
-}
-
-static void
-setfn_option (int flag, int neg, char *arg, struct wsclosure *wsc)
-{
- wsc->wsflags |= WRDSF_OPTIONS;
- if (neg)
- wsc->ws.ws_options &= ~flag;
- else
- wsc->ws.ws_options |= flag;
-}
-
-static void
-setfn_delim (int flag, int neg, char *arg, struct wsclosure *wsc)
-{
- wsc->wsflags |= flag;
- wsc->ws.ws_delim = arg;
-}
-
-static void
-setfn_comment (int flag, int neg, char *arg, struct wsclosure *wsc)
-{
- wsc->wsflags |= flag;
- wsc->ws.ws_comment = arg;
-}
-
-static void
-set_escape_string (wordsplit_t *ws, int *wsflags, int q, const char *str)
-{
- if (*str == ':')
- {
- while (*++str != ':')
- {
- int f;
- switch (*str)
- {
- case '+':
- f = WRDSO_BSKEEP;
- break;
-
- case '0':
- f = WRDSO_OESC;
- break;
-
- case 'x':
- f = WRDSO_XESC;
- break;
-
- default:
- fprintf (stderr, "%s: invalid escape flag near %s\n",
- progname, str);
- abort ();
- }
- WRDSO_ESC_SET (ws, q, f);
- }
- *wsflags |= WRDSF_OPTIONS;
- ++str;
- }
- ws->ws_escape[q] = str;
-}
-
-static void
-setfn_escape (int flag, int neg, char *arg, struct wsclosure *wsc)
-{
- wsc->wsflags |= flag;
- set_escape_string (&wsc->ws, &wsc->wsflags, 0, arg);
- set_escape_string (&wsc->ws, &wsc->wsflags, 1, arg);
-}
-
-static void
-setfn_escape_qw (char *arg, int quote, struct wsclosure *wsc)
-{
- if (!(wsc->wsflags & WRDSF_ESCAPE))
- {
- wsc->wsflags |= WRDSF_ESCAPE;
- wsc->ws.ws_escape[!quote] = NULL;
- }
- set_escape_string (&wsc->ws, &wsc->wsflags, quote, arg);
-}
-
-static void
-setfn_escape_word (int flag, int neg, char *arg, struct wsclosure *wsc)
-{
- setfn_escape_qw (arg, 0, wsc);
-}
-
-static void
-setfn_escape_quote (int flag, int neg, char *arg, struct wsclosure *wsc)
-{
- setfn_escape_qw (arg, 1, wsc);
-}
-
-static void
-setfn_maxwords (int flag, int neg, char *arg, struct wsclosure *wsc)
-{
- char *p;
-
- wsc->wsflags |= WRDSF_OPTIONS;
- wsc->ws.ws_options |= WRDSO_MAXWORDS;
-
- wsc->ws.ws_maxwords = strtoul (arg, &p, 10);
- if (*p)
- {
- fprintf (stderr, "%s: invalid number: %s\n", progname, arg);
- exit (1);
- }
-}
-
-static void
-setfn_global (int flag, int neg, char *arg, struct wsclosure *wsc)
-{
- if (neg)
- wsc->options &= ~flag;
- else
- wsc->options |= flag;
-}
-
-static void
-setfn_env (int flag, int neg, char *arg, struct wsclosure *wsc)
-{
- if (strcmp (arg, "none") == 0)
- wsc->env_type = env_none;
- else if (strcmp (arg, "null") == 0)
- wsc->env_type = env_null;
- else if (strcmp (arg, "sys") == 0)
- wsc->env_type = env_sys;
- else
- {
- fprintf (stderr, "%s: environment flag: %s\n", progname, arg);
- exit (1);
- }
-}
-
-static void
-setfn_dooffs (int flag, int neg, char *arg, struct wsclosure *wsc)
-{
- if (!(wsc->wsflags & flag))
- {
- wsc->wsflags |= flag;
- wsc->offarg = wsoptind - 1;
- wsc->ws.ws_offs = 0;
- }
- wsc->ws.ws_offs++;
-}
-
-static void
-setfn_append (int flag, int neg, char *arg, struct wsclosure *wsc)
-{
- if (wsc->append_count == 0)
- wsc->append_start = wsoptind - 1;
- wsc->append_count++;
-}
-
-static void help (void);
-
-static void
-setfn_help (int flag, int neg, char *arg, struct wsclosure *wsc)
-{
- help ();
- exit (0);
-}
-
-/* Available options: */
-struct wsopt opttab[] = {
- /* Global options */
- { "trimnl", TRIMNL_OPTION, ws_boolean, setfn_global },
- { "plaintext", PLAINTEXT_OPTION, ws_boolean, setfn_global },
- { "env", 0, ws_required_argument, setfn_env },
-
- /* Wordsplit flags */
- { "append", WRDSF_APPEND, ws_boolean, setfn_flag },
- /*{ "reuse", WRDSF_REUSE, ws_boolean, setfn_flag },*/
- { "undef", WRDSF_UNDEF, ws_boolean, setfn_flag },
- { "novar", WRDSF_NOVAR, ws_boolean, setfn_flag },
- { "nocmd", WRDSF_NOCMD, ws_boolean, setfn_flag },
- { "ws", WRDSF_WS, ws_boolean, setfn_flag },
- { "quote", WRDSF_QUOTE, ws_boolean, setfn_flag },
- { "squote", WRDSF_SQUOTE, ws_boolean, setfn_flag },
- { "dquote", WRDSF_DQUOTE, ws_boolean, setfn_flag },
- { "squeeze_delims", WRDSF_SQUEEZE_DELIMS, ws_boolean, setfn_flag },
- { "return_delims", WRDSF_RETURN_DELIMS, ws_boolean, setfn_flag },
- { "sed", WRDSF_SED_EXPR, ws_boolean, setfn_flag },
- { "debug", WRDSF_SHOWDBG, ws_boolean, setfn_flag },
- { "nosplit", WRDSF_NOSPLIT, ws_boolean, setfn_flag },
- { "keepundef", WRDSF_KEEPUNDEF, ws_boolean, setfn_flag },
- { "warnundef", WRDSF_WARNUNDEF, ws_boolean, setfn_flag },
- { "cescapes", WRDSF_CESCAPES, ws_boolean, setfn_flag },
- { "default", WRDSF_DEFFLAGS, ws_boolean, setfn_flag },
- { "env_kv", WRDSF_ENV_KV, ws_boolean, setfn_flag },
- { "incremental", WRDSF_INCREMENTAL, ws_boolean, setfn_flag },
- { "pathexpand", WRDSF_PATHEXPAND, ws_boolean, setfn_flag },
- { "default", WRDSF_DEFFLAGS, ws_boolean, setfn_flag },
- /* Wordsplit options */
- { "nullglob", WRDSO_NULLGLOB, ws_boolean, setfn_option },
- { "failglob", WRDSO_FAILGLOB, ws_boolean, setfn_option },
- { "dotglob", WRDSO_DOTGLOB, ws_boolean, setfn_option },
- { "bskeep_words", WRDSO_BSKEEP_WORD, ws_boolean, setfn_option },
- { "bskeep_quote", WRDSO_BSKEEP_QUOTE, ws_boolean, setfn_option },
- { "bskeep", WRDSO_BSKEEP_WORD|WRDSO_BSKEEP_QUOTE,
- ws_boolean, setfn_option },
- { "novarsplit", WRDSO_NOVARSPLIT, ws_boolean, setfn_option },
- { "nocmdsplit", WRDSO_NOCMDSPLIT, ws_boolean, setfn_option },
- { "maxwords", WRDSO_MAXWORDS, ws_required_argument, setfn_maxwords },
- /* String options */
- { "delim", WRDSF_DELIM, ws_required_argument, setfn_delim },
- { "comment", WRDSF_COMMENT,ws_required_argument, setfn_comment },
- { "escape", WRDSF_ESCAPE, ws_required_argument, setfn_escape },
- { "escape-word", WRDSF_ESCAPE, ws_required_argument, setfn_escape_word },
- { "escape-quote", WRDSF_ESCAPE, ws_required_argument, setfn_escape_quote },
-
- { "dooffs", WRDSF_DOOFFS, ws_multiple_arguments, setfn_dooffs },
- { "append-args", 0, ws_multiple_arguments, setfn_append },
-
- { "help", 0, ws_no_argument, setfn_help },
-
- { NULL, 0 }
-};
-
-static void
-help (void)
-{
- size_t i;
-
- printf ("usage: %s [options] [VAR=VALUE...] [-- EXTRA...]\n", progname);
- printf ("options are:\n");
- for (i = 0; opttab[i].name; i++)
- {
- printf (" -");
- if (opttab[i].arg == ws_boolean)
- printf ("[no]");
- if (strncmp (opttab[i].name, "no", 2) == 0)
- printf ("%s", opttab[i].name + 2);
- else
- printf ("%s", opttab[i].name);
- switch (opttab[i].arg)
- {
- case ws_no_argument:
- case ws_boolean:
- break;
- case ws_required_argument:
- printf(" ARG");
- break;
- case ws_multiple_arguments:
- printf(" ARGS... --");
- }
- putchar ('\n');
- }
- putchar ('\n');
-}
-
-void
-print_qword (const char *word, int plaintext)
-{
- static char *qbuf = NULL;
- static size_t qlen = 0;
- int quote;
- size_t size = wordsplit_c_quoted_length (word, 0, &quote);
-
- if (plaintext)
- {
- printf ("%s", word);
- return;
- }
-
- if (*word == 0)
- quote = 1;
-
- if (size >= qlen)
- {
- qlen = size + 1;
- qbuf = realloc (qbuf, qlen);
- assert (qbuf != NULL);
- }
- wordsplit_c_quote_copy (qbuf, word, 0);
- qbuf[size] = 0;
- if (quote)
- printf ("\"%s\"", qbuf);
- else
- printf ("%s", qbuf);
-}
-
-/* Convert environment to K/V form */
-static char **
-make_env_kv ()
-{
- size_t i, j, size;
- char **newenv;
-
- /* Count the number of entries */
- for (i = 0; environ[i]; i++)
- ;
-
- size = i * 2 + 1;
- newenv = calloc (size, sizeof (newenv[0]));
- assert (newenv != NULL);
-
- for (i = j = 0; environ[i]; i++)
- {
- size_t len = strcspn (environ[i], "=");
- char *p = malloc (len+1);
- assert (p != NULL);
- memcpy (p, environ[i], len);
- p[len] = 0;
- newenv[j++] = p;
- p = strdup (environ[i] + len + 1);
- assert (p != NULL);
- newenv[j++] = p;
- }
- newenv[j] = NULL;
- return newenv;
-}
-
-static int
-wsp_getvar (char **ret, const char *vptr, size_t vlen, void *data)
-{
- char **base = data;
- int i;
-
- for (i = 0; base[i]; i++)
- {
- size_t l = strcspn (base[i], "=");
- if (l == vlen && memcmp (base[i], vptr, vlen) == 0)
- {
- char *p = strdup (base[i] + vlen + 1);
- if (p == NULL)
- return WRDSE_NOSPACE;
- *ret = p;
- return WRDSE_OK;
- }
- }
- return WRDSE_UNDEF;
-}
-
-static int
-cmd_quote (char **ret, const char *str, size_t len, char **argv)
-{
- int alen;
- for (alen = 0; alen < len && !(str[alen] == ' ' || str[alen] == '\t'); alen++)
- ;
- for (; alen < len && (str[alen] == ' ' || str[alen] == '\t'); alen++)
- ;
- len -= alen;
- *ret = malloc (len + 1);
- if (!*ret)
- return WRDSE_NOSPACE;
- memcpy (*ret, str + alen, len);
- (*ret)[len] = 0;
- return WRDSE_OK;
-}
-
-static int
-cmd_words (char **ret, const char *str, size_t len, char **argv)
-{
- char *p;
- int i;
-
- p = malloc (len + 1);
- if (!p)
- return WRDSE_NOSPACE;
- *ret = p;
- for (i = 1; argv[i]; i++)
- {
- size_t s = strlen (argv[i]);
- if (i > 1)
- *p++ = ' ';
- memcpy (p, argv[i], s);
- p += s;
- }
- *p = 0;
- return WRDSE_OK;
-}
-
-static int
-cmd_lines (char **ret, const char *str, size_t len, char **argv)
-{
- char *p;
- int i;
-
- p = malloc (len + 1);
- if (!p)
- return WRDSE_NOSPACE;
- *ret = p;
- for (i = 1; argv[i]; i++)
- {
- size_t s = strlen (argv[i]);
- if (i > 1)
- *p++ = '\n';
- memcpy (p, argv[i], s);
- p += s;
- }
- *p = 0;
- return WRDSE_OK;
-}
-
-static struct command
-{
- char const *name;
- int (*cmd)(char **ret, const char *str, size_t len, char **argv);
-} comtab[] = {
- { "quote", cmd_quote },
- { "words", cmd_words },
- { "lines", cmd_lines }
-};
-
-static int
-wsp_runcmd (char **ret, const char *str, size_t len, char **argv, void *closure)
-{
- int i;
- size_t s = 0;
-
- for (i = 0; ; i++)
- {
- if (i == sizeof (comtab) / sizeof (comtab[0]))
- break;
- if (strcmp (comtab[i].name, argv[0]) == 0)
- return comtab[i].cmd (ret, str, len, argv);
- }
-
- *ret = NULL;
- if (grecs_asprintf (ret, &s, "unknown command: %s", argv[0]))
- return WRDSE_NOSPACE;
- else
- return WRDSE_USERERR;
-}
-
-int
-main (int argc, char **argv)
-{
- struct wsclosure wsc;
- char *fenvbase[128];
- char buf[1024], *ptr, *saved_ptr;
- int next_call = 0;
-
- wsc.options = 0;
- wsc.wsflags = 0;
- wsc.env_type = env_sys;
- wsc.offarg = 0;
- wsc.fenvbase = fenvbase;
- wsc.fenvmax = sizeof (fenvbase) / sizeof (fenvbase[0]);
- wsc.fenvidx = 0;
- wsc.ws.ws_options = 0;
- wsc.wsflags = (WRDSF_DEFFLAGS & ~WRDSF_NOVAR) |
- WRDSF_ENOMEMABRT |
- WRDSF_SHOWERR;
- wsc.append_count = 0;
-
- progname = argv[0];
- while (getwsopt (argc, argv, opttab, &wsc) != EOF)
- ;
-
- if (wsc.fenvidx > 0)
- {
- wsc.fenvbase[wsc.fenvidx] = NULL;
- wsc.wsflags |= WRDSF_GETVAR | WRDSF_CLOSURE;
- wsc.ws.ws_getvar = wsp_getvar;
- wsc.ws.ws_closure = fenvbase;
- }
-
- if (wsoptind < argc)
- {
- wsc.ws.ws_paramc = argc - wsoptind;
- wsc.ws.ws_paramv = (char const **) (argv + wsoptind);
- wsc.ws.ws_options |= WRDSO_PARAMV|WRDSO_PARAM_NEGIDX;
- wsc.wsflags |= WRDSF_OPTIONS;
- }
-
- switch (wsc.env_type)
- {
- case env_null:
- wsc.wsflags |= WRDSF_ENV;
- wsc.ws.ws_env = NULL;
- break;
-
- case env_none:
- break;
-
- case env_sys:
- wsc.wsflags |= WRDSF_ENV;
- if (wsc.wsflags & WRDSF_ENV_KV)
- wsc.ws.ws_env = (const char **) make_env_kv ();
- else
- wsc.ws.ws_env = (const char **) environ;
- break;
- }
-
- if (!(wsc.wsflags & WRDSF_NOCMD))
- wsc.ws.ws_command = wsp_runcmd;
-
- if (wsc.wsflags & WRDSF_INCREMENTAL)
- wsc.options |= TRIMNL_OPTION;
-
- next_call = 0;
- while ((ptr = fgets (buf, sizeof (buf), stdin)))
- {
- int rc;
- size_t i;
-
- if (wsc.options & TRIMNL_OPTION)
- {
- size_t len = strlen (ptr);
- if (len && ptr[len-1] == '\n')
- ptr[len-1] = 0;
- }
-
- if (wsc.wsflags & WRDSF_INCREMENTAL)
- {
- if (next_call)
- {
- if (*ptr == 0)
- ptr = NULL;
- else
- free (saved_ptr);
- }
- else
- next_call = 1;
- if (ptr)
- {
- ptr = saved_ptr = strdup (ptr);
- assert (ptr != NULL);
- }
- }
-
- rc = wordsplit (ptr, &wsc.ws, wsc.wsflags);
- if (rc)
- {
- if (!(wsc.wsflags & WRDSF_SHOWERR))
- wordsplit_perror (&wsc.ws);
- continue;
- }
-
- if (wsc.offarg)
- {
- size_t i;
- for (i = 0; i < wsc.ws.ws_offs; i++)
- wsc.ws.ws_wordv[i] = argv[wsc.offarg + i];
- wsc.offarg = 0;
- }
-
- if (wsc.append_count)
- {
- rc = wordsplit_append (&wsc.ws, wsc.append_count,
- argv + wsc.append_start);
- if (rc)
- {
- if (!(wsc.wsflags & WRDSF_SHOWERR))
- wordsplit_perror (&wsc.ws);
- continue;
- }
- }
-
- wsc.wsflags |= WRDSF_REUSE;
- printf ("NF: %lu", (unsigned long) wsc.ws.ws_wordc);
- if (wsc.wsflags & WRDSF_DOOFFS)
- printf (" (%lu)", (unsigned long) wsc.ws.ws_offs);
- putchar ('\n');
- for (i = 0; i < wsc.ws.ws_offs; i++)
- {
- printf ("(%lu): ", (unsigned long) i);
- print_qword (wsc.ws.ws_wordv[i], wsc.options & PLAINTEXT_OPTION);
- putchar ('\n');
- }
- for (; i < wsc.ws.ws_offs + wsc.ws.ws_wordc; i++)
- {
- printf ("%lu: ", (unsigned long) i);
- print_qword (wsc.ws.ws_wordv[i], wsc.options & PLAINTEXT_OPTION);
- putchar ('\n');
- }
- printf ("TOTAL: %lu\n", (unsigned long) wsc.ws.ws_wordi);
- }
- return 0;
-}

Return to:

Send suggestions and report system problems to the System administrator.