#include <unistd.h>
#include <c-ctype.h>
+#include <ialloc.h>
#if ENABLE_NLS
# include <gettext.h>
#define WSP_RETURN_DELIMS(wsp) \
((wsp)->ws_flags & WRDSF_RETURN_DELIMS || ((wsp)->ws_options & WRDSO_MAXWORDS))
+/* When printing diagnostics with %.*s, output at most this many bytes.
+ Users typically don't want super-long strings in diagnostics,
+ and anyway printf fails if it outputs more than INT_MAX bytes.
+ printflen (LEN) returns LEN as an int, but at most PRINTMAX;
+ printfdots (LEN) returns "..." if LEN exceeds PRINTMAX, "" otherwise. */
+
+enum { PRINTMAX = 10 * 1024 };
+
+static int
+printflen (idx_t len)
+{
+ return len <= PRINTMAX ? len : PRINTMAX;
+}
+
+static char const *
+printfdots (idx_t len)
+{
+ return &"..."[3 * (len <= PRINTMAX)];
+}
+
+
static void
_wsplt_alloc_die (struct wordsplit *wsp)
{
return wsp->ws_errno;
}
-static int wordsplit_run (const char *command, size_t length,
- struct wordsplit *wsp,
- unsigned flags, int lvl);
-
-static int wordsplit_init (struct wordsplit *wsp, const char *input, size_t len,
- unsigned flags);
-static int wordsplit_process_list (struct wordsplit *wsp, size_t start);
+static int wordsplit_init (struct wordsplit *wsp, char const *input,
+ idx_t len, unsigned flags);
+static int wordsplit_process_list (struct wordsplit *wsp, idx_t start);
static int wordsplit_finish (struct wordsplit *wsp);
static int
_wsplt_subsplit (struct wordsplit *wsp, struct wordsplit *wss,
- char const *str, int len,
+ char const *str, idx_t len,
unsigned flags, int finalize)
{
int rc;
rc = wordsplit_init (wss, str, len, flags);
if (rc)
return rc;
- wss->ws_lvl = wsp->ws_lvl + 1;
+ wss->ws_lvl++;
rc = wordsplit_process_list (wss, 0);
if (rc)
{
static char wordsplit_c_escape_tab[] = "\\\\\"\"a\ab\bf\fn\nr\rt\tv\v";
static int
-wordsplit_init (struct wordsplit *wsp, const char *input, size_t len,
+wordsplit_init (struct wordsplit *wsp, char const *input, idx_t len,
unsigned flags)
{
wsp->ws_flags = flags;
}
static int
-alloc_space (struct wordsplit *wsp, size_t count)
+alloc_space (struct wordsplit *wsp, idx_t count)
{
- size_t offs_plus_count;
+ idx_t offs_plus_count;
if (ckd_add (&offs_plus_count, count,
wsp->ws_flags & WRDSF_DOOFFS ? wsp->ws_offs : 0))
return _wsplt_nomem (wsp);
- size_t wordn;
+ idx_t wordn;
char **wordv;
if (!wsp->ws_wordv)
}
else
{
- size_t wordroom = wsp->ws_wordn - wsp->ws_wordc;
+ idx_t wordroom = wsp->ws_wordn - wsp->ws_wordc;
if (offs_plus_count <= wordroom)
return 0;
/* Grow the allocation by at least MININCR. To avoid quadratic
behavior, also grow it by at least 50% if possible. */
- size_t minincr = offs_plus_count - wordroom;
- size_t halfn = wsp->ws_wordn >> 1;
+ idx_t minincr = offs_plus_count - wordroom;
+ idx_t halfn = wsp->ws_wordn >> 1;
wordv = (halfn <= minincr || ckd_add (&wordn, wsp->ws_wordn, halfn)
? nullptr
: reallocarray (wsp->ws_wordv, wordn, sizeof *wordv));
{
struct
{
- size_t beg; /* Start of word in ws_input */
- size_t end; /* End of word in ws_input */
+ idx_t beg; /* Start of word in ws_input */
+ idx_t end; /* End of word in ws_input */
} segm;
char *word;
} v;
return wsp->ws_input + p->v.segm.beg;
}
-static size_t
+static idx_t
wsnode_len (struct wordsplit_node *p)
{
if (p->flags & _WSNF_NULL)
}
static int
-wordsplit_add_segm (struct wordsplit *wsp, size_t beg, size_t end, int flg)
+wordsplit_add_segm (struct wordsplit *wsp, idx_t beg, idx_t end, int flg)
{
if (end == beg && !(flg & _WSNF_EMPTYOK))
return 0;
wordsplit_dump_nodes (struct wordsplit *wsp)
{
struct wordsplit_node *p;
- int n = 0;
+ intmax_t 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_debug ("(%02td) %4jd: %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);
+ {
+ idx_t seglen = p->v.segm.end - p->v.segm.beg;
+ wsp->ws_debug ("(%02td) %4jd: %p: %#04x (%s):%.*s%s;",
+ wsp->ws_lvl,
+ n, p, p->flags, wsnode_flagstr (p->flags),
+ printflen (seglen), wsp->ws_input + p->v.segm.beg,
+ printfdots (seglen));
+ }
}
}
coalesce_segment (struct wordsplit *wsp, struct wordsplit_node *node)
{
struct wordsplit_node *p, *end;
- size_t len = 0;
+ idx_t len = 0;
char *buf, *cur;
if (!(node->flags & _WSNF_JOIN))
len += wsnode_len (p);
end = p;
- buf = malloc (len + 1);
+ buf = imalloc (len + 1);
if (!buf)
return _wsplt_nomem (wsp);
cur = buf;
{
struct wordsplit_node *next = p->next;
const char *str = wsnode_ptr (wsp, p);
- size_t slen = wsnode_len (p);
+ idx_t slen = wsnode_len (p);
memcpy (cur, str, slen);
cur += slen;
static void wordsplit_string_unquote_copy (struct wordsplit *ws, int inquote,
char *dst, const char *src,
- size_t n);
+ idx_t n);
static int
wsnode_quoteremoval (struct wordsplit *wsp)
for (p = wsp->ws_head; p; p = p->next)
{
const char *str = wsnode_ptr (wsp, p);
- size_t slen = wsnode_len (p);
+ idx_t slen = wsnode_len (p);
int unquote;
if (wsp->ws_flags & WRDSF_QUOTE)
{
if (!(p->flags & _WSNF_WORD))
{
- char *newstr = malloc (slen + 1);
+ char *newstr = imalloc (slen + 1);
if (!newstr)
return _wsplt_nomem (wsp);
memcpy (newstr, str, slen);
return 0;
}
-static size_t skip_delim (struct wordsplit *wsp);
+static idx_t skip_delim (struct wordsplit *wsp);
static int
wordsplit_finish (struct wordsplit *wsp)
{
struct wordsplit_node *p;
- size_t n;
+ idx_t n;
int delim;
/* Postprocess delimiters. It would be rather simple, if it weren't for
while (wsp->ws_head)
{
const char *str = wsnode_ptr (wsp, wsp->ws_head);
- size_t slen = wsnode_len (wsp->ws_head);
- char *newstr = malloc (slen + 1);
+ idx_t slen = wsnode_len (wsp->ws_head);
+ char *newstr = imalloc (slen + 1);
/* Assign newstr first, even if it is NULL. This way
wordsplit_free will work even if we return
wordsplit_append (wordsplit_t *wsp, int argc, char **argv)
{
int rc;
- size_t i;
+ idx_t i;
rc = alloc_space (wsp, wsp->ws_wordc + argc + 1);
if (rc)
node_split_prefix (struct wordsplit *wsp,
struct wordsplit_node **ptail,
struct wordsplit_node *node,
- size_t beg, size_t len, int flg)
+ idx_t beg, idx_t len, int flg)
{
-
if (len == 0)
return 0;
struct wordsplit_node *newnode = wsnode_new (wsp);
if (node->flags & _WSNF_WORD)
{
const char *str = wsnode_ptr (wsp, node);
- char *newstr = malloc (len + 1);
+ char *newstr = imalloc (len + 1);
if (!newstr)
return _wsplt_nomem (wsp);
memcpy (newstr, str + beg, len);
}
static int
-find_closing_paren (const char *str, size_t i, size_t len, size_t *poff,
+find_closing_paren (char const *str, idx_t i, idx_t len, idx_t *poff,
char const *paren)
{
enum { st_init, st_squote, st_dquote } state = st_init;
- size_t level = 1;
+ idx_t level = 1;
for (; i < len; i++)
{
}
static int
-wordsplit_find_env (struct wordsplit *wsp, const char *name, size_t len,
+wordsplit_find_env (struct wordsplit *wsp, char const *name, idx_t len,
char const **ret)
{
- size_t i;
+ idx_t i;
if (!(wsp->ws_flags & WRDSF_ENV))
return WRDSE_UNDEF;
/* A key-value pair environment */
for (i = 0; wsp->ws_env[i]; i++)
{
- size_t elen = strlen (wsp->ws_env[i]);
+ idx_t elen = strlen (wsp->ws_env[i]);
if (elen == len && memcmp (wsp->ws_env[i], name, elen) == 0)
{
*ret = wsp->ws_env[i + 1];
/* Usual (A=B) environment. */
for (i = 0; wsp->ws_env[i]; i++)
{
- size_t j;
+ idx_t j;
const char *var = wsp->ws_env[i];
for (j = 0; j < len; j++)
}
static int
-wsplt_assign_var (struct wordsplit *wsp, const char *name, size_t namelen,
+wsplt_assign_var (struct wordsplit *wsp, char const *name, idx_t namelen,
char *value)
{
int n = (wsp->ws_flags & WRDSF_ENV_KV) ? 2 : 1;
if (wsp->ws_envidx + n >= wsp->ws_envsiz)
{
- size_t sz;
+ idx_t sz;
char **newenv;
if (!wsp->ws_envbuf)
{
if (wsp->ws_flags & WRDSF_ENV)
{
- size_t i = 0, j;
+ idx_t i = 0, j;
if (wsp->ws_env)
{
if (wsp->ws_flags & WRDSF_ENV_KV)
{
/* A key-value pair environment */
- char *p = malloc (namelen + 1);
+ char *p = imalloc (namelen + 1);
if (!p)
return _wsplt_nomem (wsp);
memcpy (p, name, namelen);
}
else
{
- v = malloc (namelen + strlen (value) + 2);
+ v = imalloc (namelen + strlen (value) + 2);
if (!v)
return _wsplt_nomem (wsp);
memcpy (v, name, namelen);
}
static int
-expvar (struct wordsplit *wsp, const char *str, size_t len,
+expvar (struct wordsplit *wsp, char const *str, idx_t len,
struct wordsplit_node **ptail, const char **pend, unsigned flg)
{
- size_t i = 0;
+ idx_t i = 0;
const char *defstr = NULL;
char *value;
const char *vptr;
{
if (str[i] == ':')
{
- size_t j;
+ idx_t j;
defstr = str + i + 1;
if (find_closing_paren (str, i + 1, len, &j, "{}"))
}
else if (str[i] && strchr ("-+?=", str[i]))
{
- size_t j;
+ idx_t j;
defstr = str + i;
if (find_closing_paren (str, i, len, &j, "{}"))
case WRDSE_OK:
if (defstr && *defstr == '+')
{
- size_t size = *pend - ++defstr;
+ idx_t size = *pend - ++defstr;
rc = _wsplt_subsplit (wsp, &ws, defstr, size,
WRDSF_NOSPLIT | WRDSF_WS | WRDSF_QUOTE |
case WRDSE_UNDEF:
if (defstr)
{
- size_t size;
+ idx_t size;
if (*defstr == '-' || *defstr == '=')
{
size = *pend - ++defstr;
{
size = *pend - ++defstr;
if (size == 0)
- wsp->ws_error (_("%.*s: variable null or not set"),
- (int) i, str);
+ wsp->ws_error (_("%.*s%s: variable null or not set"),
+ printflen (i), str, printfdots (i));
else
{
rc = _wsplt_subsplit (wsp, &ws, defstr, size,
(WRDSF_NOVAR | WRDSF_NOCMD)),
1);
if (rc == 0)
- wsp->ws_error ("%.*s: %s",
- (int) i, str, ws.ws_wordv[0]);
+ wsp->ws_error ("%.*s%s: %s",
+ printflen (i), str, printfdots (i),
+ ws.ws_wordv[0]);
else
- wsp->ws_error ("%.*s: %.*s",
- (int) i, str, (int) size, defstr);
+ wsp->ws_error ("%.*s%s: %.*s%s",
+ printflen (i), str, printfdots (i),
+ printflen (size), defstr,
+ printfdots (size));
wordsplit_free (&ws);
}
}
else
{
if (wsp->ws_flags & WRDSF_WARNUNDEF)
- wsp->ws_error (_("warning: undefined variable `%.*s'"),
- (int) i, str);
+ wsp->ws_error (_("warning: undefined variable '%.*s%s'"),
+ printflen (i), str, printfdots (i));
if (wsp->ws_flags & WRDSF_KEEPUNDEF)
value = NULL;
else
}
else if (wsp->ws_flags & WRDSF_KEEPUNDEF)
{
- size_t size = *pend - start + 1;
+ idx_t size = *pend - start + 1;
newnode = wsnode_new (wsp);
if (!newnode)
node_expand (struct wordsplit *wsp, struct wordsplit_node *node,
int (*beg_p) (int),
int (*ws_exp_fn) (struct wordsplit *wsp,
- const char *str, size_t len,
+ char const *str, idx_t len,
struct wordsplit_node **ptail,
const char **pend,
unsigned flg))
{
const char *str = wsnode_ptr (wsp, node);
- size_t slen = wsnode_len (node);
+ idx_t slen = wsnode_len (node);
const char *end = str + slen;
const char *p;
- size_t off = 0;
+ idx_t off = 0;
struct wordsplit_node *tail = node;
for (p = str; p < end; p++)
}
if (*p == '$' && beg_p (p[1]))
{
- size_t n = p - str;
+ idx_t n = p - str;
if (tail != node)
tail->flags |= _WSNF_JOIN;
}
static int
-expcmd (struct wordsplit *wsp, const char *str, size_t len,
+expcmd (struct wordsplit *wsp, char const *str, idx_t len,
struct wordsplit_node **ptail, const char **pend, unsigned flg)
{
int rc;
- size_t j;
+ idx_t j;
char *value;
struct wordsplit_node *newnode;
for (p = wsp->ws_head; p; p = p->next)
{
- size_t n;
+ idx_t n;
if (!(p->flags & _WSNF_QUOTE))
{
{
struct wordsplit_node *p;
char *uname = NULL;
- size_t usize = 0;
+ idx_t usize = 0;
for (p = wsp->ws_head; p; p = p->next)
{
str = wsnode_ptr (wsp, p);
if (str[0] == '~')
{
- size_t i, size, dlen;
- size_t slen = wsnode_len (p);
+ idx_t i, size, dlen;
+ idx_t slen = wsnode_len (p);
struct passwd *pw;
char *newstr;
}
\f
static bool
-isglob (char const *s, size_t l)
+isglob (char const *s, idx_t l)
{
- while (l--)
+ for (ptrdiff_t i = l; i--; )
{
char c = *s++;
if (c && strchr ("*?[", c))
wordsplit_pathexpand (struct wordsplit *wsp)
{
struct wordsplit_node *p, *next;
- size_t slen;
+ idx_t slen;
int flags = 0;
#ifdef GLOB_PERIOD
}
\f
static int
-skip_sed_expr (const char *command, size_t i, size_t len)
+skip_sed_expr (char const *command, idx_t i, idx_t len)
{
int state;
/* wsp->ws_endp points to a delimiter character. If RETURN_DELIMS
is true, return its value, otherwise return the index past it. */
-static size_t
-skip_delim_internal (struct wordsplit *wsp, int return_delims)
+static idx_t
+skip_delim_internal (struct wordsplit *wsp, bool return_delims)
{
- return return_delims ? wsp->ws_endp : wsp->ws_endp + 1;
+ return wsp->ws_endp + !return_delims;
}
-static size_t
+static idx_t
skip_delim (struct wordsplit *wsp)
{
return skip_delim_internal (wsp, WSP_RETURN_DELIMS (wsp));
}
-static size_t
+static idx_t
skip_delim_real (struct wordsplit *wsp)
{
- return skip_delim_internal (wsp, wsp->ws_flags & WRDSF_RETURN_DELIMS);
+ return skip_delim_internal (wsp, !!(wsp->ws_flags & WRDSF_RETURN_DELIMS));
}
#define _WRDS_EOF 0
#define _WRDS_ERR 2
static int
-scan_qstring (struct wordsplit *wsp, size_t start, size_t *end)
+scan_qstring (struct wordsplit *wsp, idx_t start, idx_t *end)
{
- size_t j;
+ idx_t j;
const char *command = wsp->ws_input;
- size_t len = wsp->ws_len;
+ idx_t len = wsp->ws_len;
char q = command[start];
for (j = start + 1; j < len && command[j] != q; j++)
}
static int
-scan_word (struct wordsplit *wsp, size_t start, int consume_all)
+scan_word (struct wordsplit *wsp, idx_t start, int consume_all)
{
- size_t len = wsp->ws_len;
+ idx_t len = wsp->ws_len;
const char *command = wsp->ws_input;
const char *comment = wsp->ws_comment;
int join = 0;
unsigned flags = 0;
struct wordsplit_node *np = wsp->ws_tail;
- size_t i = start;
+ idx_t i = start;
if (i >= len)
{
{
if (comment && command[i] && strchr (comment, command[i]) != NULL)
{
- size_t j;
+ idx_t j;
for (j = i + 1; j < len && command[j] != '\n'; j++)
;
if (wordsplit_add_segm (wsp, start, i, 0))
return i;
}
-size_t
+idx_t
wordsplit_c_quoted_length (const char *str, int quote_hex, int *quote)
{
- size_t len = 0;
+ idx_t len = 0;
*quote = 0;
for (; *str; str++)
void
wordsplit_string_unquote_copy (struct wordsplit *ws, int inquote,
- char *dst, const char *src, size_t n)
+ char *dst, char const *src, idx_t n)
{
- int i = 0;
+ idx_t i = 0;
int c;
inquote = !!inquote;
if (quote_hex)
{
- snprintf (tmp, sizeof tmp, "%%%02X", *(unsigned char *) src);
+ unsigned char c = *src;
+ snprintf (tmp, sizeof tmp, "%%%02X", c);
memcpy (dst, tmp, 3);
dst += 3;
}
*dst++ = c;
else
{
- snprintf (tmp, sizeof tmp, "%03o", *(unsigned char *) src);
+ unsigned char ch = *src;
+ snprintf (tmp, sizeof tmp, "%03o", ch);
memcpy (dst, tmp, 3);
dst += 3;
}
}
static int
-wordsplit_process_list (struct wordsplit *wsp, size_t start)
+wordsplit_process_list (struct wordsplit *wsp, idx_t start)
{
struct exptab *p;
if (wsp->ws_flags & WRDSF_SHOWDBG)
- wsp->ws_debug (_("(%02d) Input:%.*s;"),
- wsp->ws_lvl, (int) wsp->ws_len, wsp->ws_input);
+ wsp->ws_debug (_("(%02td) Input:%.*s%s;"),
+ wsp->ws_lvl, printflen (wsp->ws_len), wsp->ws_input,
+ printfdots (wsp->ws_len));
if ((wsp->ws_flags & WRDSF_NOSPLIT)
|| ((wsp->ws_options & WRDSO_MAXWORDS)
if (wsp->ws_flags & WRDSF_SHOWDBG)
{
- wsp->ws_debug ("(%02d) %s", wsp->ws_lvl, _("Initial list:"));
+ wsp->ws_debug ("(%02td) %s", wsp->ws_lvl, _("Initial list:"));
wordsplit_dump_nodes (wsp);
}
break;
if (wsp->ws_flags & WRDSF_SHOWDBG)
{
- wsp->ws_debug ("(%02d) %s", wsp->ws_lvl,
+ wsp->ws_debug ("(%02td) %s", wsp->ws_lvl,
_("Coalesced list:"));
wordsplit_dump_nodes (wsp);
}
break;
if (wsp->ws_flags & WRDSF_SHOWDBG)
{
- wsp->ws_debug ("(%02d) %s", wsp->ws_lvl, _(p->descr));
+ wsp->ws_debug ("(%02td) %s", wsp->ws_lvl, _(p->descr));
wordsplit_dump_nodes (wsp);
}
}
return wsp->ws_errno;
}
-static int
-wordsplit_run (const char *command, size_t length, struct wordsplit *wsp,
- unsigned flags, int lvl)
+int
+wordsplit_len (char const *command, idx_t length, struct wordsplit *wsp,
+ unsigned flags)
{
int rc;
- size_t start;
+ idx_t start;
if (!command)
{
rc = wordsplit_init (wsp, command, length, flags);
if (rc)
return rc;
- wsp->ws_lvl = lvl;
+ wsp->ws_lvl = 0;
}
rc = wordsplit_process_list (wsp, start);
return wordsplit_finish (wsp);
}
-int
-wordsplit_len (const char *command, size_t length, struct wordsplit *wsp,
- unsigned flags)
-{
- return wordsplit_run (command, length, wsp, flags, 0);
-}
-
int
wordsplit (const char *command, struct wordsplit *ws, unsigned flags)
{
void
wordsplit_free_words (struct wordsplit *ws)
{
- size_t i;
+ idx_t i;
for (i = 0; i < ws->ws_wordc; i++)
{
return;
if (ws->ws_envbuf)
{
- size_t i;
+ idx_t i;
for (i = 0; ws->ws_envbuf[i]; i++)
free (ws->ws_envbuf[i]);
}
int
-wordsplit_get_words (struct wordsplit *ws, size_t *wordc, char ***wordv)
+wordsplit_get_words (struct wordsplit *ws, idx_t *wordc, char ***wordv)
{
/* Tell the memory manager that ws->ws_wordv can be shrunk. */
char **p = realloc (ws->ws_wordv,
switch (wsp->ws_errno)
{
case WRDSE_QUOTE:
- wsp->ws_error (_("missing closing %c (start near #%lu)"),
+ wsp->ws_error (_("missing closing %c (start near #%td)"),
wsp->ws_input[wsp->ws_endp],
- (unsigned long) wsp->ws_endp);
+ wsp->ws_endp);
break;
default: