mirror of
https://github.com/gryf/wmaker.git
synced 2025-12-19 20:38:08 +01:00
make wtrimspace() use wings' own function for a task semantics change: it used to segfault given null, now it returns null. this doesn't affect any current use (there's exactly one..), and i see no harm in this behaviour, and perceive this to be more natural.
224 lines
3.8 KiB
C
224 lines
3.8 KiB
C
|
|
#include "wconfig.h"
|
|
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <ctype.h>
|
|
|
|
#include "WUtil.h"
|
|
|
|
#define PRC_ALPHA 0
|
|
#define PRC_BLANK 1
|
|
#define PRC_ESCAPE 2
|
|
#define PRC_DQUOTE 3
|
|
#define PRC_EOS 4
|
|
#define PRC_SQUOTE 5
|
|
|
|
typedef struct {
|
|
short nstate;
|
|
short output;
|
|
} DFA;
|
|
|
|
static DFA mtable[9][6] = {
|
|
{{3, 1}, {0, 0}, {4, 0}, {1, 0}, {8, 0}, {6, 0}},
|
|
{{1, 1}, {1, 1}, {2, 0}, {3, 0}, {5, 0}, {1, 1}},
|
|
{{1, 1}, {1, 1}, {1, 1}, {1, 1}, {5, 0}, {1, 1}},
|
|
{{3, 1}, {5, 0}, {4, 0}, {1, 0}, {5, 0}, {6, 0}},
|
|
{{3, 1}, {3, 1}, {3, 1}, {3, 1}, {5, 0}, {3, 1}},
|
|
{{-1, -1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}, /* final state */
|
|
{{6, 1}, {6, 1}, {7, 0}, {6, 1}, {5, 0}, {3, 0}},
|
|
{{6, 1}, {6, 1}, {6, 1}, {6, 1}, {5, 0}, {6, 1}},
|
|
{{-1, -1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}, /* final state */
|
|
};
|
|
|
|
char *wtokennext(char *word, char **next)
|
|
{
|
|
char *ptr;
|
|
char *ret, *t;
|
|
int state, ctype;
|
|
|
|
t = ret = wmalloc(strlen(word) + 1);
|
|
ptr = word;
|
|
|
|
state = 0;
|
|
*t = 0;
|
|
while (1) {
|
|
if (*ptr == 0)
|
|
ctype = PRC_EOS;
|
|
else if (*ptr == '\\')
|
|
ctype = PRC_ESCAPE;
|
|
else if (*ptr == '"')
|
|
ctype = PRC_DQUOTE;
|
|
else if (*ptr == '\'')
|
|
ctype = PRC_SQUOTE;
|
|
else if (*ptr == ' ' || *ptr == '\t')
|
|
ctype = PRC_BLANK;
|
|
else
|
|
ctype = PRC_ALPHA;
|
|
|
|
if (mtable[state][ctype].output) {
|
|
*t = *ptr;
|
|
t++;
|
|
*t = 0;
|
|
}
|
|
state = mtable[state][ctype].nstate;
|
|
ptr++;
|
|
if (mtable[state][0].output < 0) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (*ret == 0)
|
|
t = NULL;
|
|
else
|
|
t = wstrdup(ret);
|
|
|
|
wfree(ret);
|
|
|
|
if (ctype == PRC_EOS)
|
|
*next = NULL;
|
|
else
|
|
*next = ptr;
|
|
|
|
return t;
|
|
}
|
|
|
|
/* separate a string in tokens, taking " and ' into account */
|
|
void wtokensplit(char *command, char ***argv, int *argc)
|
|
{
|
|
char *token, *line;
|
|
int count;
|
|
|
|
count = 0;
|
|
line = command;
|
|
do {
|
|
token = wtokennext(line, &line);
|
|
if (token) {
|
|
if (count == 0)
|
|
*argv = wmalloc(sizeof(char **));
|
|
else
|
|
*argv = wrealloc(*argv, (count + 1) * sizeof(char **));
|
|
(*argv)[count++] = token;
|
|
}
|
|
} while (token != NULL && line != NULL);
|
|
|
|
*argc = count;
|
|
}
|
|
|
|
char *wtokenjoin(char **list, int count)
|
|
{
|
|
int i, j;
|
|
char *flat_string, *wspace;
|
|
|
|
j = 0;
|
|
for (i = 0; i < count; i++) {
|
|
if (list[i] != NULL && list[i][0] != 0) {
|
|
j += strlen(list[i]);
|
|
if (strpbrk(list[i], " \t"))
|
|
j += 2;
|
|
}
|
|
}
|
|
|
|
flat_string = wmalloc(j + count + 1);
|
|
|
|
*flat_string = 0;
|
|
for (i = 0; i < count; i++) {
|
|
if (list[i] != NULL && list[i][0] != 0) {
|
|
if (i > 0)
|
|
strcat(flat_string, " ");
|
|
wspace = strpbrk(list[i], " \t");
|
|
if (wspace)
|
|
strcat(flat_string, "\"");
|
|
strcat(flat_string, list[i]);
|
|
if (wspace)
|
|
strcat(flat_string, "\"");
|
|
}
|
|
}
|
|
|
|
return flat_string;
|
|
}
|
|
|
|
void wtokenfree(char **tokens, int count)
|
|
{
|
|
while (count--)
|
|
wfree(tokens[count]);
|
|
wfree(tokens);
|
|
}
|
|
|
|
char *wtrimspace(const char *s)
|
|
{
|
|
char *t;
|
|
|
|
if (s == NULL)
|
|
return NULL;
|
|
|
|
while (isspace(*s) && *s)
|
|
s++;
|
|
t = (char *)s + strlen(s) - 1;
|
|
while (t > s && isspace(*t))
|
|
t--;
|
|
|
|
return wstrndup(s, t - s + 1);
|
|
}
|
|
|
|
char *wstrdup(const char *str)
|
|
{
|
|
assert(str != NULL);
|
|
|
|
return strcpy(wmalloc(strlen(str) + 1), str);
|
|
}
|
|
|
|
char *wstrndup(const char *str, size_t len)
|
|
{
|
|
char *copy;
|
|
|
|
assert(str != NULL);
|
|
|
|
len = WMIN(len, strlen(str));
|
|
copy = strncpy(wmalloc(len + 1), str, len);
|
|
copy[len] = 0;
|
|
|
|
return copy;
|
|
}
|
|
|
|
char *wstrconcat(char *str1, char *str2)
|
|
{
|
|
char *str;
|
|
|
|
if (!str1)
|
|
return wstrdup(str2);
|
|
else if (!str2)
|
|
return wstrdup(str1);
|
|
|
|
str = wmalloc(strlen(str1) + strlen(str2) + 1);
|
|
strcpy(str, str1);
|
|
strcat(str, str2);
|
|
|
|
return str;
|
|
}
|
|
|
|
char *wstrappend(char *dst, char *src)
|
|
{
|
|
if (!dst)
|
|
return wstrdup(src);
|
|
else if (!src || *src == 0)
|
|
return dst;
|
|
|
|
dst = wrealloc(dst, strlen(dst) + strlen(src) + 1);
|
|
strcat(dst, src);
|
|
|
|
return dst;
|
|
}
|
|
|
|
#ifndef HAVE_STRCASECMP
|
|
int strcasecmp(const char *s1, const char *s2)
|
|
{
|
|
while (*s1 && *s2 && (tolower(*s1) == tolower(*s2))) {
|
|
s1++;
|
|
s2++;
|
|
}
|
|
|
|
return (tolower(*s1) - tolower(*s2));
|
|
}
|
|
#endif
|