summaryrefslogtreecommitdiffstats
path: root/usr.bin/make/str.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/make/str.c')
-rw-r--r--usr.bin/make/str.c311
1 files changed, 176 insertions, 135 deletions
diff --git a/usr.bin/make/str.c b/usr.bin/make/str.c
index 372b3d8..4c508b8 100644
--- a/usr.bin/make/str.c
+++ b/usr.bin/make/str.c
@@ -50,23 +50,50 @@ __FBSDID("$FreeBSD$");
#include "str.h"
#include "util.h"
-static char **argv;
-static char *buffer;
-static int argmax;
-static int curlen;
+/**
+ * Initialize the argument array object. The array is initially
+ * eight positions, and will be expaned as neccessary. The first
+ * position is set to NULL since everything ignores it. We allocate
+ * (size + 1) since we need space for the terminating NULL. The
+ * buffer is set to NULL, since no common buffer is alloated yet.
+ */
+static void
+ArgArray_Init(ArgArray *aa)
+{
-/*
- * str_init --
- * Initialize the strings package
- *
+ aa->size = 8;
+ aa->argv = emalloc((aa->size + 1) * sizeof(char *));
+ aa->argc = 0;
+ aa->argv[aa->argc++] = NULL;
+ aa->len = 0;
+ aa->buffer = NULL;
+}
+
+/**
+ * Cleanup the memory allocated for in the argument array object.
*/
void
-str_init(void)
+ArgArray_Done(ArgArray *aa)
{
- argmax = 50;
- argv = emalloc((argmax + 1) * sizeof(char *));
- argv[0] = NULL;
+ if (aa->buffer == NULL) {
+ int i;
+ /* args are individually allocated */
+ for (i = 0; i < aa->argc; ++i) {
+ if (aa->argv[i]) {
+ free(aa->argv[i]);
+ aa->argv[i] = NULL;
+ }
+ }
+ } else {
+ /* args are part of a single allocation */
+ free(aa->buffer);
+ aa->buffer = NULL;
+ }
+ free(aa->argv);
+ aa->argv = NULL;
+ aa->argc = 0;
+ aa->size = 0;
}
/*-
@@ -107,130 +134,144 @@ str_concat(const char *s1, const char *s2, int flags)
return (result);
}
-/*-
- * brk_string --
- * Fracture a string into an array of words (as delineated by tabs or
- * spaces) taking quotation marks into account. Leading tabs/spaces
- * are ignored.
- *
- * returns --
- * Pointer to the array of pointers to the words.
+/**
+ * Fracture a string into an array of words (as delineated by tabs or
+ * spaces) taking quotation marks into account. Leading tabs/spaces
+ * are ignored.
*/
-char **
-brk_string(const char *str, int *store_argc, Boolean expand)
+void
+brk_string(ArgArray *aa, const char str[], Boolean expand)
{
- int argc, ch;
- char inquote;
- const char *p;
- char *start, *t;
- int len;
+ char inquote;
+ char *start;
+ char *arg;
/* skip leading space chars. */
for (; *str == ' ' || *str == '\t'; ++str)
continue;
- /* allocate room for a copy of the string */
- if ((len = strlen(str) + 1) > curlen) {
- if (buffer)
- free(buffer);
- buffer = emalloc(curlen = len);
- }
+ ArgArray_Init(aa);
+
+ aa->buffer = estrdup(str);;
+
+ arg = aa->buffer;
+ start = arg;
+ inquote = '\0';
/*
* copy the string; at the same time, parse backslashes,
* quotes and build the argument list.
*/
- argc = 1;
- inquote = '\0';
- for (p = str, start = t = buffer;; ++p) {
- switch(ch = *p) {
+ for (;;) {
+ switch (str[0]) {
case '"':
case '\'':
- if (inquote) {
- if (ch != inquote)
+ if (inquote == '\0') {
+ inquote = str[0];
+ if (expand)
break;
+ if (start == NULL)
+ start = arg;
+ } else if (inquote == str[0]) {
inquote = '\0';
/* Don't miss "" or '' */
- if (!start)
- start = t;
- } else
- inquote = (char)ch;
- if (expand)
- continue;
+ if (start == NULL)
+ start = arg;
+ if (expand)
+ break;
+ } else {
+ /* other type of quote found */
+ if (start == NULL)
+ start = arg;
+ }
+ *arg++ = str[0];
break;
case ' ':
case '\t':
case '\n':
- if (inquote)
+ if (inquote) {
+ if (start == NULL)
+ start = arg;
+ *arg++ = str[0];
+ break;
+ }
+ if (start == NULL)
break;
- if (!start)
- continue;
/* FALLTHROUGH */
case '\0':
/*
* end of a token -- make sure there's enough argv
* space and save off a pointer.
*/
- if (!start)
- goto done;
-
- *t++ = '\0';
- if (argc == argmax) {
- argmax *= 2; /* ramp up fast */
- argv = erealloc(argv,
- (argmax + 1) * sizeof(char *));
- }
- argv[argc++] = start;
- start = NULL;
- if (ch == '\n' || ch == '\0')
- goto done;
- continue;
- case '\\':
- if (!expand) {
- if (!start)
- start = t;
- *t++ = '\\';
- ch = *++p;
- break;
+ if (aa->argc == aa->size) {
+ aa->size *= 2; /* ramp up fast */
+ aa->argv = erealloc(aa->argv,
+ (aa->size + 1) * sizeof(char *));
}
- switch (ch = *++p) {
- case '\0':
- case '\n':
- /* hmmm; fix it up as best we can */
- ch = '\\';
- --p;
- break;
- case 'b':
- ch = '\b';
- break;
- case 'f':
- ch = '\f';
- break;
- case 'n':
- ch = '\n';
- break;
- case 'r':
- ch = '\r';
- break;
- case 't':
- ch = '\t';
- break;
- default:
+ *arg++ = '\0';
+ if (start == NULL) {
+ aa->argv[aa->argc] = start;
+ return;
+ }
+ if (str[0] == '\n' || str[0] == '\0') {
+ aa->argv[aa->argc++] = start;
+ aa->argv[aa->argc] = NULL;
+ return;
+ } else {
+ aa->argv[aa->argc++] = start;
+ start = NULL;
break;
}
+ case '\\':
+ if (start == NULL)
+ start = arg;
+ if (expand) {
+ switch (str[1]) {
+ case '\0':
+ case '\n':
+ /* hmmm; fix it up as best we can */
+ *arg++ = '\\';
+ break;
+ case 'b':
+ *arg++ = '\b';
+ ++str;
+ break;
+ case 'f':
+ *arg++ = '\f';
+ ++str;
+ break;
+ case 'n':
+ *arg++ = '\n';
+ ++str;
+ break;
+ case 'r':
+ *arg++ = '\r';
+ ++str;
+ break;
+ case 't':
+ *arg++ = '\t';
+ ++str;
+ break;
+ default:
+ *arg++ = str[1];
+ ++str;
+ break;
+ }
+ } else {
+ *arg++ = str[0];
+ ++str;
+ *arg++ = str[0];
+ }
break;
default:
+ if (start == NULL)
+ start = arg;
+ *arg++ = str[0];
break;
}
- if (!start)
- start = t;
- *t++ = (char)ch;
+ ++str;
}
-done: argv[argc] = NULL;
- if (store_argc != NULL)
- *store_argc = argc;
- return (argv);
}
/*
@@ -271,23 +312,23 @@ MAKEFLAGS_quote(const char *str)
return (ret);
}
-char **
-MAKEFLAGS_break(const char *str, int *pargc)
+void
+MAKEFLAGS_break(ArgArray *aa, const char str[])
{
- char *q, *start;
- int len;
+ char *arg;
+ char *start;
+
+ ArgArray_Init(aa);
- /* allocate room for a copy of the string */
- if ((len = strlen(str) + 1) > curlen)
- buffer = erealloc(buffer, curlen = len);
+ aa->buffer = strdup(str);
+ arg = aa->buffer;
start = NULL;
- *pargc = 1;
- for (q = buffer;;) {
- switch (*str) {
- case ' ':
- case '\t':
+ for (;;) {
+ switch (str[0]) {
+ case ' ':
+ case '\t':
/* word separator */
if (start == NULL) {
/* not in a word */
@@ -295,41 +336,41 @@ MAKEFLAGS_break(const char *str, int *pargc)
continue;
}
/* FALLTHRU */
- case '\0':
- if (start == NULL)
- goto done;
-
- /* finish word */
- *q++ = '\0';
- if (argmax == *pargc) {
- argmax *= 2;
- argv = erealloc(argv,
- sizeof(*argv) * (argmax + 1));
+ case '\0':
+ if (aa->argc == aa->size) {
+ aa->size *= 2;
+ aa->argv = erealloc(aa->argv,
+ (aa->size + 1) * sizeof(char *));
}
- argv[(*pargc)++] = start;
- start = NULL;
- if (*str++ == '\0')
- goto done;
- continue;
+ *arg++ = '\0';
+ if (start == NULL) {
+ aa->argv[aa->argc] = start;
+ return;
+ }
+ if (str[0] == '\0') {
+ aa->argv[aa->argc++] = start;
+ aa->argv[aa->argc] = NULL;
+ return;
+ } else {
+ aa->argv[aa->argc++] = start;
+ start = NULL;
+ str++;
+ continue;
+ }
- case '\\':
+ case '\\':
if (str[1] == ' ' || str[1] == '\t')
- /* was a quote */
str++;
break;
- default:
+ default:
break;
}
if (start == NULL)
- /* start of new word */
- start = q;
- *q++ = *str++;
+ start = arg;
+ *arg++ = *str++;
}
- done:
- argv[(*pargc)] = NULL;
- return (argv);
}
/*
OpenPOWER on IntegriCloud