aboutsummaryrefslogtreecommitdiff
path: root/gconf/wordsplit.c
diff options
context:
space:
mode:
Diffstat (limited to 'gconf/wordsplit.c')
-rw-r--r--gconf/wordsplit.c568
1 files changed, 0 insertions, 568 deletions
diff --git a/gconf/wordsplit.c b/gconf/wordsplit.c
deleted file mode 100644
index a5bb13e..0000000
--- a/gconf/wordsplit.c
+++ /dev/null
@@ -1,568 +0,0 @@
-/* wordsplit - a word splitter
- Copyright (C) 2009 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/>. */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <ctype.h>
-#include <c-ctype.h>
-#include <errno.h>
-#include <unistd.h>
-#include <string.h>
-#include <wordsplit.h>
-
-#include <error.h>
-#include <gettext.h>
-#define _(msgid) gettext (msgid)
-#include <xalloc.h>
-
-#define isws(c) ((c)==' '||(c)=='\t'||(c)=='\n')
-#define isdelim(c,delim) (strchr(delim,(c))!=NULL)
-
-#define _ARGCV_WORD_SED_EXPR 0x10000
-#define _ARGCV_WORD_MASK 0xf0000
-
-#define ALLOC_INIT 128
-#define ALLOC_INCR 128
-
-static int
-wordsplit_init (struct wordsplit *wsp, const char *input, size_t len,
- int flags)
-{
- wsp->ws_flags = flags;
- if ((wsp->ws_flags & (WRDSF_NOVAR|WRDSF_NOCMD))
- != (WRDSF_NOVAR|WRDSF_NOCMD))
- {
- if (wsp->ws_flags & WRDSF_SHOWERR)
- error (0, 0,
- _("variable expansion and command substitution "
- "are not yet supported"));
- errno = EINVAL;
- return 1;
- }
-
- wsp->ws_input = input;
- wsp->ws_len = len;
-
- if (!(wsp->ws_flags & WRDSF_DOOFFS))
- wsp->ws_offs = 0;
-
- if (!(wsp->ws_flags & WRDSF_DELIM))
- wsp->ws_delim = " ";
-
- if (!(wsp->ws_flags & WRDSF_COMMENT))
- wsp->ws_comment = NULL;
-
- if (wsp->ws_flags & WRDSF_REUSE)
- {
- wsp->ws_wordn = wsp->ws_wordc + 1;
- if (wsp->ws_flags & WRDSF_DOOFFS)
- wsp->ws_wordn += wsp->ws_offs;
- if (!(wsp->ws_flags & WRDSF_APPEND))
- wsp->ws_wordc = 0;
- }
- else
- {
- wsp->ws_wordv = NULL;
- wsp->ws_wordc = 0;
- wsp->ws_wordn = 0;
- }
-
- wsp->ws_endp = 0;
- return 0;
-}
-
-static int
-alloc_space (struct wordsplit *wsp)
-{
- size_t offs = (wsp->ws_flags & WRDSF_DOOFFS) ? wsp->ws_offs : 0;
- char **ptr;
- size_t newalloc;
-
- if (wsp->ws_wordv == NULL)
- {
- newalloc = offs + ALLOC_INIT;
- ptr = calloc (newalloc, sizeof (ptr[0]));
- }
- else if (wsp->ws_wordn < offs + wsp->ws_wordc + 1)
- {
- newalloc = offs + wsp->ws_wordc + 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
- {
- if (wsp->ws_flags & WRDSF_ENOMEMABRT)
- xalloc_die ();
- else if (wsp->ws_flags & WRDSF_SHOWERR)
- error (0, 0, _("memory exhausted"));
- errno = ENOMEM;
- return 1;
- }
- 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 && c_ispunct(command[i+1])))
- break;
-
- delim = command[++i];
- state = 1;
- for (i++; i < len; i++)
- {
- if (state == 3)
- {
- if (command[i] == delim || !c_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 wordsplit *wsp)
-{
- size_t start = wsp->ws_endp;
- if (wsp->ws_flags & WRDSF_SQUEEZE_DELIMS)
- {
- do
- start++;
- while (start < wsp->ws_len
- && isdelim (wsp->ws_input[start], wsp->ws_delim));
- start--;
- }
-
- if (!(wsp->ws_flags & WRDSF_RETURN_DELIMS))
- start++;
-
- return start;
-}
-
-#define _WRDS_WORD 1
-#define _WRDS_CONT 2
-
-static int
-scan_word (struct wordsplit *wsp, size_t *pstart, size_t *pend)
-{
- size_t start = *pstart;
- size_t len = wsp->ws_len;
- const char *command = wsp->ws_input;
- const char *delim = wsp->ws_delim;
- const char *comment = wsp->ws_comment;
-
- size_t i = start;
-
- if (i >= len)
- return WRDSE_EOF;
-
- if (wsp->ws_flags & WRDSF_WS)
- {
- /* Skip initial whitespace */
- while (i < len && isws (command[i]))
- i++;
- }
-
- start = i;
-
- wsp->ws_flags &= ~_ARGCV_WORD_MASK;
-
- if (wsp->ws_flags & WRDSF_SED_EXPR
- && command[i] == 's' && i + 3 < len && c_ispunct (command[i+1]))
- {
- wsp->ws_flags |= _ARGCV_WORD_SED_EXPR;
- i = skip_sed_expr (command, i, len);
- }
- else if (!isdelim (command[i], delim))
- {
- while (i < len)
- {
- if (comment && strchr (comment, command[i]) != NULL)
- {
- size_t j;
- for (j = i + 1; j < len && command[j] != '\n'; j++)
- ;
- *pstart = start;
- *pend = i;
- wsp->ws_endp = j;
- return i > start ? _WRDS_WORD : _WRDS_CONT;
- }
-
- if (wsp->ws_flags & WRDSF_QUOTE)
- {
- if (command[i] == '\\')
- {
- if (++i == len)
- break;
- i++;
- continue;
- }
-
- if (command[i] == '\'' || command[i] == '"')
- {
- size_t j;
- for (j = i + 1; j < len && command[j] != command[i]; j++)
- if (command[j] == '\\')
- j++;
- if (j < len && command[j] == command[i])
- i = j + 1;
- else
- {
- wsp->ws_endp = i;
- if (wsp->ws_flags & WRDSF_SHOWERR)
- error (0, 0,
- _("missing closing %c (start near #%lu)"),
- command[i], (unsigned long) i);
- return WRDSE_QUOTE;
- }
- }
- }
-
- if (((wsp->ws_flags & WRDSF_WS) && isws (command[i]))
- || isdelim (command[i], delim))
- break;
- else
- i++;
- }
- }
- else if (wsp->ws_flags & WRDSF_RETURN_DELIMS)
- i++;
-
- *pstart = start;
- *pend = i;
- wsp->ws_endp = i;
-
- return _WRDS_WORD;
-}
-
-static char quote_transtab[] = "\\\\a\ab\bf\fn\nr\rt\tv\v";
-
-int
-wordsplit_unquote_char (int c)
-{
- char *p;
-
- for (p = quote_transtab; *p; p += 2)
- {
- if (*p == c)
- return p[1];
- }
- return c;
-}
-
-int
-wordsplit_quote_char (int c)
-{
- char *p;
-
- for (p = quote_transtab + sizeof(quote_transtab) - 2;
- p > quote_transtab; p -= 2)
- {
- if (*p == c)
- return p[-1];
- }
- return -1;
-}
-
-#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
-wordsplit_quoted_length (const char *str, int quote_hex, int *quote)
-{
- size_t len = 0;
-
- *quote = 0;
- for (; *str; str++)
- {
- if (*str == ' ')
- {
- len++;
- *quote = 1;
- }
- else if (*str == '"')
- {
- len += 2;
- *quote = 1;
- }
- else if (*str != '\t' && *str != '\\' && isprint (*str))
- len++;
- else if (quote_hex)
- len += 3;
- else
- {
- if (wordsplit_quote_char (*str) != -1)
- len += 2;
- else
- len += 4;
- }
- }
- return len;
-}
-
-void
-wordsplit_unquote_copy (char *dst, const char *src, size_t n)
-{
- int i = 0;
- int c;
- int expect_delim = 0;
-
- while (i < n)
- {
- switch (src[i])
- {
- case '\'':
- case '"':
- if (!expect_delim)
- {
- const char *p;
-
- for (p = src+i+1; *p && *p != src[i]; p++)
- if (*p == '\\')
- p++;
- if (*p)
- expect_delim = src[i++];
- else
- *dst++ = src[i++];
- }
- else if (expect_delim == src[i])
- ++i;
- else
- *dst++ = src[i++];
- break;
-
- case '\\':
- ++i;
- if (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 ((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
- *dst++ = wordsplit_unquote_char (src[i++]);
- break;
-
- default:
- *dst++ = src[i++];
- }
- }
- *dst = 0;
-}
-
-void
-wordsplit_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 = wordsplit_quote_char (*src);
- *dst++ = '\\';
- if (c != -1)
- *dst++ = c;
- else
- {
- snprintf (tmp, sizeof tmp, "%03o", *(unsigned char*)src);
- memcpy (dst, tmp, 3);
- dst += 3;
- }
- }
- }
- }
-}
-
-int
-wordsplit_len (const char *command, size_t len, struct wordsplit *wsp,
- int flags)
-{
- int rc;
- size_t start = 0, end = 0;
-
- rc = wordsplit_init (wsp, command, len, flags);
- if (rc)
- return rc;
-
- for (; (rc = scan_word (wsp, &start, &end)) > 0; start = skip_delim (wsp))
- {
- int unquote = 1;
- size_t n;
- char *p;
-
- if (rc == _WRDS_CONT)
- continue;
-
- if (alloc_space (wsp))
- return WRDSE_NOSPACE;
-
- n = end - start;
-
- if (wsp->ws_flags & WRDSF_QUOTE &&
- !(wsp->ws_flags & _ARGCV_WORD_SED_EXPR))
- {
- if (start < end
- && (command[start] == '"' || command[start] == '\'')
- && command[end-1] == command[start])
- {
- unquote = command[start] == '"';
- start++;
- n -= 2;
- }
- }
- else
- unquote = 0;
-
- p = malloc (n + 1);
- if (!p)
- {
- if (wsp->ws_flags & WRDSF_ENOMEMABRT)
- xalloc_die ();
- if (wsp->ws_flags & WRDSF_SHOWERR)
- error (0, 0, _("memory exhausted"));
- if (!(wsp->ws_flags & WRDSF_REUSE))
- wordsplit_free (wsp);
- errno = ENOMEM;
- return WRDSE_NOSPACE;
- }
-
- if (unquote)
- wordsplit_unquote_copy (p, &command[start], n);
- else
- {
- memcpy (p, &command[start], n);
- p[n] = 0;
- }
- wsp->ws_wordv[wsp->ws_offs + wsp->ws_wordc] = p;
- wsp->ws_wordc++;
-
- ;
- }
- if (alloc_space (wsp))
- return WRDSE_NOSPACE;
- wsp->ws_wordv[wsp->ws_offs + wsp->ws_wordc] = NULL;
- /* FIXME: if (rc) free(ws) */
- return rc;
-}
-
-int
-wordsplit (const char *command, struct wordsplit *ws, int flags)
-{
- return wordsplit_len (command, strlen (command), ws, flags);
-}
-
-void
-wordsplit_free (struct wordsplit *ws)
-{
- free (ws->ws_wordv);
- ws->ws_wordv = NULL;
-}
-
-
-

Return to:

Send suggestions and report system problems to the System administrator.