+/*----- Word splitting ----------------------------------------------------*/
+
+#ifdef BUILDING_MLIB
+# include "str.h"
+# define qword str_qword
+#else
+
+/* --- @qword@ --- *
+ *
+ * Arguments: @char **pp@ = address of pointer into string
+ * @unsigned f@ = various flags
+ *
+ * Returns: Pointer to the next space-separated possibly-quoted word from
+ * the string, or null.
+ *
+ * Use: Fetches the next word from a string. If the flag
+ * @STRF_QUOTE@ is set, the `\' character acts as an escape, and
+ * single and double quotes protect whitespace.
+ */
+
+#define STRF_QUOTE 1u
+
+static char *qword(char **pp, unsigned f)
+{
+ char *p = *pp, *q, *qq;
+ int st = 0, pst = 0;
+
+ /* --- Preliminaries --- */
+
+ if (!p)
+ return (0);
+ while (isspace((unsigned char)*p))
+ p++;
+ if (!*p) {
+ *pp = 0;
+ return (0);
+ }
+
+ /* --- Main work --- */
+
+ for (q = qq = p; *q; q++) {
+ switch (st) {
+ case '\\':
+ *qq++ = *q;
+ st = pst;
+ break;
+ case '\'':
+ case '\"':
+ if (*q == st)
+ st = pst = 0;
+ else if (*q == '\\')
+ st = '\\';
+ else
+ *qq++ = *q;
+ break;
+ default:
+ if (isspace((unsigned char)*q)) {
+ do q++; while (*q && isspace((unsigned char)*q));
+ goto done;
+ } else if (!(f & STRF_QUOTE))
+ goto stdchar;
+ switch (*q) {
+ case '\\':
+ st = '\\';
+ break;
+ case '\'':
+ case '\"':
+ st = pst = *q;
+ break;
+ default:
+ stdchar:
+ *qq++ = *q;
+ break;
+ }
+ }
+ }
+
+ /* --- Finished --- */
+
+done:
+ *pp = *q ? q : 0;
+ *qq++ = 0;
+ return (p);
+}
+
+#endif
+