/*-
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
*
* Jordan K. Hubbard
* 29 August 1998
*
* The meat of the simple parser.
*/
__FBSDID("$FreeBSD$");
#include <stand.h>
#include <string.h>
#include "bootstrap.h"
static void clean(void);
static char *variable_lookup(char *name);
/*
* parse: accept a string of input and "parse" it for backslash
* substitutions and environment variable expansions (${var}),
* arguments. Returns 0 on success, 1 on failure (ok, ok, so I
* wimped-out on the error codes! :).
*
* Note that the argv array returned must be freed by the caller, but
* we own the space allocated for arguments and will free that on next
* invocation. This allows argv consumers to modify the array if
* required.
*
* NB: environment variables that expand to more than one whitespace
* separated token will be returned as a single argv[] element, not
* split in turn. Expanded text is also immune to further backslash
* elimination or expansion since this is a one-pass, non-recursive
* parser. You didn't specify more than this so if you want more, ask
* me. - jkh
*/
if (expr) { \
clean(); \
return 1; \
}
/* Accept the usual delimiters for a variable, returning counterpart */
static char
{
if (ch == '{')
return '}';
else if (ch == '(')
return ')';
return '\0';
}
static int
{
return (ch == '\'');
}
static int
{
return (ch == '"');
}
int
{
int ac;
size_t i = 0;
return 1;
/* Initialize vector and state */
clean();
token = 0;
/* And awaaaaaaaaay we go! */
while (*p) {
switch (state) {
case STR:
if ((*p == '\\') && p[1]) {
p++;
buf[i++] = *p++;
} else if (isquote(*p)) {
if (dquote) { /* keep quote */
buf[i++] = *p++;
} else {
++p;
}
} else if (isdquote(*p)) {
if (quote) { /* keep dquote */
buf[i++] = *p++;
} else {
++p;
}
if (i) {
buf[i] = '\0';
i = 0;
}
++p;
} else if (*p == '$' && !quote) {
if (token)
p += 2;
else
++p;
} else {
buf[i++] = *p++;
}
break;
case WHITE:
if (isspace(*p))
++p;
else
break;
case VAR:
if (token) {
} else {
q = p;
while (*q && !isspace(*q))
++q;
}
tmp = *q;
*q = '\0';
}
*q = tmp; /* restore value */
p = q + (token ? 1 : 0);
break;
}
}
/* missing terminating ' or " */
/* If at end of token, add it */
buf[i] = '\0';
}
return 0;
}
/* Clean vector space */
static void
clean(void)
{
int i;
for (i = 0; i < MAXARGS; i++) {
}
}
}
static int
{
return 1;
return 0;
}
static char *
{
/* XXX search "special variable" space first? */
}