summaryrefslogtreecommitdiffabout
authorSergey Poznyakoff <gray@gnu.org>2019-07-11 08:29:34 (GMT)
committer Sergey Poznyakoff <gray@gnu.org>2019-07-11 08:29:34 (GMT)
commit2ad00905cde7230317c27fcbb3c41969ca5b79ab (patch) (side-by-side diff)
tree5a159e95e5d9a649b189fc634832320010ec4657
parent4ba3d95fe9bd9bb3b93be60a8ea89e381c5f88c0 (diff)
downloadmailutils-2ad00905cde7230317c27fcbb3c41969ca5b79ab.tar.gz
mailutils-2ad00905cde7230317c27fcbb3c41969ca5b79ab.tar.bz2
Pull wordsplit from submodule.
* .gitmodules: Add wordsplit. * configure.ac: Version 3.7.90 * NEWS: Raise version number. * include/mailutils/sys/Makefile.am: Include wordsplit.h from the submodule. * include/mailutils/sys/wordsplit.h: New file. * include/mailutils/wordsplit.h: Rewrite as a wrapper over mailutils/sys/wordsplit.h * libmailutils/Makefile.am: Distribute files from wordsplit. * libmailutils/string/Makefile.am: Add libmailutils/wordsplit to the include path. * libmailutils/string/wordsplit.c: Replace with a wrapper over wordsplit/wordsplit.c * libmailutils/tests/.gitignore: Update. * libmailutils/tests/Makefile.am: Pull wordsplit testsuite from the submodule. * libmailutils/tests/wordsplit.at: Remove. * libmailutils/tests/wsp.c: Remove.
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--.gitmodules3
-rw-r--r--NEWS2
-rw-r--r--configure.ac4
-rw-r--r--include/mailutils/sys/Makefile.am3
l---------include/mailutils/sys/wordsplit.h1
-rw-r--r--include/mailutils/wordsplit.h358
-rw-r--r--libmailutils/Makefile.am6
-rw-r--r--libmailutils/string/Makefile.am6
-rw-r--r--libmailutils/string/wordsplit.c2382
-rw-r--r--libmailutils/tests/.gitignore1
-rw-r--r--libmailutils/tests/Makefile.am35
-rw-r--r--libmailutils/tests/wordsplit.at787
-rw-r--r--libmailutils/tests/wsp.c654
m---------libmailutils/wordsplit0
14 files changed, 164 insertions, 4078 deletions
diff --git a/.gitmodules b/.gitmodules
index bdc2cb0..142e50c 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -7,3 +7,6 @@
[submodule "gnulib"]
path = gnulib
url = git://git.sv.gnu.org/gnulib.git
+[submodule "libmailutils/wordsplit"]
+ path = libmailutils/wordsplit
+ url = git://git.gnu.org.ua/wordsplit.git
diff --git a/NEWS b/NEWS
index 6928a7d..6b16f17 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,8 @@ See the end of file for copying conditions.
Please send mailutils bug reports to <bug-mailutils@gnu.org>.
+Version 3.7.90 (git)
+
Version 3.7 - 2019-06-21
* Support for the new mailbox format - dotmail
diff --git a/configure.ac b/configure.ac
index eb14361..c841acf 100644
--- a/configure.ac
+++ b/configure.ac
@@ -16,7 +16,7 @@ dnl You should have received a copy of the GNU General Public License along
dnl with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
AC_PREREQ(2.63)
-AC_INIT([GNU Mailutils], [3.7], [bug-mailutils@gnu.org], [mailutils],
+AC_INIT([GNU Mailutils], [3.7.90], [bug-mailutils@gnu.org], [mailutils],
[http://mailutils.org])
AC_CONFIG_SRCDIR([libmailutils/mailbox/mailbox.c])
AC_CONFIG_AUX_DIR([build-aux])
@@ -115,6 +115,8 @@ AC_CHECK_TYPE(iconv_t,:,
#
AC_CONFIG_LINKS(include/gettext.h:lib/gnu/gettext.h)
+AC_CONFIG_LINKS(include/mailutils/sys/wordsplit.h:libmailutils/wordsplit/wordsplit.h)
+
AH_BOTTOM([
#define DEFAULT_TEXT_DOMAIN PACKAGE
])
diff --git a/include/mailutils/sys/Makefile.am b/include/mailutils/sys/Makefile.am
index 7f31291..321c5f1 100644
--- a/include/mailutils/sys/Makefile.am
+++ b/include/mailutils/sys/Makefile.am
@@ -62,7 +62,8 @@ sysinclude_HEADERS = \
temp_file_stream.h\
tls-stream.h\
url.h\
- xscript-stream.h
+ xscript-stream.h\
+ $(top_srcdir)/libmailutils/wordsplit/wordsplit.h
BUILT_SOURCES = debcat.h
diff --git a/include/mailutils/sys/wordsplit.h b/include/mailutils/sys/wordsplit.h
new file mode 120000
index 0000000..5c46e03
--- a/dev/null
+++ b/include/mailutils/sys/wordsplit.h
@@ -0,0 +1 @@
+../../../libmailutils/wordsplit/wordsplit.h \ No newline at end of file
diff --git a/include/mailutils/wordsplit.h b/include/mailutils/wordsplit.h
index d5631dd..203d924 100644
--- a/include/mailutils/wordsplit.h
+++ b/include/mailutils/wordsplit.h
@@ -1,261 +1,121 @@
-/* wordsplit - a word splitter
- Copyright (C) 2009-2018 Sergey Poznyakoff
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 1999-2019 Free Software Foundation, Inc.
- This program 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.
+ GNU Mailutils 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, or (at your option)
+ any later version.
- This program is distributed in the hope that it will be useful,
+ GNU Mailutils 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 this program. If not, see <http://www.gnu.org/licenses/>. */
+ You should have received a copy of the GNU General Public License
+ along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
+
+/* This header converts wordsplit to mailutils namespace by prefixing each
+ exported identifier with mu_ (or MU_, for macros).
+ The canonical wordsplit.h header is located in mailutils/sys.
+*/
#ifndef __MAILUTILS_WORDSPLIT_H
#define __MAILUTILS_WORDSPLIT_H
-#include <stddef.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct mu_wordsplit mu_wordsplit_t;
-
-/* Structure used to direct the splitting. Members marked with [Input]
- can be defined before calling mu_wordsplit(), those marked with [Output]
- provide return values when the function returns. If neither mark is
- used, the member is internal and must not be used by the caller.
-
- In the comments below, the
- identifiers in parentheses indicate bits that must be set (or unset, if
- starting with !) in the ws_flags to initialize or use the given member.
- If not redefined explicitly, most of them are set to some reasonable
- default value upon entry to mu_wordsplit(). */
-struct mu_wordsplit
-{
- size_t ws_wordc; /* [Output] Number of words in ws_wordv. */
- char **ws_wordv; /* [Output] Array of parsed out words. */
- size_t ws_offs; /* [Input] (MU_WRDSF_DOOFFS) Number of initial
- elements in ws_wordv to fill with NULLs. */
- size_t ws_wordn; /* Number of elements ws_wordv can accomodate. */
- int ws_flags; /* [Input] Flags passed to mu_wordsplit. */
- int ws_options; /* [Input] (MU_WRDSF_PATHEXPAND)
- Additional options. */
- const char *ws_delim; /* [Input] (MU_WRDSF_DELIM) Word delimiters. */
- const char *ws_comment; /* [Input] (MU_WRDSF_COMMENT) Comment characters. */
- const char *ws_escape[2]; /* [Input] (MU_WRDSF_ESCAPE) Characters to be escaped
- with backslash. */
- void (*ws_alloc_die) (mu_wordsplit_t *wsp);
- /* [Input] (MU_WRDSF_ALLOC_DIE) Function called when
- out of memory. Must not return. */
- void (*ws_error) (const char *, ...)
- __attribute__ ((__format__ (__printf__, 1, 2)));
- /* [Input] (MU_WRDSF_ERROR) Function used for error
- reporting */
- void (*ws_debug) (const char *, ...)
- __attribute__ ((__format__ (__printf__, 1, 2)));
- /* [Input] (MU_WRDSF_DEBUG) Function used for debug
- output. */
- const char **ws_env; /* [Input] (MU_WRDSF_ENV, !MU_WRDSF_NOVAR) Array of
- environment variables. */
+# define wordsplit mu_wordsplit
+
+# define wordsplit_t mu_wordsplit_t
+
+# define wordsplit_len mu_wordsplit_len
+# define wordsplit_free mu_wordsplit_free
+# define wordsplit_free_words mu_wordsplit_free_words
+# define wordsplit_free_envbuf mu_wordsplit_free_envbuf
+# define wordsplit_free_parambuf mu_wordsplit_free_parambuf
+# define wordsplit_getwords mu_wordsplit_getwords
+# define wordsplit_get_words mu_wordsplit_get_words
+# define wordsplit_append mu_wordsplit_append
+# define wordsplit_c_unquote_char mu_wordsplit_c_unquote_char
+# define wordsplit_c_quote_char mu_wordsplit_c_quote_char
+# define wordsplit_c_quoted_length mu_wordsplit_c_quoted_length
+# define wordsplit_c_quote_copy mu_wordsplit_c_quote_copy
+# define wordsplit_perror mu_wordsplit_perror
+# define wordsplit_strerror mu_wordsplit_strerror
+# define wordsplit_clearerr mu_wordsplit_clearerr
+
+# include <mailutils/sys/wordsplit.h>
+
+# define MU_WORDSPLIT_ENV_INIT WORDSPLIT_ENV_INIT
+# define MU_WRDSF_APPEND WRDSF_APPEND
+# define MU_WRDSF_DOOFFS WRDSF_DOOFFS
+# define MU_WRDSF_NOCMD WRDSF_NOCMD
+# define MU_WRDSF_REUSE WRDSF_REUSE
+# define MU_WRDSF_SHOWERR WRDSF_SHOWERR
+# define MU_WRDSF_UNDEF WRDSF_UNDEF
+# define MU_WRDSF_NOVAR WRDSF_NOVAR
+# define MU_WRDSF_ENOMEMABRT WRDSF_ENOMEMABRT
+# define MU_WRDSF_WS WRDSF_WS
+# define MU_WRDSF_SQUOTE WRDSF_SQUOTE
+# define MU_WRDSF_DQUOTE WRDSF_DQUOTE
+# define MU_WRDSF_QUOTE WRDSF_QUOTE
+# define MU_WRDSF_SQUEEZE_DELIMS WRDSF_SQUEEZE_DELIMS
+# define MU_WRDSF_RETURN_DELIMS WRDSF_RETURN_DELIMS
+# define MU_WRDSF_SED_EXPR WRDSF_SED_EXPR
+# define MU_WRDSF_DELIM WRDSF_DELIM
+# define MU_WRDSF_COMMENT WRDSF_COMMENT
+# define MU_WRDSF_ALLOC_DIE WRDSF_ALLOC_DIE
+# define MU_WRDSF_ERROR WRDSF_ERROR
+# define MU_WRDSF_DEBUG WRDSF_DEBUG
+# define MU_WRDSF_ENV WRDSF_ENV
+# define MU_WRDSF_GETVAR WRDSF_GETVAR
+# define MU_WRDSF_SHOWDBG WRDSF_SHOWDBG
+# define MU_WRDSF_NOSPLIT WRDSF_NOSPLIT
+# define MU_WRDSF_KEEPUNDEF WRDSF_KEEPUNDEF
+# define MU_WRDSF_WARNUNDEF WRDSF_WARNUNDEF
+# define MU_WRDSF_CESCAPES WRDSF_CESCAPES
+# define MU_WRDSF_CLOSURE WRDSF_CLOSURE
+# define MU_WRDSF_ENV_KV WRDSF_ENV_KV
+# define MU_WRDSF_ESCAPE WRDSF_ESCAPE
+# define MU_WRDSF_INCREMENTAL WRDSF_INCREMENTAL
+# define MU_WRDSF_PATHEXPAND WRDSF_PATHEXPAND
+# define MU_WRDSF_OPTIONS WRDSF_OPTIONS
+# define MU_WRDSF_DEFFLAGS WRDSF_DEFFLAGS
+
+# define MU_WRDSO_NULLGLOB WRDSO_NULLGLOB
+# define MU_WRDSO_FAILGLOB WRDSO_FAILGLOB
+# define MU_WRDSO_DOTGLOB WRDSO_DOTGLOB
+# define MU_WRDSO_GETVARPREF WRDSO_GETVARPREF
+# define MU_WRDSO_BSKEEP_WORD WRDSO_BSKEEP_WORD
+# define MU_WRDSO_OESC_WORD WRDSO_OESC_WORD
+# define MU_WRDSO_XESC_WORD WRDSO_XESC_WORD
+# define MU_WRDSO_MAXWORDS WRDSO_MAXWORDS
+# define MU_WRDSO_BSKEEP_QUOTE WRDSO_BSKEEP_QUOTE
+# define MU_WRDSO_OESC_QUOTE WRDSO_OESC_QUOTE
+# define MU_WRDSO_XESC_QUOTE WRDSO_XESC_QUOTE
+# define MU_WRDSO_NOVARSPLIT WRDSO_NOVARSPLIT
+# define MU_WRDSO_NOCMDSPLIT WRDSO_NOCMDSPLIT
+# define MU_WRDSO_PARAMV WRDSO_PARAMV
+# define MU_WRDSO_PARAM_NEGIDX WRDSO_PARAM_NEGIDX
+# define MU_WRDSO_BSKEEP WRDSO_BSKEEP
+# define MU_WRDSO_OESC WRDSO_OESC
+# define MU_WRDSO_XESC WRDSO_XESC
+
+# define MU_WRDSO_ESC_SET WRDSO_ESC_SET
+# define MU_WRDSO_ESC_TEST WRDSO_ESC_TEST
+
+# define MU_WRDSX_WORD WRDSX_WORD
+# define MU_WRDSX_QUOTE WRDSX_QUOTE
+
+# define MU_WRDSE_OK WRDSE_OK
+# define MU_WRDSE_EOF WRDSE_EOF
+# define MU_WRDSE_QUOTE WRDSE_QUOTE
+# define MU_WRDSE_NOSPACE WRDSE_NOSPACE
+# define MU_WRDSE_USAGE WRDSE_USAGE
+# define MU_WRDSE_CBRACE WRDSE_CBRACE
+# define MU_WRDSE_UNDEF WRDSE_UNDEF
+# define MU_WRDSE_NOINPUT WRDSE_NOINPUT
+# define MU_WRDSE_PAREN WRDSE_PAREN
+# define MU_WRDSE_GLOBERR WRDSE_GLOBERR
+# define MU_WRDSE_USERERR WRDSE_USERERR
+# define MU_WRDSE_BADPARAM WRDSE_BADPARAM
- char **ws_envbuf;
- size_t ws_envidx;
- size_t ws_envsiz;
-
- int (*ws_getvar) (char **ret, const char *var, size_t len, void *clos);
- /* [Input] (MU_WRDSF_GETVAR, !MU_WRDSF_NOVAR) Looks up
- the name VAR (LEN bytes long) in the table of
- variables and, if found returns the value of
- that variable in memory location pointed to
- by RET . Returns WRDSE_OK (0) on success,
- and an error code (see WRDSE_* defines below)
- on error. User-specific errors can be returned
- by storing the error diagnostic string in RET
- and returning WRDSE_USERERR.
- Whatever is stored in RET, it must be allocated
- using malloc(3). */
- void *ws_closure; /* [Input] (MU_WRDSF_CLOSURE) Passed as the CLOS
- argument to ws_getvar and ws_command. */
- int (*ws_command) (char **ret, const char *cmd, size_t len, char **argv,
- void *clos);
- /* [Input] (!MU_WRDSF_NOCMD) Returns in the memory
- location pointed to by RET the expansion of
- the command CMD (LEN bytes long). On input,
- ARGV contains CMD split out to words.
-
- See ws_getvar for a discussion of possible
- return values. */
-
- const char *ws_input; /* Input string (the S argument to mu_wordsplit. */
- size_t ws_len; /* Length of ws_input. */
- size_t ws_endp; /* Points past the last processed byte in
- ws_input. */
- int ws_errno; /* [Output] Error code, if an error occurred. */
- char *ws_usererr; /* Points to textual description of
- the error, if ws_errno is WRDSE_USERERR. Must
- be allocated with malloc(3). */
- struct mu_wordsplit_node *ws_head, *ws_tail;
- /* Doubly-linked list of parsed out nodes. */
- int ws_lvl; /* Invocation nesting level. */
-};
-
-/* Initial size for ws_env, if allocated automatically */
-#define MU_WORDSPLIT_ENV_INIT 16
-
-/* Mu_Wordsplit flags. */
-/* Append the words found to the array resulting from a previous
- call. */
-#define MU_WRDSF_APPEND 0x00000001
-/* Insert ws_offs initial NULLs in the array ws_wordv.
- (These are not counted in the returned ws_wordc.) */
-#define MU_WRDSF_DOOFFS 0x00000002
-/* Don't do command substitution. */
-#define MU_WRDSF_NOCMD 0x00000004
-/* The parameter p resulted from a previous call to
- mu_wordsplit(), and mu_wordsplit_free() was not called. Reuse the
- allocated storage. */
-#define MU_WRDSF_REUSE 0x00000008
-/* Print errors */
-#define MU_WRDSF_SHOWERR 0x00000010
-/* Consider it an error if an undefined variable is expanded. */
-#define MU_WRDSF_UNDEF 0x00000020
-/* Don't do variable expansion. */
-#define MU_WRDSF_NOVAR 0x00000040
-/* Abort on ENOMEM error */
-#define MU_WRDSF_ENOMEMABRT 0x00000080
-/* Trim off any leading and trailind whitespace */
-#define MU_WRDSF_WS 0x00000100
-/* Handle single quotes */
-#define MU_WRDSF_SQUOTE 0x00000200
-/* Handle double quotes */
-#define MU_WRDSF_DQUOTE 0x00000400
-/* Handle single and double quotes */
-#define MU_WRDSF_QUOTE (MU_WRDSF_SQUOTE|MU_WRDSF_DQUOTE)
-/* Replace each input sequence of repeated delimiters with a single
- delimiter */
-#define MU_WRDSF_SQUEEZE_DELIMS 0x00000800
-/* Return delimiters */
-#define MU_WRDSF_RETURN_DELIMS 0x00001000
-/* Treat sed expressions as words */
-#define MU_WRDSF_SED_EXPR 0x00002000
-/* ws_delim field is initialized */
-#define MU_WRDSF_DELIM 0x00004000
-/* ws_comment field is initialized */
-#define MU_WRDSF_COMMENT 0x00008000
-/* ws_alloc_die field is initialized */
-#define MU_WRDSF_ALLOC_DIE 0x00010000
-/* ws_error field is initialized */
-#define MU_WRDSF_ERROR 0x00020000
-/* ws_debug field is initialized */
-#define MU_WRDSF_DEBUG 0x00040000
-/* ws_env field is initialized */
-#define MU_WRDSF_ENV 0x00080000
-/* ws_getvar field is initialized */
-#define MU_WRDSF_GETVAR 0x00100000
-/* enable debugging */
-#define MU_WRDSF_SHOWDBG 0x00200000
-/* Don't split input into words. Useful for side effects. */
-#define MU_WRDSF_NOSPLIT 0x00400000
-/* Keep undefined variables in place, instead of expanding them to
- empty strings. */
-#define MU_WRDSF_KEEPUNDEF 0x00800000
-/* Warn about undefined variables */
-#define MU_WRDSF_WARNUNDEF 0x01000000
-/* Handle C escapes */
-#define MU_WRDSF_CESCAPES 0x02000000
-/* ws_closure is set */
-#define MU_WRDSF_CLOSURE 0x04000000
-/* ws_env is a Key/Value environment, i.e. the value of a variable is
- stored in the element that follows its name. */
-#define MU_WRDSF_ENV_KV 0x08000000
-/* ws_escape is set */
-#define MU_WRDSF_ESCAPE 0x10000000
-/* Incremental mode */
-#define MU_WRDSF_INCREMENTAL 0x20000000
-/* Perform pathname and tilde expansion */
-#define MU_WRDSF_PATHEXPAND 0x40000000
-/* ws_options is initialized */
-#define MU_WRDSF_OPTIONS 0x80000000
-
-#define MU_WRDSF_DEFFLAGS \
- (MU_WRDSF_NOVAR | MU_WRDSF_NOCMD | \
- MU_WRDSF_QUOTE | MU_WRDSF_SQUEEZE_DELIMS | MU_WRDSF_CESCAPES)
-
-/* Remove the word that produces empty string after path expansion */
-#define MU_WRDSO_NULLGLOB 0x00000001
-/* Print error message if path expansion produces empty string */
-#define MU_WRDSO_FAILGLOB 0x00000002
-/* Allow a leading period to be matched by metacharacters. */
-#define MU_WRDSO_DOTGLOB 0x00000004
-#if 0
-/* Unused */
-#define MU_WRDSO_ARGV 0x00000008
-#endif
-/* Keep backslash in unrecognized escape sequences in words */
-#define MU_WRDSO_BSKEEP_WORD 0x00000010
-/* Handle octal escapes in words */
-#define MU_WRDSO_OESC_WORD 0x00000020
-/* Handle hex escapes in words */
-#define MU_WRDSO_XESC_WORD 0x00000040
-
-/* Keep backslash in unrecognized escape sequences in quoted strings */
-#define MU_WRDSO_BSKEEP_QUOTE 0x00000100
-/* Handle octal escapes in quoted strings */
-#define MU_WRDSO_OESC_QUOTE 0x00000200
-/* Handle hex escapes in quoted strings */
-#define MU_WRDSO_XESC_QUOTE 0x00000400
-
-#define MU_WRDSO_BSKEEP MU_WRDSO_BSKEEP_WORD
-#define MU_WRDSO_OESC MU_WRDSO_OESC_WORD
-#define MU_WRDSO_XESC MU_WRDSO_XESC_WORD
-
-/* Indices into ws_escape */
-#define MU_WRDSX_WORD 0
-#define MU_WRDSX_QUOTE 1
-
-/* Set escape option F in WS for words (Q==0) or quoted strings (Q==1) */
-#define MU_WRDSO_ESC_SET(ws,q,f) ((ws)->ws_options |= ((f) << 4*(q)))
-/* Test WS for escape option F for words (Q==0) or quoted strings (Q==1) */
-#define MU_WRDSO_ESC_TEST(ws,q,f) ((ws)->ws_options & ((f) << 4*(q)))
-
-#define MU_WRDSE_OK 0
-#define MU_WRDSE_EOF MU_WRDSE_OK
-#define MU_WRDSE_QUOTE 1
-#define MU_WRDSE_NOSPACE 2
-#define MU_WRDSE_USAGE 3
-#define MU_WRDSE_CBRACE 4
-#define MU_WRDSE_UNDEF 5
-#define MU_WRDSE_NOINPUT 6
-#define MU_WRDSE_PAREN 7
-#define MU_WRDSE_GLOBERR 8
-#define MU_WRDSE_USERERR 9
-
-int mu_wordsplit (const char *s, mu_wordsplit_t *ws, int flags);
-int mu_wordsplit_len (const char *s, size_t len, mu_wordsplit_t *ws, int flags);
-void mu_wordsplit_free (mu_wordsplit_t *ws);
-void mu_wordsplit_free_words (mu_wordsplit_t *ws);
-void mu_wordsplit_free_envbuf (mu_wordsplit_t *ws);
-
-int mu_wordsplit_get_words (mu_wordsplit_t *ws, size_t *wordc, char ***wordv);
-int mu_wordsplit_append (struct mu_wordsplit *wsp, int argc, char **argv);
-
-int mu_wordsplit_c_unquote_char (int c);
-int mu_wordsplit_c_quote_char (int c);
-size_t mu_wordsplit_c_quoted_length (const char *str, int quote_hex, int *quote);
-void mu_wordsplit_c_quote_copy (char *dst, const char *src, int quote_hex);
-
-void mu_wordsplit_perror (mu_wordsplit_t *ws);
-const char *mu_wordsplit_strerror (mu_wordsplit_t *ws);
-
-void mu_wordsplit_clearerr (mu_wordsplit_t *ws);
-
-#ifdef __cplusplus
-}
-#endif
-
#endif
diff --git a/libmailutils/Makefile.am b/libmailutils/Makefile.am
index 422d2c1..71bcda2 100644
--- a/libmailutils/Makefile.am
+++ b/libmailutils/Makefile.am
@@ -80,3 +80,9 @@ libmailutils_la_LIBADD = \
libmailutils_la_LDFLAGS = -version-info @VI_CURRENT@:@VI_REVISION@:@VI_AGE@
+EXTRA_DIST =\
+ wordsplit/wordsplit.c\
+ wordsplit/wordsplit.h\
+ wordsplit/wordsplit.at\
+ wordsplit/wsp.c
+
diff --git a/libmailutils/string/Makefile.am b/libmailutils/string/Makefile.am
index 5cdd739..2455771 100644
--- a/libmailutils/string/Makefile.am
+++ b/libmailutils/string/Makefile.am
@@ -50,4 +50,8 @@ libstring_la_SOURCES = \
EXTRA_DIST=to_sn.c to_un.c
-AM_CPPFLAGS = @MU_LIB_COMMON_INCLUDES@ -I/libmailutils -I${srcdir}
+AM_CPPFLAGS = \
+ @MU_LIB_COMMON_INCLUDES@\
+ -I${srcdir}\
+ -I${top_srcdir}/libmailutils\
+ -I${top_srcdir}/libmailutils/wordsplit
diff --git a/libmailutils/string/wordsplit.c b/libmailutils/string/wordsplit.c
index 1f9b32a..dc3a04d 100644
--- a/libmailutils/string/wordsplit.c
+++ b/libmailutils/string/wordsplit.c
@@ -1,2382 +1,2 @@
-/* wordsplit - a word splitter
- Copyright (C) 2009-2015 Sergey Poznyakoff
-
- This program 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.
-
- This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */
-
-/* This module is shared with Grecs: http://puszcza.gnu.org.ua/projects/grecs.
- The intent is to keep it as mu-independent as possible, so that the two
- projects can be easily synchronized. Some time in the future I'll think
- about providing a better way of synching, perhaps by integrating Grecs to
- Mailutils as a submodule. */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <errno.h>
-#include <ctype.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <pwd.h>
-#include <glob.h>
-
-#include <mailutils/nls.h>
#include <mailutils/wordsplit.h>
-
-#define ISWS(c) ((c)==' '||(c)=='\t'||(c)=='\n')
-#define ISDELIM(ws,c) \
- (strchr ((ws)->ws_delim, (c)) != NULL)
-#define ISPUNCT(c) (strchr("!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",(c))!=NULL)
-#define ISUPPER(c) ('A' <= ((unsigned) (c)) && ((unsigned) (c)) <= 'Z')
-#define ISLOWER(c) ('a' <= ((unsigned) (c)) && ((unsigned) (c)) <= 'z')
-#define ISALPHA(c) (ISUPPER(c) || ISLOWER(c))
-#define ISDIGIT(c) ('0' <= ((unsigned) (c)) && ((unsigned) (c)) <= '9')
-#define ISXDIGIT(c) (strchr("abcdefABCDEF", c)!=NULL)
-#define ISALNUM(c) (ISALPHA(c) || ISDIGIT(c))
-#define ISPRINT(c) (' ' <= ((unsigned) (c)) && ((unsigned) (c)) <= 127)
-
-#define ISVARBEG(c) (ISALPHA(c) || c == '_')
-#define ISVARCHR(c) (ISALNUM(c) || c == '_')
-
-#define ALLOC_INIT 128
-#define ALLOC_INCR 128
-
-static void
-_wsplt_alloc_die (struct mu_wordsplit *wsp)
-{
- wsp->ws_error ("%s", _("memory exhausted"));
- abort ();
-}
-
-static void
-_wsplt_error (const char *fmt, ...)
-{
- va_list ap;
-
- va_start (ap, fmt);
- vfprintf (stderr, fmt, ap);
- va_end (ap);
- fputc ('\n', stderr);
-}
-
-static void mu_wordsplit_free_nodes (struct mu_wordsplit *);
-
-static int
-_wsplt_seterr (struct mu_wordsplit *wsp, int ec)
-{
- wsp->ws_errno = ec;
- if (wsp->ws_flags & MU_WRDSF_SHOWERR)
- mu_wordsplit_perror (wsp);
- return ec;
-}
-
-static int
-_wsplt_nomem (struct mu_wordsplit *wsp)
-{
- errno = ENOMEM;
- wsp->ws_errno = MU_WRDSE_NOSPACE;
- if (wsp->ws_flags & MU_WRDSF_ENOMEMABRT)
- wsp->ws_alloc_die (wsp);
- if (wsp->ws_flags & MU_WRDSF_SHOWERR)
- mu_wordsplit_perror (wsp);
- if (!(wsp->ws_flags & MU_WRDSF_REUSE))
- mu_wordsplit_free (wsp);
- mu_wordsplit_free_nodes (wsp);
- return wsp->ws_errno;
-}
-
-static int mu_wordsplit_run (const char *command, size_t length,
- struct mu_wordsplit *wsp,
- int flags, int lvl);
-
-static int
-_wsplt_subsplit (struct mu_wordsplit *wsp, struct mu_wordsplit *wss,
- char const *str, int len,
- int flags)
-{
- wss->ws_delim = wsp->ws_delim;
- wss->ws_debug = wsp->ws_debug;
- wss->ws_error = wsp->ws_error;
- wss->ws_alloc_die = wsp->ws_alloc_die;
-
- if (!(flags & MU_WRDSF_NOVAR))
- {
- wss->ws_env = wsp->ws_env;
- wss->ws_getvar = wsp->ws_getvar;
- flags |= wsp->ws_flags & (MU_WRDSF_ENV | MU_WRDSF_ENV_KV | MU_WRDSF_GETVAR);
- }
- if (!(flags & MU_WRDSF_NOCMD))
- {
- wss->ws_command = wsp->ws_command;
- }
-
- if ((flags & (MU_WRDSF_NOVAR|MU_WRDSF_NOCMD)) != (MU_WRDSF_NOVAR|MU_WRDSF_NOCMD))
- {
- wss->ws_closure = wsp->ws_closure;
- flags |= wsp->ws_flags & MU_WRDSF_CLOSURE;
- }
-
- wss->ws_options = wsp->ws_options;
-
- flags |= MU_WRDSF_DELIM
- | MU_WRDSF_ALLOC_DIE
- | MU_WRDSF_ERROR
- | MU_WRDSF_DEBUG
- | (wsp->ws_flags & (MU_WRDSF_SHOWDBG | MU_WRDSF_SHOWERR | MU_WRDSF_OPTIONS));
-
- return mu_wordsplit_run (str, len, wss, flags, wsp->ws_lvl + 1);
-}
-
-static void
-_wsplt_seterr_sub (struct mu_wordsplit *wsp, struct mu_wordsplit *wss)
-{
- if (wsp->ws_errno == MU_WRDSE_USERERR)
- free (wsp->ws_usererr);
- wsp->ws_errno = wss->ws_errno;
- if (wss->ws_errno == MU_WRDSE_USERERR)
- {
- wsp->ws_usererr = wss->ws_usererr;
- wss->ws_errno = MU_WRDSE_EOF;
- wss->ws_usererr = NULL;
- }
-}
-
-static void
-mu_wordsplit_init0 (struct mu_wordsplit *wsp)
-{
- if (wsp->ws_flags & MU_WRDSF_REUSE)
- {
- if (!(wsp->ws_flags & MU_WRDSF_APPEND))
- mu_wordsplit_free_words (wsp);
- mu_wordsplit_clearerr (wsp);
- }
- else
- {
- wsp->ws_wordv = NULL;
- wsp->ws_wordc = 0;
- wsp->ws_wordn = 0;
- }
-
- wsp->ws_errno = 0;
- wsp->ws_head = wsp->ws_tail = NULL;
-}
-
-char mu_wordsplit_c_escape_tab[] = "\\\\\"\"a\ab\bf\fn\nr\rt\tv\v";
-
-static int
-mu_wordsplit_init (struct mu_wordsplit *wsp, const char *input, size_t len,
- int flags)
-{
- wsp->ws_flags = flags;
-
- if (!(wsp->ws_flags & MU_WRDSF_ALLOC_DIE))
- wsp->ws_alloc_die = _wsplt_alloc_die;
- if (!(wsp->ws_flags & MU_WRDSF_ERROR))
- wsp->ws_error = _wsplt_error;
-
- if (!(wsp->ws_flags & MU_WRDSF_NOVAR))
- {
- /* These will be initialized on first variable assignment */
- wsp->ws_envidx = wsp->ws_envsiz = 0;
- wsp->ws_envbuf = NULL;
- }
-
- if (!(wsp->ws_flags & MU_WRDSF_NOCMD))
- {
- if (!wsp->ws_command)
- {
- _wsplt_seterr (wsp, MU_WRDSE_USAGE);
- errno = EINVAL;
- return wsp->ws_errno;
- }
- }
-
- if (wsp->ws_flags & MU_WRDSF_SHOWDBG)
- {
- if (!(wsp->ws_flags & MU_WRDSF_DEBUG))
- {
- if (wsp->ws_flags & MU_WRDSF_ERROR)
- wsp->ws_debug = wsp->ws_error;
- else if (wsp->ws_flags & MU_WRDSF_SHOWERR)
- wsp->ws_debug = _wsplt_error;
- else
- wsp->ws_flags &= ~MU_WRDSF_SHOWDBG;
- }
- }
-
- wsp->ws_input = input;
- wsp->ws_len = len;
-
- if (!(wsp->ws_flags & MU_WRDSF_DOOFFS))
- wsp->ws_offs = 0;
-
- if (!(wsp->ws_flags & MU_WRDSF_DELIM))
- wsp->ws_delim = " \t\n";
-
- if (!(wsp->ws_flags & MU_WRDSF_COMMENT))
- wsp->ws_comment = NULL;
-
- if (!(wsp->ws_flags & MU_WRDSF_CLOSURE))
- wsp->ws_closure = NULL;
-
- if (!(wsp->ws_flags & MU_WRDSF_OPTIONS))
- wsp->ws_options = 0;
-
- if (wsp->ws_flags & MU_WRDSF_ESCAPE)
- {
- if (!wsp->ws_escape[MU_WRDSX_WORD])
- wsp->ws_escape[MU_WRDSX_WORD] = "";
- if (!wsp->ws_escape[MU_WRDSX_QUOTE])
- wsp->ws_escape[MU_WRDSX_QUOTE] = "";
- }
- else
- {
- if (wsp->ws_flags & MU_WRDSF_CESCAPES)
- {
- wsp->ws_escape[MU_WRDSX_WORD] = mu_wordsplit_c_escape_tab;
- wsp->ws_escape[MU_WRDSX_QUOTE] = mu_wordsplit_c_escape_tab;
- wsp->ws_options |= MU_WRDSO_OESC_QUOTE | MU_WRDSO_OESC_WORD
- | MU_WRDSO_XESC_QUOTE | MU_WRDSO_XESC_WORD;
- }
- else
- {
- wsp->ws_escape[MU_WRDSX_WORD] = "";
- wsp->ws_escape[MU_WRDSX_QUOTE] = "\\\\\"\"";
- wsp->ws_options |= MU_WRDSO_BSKEEP_QUOTE;
- }
- }
-
- wsp->ws_endp = 0;
-
- mu_wordsplit_init0 (wsp);
-
- return 0;
-}
-
-static int
-alloc_space (struct mu_wordsplit *wsp, size_t count)
-{
- size_t offs = (wsp->ws_flags & MU_WRDSF_DOOFFS) ? wsp->ws_offs : 0;
- char **ptr;
- size_t newalloc;
-
- if (wsp->ws_wordv == NULL)
- {
- newalloc = offs + count > ALLOC_INIT ? count : ALLOC_INIT;
- ptr = calloc (newalloc, sizeof (ptr[0]));
- }
- else if (wsp->ws_wordn < offs + wsp->ws_wordc + count)
- {
- newalloc = offs + wsp->ws_wordc +
- (count > ALLOC_INCR ? count : ALLOC_INCR);
- ptr = realloc (wsp->ws_wordv, newalloc * sizeof (ptr[0]));
- }
- else
- return 0;
-
- if (ptr)
- {
- wsp->ws_wordn = newalloc;
- wsp->ws_wordv = ptr;
- }
- else
- return _wsplt_nomem (wsp);
- return 0;
-}
-
-
-/* Node state flags */
-#define _WSNF_NULL 0x01 /* null node (a noop) */
-#define _WSNF_WORD 0x02 /* node contains word in v.word */
-#define _WSNF_QUOTE 0x04 /* text is quoted */
-#define _WSNF_NOEXPAND 0x08 /* text is not subject to expansion */
-#define _WSNF_JOIN 0x10 /* node must be joined with the next node */
-#define _WSNF_SEXP 0x20 /* is a sed expression */
-#define _WSNF_DELIM 0x40 /* node is a delimiter */
-
-#define _WSNF_EMPTYOK 0x0100 /* special flag indicating that
- mu_wordsplit_add_segm must add the
- segment even if it is empty */
-
-struct mu_wordsplit_node
-{
- struct mu_wordsplit_node *prev; /* Previous element */
- struct mu_wordsplit_node *next; /* Next element */
- int flags; /* Node flags */
- union
- {
- struct
- {
- size_t beg; /* Start of word in ws_input */
- size_t end; /* End of word in ws_input */
- } segm;
- char *word;
- } v;
-};
-
-static const char *
-wsnode_flagstr (int flags)
-{
- static char retbuf[7];
- char *p = retbuf;
-
- if (flags & _WSNF_WORD)
- *p++ = 'w';
- else if (flags & _WSNF_NULL)
- *p++ = 'n';
- else
- *p++ = '-';
- if (flags & _WSNF_QUOTE)
- *p++ = 'q';
- else
- *p++ = '-';
- if (flags & _WSNF_NOEXPAND)
- *p++ = 'E';
- else
- *p++ = '-';
- if (flags & _WSNF_JOIN)
- *p++ = 'j';
- else
- *p++ = '-';
- if (flags & _WSNF_SEXP)
- *p++ = 's';
- else
- *p++ = '-';
- if (flags & _WSNF_DELIM)
- *p++ = 'd';
- else
- *p++ = '-';
- *p = 0;
- return retbuf;
-}
-
-static const char *
-wsnode_ptr (struct mu_wordsplit *wsp, struct mu_wordsplit_node *p)
-{
- if (p->flags & _WSNF_NULL)
- return "";
- else if (p->flags & _WSNF_WORD)
- return p->v.word;
- else
- return wsp->ws_input + p->v.segm.beg;
-}
-
-static size_t
-wsnode_len (struct mu_wordsplit_node *p)
-{
- if (p->flags & _WSNF_NULL)
- return 0;
- else if (p->flags & _WSNF_WORD)
- return strlen (p->v.word);
- else
- return p->v.segm.end - p->v.segm.beg;
-}
-
-static int
-wsnode_new (struct mu_wordsplit *wsp, struct mu_wordsplit_node **pnode)
-{
- struct mu_wordsplit_node *node = calloc (1, sizeof (*node));
- if (!node)
- return _wsplt_nomem (wsp);
- *pnode = node;
- return 0;
-}
-
-static void
-wsnode_free (struct mu_wordsplit_node *p)
-{
- if (p->flags & _WSNF_WORD)
- free (p->v.word);
- free (p);
-}
-
-static void
-wsnode_append (struct mu_wordsplit *wsp, struct mu_wordsplit_node *node)
-{
- node->next = NULL;
- node->prev = wsp->ws_tail;
- if (wsp->ws_tail)
- wsp->ws_tail->next = node;
- else
- wsp->ws_head = node;
- wsp->ws_tail = node;
-}
-
-static void
-wsnode_remove (struct mu_wordsplit *wsp, struct mu_wordsplit_node *node)
-{
- struct mu_wordsplit_node *p;
-
- p = node->prev;
- if (p)
- {
- p->next = node->next;
- if (!node->next)
- p->flags &= ~_WSNF_JOIN;
- }
- else
- wsp->ws_head = node->next;
-
- p = node->next;
- if (p)
- p->prev = node->prev;
- else
- wsp->ws_tail = node->prev;
-
- node->next = node->prev = NULL;
-}
-
-static void
-wsnode_insert (struct mu_wordsplit *wsp, struct mu_wordsplit_node *node,
- struct mu_wordsplit_node *anchor, int before)
-{
- if (!wsp->ws_head)
- {
- node->next = node->prev = NULL;
- wsp->ws_head = wsp->ws_tail = node;
- }
- else if (before)
- {
- if (anchor->prev)
- wsnode_insert (wsp, node, anchor->prev, 0);
- else
- {
- node->prev = NULL;
- node->next = anchor;
- anchor->prev = node;
- wsp->ws_head = node;
- }
- }
- else
- {
- struct mu_wordsplit_node *p;
-
- p = anchor->next;
- if (p)
- p->prev = node;
- else
- wsp->ws_tail = node;
- node->next = p;
- node->prev = anchor;
- anchor->next = node;
- }
-}
-
-static int
-mu_wordsplit_add_segm (struct mu_wordsplit *wsp, size_t beg, size_t end, int flg)
-{
- struct mu_wordsplit_node *node;
- int rc;
-
- if (end == beg && !(flg & _WSNF_EMPTYOK))
- return 0;
- rc = wsnode_new (wsp, &node);
- if (rc)
- return rc;
- node->flags = flg & ~(_WSNF_WORD | _WSNF_EMPTYOK);
- node->v.segm.beg = beg;
- node->v.segm.end = end;
- wsnode_append (wsp, node);
- return 0;
-}
-
-static void
-mu_wordsplit_free_nodes (struct mu_wordsplit *wsp)
-{
- struct mu_wordsplit_node *p;
-
- for (p = wsp->ws_head; p;)
- {
- struct mu_wordsplit_node *next = p->next;
- wsnode_free (p);
- p = next;
- }
- wsp->ws_head = wsp->ws_tail = NULL;
-}
-
-static void
-mu_wordsplit_dump_nodes (struct mu_wordsplit *wsp)
-{
- struct mu_wordsplit_node *p;
- int n = 0;
-
- for (p = wsp->ws_head, n = 0; p; p = p->next, n++)
- {
- if (p->flags & _WSNF_WORD)
- wsp->ws_debug ("(%02d) %4d: %p: %#04x (%s):%s;",
- wsp->ws_lvl,
- n, p, p->flags, wsnode_flagstr (p->flags), p->v.word);
- else
- wsp->ws_debug ("(%02d) %4d: %p: %#04x (%s):%.*s;",
- wsp->ws_lvl,
- n, p, p->flags, wsnode_flagstr (p->flags),
- (int) (p->v.segm.end - p->v.segm.beg),
- wsp->ws_input + p->v.segm.beg);
- }
-}
-
-static int
-coalesce_segment (struct mu_wordsplit *wsp, struct mu_wordsplit_node *node)
-{
- struct mu_wordsplit_node *p, *end;
- size_t len = 0;
- char *buf, *cur;
- int stop;
-
- for (p = node; p && (p->flags & _WSNF_JOIN); p = p->next)
- {
- len += wsnode_len (p);
- }
- if (p)
- len += wsnode_len (p);
- end = p;
-
- buf = malloc (len + 1);
- if (!buf)
- return _wsplt_nomem (wsp);
- cur = buf;
-
- p = node;
- for (stop = 0; !stop;)
- {
- struct mu_wordsplit_node *next = p->next;
- const char *str = wsnode_ptr (wsp, p);
- size_t slen = wsnode_len (p);
-
- memcpy (cur, str, slen);
- cur += slen;
- if (p != node)
- {
- node->flags |= p->flags & _WSNF_QUOTE;
- wsnode_remove (wsp, p);
- stop = p == end;
- wsnode_free (p);
- }
- p = next;
- }
-
- *cur = 0;
-
- node->flags &= ~_WSNF_JOIN;
-
- if (node->flags & _WSNF_WORD)
- free (node->v.word);
- else
- node->flags |= _WSNF_WORD;
- node->v.word = buf;
- return 0;
-}
-
-static void mu_wordsplit_string_unquote_copy (struct mu_wordsplit *ws,
- int inquote,
- char *dst, const char *src,
- size_t n);
-
-static int
-wsnode_quoteremoval (struct mu_wordsplit *wsp)
-{
- struct mu_wordsplit_node *p;
-
- for (p = wsp->ws_head; p; p = p->next)
- {
- const char *str = wsnode_ptr (wsp, p);
- size_t slen = wsnode_len (p);
- int unquote;
-
- if (wsp->ws_flags & MU_WRDSF_QUOTE)
- {
- unquote = !(p->flags & _WSNF_NOEXPAND);
- }
- else
- unquote = 0;
-
- if (unquote)
- {
- if (!(p->flags & _WSNF_WORD))
- {
- char *newstr = malloc (slen + 1);
- if (!newstr)
- return _wsplt_nomem (wsp);
- memcpy (newstr, str, slen);
- newstr[slen] = 0;
- p->v.word = newstr;
- p->flags |= _WSNF_WORD;
- }
-
- mu_wordsplit_string_unquote_copy (wsp, p->flags & _WSNF_QUOTE,
- p->v.word, str, slen);
- }
- }
- return 0;
-}
-
-static int
-wsnode_coalesce (struct mu_wordsplit *wsp)
-{
- struct mu_wordsplit_node *p;
-
- for (p = wsp->ws_head; p; p = p->next)
- {
- if (p->flags & _WSNF_JOIN)
- if (coalesce_segment (wsp, p))
- return 1;
- }
- return 0;
-}
-
-static int
-mu_wordsplit_finish (struct mu_wordsplit *wsp)
-{
- struct mu_wordsplit_node *p;
- size_t n;
-
- n = 0;
-
- for (p = wsp->ws_head; p; p = p->next)
- n++;
-
- if (alloc_space (wsp, n + 1))
- return 1;
-
- for (p = wsp->ws_head; p; p = p->next)
- {
- const char *str = wsnode_ptr (wsp, p);
- size_t slen = wsnode_len (p);
- char *newstr = malloc (slen + 1);
-
- /* Assign newstr first, even if it is NULL. This way
- mu_wordsplit_free will work even if we return
- nomem later. */
- wsp->ws_wordv[wsp->ws_offs + wsp->ws_wordc] = newstr;
- if (!newstr)
- return _wsplt_nomem (wsp);
- memcpy (newstr, str, slen);
- newstr[slen] = 0;
-
- wsp->ws_wordc++;
-
- }
- wsp->ws_wordv[wsp->ws_offs + wsp->ws_wordc] = NULL;
- return 0;
-}
-
-int
-mu_wordsplit_append (struct mu_wordsplit *wsp, int argc, char **argv)
-{
- int rc;
- size_t i;
-
- rc = alloc_space (wsp, wsp->ws_wordc + argc + 1);
- if (rc)
- return rc;
- for (i = 0; i < argc; i++)
- {
- char *newstr = strdup (argv[i]);
- if (!newstr)
- {
- while (i > 0)
- {
- free (wsp->ws_wordv[wsp->ws_offs + wsp->ws_wordc + i - 1]);
- wsp->ws_wordv[wsp->ws_offs + wsp->ws_wordc + i - 1] = NULL;
- i--;
- }
- return _wsplt_nomem (wsp);
- }
- wsp->ws_wordv[wsp->ws_offs + wsp->ws_wordc + i] = newstr;
- }
- wsp->ws_wordc += i;
- wsp->ws_wordv[wsp->ws_offs + wsp->ws_wordc] = NULL;
- return 0;
-}
-
-/* Variable expansion */
-static int
-node_split_prefix (struct mu_wordsplit *wsp,
- struct mu_wordsplit_node **ptail,
- struct mu_wordsplit_node *node,
- size_t beg, size_t len, int flg)
-{
- struct mu_wordsplit_node *newnode;
-
- if (len == 0)
- return 0;
- if (wsnode_new (wsp, &newnode))
- return 1;
- wsnode_insert (wsp, newnode, *ptail, 0);
- if (node->flags & _WSNF_WORD)
- {
- const char *str = wsnode_ptr (wsp, node);
- char *newstr = malloc (len + 1);
- if (!newstr)
- return _wsplt_nomem (wsp);
- memcpy (newstr, str + beg, len);
- newstr[len] = 0;
- newnode->flags = _WSNF_WORD;
- newnode->v.word = newstr;
- }
- else
- {
- newnode->v.segm.beg = node->v.segm.beg + beg;
- newnode->v.segm.end = newnode->v.segm.beg + len;
- }
- newnode->flags |= flg;
- *ptail = newnode;
- return 0;
-}
-
-static int
-find_closing_paren (const char *str, size_t i, size_t len, size_t *poff,
- char *paren)
-{
- enum { st_init, st_squote, st_dquote } state = st_init;
- size_t level = 1;
-
- for (; i < len; i++)
- {
- switch (state)
- {
- case st_init:
- switch (str[i])
- {
- default:
- if (str[i] == paren[0])
- {
- level++;
- break;
- }
- else if (str[i] == paren[1])
- {
- if (--level == 0)
- {
- *poff = i;
- return 0;
- }
- break;
- }
- break;
-
- case '"':
- state = st_dquote;
- break;
-
- case '\'':
- state = st_squote;
- break;
- }
- break;
-
- case st_squote:
- if (str[i] == '\'')
- state = st_init;
- break;
-
- case st_dquote:
- if (str[i] == '\\')
- i++;
- else if (str[i] == '"')
- state = st_init;
- break;
- }
- }
- return 1;
-}
-
-static int
-mu_wordsplit_find_env (struct mu_wordsplit *wsp, const char *name, size_t len,
- char const **ret)
-{
- size_t i;
-
- if (!(wsp->ws_flags & MU_WRDSF_ENV))
- return MU_WRDSE_UNDEF;
-
- if (wsp->ws_flags & MU_WRDSF_ENV_KV)
- {
- /* A key-value pair environment */
- for (i = 0; wsp->ws_env[i]; i++)
- {
- size_t elen = strlen (wsp->ws_env[i]);
- if (elen == len && memcmp (wsp->ws_env[i], name, elen) == 0)
- {
- *ret = wsp->ws_env[i + 1];
- return MU_WRDSE_OK;
- }
- /* Skip the value. Break the loop if it is NULL. */
- i++;
- if (wsp->ws_env[i] == NULL)
- break;
- }
- }
- else if (wsp->ws_env)
- {
- /* Usual (A=B) environment. */
- for (i = 0; wsp->ws_env[i]; i++)
- {
- size_t j;
- const char *var = wsp->ws_env[i];
-
- for (j = 0; j < len; j++)
- if (name[j] != var[j])
- break;
- if (j == len && var[j] == '=')
- {
- *ret = var + j + 1;
- return MU_WRDSE_OK;
- }
- }
- }
- return MU_WRDSE_UNDEF;
-}
-
-static int
-wsplt_assign_var (struct mu_wordsplit *wsp, const char *name, size_t namelen,
- char *value)
-{
- int n = (wsp->ws_flags & MU_WRDSF_ENV_KV) ? 2 : 1;
- char *v;
-
- if (wsp->ws_envidx + n >= wsp->ws_envsiz)
- {
- size_t sz;
- char **newenv;
-
- if (!wsp->ws_envbuf)
- {
- if (wsp->ws_flags & MU_WRDSF_ENV)
- {
- size_t i = 0, j;
-
- if (wsp->ws_env)
- {
- for (; wsp->ws_env[i]; i++)
- ;
- }
-
- sz = i + n + 1;
-
- newenv = calloc (sz, sizeof(newenv[0]));
- if (!newenv)
- return _wsplt_nomem (wsp);
-
- for (j = 0; j < i; j++)
- {
- newenv[j] = strdup (wsp->ws_env[j]);
- if (!newenv[j])
- {
- for (; j > 1; j--)
- free (newenv[j-1]);
- free (newenv[j-1]);
- return _wsplt_nomem (wsp);
- }
- }
- newenv[j] = NULL;
-
- wsp->ws_envbuf = newenv;
- wsp->ws_envidx = i;
- wsp->ws_envsiz = sz;
- wsp->ws_env = (const char**) wsp->ws_envbuf;
- }
- else
- {
- newenv = calloc (MU_WORDSPLIT_ENV_INIT, sizeof(newenv[0]));
- if (!newenv)
- return _wsplt_nomem (wsp);
- wsp->ws_envbuf = newenv;
- wsp->ws_envidx = 0;
- wsp->ws_envsiz = MU_WORDSPLIT_ENV_INIT;
- wsp->ws_env = (const char**) wsp->ws_envbuf;
- wsp->ws_flags |= MU_WRDSF_ENV;
- }
- }
- else
- {
- wsp->ws_envsiz *= 2;
- newenv = realloc (wsp->ws_envbuf,
- wsp->ws_envsiz * sizeof (wsp->ws_envbuf[0]));
- if (!newenv)
- return _wsplt_nomem (wsp);
- wsp->ws_envbuf = newenv;
- wsp->ws_env = (const char**) wsp->ws_envbuf;
- }
- }
-
- if (wsp->ws_flags & MU_WRDSF_ENV_KV)
- {
- /* A key-value pair environment */
- char *p = malloc (namelen + 1);
- if (!p)
- return _wsplt_nomem (wsp);
- memcpy (p, name, namelen);
- p[namelen] = 0;
-
- v = strdup (value);
- if (!v)
- {
- free (p);
- return _wsplt_nomem (wsp);
- }
- wsp->ws_env[wsp->ws_envidx++] = p;
- wsp->ws_env[wsp->ws_envidx++] = v;
- }
- else
- {
- v = malloc (namelen + strlen(value) + 2);
- if (!v)
- return _wsplt_nomem (wsp);
- memcpy (v, name, namelen);
- v[namelen++] = '=';
- strcpy(v + namelen, value);
- wsp->ws_env[wsp->ws_envidx++] = v;
- }
- wsp->ws_env[wsp->ws_envidx++] = NULL;
- return MU_WRDSE_OK;
-}
-
-static int
-expvar (struct mu_wordsplit *wsp, const char *str, size_t len,
- struct mu_wordsplit_node **ptail, const char **pend, int flg)
-{
- size_t i = 0;
- const char *defstr = NULL;
- char *value;
- const char *vptr;
- struct mu_wordsplit_node *newnode;
- const char *start = str - 1;
- int rc;
- struct mu_wordsplit ws;
-
- if (ISVARBEG (str[0]))
- {
- for (i = 1; i < len; i++)
- if (!ISVARCHR (str[i]))
- break;
- *pend = str + i - 1;
- }
- else if (str[0] == '{')
- {
- str++;
- len--;
- for (i = 1; i < len; i++)
- {
- if (str[i] == ':')
- {
- size_t j;
-
- defstr = str + i + 1;
- if (find_closing_paren (str, i + 1, len, &j, "{}"))
- return _wsplt_seterr (wsp, MU_WRDSE_CBRACE);
- *pend = str + j;
- break;
- }
- else if (str[i] == '}')
- {
- defstr = NULL;
- *pend = str + i;
- break;
- }
- else if (strchr ("-+?=", str[i]))
- {
- size_t j;
-
- defstr = str + i;
- if (find_closing_paren (str, i, len, &j, "{}"))
- return _wsplt_seterr (wsp, MU_WRDSE_CBRACE);
- *pend = str + j;
- break;
- }
- }
- if (i == len)
- return _wsplt_seterr (wsp, MU_WRDSE_CBRACE);
- }
- else
- {
- if (wsnode_new (wsp, &newnode))
- return 1;
- wsnode_insert (wsp, newnode, *ptail, 0);
- *ptail = newnode;
- newnode->flags = _WSNF_WORD | flg;
- newnode->v.word = malloc (3);
- if (!newnode->v.word)
- return _wsplt_nomem (wsp);
- newnode->v.word[0] = '$';
- newnode->v.word[1] = str[0];
- newnode->v.word[2] = 0;
- *pend = str;
- return 0;
- }
-
- /* Actually expand the variable */
- /* str - start of the variable name
- i - its length
- defstr - default replacement str */
-
- if (defstr && strchr("-+?=", defstr[0]) == 0)
- {
- rc = MU_WRDSE_UNDEF;
- defstr = NULL;
- }
- else
- {
- rc = mu_wordsplit_find_env (wsp, str, i, &vptr);
- if (rc == MU_WRDSE_OK)
- {
- if (vptr)
- {
- value = strdup (vptr);
- if (!value)
- rc = MU_WRDSE_NOSPACE;
- }
- else
- rc = MU_WRDSE_UNDEF;
- }
- else if (wsp->ws_flags & MU_WRDSF_GETVAR)
- rc = wsp->ws_getvar (&value, str, i, wsp->ws_closure);
- else
- rc = MU_WRDSE_UNDEF;
-
- if (rc == MU_WRDSE_OK
- && (!value || value[0] == 0)
- && defstr && defstr[-1] == ':')
- {
- free (value);
- rc = MU_WRDSE_UNDEF;
- }
- }
-
- switch (rc)
- {
- case MU_WRDSE_OK:
- if (defstr && *defstr == '+')
- {
- size_t size = *pend - ++defstr;
-
- rc = _wsplt_subsplit (wsp, &ws, defstr, size,
- MU_WRDSF_NOSPLIT | MU_WRDSF_WS | MU_WRDSF_QUOTE |
- (wsp->ws_flags &
- (MU_WRDSF_NOVAR | MU_WRDSF_NOCMD)));
- if (rc)
- return rc;
- free (value);
- value = ws.ws_wordv[0];
- ws.ws_wordv[0] = NULL;
- mu_wordsplit_free (&ws);
- }
- break;
-
- case MU_WRDSE_UNDEF:
- if (defstr)
- {
- size_t size;
- if (*defstr == '-' || *defstr == '=')
- {
- size = *pend - ++defstr;
-
- rc = _wsplt_subsplit (wsp, &ws, defstr, size,
- MU_WRDSF_NOSPLIT | MU_WRDSF_WS | MU_WRDSF_QUOTE |
- (wsp->ws_flags &
- (MU_WRDSF_NOVAR | MU_WRDSF_NOCMD)));
- if (rc)
- return rc;
-
- value = ws.ws_wordv[0];
- ws.ws_wordv[0] = NULL;
- mu_wordsplit_free (&ws);
-
- if (defstr[-1] == '=')
- wsplt_assign_var (wsp, str, i, value);
- }
- else
- {
- if (*defstr == '?')
- {
- size = *pend - ++defstr;
- if (size == 0)
- wsp->ws_error (_("%.*s: variable null or not set"),
- (int) i, str);
- else
- {
- rc = _wsplt_subsplit (wsp, &ws, defstr, size,
- MU_WRDSF_NOSPLIT | MU_WRDSF_WS |
- MU_WRDSF_QUOTE |
- (wsp->ws_flags &
- (MU_WRDSF_NOVAR | MU_WRDSF_NOCMD)));
- if (rc == 0)
- wsp->ws_error ("%.*s: %s",
- (int) i, str, ws.ws_wordv[0]);
- else
- wsp->ws_error ("%.*s: %.*s",
- (int) i, str, (int) size, defstr);
- mu_wordsplit_free (&ws);
- }
- }
- value = NULL;
- }
- }
- else if (wsp->ws_flags & MU_WRDSF_UNDEF)
- {
- _wsplt_seterr (wsp, MU_WRDSE_UNDEF);
- return 1;
- }
- else
- {
- if (wsp->ws_flags & MU_WRDSF_WARNUNDEF)
- wsp->ws_error (_("warning: undefined variable `%.*s'"),
- (int) i, str);
- if (wsp->ws_flags & MU_WRDSF_KEEPUNDEF)
- value = NULL;
- else
- {
- value = strdup ("");
- if (!value)
- return _wsplt_nomem (wsp);
- }
- }
- break;
-
- case MU_WRDSE_NOSPACE:
- return _wsplt_nomem (wsp);
-
- case MU_WRDSE_USERERR:
- if (wsp->ws_errno == MU_WRDSE_USERERR)
- free (wsp->ws_usererr);
- wsp->ws_usererr = value;
- /* fall through */
- default:
- _wsplt_seterr (wsp, rc);
- return 1;
- }
-
- if (value)
- {
- if (flg & _WSNF_QUOTE)
- {
- if (wsnode_new (wsp, &newnode))
- return 1;
- wsnode_insert (wsp, newnode, *ptail, 0);
- *ptail = newnode;
- newnode->flags = _WSNF_WORD | _WSNF_NOEXPAND | flg;
- newnode->v.word = value;
- }
- else if (*value == 0)
- {
- free (value);
- /* Empty string is a special case */
- if (wsnode_new (wsp, &newnode))
- return 1;
- wsnode_insert (wsp, newnode, *ptail, 0);
- *ptail = newnode;
- newnode->flags = _WSNF_NULL;
- }
- else
- {
- struct mu_wordsplit ws;
- int i, rc;
-
- rc = _wsplt_subsplit (wsp, &ws, value, strlen (value),
- MU_WRDSF_NOVAR | MU_WRDSF_NOCMD |
- MU_WRDSF_QUOTE);
- free (value);
- if (rc)
- {
- _wsplt_seterr_sub (wsp, &ws);
- mu_wordsplit_free (&ws);
- return 1;
- }
- for (i = 0; i < ws.ws_wordc; i++)
- {
- if (wsnode_new (wsp, &newnode))
- return 1;
- wsnode_insert (wsp, newnode, *ptail, 0);
- *ptail = newnode;
- newnode->flags = _WSNF_WORD |
- _WSNF_NOEXPAND |
- (i + 1 < ws.ws_wordc ? (flg & ~_WSNF_JOIN) : flg);
- newnode->v.word = strdup (ws.ws_wordv[i]);
- if (!newnode->v.word)
- return _wsplt_nomem (wsp);
- }
- mu_wordsplit_free (&ws);
- }
- }
- else if (wsp->ws_flags & MU_WRDSF_KEEPUNDEF)
- {
- size_t size = *pend - start + 1;
-
- if (wsnode_new (wsp, &newnode))
- return 1;
- wsnode_insert (wsp, newnode, *ptail, 0);
- *ptail = newnode;
- newnode->flags = _WSNF_WORD | _WSNF_NOEXPAND | flg;
- newnode->v.word = malloc (size + 1);
- if (!newnode->v.word)
- return _wsplt_nomem (wsp);
- memcpy (newnode->v.word, start, size);
- newnode->v.word[size] = 0;
- }
- else
- {
- if (wsnode_new (wsp, &newnode))
- return 1;
- wsnode_insert (wsp, newnode, *ptail, 0);
- *ptail = newnode;
- newnode->flags = _WSNF_NULL;
- }
- return 0;
-}
-
-static int
-begin_var_p (int c)
-{
- return c == '{' || ISVARBEG (c);
-}
-
-static int
-node_expand (struct mu_wordsplit *wsp, struct mu_wordsplit_node *node,
- int (*beg_p) (int),
- int (*ws_exp_fn) (struct mu_wordsplit *wsp,
- const char *str, size_t len,
- struct mu_wordsplit_node **ptail,
- const char **pend,
- int flg))
-{
- const char *str = wsnode_ptr (wsp, node);
- size_t slen = wsnode_len (node);
- const char *end = str + slen;
- const char *p;
- size_t off = 0;
- struct mu_wordsplit_node *tail = node;
-
- for (p = str; p < end; p++)
- {
- if (*p == '\\')
- {
- p++;
- continue;
- }
- if (*p == '$' && beg_p (p[1]))
- {
- size_t n = p - str;
-
- if (tail != node)
- tail->flags |= _WSNF_JOIN;
- if (node_split_prefix (wsp, &tail, node, off, n, _WSNF_JOIN))
- return 1;
- p++;
- if (ws_exp_fn (wsp, p, slen - n, &tail, &p,
- node->flags & (_WSNF_JOIN | _WSNF_QUOTE)))
- return 1;
- off += p - str + 1;
- str = p + 1;
- }
- }
- if (p > str)
- {
- if (tail != node)
- tail->flags |= _WSNF_JOIN;
- if (node_split_prefix (wsp, &tail, node, off, p - str,
- node->flags & (_WSNF_JOIN|_WSNF_QUOTE)))
- return 1;
- }
- if (tail != node)
- {
- wsnode_remove (wsp, node);
- wsnode_free (node);
- }
- return 0;
-}
-
-/* Remove NULL nodes from the list */
-static void
-wsnode_nullelim (struct mu_wordsplit *wsp)
-{
- struct mu_wordsplit_node *p;
-
- for (p = wsp->ws_head; p;)
- {
- struct mu_wordsplit_node *next = p->next;
- if (p->flags & _WSNF_DELIM && p->prev)
- p->prev->flags &= ~_WSNF_JOIN;
- if (p->flags & _WSNF_NULL)
- {
- wsnode_remove (wsp, p);
- wsnode_free (p);
- }
- p = next;
- }
-}
-
-static int
-mu_wordsplit_varexp (struct mu_wordsplit *wsp)
-{
- struct mu_wordsplit_node *p;
-
- for (p = wsp->ws_head; p;)
- {
- struct mu_wordsplit_node *next = p->next;
- if (!(p->flags & _WSNF_NOEXPAND))
- if (node_expand (wsp, p, begin_var_p, expvar))
- return 1;
- p = next;
- }
-
- wsnode_nullelim (wsp);
- return 0;
-}
-
-static int
-begin_cmd_p (int c)
-{
- return c == '(';
-}
-
-static int
-expcmd (struct mu_wordsplit *wsp, const char *str, size_t len,
- struct mu_wordsplit_node **ptail, const char **pend, int flg)
-{
- int rc;
- size_t j;
- char *value;
- struct mu_wordsplit_node *newnode;
- struct mu_wordsplit ws;
-
- str++;
- len--;
-
- if (find_closing_paren (str, 0, len, &j, "()"))
- {
- _wsplt_seterr (wsp, MU_WRDSE_PAREN);
- return 1;
- }
-
- *pend = str + j;
-
- rc = _wsplt_subsplit (wsp, &ws, str, j, MU_WRDSF_WS | MU_WRDSF_QUOTE);
- if (rc)
- {
- _wsplt_seterr_sub (wsp, &ws);
- mu_wordsplit_free (&ws);
- return 1;
- }
- rc = wsp->ws_command (&value, str, j, ws.ws_wordv, wsp->ws_closure);
- mu_wordsplit_free (&ws);
-
- if (rc == MU_WRDSE_NOSPACE)
- return _wsplt_nomem (wsp);
- else if (rc)
- {
- if (rc == MU_WRDSE_USERERR)
- {
- if (wsp->ws_errno == MU_WRDSE_USERERR)
- free (wsp->ws_usererr);
- wsp->ws_usererr = value;
- }
- _wsplt_seterr (wsp, rc);
- return 1;
- }
-
- if (value)
- {
- if (flg & _WSNF_QUOTE)
- {
- if (wsnode_new (wsp, &newnode))
- return 1;
- wsnode_insert (wsp, newnode, *ptail, 0);
- *ptail = newnode;
- newnode->flags = _WSNF_WORD | _WSNF_NOEXPAND | flg;
- newnode->v.word = value;
- }
- else if (*value == 0)
- {
- free (value);
- /* Empty string is a special case */
- if (wsnode_new (wsp, &newnode))
- return 1;
- wsnode_insert (wsp, newnode, *ptail, 0);
- *ptail = newnode;
- newnode->flags = _WSNF_NULL;
- }
- else
- {
- struct mu_wordsplit ws;
- int i, rc;
-
- rc = _wsplt_subsplit (wsp, &ws, value, strlen (value),
- MU_WRDSF_NOVAR | MU_WRDSF_NOCMD |
- MU_WRDSF_WS | MU_WRDSF_QUOTE);
- free (value);
- if (rc)
- {
- _wsplt_seterr_sub (wsp, &ws);
- mu_wordsplit_free (&ws);
- return 1;
- }
- for (i = 0; i < ws.ws_wordc; i++)
- {
- if (wsnode_new (wsp, &newnode))
- return 1;
- wsnode_insert (wsp, newnode, *ptail, 0);
- *ptail = newnode;
- newnode->flags = _WSNF_WORD |
- _WSNF_NOEXPAND |
- (i + 1 < ws.ws_wordc ? (flg & ~_WSNF_JOIN) : flg);
- newnode->v.word = strdup (ws.ws_wordv[i]);
- if (!newnode->v.word)
- return _wsplt_nomem (wsp);
- }
- mu_wordsplit_free (&ws);
- }
- }
- else
- {
- if (wsnode_new (wsp, &newnode))
- return 1;
- wsnode_insert (wsp, newnode, *ptail, 0);
- *ptail = newnode;
- newnode->flags = _WSNF_NULL;
- }
- return 0;
-}
-
-static int
-mu_wordsplit_cmdexp (struct mu_wordsplit *wsp)
-{
- struct mu_wordsplit_node *p;
-
- for (p = wsp->ws_head; p;)
- {
- struct mu_wordsplit_node *next = p->next;
- if (!(p->flags & _WSNF_NOEXPAND))
- if (node_expand (wsp, p, begin_cmd_p, expcmd))
- return 1;
- p = next;
- }
-
- wsnode_nullelim (wsp);
- return 0;
-}
-
-/* Strip off any leading and trailing whitespace. This function is called
- right after the initial scanning, therefore it assumes that every
- node in the list is a text reference node. */
-static int
-mu_wordsplit_trimws (struct mu_wordsplit *wsp)
-{
- struct mu_wordsplit_node *p;
-
- for (p = wsp->ws_head; p; p = p->next)
- {
- size_t n;
-
- if (!(p->flags & _WSNF_QUOTE))
- {
- /* Skip leading whitespace: */
- for (n = p->v.segm.beg; n < p->v.segm.end && ISWS (wsp->ws_input[n]);
- n++)
- ;
- p->v.segm.beg = n;
- }
-
- while (p->next && (p->flags & _WSNF_JOIN))
- p = p->next;
-
- if (p->flags & _WSNF_QUOTE)
- continue;
-
- /* Trim trailing whitespace */
- for (n = p->v.segm.end;
- n > p->v.segm.beg && ISWS (wsp->ws_input[n - 1]); n--);
- p->v.segm.end = n;
- if (p->v.segm.beg == p->v.segm.end)
- p->flags |= _WSNF_NULL;
- }
-
- wsnode_nullelim (wsp);
- return 0;
-}
-
-static int
-mu_wordsplit_tildexpand (struct mu_wordsplit *wsp)
-{
- struct mu_wordsplit_node *p;
- char *uname = NULL;
- size_t usize = 0;
-
- for (p = wsp->ws_head; p; p = p->next)
- {
- const char *str;
-
- if (p->flags & _WSNF_QUOTE)
- continue;
-
- str = wsnode_ptr (wsp, p);
- if (str[0] == '~')
- {
- size_t i, size, dlen;
- size_t slen = wsnode_len (p);
- struct passwd *pw;
- char *newstr;
-
- for (i = 1; i < slen && str[i] != '/'; i++)
- ;
- if (i == slen)
- continue;
- if (i > 1)
- {
- if (i > usize)
- {
- char *p = realloc (uname, i);
- if (!p)
- {
- free (uname);
- return _wsplt_nomem (wsp);
- }
- uname = p;
- usize = i;
- }
- --i;
- memcpy (uname, str + 1, i);
- uname[i] = 0;
- pw = getpwnam (uname);
- }
- else
- pw = getpwuid (getuid ());
-
- if (!pw)
- continue;
-
- dlen = strlen (pw->pw_dir);
- size = slen - i + dlen;
- newstr = malloc (size);
- if (!newstr)
- {
- free (uname);
- return _wsplt_nomem (wsp);
- }
- --size;
-
- memcpy (newstr, pw->pw_dir, dlen);
- memcpy (newstr + dlen, str + i + 1, slen - i - 1);
- newstr[size] = 0;
- if (p->flags & _WSNF_WORD)
- free (p->v.word);
- p->v.word = newstr;
- p->flags |= _WSNF_WORD;
- }
- }
- free (uname);
- return 0;
-}
-
-static int
-isglob (const char *s, int l)
-{
- while (l--)
- {
- if (strchr ("*?[", *s++))
- return 1;
- }
- return 0;
-}
-
-static int
-mu_wordsplit_pathexpand (struct mu_wordsplit *wsp)
-{
- struct mu_wordsplit_node *p, *next;
- char *pattern = NULL;
- size_t patsize = 0;
- size_t slen;
- int flags = 0;
-
-#ifdef GLOB_PERIOD
- if (wsp->ws_options & MU_WRDSO_DOTGLOB)
- flags = GLOB_PERIOD;
-#endif
-
- for (p = wsp->ws_head; p; p = next)
- {
- const char *str;
-
- next = p->next;
-
- if (p->flags & _WSNF_QUOTE)
- continue;
-
- str = wsnode_ptr (wsp, p);
- slen = wsnode_len (p);
-
- if (isglob (str, slen))
- {
- int i;
- glob_t g;
- struct mu_wordsplit_node *prev;
-
- if (slen + 1 > patsize)
- {
- char *p = realloc (pattern, slen + 1);
- if (!p)
- return _wsplt_nomem (wsp);
- pattern = p;
- patsize = slen + 1;
- }
- memcpy (pattern, str, slen);
- pattern[slen] = 0;
-
- switch (glob (pattern, flags, NULL, &g))
- {
- case 0:
- break;
-
- case GLOB_NOSPACE:
- free (pattern);
- return _wsplt_nomem (wsp);
-
- case GLOB_NOMATCH:
- if (wsp->ws_options & MU_WRDSO_NULLGLOB)
- {
- wsnode_remove (wsp, p);
- wsnode_free (p);
- }
- else if (wsp->ws_options & MU_WRDSO_FAILGLOB)
- {
- char buf[128];
- if (wsp->ws_errno == MU_WRDSE_USERERR)
- free (wsp->ws_usererr);
- snprintf (buf, sizeof (buf), _("no files match pattern %s"),
- pattern);
- free (pattern);
- wsp->ws_usererr = strdup (buf);
- if (!wsp->ws_usererr)
- return _wsplt_nomem (wsp);
- else
- return _wsplt_seterr (wsp, MU_WRDSE_USERERR);
- }
- continue;
-
- default:
- free (pattern);
- return _wsplt_seterr (wsp, MU_WRDSE_GLOBERR);
- }
-
- prev = p;
- for (i = 0; i < g.gl_pathc; i++)
- {
- struct mu_wordsplit_node *newnode;
- char *newstr;
-
- if (wsnode_new (wsp, &newnode))
- return 1;
- newstr = strdup (g.gl_pathv[i]);
- if (!newstr)
- return _wsplt_nomem (wsp);
- newnode->v.word = newstr;
- newnode->flags |= _WSNF_WORD|_WSNF_QUOTE;
- wsnode_insert (wsp, newnode, prev, 0);
- prev = newnode;
- }
- globfree (&g);
-
- wsnode_remove (wsp, p);
- wsnode_free (p);
- }
- }
- free (pattern);
- return 0;
-}
-
-static int
-skip_sed_expr (const char *command, size_t i, size_t len)
-{
- int state;
-
- do
- {
- int delim;
-
- if (command[i] == ';')
- i++;
- if (!(command[i] == 's' && i + 3 < len && ISPUNCT (command[i + 1])))
- break;
-
- delim = command[++i];
- state = 1;
- for (i++; i < len; i++)
- {
- if (state == 3)
- {
- if (command[i] == delim || !ISALNUM (command[i]))
- break;
- }
- else if (command[i] == '\\')
- i++;
- else if (command[i] == delim)
- state++;
- }
- }
- while (state == 3 && i < len && command[i] == ';');
- return i;
-}
-
-static size_t
-skip_delim (struct mu_wordsplit *wsp)
-{
- size_t start = wsp->ws_endp;
- if (wsp->ws_flags & MU_WRDSF_SQUEEZE_DELIMS)
- {
- if ((wsp->ws_flags & MU_WRDSF_RETURN_DELIMS) &&
- ISDELIM (wsp, wsp->ws_input[start]))
- {
- int delim = wsp->ws_input[start];
- do
- start++;
- while (start < wsp->ws_len && delim == wsp->ws_input[start]);
- }
- else
- {
- do
- start++;
- while (start < wsp->ws_len && ISDELIM (wsp, wsp->ws_input[start]));
- }
- start--;
- }
-
- if (!(wsp->ws_flags & MU_WRDSF_RETURN_DELIMS))
- start++;
-
- return start;
-}
-
-#define _MU_WRDS_EOF 0
-#define _MU_WRDS_OK 1
-#define _MU_WRDS_ERR 2
-
-static int
-scan_qstring (struct mu_wordsplit *wsp, size_t start, size_t * end)
-{
- size_t j;
- const char *command = wsp->ws_input;
- size_t len = wsp->ws_len;
- char q = command[start];
-
- for (j = start + 1; j < len && command[j] != q; j++)
- if (q == '"' && command[j] == '\\')
- j++;
- if (j < len && command[j] == q)
- {
- int flags = _WSNF_QUOTE | _WSNF_EMPTYOK;
- if (q == '\'')
- flags |= _WSNF_NOEXPAND;
- if (mu_wordsplit_add_segm (wsp, start + 1, j, flags))
- return _MU_WRDS_ERR;
- *end = j;
- }
- else
- {
- wsp->ws_endp = start;
- _wsplt_seterr (wsp, MU_WRDSE_QUOTE);
- return _MU_WRDS_ERR;
- }
- return 0;
-}
-
-static int
-scan_word (struct mu_wordsplit *wsp, size_t start)
-{
- size_t len = wsp->ws_len;
- const char *command = wsp->ws_input;
- const char *comment = wsp->ws_comment;
- int join = 0;
- int flags = 0;
-
- size_t i = start;
-
- if (i >= len)
- {
- wsp->ws_errno = MU_WRDSE_EOF;
- return _MU_WRDS_EOF;
- }
-
- start = i;
-
- if (wsp->ws_flags & MU_WRDSF_SED_EXPR
- && command[i] == 's' && i + 3 < len && ISPUNCT (command[i + 1]))
- {
- flags = _WSNF_SEXP;
- i = skip_sed_expr (command, i, len);
- }
- else if (!ISDELIM (wsp, command[i]))
- {
- while (i < len)
- {
- if (comment && strchr (comment, command[i]) != NULL)
- {
- size_t j;
- for (j = i + 1; j < len && command[j] != '\n'; j++)
- ;
- if (mu_wordsplit_add_segm (wsp, start, i, 0))
- return _MU_WRDS_ERR;
- wsp->ws_endp = j;
- return _MU_WRDS_OK;
- }
-
- if (wsp->ws_flags & MU_WRDSF_QUOTE)
- {
- if (command[i] == '\\')
- {
- if (++i == len)
- break;
- i++;
- continue;
- }
-
- if (((wsp->ws_flags & MU_WRDSF_SQUOTE) && command[i] == '\'') ||
- ((wsp->ws_flags & MU_WRDSF_DQUOTE) && command[i] == '"'))
- {
- if (join && wsp->ws_tail)
- wsp->ws_tail->flags |= _WSNF_JOIN;
- if (mu_wordsplit_add_segm (wsp, start, i, _WSNF_JOIN))
- return _MU_WRDS_ERR;
- if (scan_qstring (wsp, i, &i))
- return _MU_WRDS_ERR;
- start = i + 1;
- join = 1;
- }
- }
-
- if (command[i] == '$')
- {
- if (!(wsp->ws_flags & MU_WRDSF_NOVAR)
- && command[i+1] == '{'
- && find_closing_paren (command, i + 2, len, &i, "{}") == 0)
- continue;
- if (!(wsp->ws_flags & MU_WRDSF_NOCMD)
- && command[i+1] == '('
- && find_closing_paren (command, i + 2, len, &i, "()") == 0)
- continue;
- }
-
- if (ISDELIM (wsp, command[i]))
- break;
- else
- i++;
- }
- }
- else if (wsp->ws_flags & MU_WRDSF_RETURN_DELIMS)
- {
- i++;
- flags |= _WSNF_DELIM;
- }
- else if (!(wsp->ws_flags & MU_WRDSF_SQUEEZE_DELIMS))
- flags |= _WSNF_EMPTYOK;
-
- if (join && i > start && wsp->ws_tail)
- wsp->ws_tail->flags |= _WSNF_JOIN;
- if (mu_wordsplit_add_segm (wsp, start, i, flags))
- return _MU_WRDS_ERR;
- wsp->ws_endp = i;
- if (wsp->ws_flags & MU_WRDSF_INCREMENTAL)
- return _MU_WRDS_EOF;
- return _MU_WRDS_OK;
-}
-
-#define to_num(c) \
- (ISDIGIT(c) ? c - '0' : (ISXDIGIT(c) ? toupper(c) - 'A' + 10 : 255 ))
-
-static int
-xtonum (int *pval, const char *src, int base, int cnt)
-{
- int i, val;
-
- for (i = 0, val = 0; i < cnt; i++, src++)
- {
- int n = *(unsigned char *) src;
- if (n > 127 || (n = to_num (n)) >= base)
- break;
- val = val * base + n;
- }
- *pval = val;
- return i;
-}
-
-size_t
-mu_wordsplit_c_quoted_length (const char *str, int quote_hex, int *quote)
-{
- size_t len = 0;
-
- *quote = 0;
- for (; *str; str++)
- {
- if (strchr (" \"", *str))
- *quote = 1;
-
- if (*str == ' ')
- len++;
- else if (*str == '"')
- len += 2;
- else if (*str != '\t' && *str != '\\' && ISPRINT (*str))
- len++;
- else if (quote_hex)
- len += 3;
- else
- {
- if (mu_wordsplit_c_quote_char (*str))
- len += 2;
- else
- len += 4;
- }
- }
- return len;
-}
-
-int
-wsplt_unquote_char (const char *transtab, int c)
-{
- while (*transtab && transtab[1])
- {
- if (*transtab++ == c)
- return *transtab;
- ++transtab;
- }
- return 0;
-}
-
-int
-wsplt_quote_char (const char *transtab, int c)
-{
- for (; *transtab && transtab[1]; transtab += 2)
- {
- if (transtab[1] == c)
- return *transtab;
- }
- return 0;
-}
-
-int
-mu_wordsplit_c_unquote_char (int c)
-{
- return wsplt_unquote_char (mu_wordsplit_c_escape_tab, c);
-}
-
-int
-mu_wordsplit_c_quote_char (int c)
-{
- return wsplt_quote_char (mu_wordsplit_c_escape_tab, c);
-}
-
-void
-mu_wordsplit_string_unquote_copy (struct mu_wordsplit *ws, int inquote,
- char *dst, const char *src, size_t n)
-{
- int i = 0;
- int c;
-
- inquote = !!inquote;
- while (i < n)
- {
- if (src[i] == '\\')
- {
- ++i;
- if (MU_WRDSO_ESC_TEST (ws, inquote, MU_WRDSO_XESC)
- && (src[i] == 'x' || src[i] == 'X'))
- {
- if (n - i < 2)
- {
- *dst++ = '\\';
- *dst++ = src[i++];
- }
- else
- {
- int off = xtonum (&c, src + i + 1,
- 16, 2);
- if (off == 0)
- {
- *dst++ = '\\';
- *dst++ = src[i++];
- }
- else
- {
- *dst++ = c;
- i += off + 1;
- }
- }
- }
- else if (MU_WRDSO_ESC_TEST (ws, inquote, MU_WRDSO_OESC)
- && (unsigned char) src[i] < 128 && ISDIGIT (src[i]))
- {
- if (n - i < 1)
- {
- *dst++ = '\\';
- *dst++ = src[i++];
- }
- else
- {
- int off = xtonum (&c, src + i, 8, 3);
- if (off == 0)
- {
- *dst++ = '\\';
- *dst++ = src[i++];
- }
- else
- {
- *dst++ = c;
- i += off;
- }
- }
- }
- else if ((c = wsplt_unquote_char (ws->ws_escape[inquote], src[i])))
- {
- *dst++ = c;
- ++i;
- }
- else
- {
- if (MU_WRDSO_ESC_TEST (ws, inquote, MU_WRDSO_BSKEEP))
- *dst++ = '\\';
- *dst++ = src[i++];
- }
- }
- else
- *dst++ = src[i++];
- }
- *dst = 0;
-}
-
-void
-mu_wordsplit_c_quote_copy (char *dst, const char *src, int quote_hex)
-{
- for (; *src; src++)
- {
- if (*src == '"')
- {
- *dst++ = '\\';
- *dst++ = *src;
- }
- else if (*src != '\t' && *src != '\\' && ISPRINT (*src))
- *dst++ = *src;
- else
- {
- char tmp[4];
-
- if (quote_hex)
- {
- snprintf (tmp, sizeof tmp, "%%%02X", *(unsigned char *) src);
- memcpy (dst, tmp, 3);
- dst += 3;
- }
- else
- {
- int c = mu_wordsplit_c_quote_char (*src);
- *dst++ = '\\';
- if (c)
- *dst++ = c;
- else
- {
- snprintf (tmp, sizeof tmp, "%03o", *(unsigned char *) src);
- memcpy (dst, tmp, 3);
- dst += 3;
- }
- }
- }
- }
-}
-
-
-/* This structure describes a single expansion phase */
-struct exptab
-{
- char *descr; /* Textual description (for debugging) */
- int flag; /* MU_WRDSF_ bit that controls this phase */
- int opt; /* Entry-specific options (see EXPOPT_ flags below */
- int (*expansion) (struct mu_wordsplit *wsp); /* expansion function */
-};
-
-/* The following options control expansions: */
-/* Normally the exptab entry is run if its flag bit is set in struct
- wordsplit. The EXPOPT_NEG option negates this test so that expansion
- is performed if its associated flag bit is not set in struct wordsplit. */
-#define EXPOPT_NEG 0x01
-/* Coalesce the input list before running the expansion. */
-#define EXPOPT_COALESCE 0x02
-
-static struct exptab exptab[] = {
- { N_("WS trimming"), MU_WRDSF_WS, 0,
- mu_wordsplit_trimws },
- { N_("command substitution"), MU_WRDSF_NOCMD, EXPOPT_NEG|EXPOPT_COALESCE,
- mu_wordsplit_cmdexp },
- { N_("coalesce list"), 0, EXPOPT_NEG|EXPOPT_COALESCE,
- NULL },
- { N_("tilde expansion"), MU_WRDSF_PATHEXPAND, 0,
- mu_wordsplit_tildexpand },
- { N_("variable expansion"), MU_WRDSF_NOVAR, EXPOPT_NEG,
- mu_wordsplit_varexp },
- { N_("quote removal"), 0, EXPOPT_NEG,
- wsnode_quoteremoval },
- { N_("coalesce list"), 0, EXPOPT_NEG|EXPOPT_COALESCE,
- NULL },
- { N_("path expansion"), MU_WRDSF_PATHEXPAND, 0,
- mu_wordsplit_pathexpand },
- { NULL }
-};
-
-static int
-mu_wordsplit_process_list (struct mu_wordsplit *wsp, size_t start)
-{
- struct exptab *p;
-
- if (wsp->ws_flags & MU_WRDSF_NOSPLIT)
- {
- /* Treat entire input as a quoted argument */
- if (mu_wordsplit_add_segm (wsp, start, wsp->ws_len, _WSNF_QUOTE))
- return wsp->ws_errno;
- wsp->ws_endp = wsp->ws_len;
- }
- else
- {
- int rc;
-
- while ((rc = scan_word (wsp, start)) == _MU_WRDS_OK)
- start = skip_delim (wsp);
- /* Make sure tail element is not joinable */
- if (wsp->ws_tail)
- wsp->ws_tail->flags &= ~_WSNF_JOIN;
- if (rc == _MU_WRDS_ERR)
- return wsp->ws_errno;
- }
-
- if (wsp->ws_flags & MU_WRDSF_SHOWDBG)
- {
- wsp->ws_debug ("(%02d) %s", wsp->ws_lvl, _("Initial list:"));
- mu_wordsplit_dump_nodes (wsp);
- }
-
- for (p = exptab; p->descr; p++)
- {
- if ((p->opt & EXPOPT_NEG)
- ? !(wsp->ws_flags & p->flag) : (wsp->ws_flags & p->flag))
- {
- if (p->opt & EXPOPT_COALESCE)
- {
- if (wsnode_coalesce (wsp))
- break;
- if (wsp->ws_flags & MU_WRDSF_SHOWDBG)
- {
- wsp->ws_debug ("(%02d) %s", wsp->ws_lvl,
- _("Coalesced list:"));
- mu_wordsplit_dump_nodes (wsp);
- }
- }
- if (p->expansion)
- {
- if (p->expansion (wsp))
- break;
- if (wsp->ws_flags & MU_WRDSF_SHOWDBG)
- {
- wsp->ws_debug ("(%02d) %s", wsp->ws_lvl, _(p->descr));
- mu_wordsplit_dump_nodes (wsp);
- }
- }
- }
- }
- return wsp->ws_errno;
-}
-
-static int
-mu_wordsplit_run (const char *command, size_t length, struct mu_wordsplit *wsp,
- int flags, int lvl)
-{
- int rc;
- size_t start;
- const char *cmdptr;
- size_t cmdlen;
-
- if (!command)
- {
- if (!(flags & MU_WRDSF_INCREMENTAL))
- return EINVAL;
-
- start = skip_delim (wsp);
- if (wsp->ws_endp == wsp->ws_len)
- return _wsplt_seterr (wsp, MU_WRDSE_NOINPUT);
-
- cmdptr = wsp->ws_input + wsp->ws_endp;
- cmdlen = wsp->ws_len - wsp->ws_endp;
- wsp->ws_flags |= MU_WRDSF_REUSE;
- mu_wordsplit_init0 (wsp);
- }
- else
- {
- cmdptr = command;
- cmdlen = length;
- start = 0;
- rc = mu_wordsplit_init (wsp, cmdptr, cmdlen, flags);
- if (rc)
- return rc;
- wsp->ws_lvl = lvl;
- }
-
- if (wsp->ws_flags & MU_WRDSF_SHOWDBG)
- wsp->ws_debug (_("(%02d) Input:%.*s;"), wsp->ws_lvl, (int) cmdlen, cmdptr);
-
- rc = mu_wordsplit_process_list (wsp, start);
- if (rc == 0 && (flags & MU_WRDSF_INCREMENTAL))
- {
- while (!wsp->ws_head && wsp->ws_endp < wsp->ws_len)
- {
- start = skip_delim (wsp);
- if (wsp->ws_flags & MU_WRDSF_SHOWDBG)
- {
- cmdptr = wsp->ws_input + wsp->ws_endp;
- cmdlen = wsp->ws_len - wsp->ws_endp;
- wsp->ws_debug (_("(%02d) Restart:%.*s;"),
- wsp->ws_lvl, (int) cmdlen, cmdptr);
- }
- rc = mu_wordsplit_process_list (wsp, start);
- if (rc)
- break;
- }
- }
- if (rc)
- {
- mu_wordsplit_free_nodes (wsp);
- return rc;
- }
- mu_wordsplit_finish (wsp);
- mu_wordsplit_free_nodes (wsp);
- return wsp->ws_errno;
-}
-
-int
-mu_wordsplit_len (const char *command, size_t length, struct mu_wordsplit *wsp,
- int flags)
-{
- return mu_wordsplit_run (command, length, wsp, flags, 0);
-}
-
-int
-mu_wordsplit (const char *command, struct mu_wordsplit *ws, int flags)
-{
- return mu_wordsplit_len (command, command ? strlen (command) : 0, ws, flags);
-}
-
-void
-mu_wordsplit_free_words (struct mu_wordsplit *ws)
-{
- size_t i;
-
- for (i = 0; i < ws->ws_wordc; i++)
- {
- char *p = ws->ws_wordv[ws->ws_offs + i];
- if (p)
- {
- free (p);
- ws->ws_wordv[ws->ws_offs + i] = NULL;
- }
- }
- ws->ws_wordc = 0;
-}
-
-void
-mu_wordsplit_free_envbuf (struct mu_wordsplit *ws)
-{
- if (ws->ws_flags & MU_WRDSF_NOCMD)
- return;
- if (ws->ws_envbuf)
- {
- size_t i;
-
- for (i = 0; ws->ws_envbuf[i]; i++)
- free (ws->ws_envbuf[i]);
- free (ws->ws_envbuf);
- ws->ws_envidx = ws->ws_envsiz = 0;
- ws->ws_envbuf = NULL;
- }
-}
-
-void
-mu_wordsplit_clearerr (struct mu_wordsplit *ws)
-{
- if (ws->ws_errno == MU_WRDSE_USERERR)
- free (ws->ws_usererr);
- ws->ws_usererr = NULL;
- ws->ws_errno = MU_WRDSE_OK;
-}
-
-void
-mu_wordsplit_free (struct mu_wordsplit *ws)
-{
- mu_wordsplit_free_words (ws);
- free (ws->ws_wordv);
- ws->ws_wordv = NULL;
- mu_wordsplit_free_envbuf (ws);
-}
-
-int
-mu_wordsplit_get_words (struct mu_wordsplit *ws, size_t *wordc, char ***wordv)
-{
- char **p = realloc (ws->ws_wordv,
- (ws->ws_wordc + 1) * sizeof (ws->ws_wordv[0]));
- if (!p)
- return -1;
- *wordv = p;
- *wordc = ws->ws_wordc;
-
- ws->ws_wordv = NULL;
- ws->ws_wordc = 0;
- ws->ws_wordn = 0;
-
- return 0;
-}
-
-const char *_mu_wordsplit_errstr[] = {
- N_("no error"),
- N_("missing closing quote"),
- N_("memory exhausted"),
- N_("invalid wordsplit usage"),
- N_("unbalanced curly brace"),
- N_("undefined variable"),
- N_("input exhausted"),
- N_("unbalanced parenthesis"),
- N_("globbing error")
-};
-int _mu_wordsplit_nerrs =
- sizeof (_mu_wordsplit_errstr) / sizeof (_mu_wordsplit_errstr[0]);
-
-const char *
-mu_wordsplit_strerror (struct mu_wordsplit *ws)
-{
- if (ws->ws_errno == MU_WRDSE_USERERR)
- return ws->ws_usererr;
- if (ws->ws_errno < _mu_wordsplit_nerrs)
- return _mu_wordsplit_errstr[ws->ws_errno];
- return N_("unknown error");
-}
-
-void
-mu_wordsplit_perror (struct mu_wordsplit *wsp)
-{
- switch (wsp->ws_errno)
- {
- case MU_WRDSE_QUOTE:
- wsp->ws_error (_("missing closing %c (start near #%lu)"),
- wsp->ws_input[wsp->ws_endp],
- (unsigned long) wsp->ws_endp);
- break;
-
- default:
- wsp->ws_error ("%s", mu_wordsplit_strerror (wsp));
- }
-}
-
+#include "wordsplit/wordsplit.c"
diff --git a/libmailutils/tests/.gitignore b/libmailutils/tests/.gitignore
index d72fd78..3045b18 100644
--- a/libmailutils/tests/.gitignore
+++ b/libmailutils/tests/.gitignore
@@ -45,5 +45,6 @@ url-parse
vexp
wicket
wordwrap
+wordsplit-version.h
wsp
xscript
diff --git a/libmailutils/tests/Makefile.am b/libmailutils/tests/Makefile.am
index 99b2341..bc839c3 100644
--- a/libmailutils/tests/Makefile.am
+++ b/libmailutils/tests/Makefile.am
@@ -38,7 +38,7 @@ $(srcdir)/package.m4: $(top_srcdir)/configure.ac
## Non-installable programs
## -------------------------- ##
-AM_CPPFLAGS = @MU_LIB_COMMON_INCLUDES@
+AM_CPPFLAGS = @MU_LIB_COMMON_INCLUDES@
noinst_LTLIBRARIES = libmu_tesh.la
libmu_tesh_la_SOURCES = tesh.c tesh.h
@@ -193,7 +193,6 @@ TESTSUITE_AT = \
url-comp.at\
xml.at\
wicket.at\
- wordsplit.at\
wordwrap00.at\
wordwrap01.at\
wordwrap02.at\
@@ -205,7 +204,11 @@ M4=m4
AUTOTEST = $(AUTOM4TE) --language=autotest
$(TESTSUITE): package.m4 $(TESTSUITE_AT) $(top_srcdir)/testsuite/testsuite.inc
- $(AM_V_GEN)$(AUTOTEST) -I $(srcdir) -I $(top_srcdir)/testsuite testsuite.at -o $@.tmp
+ $(AM_V_GEN)$(AUTOTEST) \
+ -I $(srcdir)\
+ -I $(top_srcdir)/testsuite\
+ -I $(top_srcdir)/libmailutils/wordsplit\
+ testsuite.at -o $@.tmp
$(AM_V_at)mv $@.tmp $@
atconfig: $(top_builddir)/config.status
@@ -214,11 +217,35 @@ atconfig: $(top_builddir)/config.status
clean-local:
@test ! -f $(TESTSUITE) || $(SHELL) $(TESTSUITE) --clean
-check-local: atconfig atlocal $(TESTSUITE)
+check-local: atconfig atlocal $(TESTSUITE)
@$(SHELL) $(TESTSUITE)
# Run the test suite on the *installed* tree.
#installcheck-local:
# $(SHELL) $(TESTSUITE) AUTOTEST_PATH=$(exec_prefix)/bin
+# ###########################
+# Wordsplit testsuite
+# ###########################
+
+# The wordsplit-version.h header is to supply the version string to
+# wsp and to force it to use the mailutils version of the wordsplit.h
+# header.
+EXTRA_DIST += wordsplit-version.h
+$(srcdir)/wordsplit-version.h: $(top_srcdir)/configure.ac
+ $(AM_V_GEN){\
+ if test -e $(top_srcdir)/libmailutils/wordsplit/.git; then \
+ wsversion=$$(cd $(top_srcdir)/libmailutils/wordsplit; git describe); \
+ else \
+ wsversion="unknown"; \
+ fi;\
+ echo "#define WORDSPLIT_VERSION \"$wsversion\"";\
+ echo '#include <mailutils/wordsplit.h>'; } \
+ > $(srcdir)/wordsplit-version.h
+
+noinst_PROGRAMS += wsp
+wsp_SOURCES =
+nodist_wsp_SOURCES = wsp.c
+wsp.o: $(srcdir)/wordsplit-version.h
+VPATH += $(top_srcdir)/libmailutils/wordsplit
diff --git a/libmailutils/tests/wordsplit.at b/libmailutils/tests/wordsplit.at
deleted file mode 100644
index f695399..0000000
--- a/libmailutils/tests/wordsplit.at
+++ b/dev/null
@@ -1,787 +0,0 @@
-# This file is part of GNU Mailutils. -*- Autotest -*-
-# Copyright (C) 2007-2019 Free Software Foundation, Inc.
-#
-# GNU Mailutils 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, or (at
-# your option) any later version.
-#
-# GNU Mailutils 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 GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
-
-AT_BANNER(Wordsplit)
-
-m4_pushdef([wspnum],[0])
-m4_pushdef([wspid])
-m4_pushdef([wspgroupnum])
-m4_pushdef([wspgroupname])
-
-m4_pushdef([genkw],[dnl
-m4_define([wspid],m4_format([wordsplit%03d wsp%03d],wspnum))dnl
-m4_if(wspgroupname,,,[m4_define([wspid],wspid[ ]dnl
-m4_format(wspgroupname[ ]wspgroupname[%03d],wspgroupnum))dnl
-m4_define([wspgroupnum],m4_incr(wspgroupnum))])dnl
-m4_define([wspnum],m4_incr(wspnum))dnl
-wspid])
-
-m4_pushdef([WSPGROUP],[
-m4_define([wspgroupname],$1)
-m4_define([wspgroupnum],0)])
-
-dnl ------------------------------------------------------------
-dnl TESTWSP([NAME], [KW = `'], [OPTS], [INPUT], [STDOUT = `'],
-dnl [STDERR = `'], [ENV])
-dnl
-m4_pushdef([TESTWSP],[
-m4_pushdef([MU_TEST_GROUP],[Wordsplit])
-m4_pushdef([MU_TEST_KEYWORDS],[wordsplit wsp])
-m4_pushdef([MU_TEST_COMMAND],[$7 wsp $3])
-MU_GENERIC_TEST([$1],[genkw $2],[$4],[],[$5],[$6])
-m4_popdef([MU_TEST_COMMAND])
-m4_popdef([MU_TEST_KEYWORDS])
-m4_popdef([MU_TEST_GROUP])
-])
-
-dnl ------------------------------------------------------------
-dnl The first part reproduces legacy argcv tests
-dnl ------------------------------------------------------------
-
-TESTWSP([simple input],[],[],
-[1 2 3],
-[NF: 3
-0: 1
-1: 2
-2: 3
-])
-
-TESTWSP([quoted space],[],[],
-[quoted\ space],
-[NF: 1
-0: "quoted space"
-])
-
-TESTWSP([tab character],[],[],
-[a "tab character"],
-[NF: 2
-0: a
-1: tab\tcharacter
-])
-
-WSPGROUP(wsp-escape)
-
-TESTWSP([octal and hex escapes],[],[],
-[\157\143\164\141\154\40and\x20\x68\x65\x78],
-[NF: 1
-0: "octal and hex"
-])
-
-TESTWSP([octal and hex escapes 2],[],[],
-[\157\143\164\141\154\40 and \x20\x68\x65\x78],
-[NF: 3
-0: "octal "
-1: and
-2: " hex"
-])
-
-TESTWSP([escape representation],[],[],
-[A\x3-\48\39],
-[NF: 1
-0: A\003-\0048\0039
-])
-
-WSPGROUP()
-
-dnl ------------------------------------------------------------
-dnl Test worsplit-specific behavior
-dnl ------------------------------------------------------------
-TESTWSP([append],[],[append],
-[jeden dwa trzy
-cztery
-piec szesc],
-[NF: 3
-0: jeden
-1: dwa
-2: trzy
-NF: 4
-0: jeden
-1: dwa
-2: trzy
-3: cztery
-NF: 6
-0: jeden
-1: dwa
-2: trzy
-3: cztery
-4: piec
-5: szesc
-])
-
-TESTWSP([dooffs],[],[dooffs 3 jeden dwa trzy],
-[cztery piec],
-[NF: 2 (3)
-(0): jeden
-(1): dwa
-(2): trzy
-3: cztery
-4: piec
-])
-
-WSPGROUP(wsp-var)
-
-TESTWSP([variable substitutions: single var],[],[],
-[a $FOO test],
-[NF: 3
-0: a
-1: bar
-2: test
-],
-[],
-[FOO=bar])
-
-TESTWSP([variable substitutions: concatenated vars],[],[],
-[a $FOO${BAR}ent test],
-[NF: 3
-0: a
-1: stringent
-2: test
-],
-[],
-[FOO=str BAR=ing])
-
-TESTWSP([variable substitutions: field splitting],[],[],
-[a $FOO test],
-[NF: 4
-0: a
-1: variable
-2: substitution
-3: test
-],
-[],
-[FOO="variable substitution"])
-
-TESTWSP([variable substitutions: double-quoted variable],[],[],
-[a "$FOO" test],
-[NF: 3
-0: a
-1: "variable substitution"
-2: test
-],
-[],
-[FOO="variable substitution"])
-
-TESTWSP([variable substitutions: single-quoted variable],[],[],
-[a '$FOO' test],
-[NF: 3
-0: a
-1: $FOO
-2: test
-],
-[],
-[FOO="variable substitution"])
-
-TESTWSP([undefined variables 1],[],[],
-[a $FOO test a${FOO}b],
-[NF: 3
-0: a
-1: test
-2: ab
-],
-[],
-[unset FOO;])
-
-TESTWSP([undefined variables 2],[],[keepundef],
-[a $FOO test a${FOO}b],
-[NF: 4
-0: a
-1: $FOO
-2: test
-3: a${FOO}b
-],
-[],
-[unset FOO;])
-
-TESTWSP([warn about undefined variables],[],[warnundef],
-[$FOO],
-[NF: 0
-],
-[warning: undefined variable `FOO'
-],
-[unset FOO;])
-
-TESTWSP([bail out on undefined variables],[],[undef],
-[$FOO],
-[],
-[undefined variable
-],
-[unset FOO;])
-
-TESTWSP([disable variable expansion],[],[novar],
-[$FOO],
-[NF: 1
-0: $FOO
-],
-[],
-[FOO=bar])
-
-TESTWSP([K/V environment],[],[env_kv],
-[$FOO a$BAZ],
-[NF: 2
-0: bar
-1: aqux
-],
-[],
-[FOO=bar BAZ=qux])
-
-TESTWSP([nosplit with expansion],[],[nosplit],
-[a $FOO test],
-[NF: 1
-0: "a variable expansion test\n"
-],
-[],
-[FOO="variable expansion"])
-
-TESTWSP([nosplit without expansion],[],[nosplit novar],
-[a $FOO test],
-[NF: 1
-0: "a $FOO test\n"
-],
-[],
-[FOO="variable expansion"])
-
-TESTWSP([default value (defined)],[],[],
-[${FOO:-bar}],
-[NF: 1
-0: qux
-],
-[],
-[FOO=qux])
-
-TESTWSP([default value],[],[],
-[${FOO:-bar}],
-[NF: 1
-0: bar
-])
-
-TESTWSP([default value (defined)],[],[],
-[${FOO:-bar}],
-[NF: 1
-0: qux
-],
-[],
-[FOO=qux])
-
-TESTWSP([default value (:- null)],[],[],
-[${FOO:-bar}],
-[NF: 1
-0: bar
-],
-[],
-[FOO=])
-
-TESTWSP([default value (- null)],[],[],
-[${FOO-bar}],
-[NF: 0
-],
-[],
-[FOO=])
-
-TESTWSP([default value (- null, unset)],[],[],
-[${FOO-bar}],
-[NF: 1
-0: bar
-])
-
-TESTWSP([assign default values],[],[],
-[${FOO=bar}
-$FOO],
-[NF: 1
-0: bar
-NF: 1
-0: bar
-])
-
-TESTWSP([default error message (var defined)],[],[],
-[a ${FOO:?} test],
-[NF: 3
-0: a
-1: bar
-2: test
-],
-[],
-[FOO=bar])
-
-TESTWSP([default error message],[],[],
-[${FOO:?}],
-[NF: 0
-],
-[FOO: variable null or not set
-])
-
-TESTWSP([custom error message (defined)],[wsp-custom-err wsp-custom-err00],[],
-[a ${FOO:?please define it} test],
-[NF: 3
-0: a
-1: bar
-2: test
-],
-[],
-[FOO=bar])
-
-TESTWSP([custom error message],[wsp-custom-err wsp-custom-err01],[],
-[a ${FOO:?please define it} test],
-[NF: 2
-0: a
-1: test
-],
-[FOO: please define it
-])
-
-TESTWSP([alternate value (defined)],[wsp-alt wsp-alt00],[],
-[a ${FOO:+isset} test],
-[NF: 3
-0: a
-1: isset
-2: test
-],
-[],
-[FOO=bar])
-
-TESTWSP([alternate value],[wsp-alt wsp-alt01],[],
-[a ${FOO:+isset} test],
-[NF: 2
-0: a
-1: test
-],
-[],
-[unset FOO;])
-
-TESTWSP([getvar],[wsp-getvar],
-[foo=bar x=quux],
-[begin $foo $x end],
-[NF: 4
-0: begin
-1: bar
-2: quux
-3: end
-],
-[],
-[],
-[unset foo; unset x])
-
-TESTWSP([getvar and env],[wsp-getvar],
-[foo=bar x=quux y=xur],
-[begin $foo $TVAR $x $y end],
-[NF: 6
-0: begin
-1: bar
-2: 12
-3: quux
-4: zwar
-5: end
-],
-[],
-[TVAR=12 y=zwar],
-[unset foo; unset x])
-
-TESTWSP([getvar, alternate value],[wsp-getvar],
-[foo=bar],
-[a ${foo:+isset}],
-[NF: 2
-0: a
-1: isset
-])
-
-WSPGROUP()
-
-TESTWSP([ignore quotes],[],[-quote],
-["a text"],
-[NF: 2
-0: "\"a"
-1: "text\""
-])
-
-WSPGROUP(wsp-delim)
-
-TESTWSP([custom delimiters (squeeze)],[],[delim : -ws trimnl],
-[semicolon: separated::list: of :words],
-[NF: 5
-0: semicolon
-1: " separated"
-2: list
-3: " of "
-4: words
-])
-
-TESTWSP([custom delimiters (no squeeze)],[],[delim : -ws -squeeze_delims trimnl],
-[semicolon: separated::list: of :words],
-[NF: 6
-0: semicolon
-1: " separated"
-2: ""
-3: list
-4: " of "
-5: words
-])
-
-TESTWSP([custom, with returned delimiters],[],[delim : -ws trimnl return_delims],
-[semicolon: separated::list: of :words],
-[NF: 9
-0: semicolon
-1: :
-2: " separated"
-3: :
-4: list
-5: :
-6: " of "
-7: :
-8: words
-])
-
-TESTWSP([custom, with returned & squeezed delimiters],[],[delim : -ws trimnl return_delims -squeeze_delims],
-[semicolon: separated::list: of :words],
-[NF: 10
-0: semicolon
-1: :
-2: " separated"
-3: :
-4: :
-5: list
-6: :
-7: " of "
-8: :
-9: words
-])
-
-WSPGROUP(wsp-sed)
-
-TESTWSP([sed expressions],[],[sed],
-[arg1 s/foo/bar/g;s/bar baz/quz quux/ arg2],
-[NF: 3
-0: arg1
-1: "s/foo/bar/g;s/bar baz/quz quux/"
-2: arg2
-])
-
-WSPGROUP()
-
-TESTWSP([C escapes on],[],[cescapes],
-[a\ttab form\ffeed and new\nline],
-[NF: 4
-0: a\ttab
-1: form\ffeed
-2: and
-3: new\nline
-])
-
-TESTWSP([C escapes off],[],[-cescapes],
-[a\ttab form\ffeed and new\nline],
-[NF: 4
-0: attab
-1: formffeed
-2: and
-3: newnline
-])
-
-TESTWSP([ws elimination],[],[delim ' ()' ws return_delims],
-[( list items )],
-[NF: 4
-0: (
-1: list
-2: items
-3: )
-])
-
-TESTWSP([empty quotes],[],[delim : ws return_delims],
-[t=""],
-[NF: 1
-0: t=
-])
-
-TESTWSP([delimiter following empty quotes],[],[delim : ws return_delims],
-[t="":r],
-[NF: 3
-0: t=
-1: :
-2: r
-])
-
-TESTWSP([suppress ws trimming within quotes],[],
-[default delim , ws return_delims],
-[nocomponent,nonewline, formatfield="In message %{text}, "],
-[NF: 5
-0: nocomponent
-1: ,
-2: nonewline
-3: ,
-4: "formatfield=In message %{text}, "
-])
-
-TESTWSP([unescape],[],[-default novar nocmd quote escape :+:'\\""'],
-[\Seen "quote \"" "bs \\"],
-[NF: 3
-0: \\Seen
-1: "quote \""
-2: "bs \\"
-])
-
-TESTWSP([unescape: word/quote],
-[wsp-unescape wsp-unescape-word],
-[-default novar nocmd quote escape-word '\\""' escape-quote ':+0x:\\""'],
-[\Seen "quote \"" "bs \\" "3\x31 \101" 3\x31 \101],
-[NF: 6
-0: Seen
-1: "quote \""
-2: "bs \\"
-3: "31 A"
-4: 3x31
-5: 101
-])
-
-TESTWSP([dquote],[],[-default novar nocmd dquote],
-[a "quoted example" isn't it],
-[NF: 4
-0: a
-1: "quoted example"
-2: isn't
-3: it
-])
-
-TESTWSP([squote],[],[-default novar nocmd squote],
-[a 'quoted example' isn"t it],
-[NF: 4
-0: a
-1: "quoted example"
-2: "isn\"t"
-3: it
-])
-
-WSPGROUP(wsp-incr)
-
-TESTWSP([incremental],[],[incremental],
-[incremental "input test" line
-
-
-],
-[NF: 1
-0: incremental
-NF: 1
-0: "input test"
-NF: 1
-0: line
-],
-[input exhausted
-])
-
-TESTWSP([incremental append],[],[incremental append],
-[incremental "input test" line
-
-
-],
-[NF: 1
-0: incremental
-NF: 2
-0: incremental
-1: "input test"
-NF: 3
-0: incremental
-1: "input test"
-2: line
-],
-[input exhausted
-])
-
-TESTWSP([incremental ws],[],[return_delims -squeeze_delims incremental ws],
-[a list test
-
-
-],
-[NF: 1
-0: a
-NF: 1
-0: list
-NF: 1
-0: test
-],
-[input exhausted
-])
-
-TESTWSP([incremental nosplit],[],[incremental nosplit],
-[incremental "input test" line
-],
-[NF: 1
-0: "incremental \"input test\" line"
-],
-[input exhausted
-])
-
-TESTWSP([simple command substitution],[],[-nocmd],
-[begin $(words a b) end],
-[NF: 4
-0: begin
-1: a
-2: b
-3: end
-])
-
-TESTWSP([quoted command substitution],[],[-nocmd],
-[begin "$(words a b)" end],
-[NF: 3
-0: begin
-1: "a b"
-2: end
-])
-
-TESTWSP([coalesced command substitution],[],[-nocmd],
-[begin($(words a b))end],
-[NF: 2
-0: begin(a
-1: b)end
-])
-
-TESTWSP([quoted coalesced command substitution],[],[-nocmd],
-["begin($(words a b))end"],
-[NF: 1
-0: "begin(a b)end"
-])
-
-TESTWSP([variable and command substitution],[],[-nocmd -novar],
-[begin $X $(words $X $Y) end],
-[NF: 5
-0: begin
-1: a
-2: a
-3: b
-4: end
-],[],[X=a Y=b])
-
-TESTWSP([variable expansion and command substitution in quotes],[],[-nocmd -novar],
-["${BEGIN}($(words $X $Y))end"],
-[NF: 1
-0: "begin(a b)end"
-],[],[X=a Y=b BEGIN=begin])
-
-TESTWSP([nested commands],[],[-nocmd -novar],
-[$(words output $(words in$SUFFIX text) end)],
-[NF: 4
-0: output
-1: input
-2: text
-3: end
-],[],[SUFFIX=put])
-
-dnl Something that doesn't fit into TESTWSP
-
-AT_SETUP([pathname expansion])
-AT_KEYWORDS([wordsplit wsp wsp-path wsp-path-1])
-AT_CHECK([
-mkdir dir
-> dir/1.c
-> dir/2.c
-> dir/3.b
-
-wsp pathexpand<<'EOT'
-begin dir/*.c end
-EOT
-],
-[0],
-[NF: 4
-0: begin
-1: dir/1.c
-2: dir/2.c
-3: end
-])
-AT_CLEANUP
-
-AT_SETUP([pathname expansion: no match])
-AT_KEYWORDS([wordsplit wsp wsp-path wsp-path-2])
-AT_CHECK([
-mkdir dir
-> dir/1.c
-> dir/2.b
-
-wsp pathexpand<<'EOT'
-begin dir/*.d end
-EOT
-],
-[0],
-[NF: 3
-0: begin
-1: dir/*.d
-2: end
-])
-AT_CLEANUP
-
-AT_SETUP([pathname expansion: nullglob])
-AT_KEYWORDS([wordsplit wsp wsp-path wsp-path-3])
-AT_CHECK([
-mkdir dir
-> dir/1.c
-> dir/2.b
-
-wsp pathexpand nullglob<<'EOT'
-begin dir/*.d end
-EOT
-],
-[0],
-[NF: 2
-0: begin
-1: end
-])
-AT_CLEANUP
-
-AT_SETUP([pathname expansion: failglob])
-AT_KEYWORDS([wordsplit wsp wsp-path wsp-path-4])
-AT_CHECK([
-mkdir dir
-> dir/1.c
-> dir/2.b
-
-wsp pathexpand failglob<<'EOT'
-begin dir/*.d end
-EOT
-],
-[0],
-[],
-[no files match pattern dir/*.d
-])
-AT_CLEANUP
-
-TESTWSP([append],[],[-- extra arguments follow],
-[some words and],
-[NF: 6
-0: some
-1: words
-2: and
-3: extra
-4: arguments
-5: follow
-])
-
-TESTWSP([append + dooffs + env],[],
-[dooffs 2 preface words V=2 -- extra arguments follow],
-[some words and var=$V],
-[NF: 7 (2)
-(0): preface
-(1): words
-2: some
-3: words
-4: and
-5: var=2
-6: extra
-7: arguments
-8: follow
-])
-
-
-m4_popdef([TESTWSP])
-m4_popdef([wspnum])
-m4_popdef([wspid])
-m4_popdef([genkw])
-m4_popdef([wspgroupnum])
-m4_popdef([wspgroupname])
-m4_popdef([WSPGROUP])
diff --git a/libmailutils/tests/wsp.c b/libmailutils/tests/wsp.c
deleted file mode 100644
index cd158dc..0000000
--- a/libmailutils/tests/wsp.c
+++ b/dev/null
@@ -1,654 +0,0 @@
-/* GNU Mailutils -- a suite of utilities for electronic mail
- Copyright (C) 2005-2019 Free Software Foundation, Inc.
-
- GNU Mailutils 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, or (at your option)
- any later version.
-
- GNU Mailutils 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 GNU Mailutils. 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 <mailutils/wordsplit.h>
-#include <mailutils/alloc.h>
-#include <mailutils/kwd.h>
-#include <mailutils/errno.h>
-#include <mailutils/error.h>
-#include <mailutils/cstr.h>
-#include <mailutils/io.h>
-
-extern char **environ;
-
-char *progname;
-
-struct mu_kwd bool_keytab[] = {
- { "append", MU_WRDSF_APPEND },
- /*{ "reuse", MU_WRDSF_REUSE },*/
- { "undef", MU_WRDSF_UNDEF },
- { "novar", MU_WRDSF_NOVAR },
- { "nocmd", MU_WRDSF_NOCMD },
- { "ws", MU_WRDSF_WS },
- { "quote", MU_WRDSF_QUOTE },
- { "squote", MU_WRDSF_SQUOTE },
- { "dquote", MU_WRDSF_DQUOTE },
- { "squeeze_delims", MU_WRDSF_SQUEEZE_DELIMS },
- { "return_delims", MU_WRDSF_RETURN_DELIMS },
- { "sed", MU_WRDSF_SED_EXPR },
- { "debug", MU_WRDSF_SHOWDBG },
- { "nosplit", MU_WRDSF_NOSPLIT },
- { "keepundef", MU_WRDSF_KEEPUNDEF },
- { "warnundef", MU_WRDSF_WARNUNDEF },
- { "cescapes", MU_WRDSF_CESCAPES },
- { "default", MU_WRDSF_DEFFLAGS },
- { "env_kv", MU_WRDSF_ENV_KV },
- { "incremental", MU_WRDSF_INCREMENTAL },
- { "pathexpand", MU_WRDSF_PATHEXPAND },
- { NULL, 0 }
-};
-
-struct mu_kwd opt_keytab[] = {
- { "nullglob", MU_WRDSO_NULLGLOB },
- { "failglob", MU_WRDSO_FAILGLOB },
- { "dotglob", MU_WRDSO_DOTGLOB },
- { NULL, 0 }
-};
-
-struct mu_kwd string_keytab[] = {
- { "delim", MU_WRDSF_DELIM },
- { "comment", MU_WRDSF_COMMENT },
- { "escape", MU_WRDSF_ESCAPE },
- { NULL, 0 }
-};
-
-static void
-help ()
-{
- size_t i;
-
- printf ("usage: %s [options] [VAR=VALUE...] [-- EXTRA...]\n", progname);
- printf ("options are:\n");
- printf (" [-]trimnl\n");
- printf (" [-]plaintext\n");
- printf (" -env\n");
- printf (" env sys|none|null\n");
- putchar ('\n');
- for (i = 0; bool_keytab[i].name; i++)
- printf (" [-]%s\n", bool_keytab[i].name);
- putchar ('\n');
- for (i = 0; string_keytab[i].name; i++)
- {
- printf (" -%s\n", string_keytab[i].name);
- printf (" %s ARG\n", string_keytab[i].name);
- }
- printf (" escape-word ARG\n");
- printf (" escape-quote ARG\n");
- putchar ('\n');
- for (i = 0; opt_keytab[i].name; i++)
- {
- printf (" [-]%s\n", opt_keytab[i].name);
- }
- putchar ('\n');
- printf (" -dooffs\n");
- printf (" dooffs COUNT ARGS...\n");
- exit (0);
-}
-
-void
-print_qword (const char *word, int plaintext)
-{
- static char *qbuf = NULL;
- static size_t qlen = 0;
- int quote;
- size_t size = mu_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 = mu_realloc (qbuf, qlen);
- }
- mu_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 = mu_calloc (size, sizeof (newenv[0]));
-
- for (i = j = 0; environ[i]; i++)
- {
- size_t len = strcspn (environ[i], "=");
- char *p = mu_alloc (len+1);
- memcpy (p, environ[i], len);
- p[len] = 0;
- newenv[j++] = p;
- p = mu_strdup (environ[i] + len + 1);
- 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 MU_WRDSE_NOSPACE;
- *ret = p;
- return MU_WRDSE_OK;
- }
- }
- return MU_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 MU_WRDSE_NOSPACE;
- memcpy (*ret, str + alen, len);
- (*ret)[len] = 0;
- return MU_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 MU_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 MU_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 MU_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 MU_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;
-
- 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 (mu_asprintf (ret, "unknown command: %s", argv[0]))
- return MU_WRDSE_NOSPACE;
- else
- return MU_WRDSE_USERERR;
-}
-
-enum env_type
- {
- env_none,
- env_null,
- env_sys
- };
-
-struct mu_kwd env_keytab[] = {
- { "none", env_none },
- { "null", env_null },
- { "sys", env_sys },
- { NULL }
-};
-
-static void
-set_escape_string (mu_wordsplit_t *ws, int *wsflags, int q, const char *str)
-{
- if (*str == ':')
- {
- while (*++str != ':')
- {
- int f;
- switch (*str)
- {
- case '+':
- f = MU_WRDSO_BSKEEP;
- break;
-
- case '0':
- f = MU_WRDSO_OESC;
- break;
-
- case 'x':
- f = MU_WRDSO_XESC;
- break;
-
- default:
- fprintf (stderr, "%s: invalid escape flag near %s\n",
- progname, str);
- abort ();
- }
- MU_WRDSO_ESC_SET (ws, q, f);
- }
- *wsflags |= MU_WRDSF_OPTIONS;
- ++str;
- }
- ws->ws_escape[q] = str;
-}
-
-int
-main (int argc, char **argv)
-{
- char buf[1024], *ptr, *saved_ptr;
- int i, offarg = 0;
- int trimnl_option = 0;
- int plaintext_option = 0;
- int wsflags = (MU_WRDSF_DEFFLAGS & ~MU_WRDSF_NOVAR) |
- MU_WRDSF_ENOMEMABRT |
- MU_WRDSF_SHOWERR;
- mu_wordsplit_t ws;
- int next_call = 0;
- char *fenvbase[128];
- size_t fenvidx = 0;
- size_t fenvmax = sizeof (fenvbase) / sizeof (fenvbase[0]);
- int use_env = env_sys;
- int appendc = 0;
- char **appendv = NULL;
-
- progname = argv[0];
-
- ws.ws_options = 0;
- for (i = 1; i < argc; i++)
- {
- char *opt = argv[i];
- int negate;
- int flag;
-
- if (opt[0] == '-')
- {
- if (opt[1] == '-' && opt[2] == 0)
- {
- appendc = argc - i - 1;
- appendv = argv + i + 1;
- break;
- }
- negate = 1;
- opt++;
- }
- else if (opt[0] == '+')
- {
- negate = 0;
- opt++;
- }
- else
- negate = 0;
-
- if (strcmp (opt, "h") == 0 ||
- strcmp (opt, "help") == 0 ||
- strcmp (opt, "-help") == 0)
- {
- help ();
- }
-
- if (strcmp (opt, "trimnl") == 0)
- {
- trimnl_option = !negate;
- continue;
- }
-
- if (strcmp (opt, "plaintext") == 0)
- {
- plaintext_option = !negate;
- continue;
- }
-
- if (strcmp (opt, "env") == 0)
- {
- if (negate)
- use_env = env_none;
- else
- {
- i++;
- if (i == argc)
- {
- fprintf (stderr, "%s: missing argument for env\n",
- progname);
- exit (1);
- }
-
- if (mu_kwd_xlat_name (env_keytab, argv[i], &use_env))
- {
- fprintf (stderr, "%s: invalid argument for env\n",
- progname);
- exit (1);
- }
- }
- continue;
- }
-
- if (mu_kwd_xlat_name (bool_keytab, opt, &flag) == 0)
- {
- if (negate)
- wsflags &= ~flag;
- else
- wsflags |= flag;
- continue;
- }
-
- if (mu_kwd_xlat_name (string_keytab, opt, &flag) == 0)
- {
- if (negate)
- wsflags &= ~flag;
- else
- {
- i++;
- if (i == argc)
- {
- fprintf (stderr, "%s: missing argument for %s\n",
- progname, opt);
- exit (1);
- }
-
- switch (flag)
- {
- case MU_WRDSF_DELIM:
- ws.ws_delim = argv[i];
- break;
-
- case MU_WRDSF_COMMENT:
- ws.ws_comment = argv[i];
- break;
-
- case MU_WRDSF_ESCAPE:
- set_escape_string (&ws, &wsflags, 0, argv[i]);
- set_escape_string (&ws, &wsflags, 1, argv[i]);
- break;
- }
-
- wsflags |= flag;
- }
- continue;
- }
-
- if (strcmp (opt, "escape-word") == 0
- || strcmp (opt, "escape-quote") == 0)
- {
- int q = opt[7] == 'q';
-
- i++;
- if (i == argc)
- {
- fprintf (stderr, "%s: missing argument for %s\n",
- progname, opt);
- exit (1);
- }
- if (!(wsflags & MU_WRDSF_ESCAPE))
- {
- wsflags |= MU_WRDSF_ESCAPE;
- ws.ws_escape[!q] = NULL;
- }
- set_escape_string (&ws, &wsflags, q, argv[i]);
- continue;
- }
-
- if (strcmp (opt, "dooffs") == 0)
- {
- if (negate)
- wsflags &= ~MU_WRDSF_DOOFFS;
- else
- {
- char *p;
-
- i++;
-
- if (i == argc)
- {
- fprintf (stderr, "%s: missing arguments for %s\n",
- progname, opt);
- exit (1);
- }
- ws.ws_offs = strtoul (argv[i], &p, 10);
- if (*p)
- {
- fprintf (stderr, "%s: invalid number: %s\n",
- progname, argv[i]);
- exit (1);
- }
-
- i++;
- if (i + ws.ws_offs > argc)
- {
- fprintf (stderr, "%s: not enough arguments for %s\n",
- progname, opt);
- exit (1);
- }
- offarg = i;
- i += ws.ws_offs - 1;
- wsflags |= MU_WRDSF_DOOFFS;
- }
- continue;
- }
-
- if (mu_kwd_xlat_name (opt_keytab, opt, &flag) == 0)
- {
- wsflags |= MU_WRDSF_OPTIONS;
- if (negate)
- ws.ws_options &= ~flag;
- else
- ws.ws_options |= flag;
- continue;
- }
-
- if (strchr (opt, '='))
- {
- if (fenvidx < fenvmax - 1)
- {
- fenvbase[fenvidx++] = opt;
- continue;
- }
- else
- {
- fprintf (stderr, "%s: environment too big\n", progname);
- exit (1);
- }
- }
-
- fprintf (stderr, "%s: unrecognized argument: %s\n",
- progname, opt);
- exit (1);
- }
-
- if (fenvidx)
- {
- fenvbase[fenvidx] = NULL;
- wsflags |= MU_WRDSF_GETVAR | MU_WRDSF_CLOSURE;
- ws.ws_getvar = wsp_getvar;
- ws.ws_closure = fenvbase;
- }
-
- switch (use_env)
- {
- case env_null:
- wsflags |= MU_WRDSF_ENV;
- ws.ws_env = NULL;
- break;
-
- case env_none:
- break;
-
- case env_sys:
- wsflags |= MU_WRDSF_ENV;
- if (wsflags & MU_WRDSF_ENV_KV)
- ws.ws_env = (const char **) make_env_kv ();
- else
- ws.ws_env = (const char **) environ;
- break;
- }
-
- if (!(wsflags & MU_WRDSF_NOCMD))
- ws.ws_command = wsp_runcmd;
-
- if (wsflags & MU_WRDSF_INCREMENTAL)
- trimnl_option = 1;
-
- next_call = 0;
- while ((ptr = fgets (buf, sizeof (buf), stdin)))
- {
- int rc;
- size_t i;
-
- if (trimnl_option)
- {
- size_t len = strlen (ptr);
- if (len && ptr[len-1] == '\n')
- ptr[len-1] = 0;
- }
-
- if (wsflags & MU_WRDSF_INCREMENTAL)
- {
- if (next_call)
- {
- if (*ptr == 0)
- ptr = NULL;
- else
- free (saved_ptr);
- }
- else
- next_call = 1;
- if (ptr)
- ptr = saved_ptr = mu_strdup (ptr);
- }
-
- rc = mu_wordsplit (ptr, &ws, wsflags);
- if (rc)
- {
- if (!(wsflags & MU_WRDSF_SHOWERR))
- mu_wordsplit_perror (&ws);
- continue;
- }
-
- if (offarg)
- {
- for (i = 0; i < ws.ws_offs; i++)
- ws.ws_wordv[i] = argv[offarg + i];
- offarg = 0;
- }
-
- if (appendc)
- {
- rc = mu_wordsplit_append (&ws, appendc, appendv);
- if (rc)
- {
- if (!(wsflags & MU_WRDSF_SHOWERR))
- mu_wordsplit_perror (&ws);
- continue;
- }
- }
-
- wsflags |= MU_WRDSF_REUSE | (ws.ws_flags & MU_WRDSF_ENV);
- printf ("NF: %lu", (unsigned long) ws.ws_wordc);
- if (wsflags & MU_WRDSF_DOOFFS)
- printf (" (%lu)", (unsigned long) ws.ws_offs);
- putchar ('\n');
- for (i = 0; i < ws.ws_offs; i++)
- {
- printf ("(%lu): ", (unsigned long) i);
- print_qword (ws.ws_wordv[i], plaintext_option);
- putchar ('\n');
- }
- for (; i < ws.ws_offs + ws.ws_wordc; i++)
- {
- printf ("%lu: ", (unsigned long) i);
- print_qword (ws.ws_wordv[i], plaintext_option);
- putchar ('\n');
- }
- }
- return 0;
-}
diff --git a/libmailutils/wordsplit b/libmailutils/wordsplit
new file mode 160000
+Subproject 6a7581f2e60a600a4915e4f55b74a15c8070197

Return to:

Send suggestions and report system problems to the System administrator.