#if 0
#include "ldmconfig.h"
#endif
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "wordexp.h"
const char *
s_wrde_err(int wrde_err)
{
switch(wrde_err) {
case 0: return "No Error";
case WRDE_BADCHAR: return "WRDE_BADCHAR";
case WRDE_BADVAL: return "WRDE_BADVAL";
case WRDE_CMDSUB: return "WRDE_CMDSUB";
case WRDE_NOSPACE: return "WRDE_NOSPACE";
case WRDE_SYNTAX: return "WRDE_SYNTAX";
}
return "Unknown Error";
}
int
wordexp(const char *words, wordexp_t *pwordexp, int flags)
{
const char *ccp;
char **argv;
const char *buf;
size_t argc;
enum states {ARGSTART, IN_QUOTE, NOT_IN_QUOTE, DONE};
enum classes {EOS, SPACE, QUOTE, OTHER};
int state = ARGSTART;
char *argbuf;
const char *sp;
char *dp;
int status = 0;
for(ccp = words; *ccp != 0 && isspace(*ccp); )
ccp++;
if(*ccp == '#')
{
pwordexp->we_wordc = 0;
pwordexp->we_wordv = NULL;
return 0;
}
#define MAXNARGS(str) ((strlen(str) +1)/2 +1)
argv = (char **)calloc(MAXNARGS(ccp), sizeof(char *));
if(argv == NULL)
return WRDE_NOSPACE;
buf = ccp;
argbuf = malloc(strlen(words)+1);
if (argbuf == NULL)
{
free(argv);
return WRDE_NOSPACE;
}
sp = buf;
dp = argbuf;
argc = 0;
while(state != DONE)
{
int class;
if (*sp == 0)
class = EOS;
else if (isspace(*sp))
class = SPACE;
else if (*sp == '"')
class = QUOTE;
else
class = OTHER;
switch (state) {
case ARGSTART:
switch(class) {
case EOS:
state = DONE;
break;
case SPACE:
sp++;
break;
case QUOTE:
sp++;
state = IN_QUOTE;
break;
case OTHER:
*dp++ = *sp++;
state = NOT_IN_QUOTE;
break;
}
break;
case IN_QUOTE:
switch(class) {
case EOS:
state = DONE;
status = WRDE_SYNTAX;
break;
case QUOTE:
sp++;
state = NOT_IN_QUOTE;
break;
case SPACE:
case OTHER:
*dp++ = *sp++;
break;
}
break;
case NOT_IN_QUOTE:
switch(class) {
case EOS:
*dp = 0;
dp = argbuf;
argv[argc++] = strdup(argbuf);
state = DONE;
break;
case SPACE:
*dp = 0;
dp = argbuf;
argv[argc++] = strdup(argbuf);
sp++;
state = ARGSTART;
break;
case QUOTE:
sp++;
state = IN_QUOTE;
break;
case OTHER:
*dp++ = *sp++;
break;
}
break;
}
}
argv[argc] = NULL;
pwordexp->we_wordc = argc;
pwordexp->we_wordv = argv;
free(argbuf);
return status;
}
void
wordfree(wordexp_t *pwordexp)
{
if(pwordexp == NULL || pwordexp->we_wordv == NULL)
return;
if(*pwordexp->we_wordv)
free(*pwordexp->we_wordv);
free(pwordexp->we_wordv);
}
#if TEST
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
main(int argc, char *argv[])
{
char strbuf[1024];
wordexp_t wrdexp;
int status;
char **cpp;
while(fgets(strbuf, sizeof(strbuf), stdin) != NULL)
{
{
char *cp = strrchr(strbuf,'\n');
if(cp)
*cp = 0;
}
fprintf(stdout, "\t%s\n", strbuf);
status = wordexp(strbuf, &wrdexp, WRDE_SHOWERR);
if(status)
{
fprintf(stderr, "wordexp: %s\n", s_wrde_err(status));
continue;
}
fprintf(stdout, "\t%d:\n", wrdexp.we_wordc);
for(cpp = wrdexp.we_wordv;
cpp < &wrdexp.we_wordv[wrdexp.we_wordc]; cpp++)
{
fprintf(stdout, "\t\t%s\n", *cpp);
}
wordfree(&wrdexp);
}
exit(EXIT_SUCCESS);
}
#endif