*/
#ifndef lint
-static char sccsid[] = "@(#)str.c 8.4 (Berkeley) 3/21/94";
+static char sccsid[] = "@(#)str.c 8.6 (Berkeley) 4/28/95";
#endif /* not lint */
#include "make.h"
+static char **argv, *buffer;
+static int argmax, curlen;
+
+/*
+ * str_init --
+ * Initialize the strings package
+ *
+ */
+void
+str_init()
+{
+ char *p1;
+ argv = (char **)emalloc((argmax = 50) * sizeof(char *));
+ argv[0] = Var_Value(".MAKE", VAR_GLOBAL, &p1);
+}
+
+
+/*
+ * str_end --
+ * Cleanup the strings package
+ *
+ */
+void
+str_end()
+{
+ if (argv[0]) {
+ free(argv[0]);
+ free((Address) argv);
+ }
+ if (buffer)
+ free(buffer);
+}
+
+
/*-
* str_concat --
* concatenate the two strings, inserting a space or slash between them,
* the first word is always the value of the .MAKE variable.
*/
char **
-brk_string(str, store_argc)
+brk_string(str, store_argc, expand)
register char *str;
int *store_argc;
+ Boolean expand;
{
- static int argmax, curlen;
- static char **argv, *buf;
register int argc, ch;
register char inquote, *p, *start, *t;
int len;
- /* save off pmake variable */
- if (!argv) {
- argv = (char **)emalloc((argmax = 50) * sizeof(char *));
- argv[0] = Var_Value(".MAKE", VAR_GLOBAL);
- }
-
/* skip leading space chars. */
for (; *str == ' ' || *str == '\t'; ++str)
continue;
/* allocate room for a copy of the string */
- if ((len = strlen(str) + 1) > curlen)
- buf = emalloc(curlen = len);
+ if ((len = strlen(str) + 1) > curlen) {
+ if (buffer)
+ free(buffer);
+ buffer = emalloc(curlen = len);
+ }
/*
* copy the string; at the same time, parse backslashes,
*/
argc = 1;
inquote = '\0';
- for (p = str, start = t = buf;; ++p) {
+ for (p = str, start = t = buffer;; ++p) {
switch(ch = *p) {
case '"':
case '\'':
inquote = '\0';
else
break;
- else
+ else {
inquote = (char) ch;
+ /* Don't miss "" or '' */
+ if (start == NULL && p[1] == inquote) {
+ start = t + 1;
+ break;
+ }
+ }
+ if (!expand) {
+ if (!start)
+ start = t;
+ *t++ = ch;
+ }
continue;
case ' ':
case '\t':
+ case '\n':
if (inquote)
break;
if (!start)
continue;
/* FALLTHROUGH */
- case '\n':
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 */
goto done;
continue;
case '\\':
+ if (!expand) {
+ if (!start)
+ start = t;
+ *t++ = '\\';
+ ch = *++p;
+ break;
+ }
+
switch (ch = *++p) {
case '\0':
case '\n':