diff options
-rw-r--r-- | .gitmodules | 3 | ||||
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | configure.ac | 4 | ||||
-rw-r--r-- | include/mailutils/sys/Makefile.am | 3 | ||||
l--------- | include/mailutils/sys/wordsplit.h | 1 | ||||
-rw-r--r-- | include/mailutils/wordsplit.h | 358 | ||||
-rw-r--r-- | libmailutils/Makefile.am | 6 | ||||
-rw-r--r-- | libmailutils/string/Makefile.am | 6 | ||||
-rw-r--r-- | libmailutils/string/wordsplit.c | 2382 | ||||
-rw-r--r-- | libmailutils/tests/.gitignore | 1 | ||||
-rw-r--r-- | libmailutils/tests/Makefile.am | 35 | ||||
-rw-r--r-- | libmailutils/tests/wordsplit.at | 787 | ||||
-rw-r--r-- | libmailutils/tests/wsp.c | 654 | ||||
m--------- | libmailutils/wordsplit | 0 |
14 files changed, 164 insertions, 4078 deletions
diff --git a/.gitmodules b/.gitmodules index bdc2cb048..142e50cfd 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 @@ -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 eb1436173..c841acfbf 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 7f31291a2..321c5f134 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 000000000..5c46e03d2 --- /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 d5631ddba..203d92458 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 422d2c154..71bcda298 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 5cdd73913..24557717a 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 1f9b32a66..dc3a04df8 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; |