summaryrefslogtreecommitdiff
path: root/devel/bmake/files/parse.c
diff options
context:
space:
mode:
Diffstat (limited to 'devel/bmake/files/parse.c')
-rw-r--r--devel/bmake/files/parse.c218
1 files changed, 161 insertions, 57 deletions
diff --git a/devel/bmake/files/parse.c b/devel/bmake/files/parse.c
index a7c3b44af00..24fd69600a2 100644
--- a/devel/bmake/files/parse.c
+++ b/devel/bmake/files/parse.c
@@ -1,4 +1,4 @@
-/* $NetBSD: parse.c,v 1.1.1.10 2015/05/19 21:36:44 joerg Exp $ */
+/* $NetBSD: parse.c,v 1.1.1.11 2020/05/24 05:35:53 nia Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -69,14 +69,14 @@
*/
#ifndef MAKE_NATIVE
-static char rcsid[] = "$NetBSD: parse.c,v 1.1.1.10 2015/05/19 21:36:44 joerg Exp $";
+static char rcsid[] = "$NetBSD: parse.c,v 1.1.1.11 2020/05/24 05:35:53 nia Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)parse.c 8.3 (Berkeley) 3/19/94";
#else
-__RCSID("$NetBSD: parse.c,v 1.1.1.10 2015/05/19 21:36:44 joerg Exp $");
+__RCSID("$NetBSD: parse.c,v 1.1.1.11 2020/05/24 05:35:53 nia Exp $");
#endif
#endif /* not lint */
#endif
@@ -128,7 +128,6 @@ __RCSID("$NetBSD: parse.c,v 1.1.1.10 2015/05/19 21:36:44 joerg Exp $");
#include <assert.h>
#include <ctype.h>
#include <errno.h>
-#include <fcntl.h>
#include <stdarg.h>
#include <stdio.h>
@@ -139,6 +138,10 @@ __RCSID("$NetBSD: parse.c,v 1.1.1.10 2015/05/19 21:36:44 joerg Exp $");
#include "buf.h"
#include "pathnames.h"
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
#ifdef HAVE_MMAP
#include <sys/mman.h>
@@ -161,6 +164,7 @@ typedef struct IFile {
int lineno; /* current line number in file */
int first_lineno; /* line number of start of text */
int cond_depth; /* 'if' nesting when file opened */
+ Boolean depending; /* state of doing_depend on EOF */
char *P_str; /* point to base of string buffer */
char *P_ptr; /* point to next char of string buffer */
char *P_end; /* point to the end of string buffer */
@@ -184,6 +188,7 @@ typedef struct IFile {
typedef enum {
Begin, /* .BEGIN */
Default, /* .DEFAULT */
+ DeleteOnError, /* .DELETE_ON_ERROR */
End, /* .END */
dotError, /* .ERROR */
Ignore, /* .IGNORE */
@@ -301,6 +306,7 @@ static const struct {
} parseKeywords[] = {
{ ".BEGIN", Begin, 0 },
{ ".DEFAULT", Default, 0 },
+{ ".DELETE_ON_ERROR", DeleteOnError, 0 },
{ ".END", End, 0 },
{ ".ERROR", dotError, 0 },
{ ".EXEC", Attribute, OP_EXEC },
@@ -365,9 +371,6 @@ static void ParseHasCommands(void *);
static void ParseDoInclude(char *);
static void ParseSetParseFile(const char *);
static void ParseSetIncludedFile(void);
-#ifdef SYSVINCLUDE
-static void ParseTraditionalInclude(char *);
-#endif
#ifdef GMAKEEXPORT
static void ParseGmakeExport(char *);
#endif
@@ -484,7 +487,7 @@ loadfile(const char *path, int fd)
{
struct loadedfile *lf;
#ifdef HAVE_MMAP
- long pagesize;
+ static long pagesize = 0;
#endif
ssize_t result;
size_t bufpos;
@@ -508,7 +511,10 @@ loadfile(const char *path, int fd)
#ifdef HAVE_MMAP
if (load_getsize(fd, &lf->len) == SUCCESS) {
/* found a size, try mmap */
- pagesize = sysconf(_SC_PAGESIZE);
+#ifdef _SC_PAGESIZE
+ if (pagesize == 0)
+ pagesize = sysconf(_SC_PAGESIZE);
+#endif
if (pagesize <= 0) {
pagesize = 0x1000;
}
@@ -533,7 +539,7 @@ loadfile(const char *path, int fd)
if (lf->buf != MAP_FAILED) {
/* succeeded */
if (lf->len == lf->maplen && lf->buf[lf->len - 1] != '\n') {
- char *b = malloc(lf->len + 1);
+ char *b = bmake_malloc(lf->len + 1);
b[lf->len] = '\n';
memcpy(b, lf->buf, lf->len++);
munmap(lf->buf, lf->maplen);
@@ -554,9 +560,15 @@ loadfile(const char *path, int fd)
while (1) {
assert(bufpos <= lf->len);
if (bufpos == lf->len) {
+ if (lf->len > SIZE_MAX/2) {
+ errno = EFBIG;
+ Error("%s: file too large", path);
+ exit(1);
+ }
lf->len *= 2;
lf->buf = bmake_realloc(lf->buf, lf->len);
}
+ assert(bufpos < lf->len);
result = read(fd, lf->buf + bufpos, lf->len - bufpos);
if (result < 0) {
Error("%s: read error: %s", path, strerror(errno));
@@ -572,7 +584,11 @@ loadfile(const char *path, int fd)
/* truncate malloc region to actual length (maybe not useful) */
if (lf->len > 0) {
+ /* as for mmap case, ensure trailing \n */
+ if (lf->buf[lf->len - 1] != '\n')
+ lf->len++;
lf->buf = bmake_realloc(lf->buf, lf->len);
+ lf->buf[lf->len - 1] = '\n';
}
#ifdef HAVE_MMAP
@@ -669,27 +685,37 @@ ParseVErrorInternal(FILE *f, const char *cfname, size_t clineno, int type,
const char *fmt, va_list ap)
{
static Boolean fatal_warning_error_printed = FALSE;
+ char dirbuf[MAXPATHLEN+1];
(void)fprintf(f, "%s: ", progname);
if (cfname != NULL) {
(void)fprintf(f, "\"");
if (*cfname != '/' && strcmp(cfname, "(stdin)") != 0) {
- char *cp;
- const char *dir;
+ char *cp, *cp2;
+ const char *dir, *fname;
/*
* Nothing is more annoying than not knowing
- * which Makefile is the culprit.
+ * which Makefile is the culprit; we try ${.PARSEDIR}
+ * and apply realpath(3) if not absolute.
*/
dir = Var_Value(".PARSEDIR", VAR_GLOBAL, &cp);
- if (dir == NULL || *dir == '\0' ||
- (*dir == '.' && dir[1] == '\0'))
- dir = Var_Value(".CURDIR", VAR_GLOBAL, &cp);
if (dir == NULL)
dir = ".";
-
- (void)fprintf(f, "%s/%s", dir, cfname);
+ if (*dir != '/') {
+ dir = realpath(dir, dirbuf);
+ }
+ fname = Var_Value(".PARSEFILE", VAR_GLOBAL, &cp2);
+ if (fname == NULL) {
+ if ((fname = strrchr(cfname, '/')))
+ fname++;
+ else
+ fname = cfname;
+ }
+ (void)fprintf(f, "%s/%s", dir, fname);
+ free(cp2);
+ free(cp);
} else
(void)fprintf(f, "%s", cfname);
@@ -700,6 +726,8 @@ ParseVErrorInternal(FILE *f, const char *cfname, size_t clineno, int type,
(void)vfprintf(f, fmt, ap);
(void)fprintf(f, "\n");
(void)fflush(f);
+ if (type == PARSE_INFO)
+ return;
if (type == PARSE_FATAL || parseWarnFatal)
fatals += 1;
if (parseWarnFatal && !fatal_warning_error_printed) {
@@ -792,7 +820,7 @@ ParseMessage(char *line)
switch(*line) {
case 'i':
- mtype = 0;
+ mtype = PARSE_INFO;
break;
case 'w':
mtype = PARSE_WARNING;
@@ -805,14 +833,14 @@ ParseMessage(char *line)
return FALSE;
}
- while (isalpha((u_char)*line))
+ while (isalpha((unsigned char)*line))
line++;
- if (!isspace((u_char)*line))
+ if (!isspace((unsigned char)*line))
return FALSE; /* not for us */
- while (isspace((u_char)*line))
+ while (isspace((unsigned char)*line))
line++;
- line = Var_Subst(NULL, line, VAR_CMD, 0);
+ line = Var_Subst(NULL, line, VAR_CMD, VARF_WANTRES);
Parse_Error(mtype, "%s", line);
free(line);
@@ -1089,15 +1117,15 @@ ParseDoSrc(int tOp, const char *src)
*-----------------------------------------------------------------------
*/
static int
-ParseFindMain(void *gnp, void *dummy)
+ParseFindMain(void *gnp, void *dummy MAKE_ATTR_UNUSED)
{
GNode *gn = (GNode *)gnp;
if ((gn->type & OP_NOTARGET) == 0) {
mainNode = gn;
Targ_SetMain(gn);
- return (dummy ? 1 : 1);
+ return 1;
} else {
- return (dummy ? 0 : 0);
+ return 0;
}
}
@@ -1135,10 +1163,10 @@ ParseAddDir(void *path, void *name)
*-----------------------------------------------------------------------
*/
static int
-ParseClearPath(void *path, void *dummy)
+ParseClearPath(void *path, void *dummy MAKE_ATTR_UNUSED)
{
Dir_ClearPath((Lst) path);
- return(dummy ? 0 : 0);
+ return 0;
}
/*-
@@ -1229,9 +1257,9 @@ ParseDoDependency(char *line)
int length;
void *freeIt;
- (void)Var_Parse(cp, VAR_CMD, TRUE, &length, &freeIt);
- if (freeIt)
- free(freeIt);
+ (void)Var_Parse(cp, VAR_CMD, VARF_UNDEFERR|VARF_WANTRES,
+ &length, &freeIt);
+ free(freeIt);
cp += length-1;
}
}
@@ -1257,6 +1285,7 @@ ParseDoDependency(char *line)
goto out;
} else {
/* Done with this word; on to the next. */
+ cp = line;
continue;
}
}
@@ -1329,6 +1358,7 @@ ParseDoDependency(char *line)
* .BEGIN
* .END
* .ERROR
+ * .DELETE_ON_ERROR
* .INTERRUPT Are not to be considered the
* main target.
* .NOTPARALLEL Make only one target at a time.
@@ -1364,6 +1394,9 @@ ParseDoDependency(char *line)
(void)Lst_AtEnd(targets, gn);
DEFAULT = gn;
break;
+ case DeleteOnError:
+ deleteOnError = TRUE;
+ break;
case NotParallel:
maxJobs = 1;
break;
@@ -1592,7 +1625,8 @@ ParseDoDependency(char *line)
goto out;
}
*line = '\0';
- } else if ((specType == NotParallel) || (specType == SingleShell)) {
+ } else if ((specType == NotParallel) || (specType == SingleShell) ||
+ (specType == DeleteOnError)) {
*line = '\0';
}
@@ -1653,7 +1687,7 @@ ParseDoDependency(char *line)
Suff_SetNull(line);
break;
case ExObjdir:
- Main_SetObjdir(line);
+ Main_SetObjdir("%s", line);
break;
default:
break;
@@ -1669,10 +1703,12 @@ ParseDoDependency(char *line)
}
if (paths) {
Lst_Destroy(paths, NULL);
+ paths = NULL;
}
if (specType == ExPath)
Dir_SetPATH();
} else {
+ assert(paths == NULL);
while (*line) {
/*
* The targets take real sources, so we must beware of archive
@@ -1731,6 +1767,8 @@ ParseDoDependency(char *line)
}
out:
+ if (paths)
+ Lst_Destroy(paths, NULL);
if (curTargs)
Lst_Destroy(curTargs, NULL);
}
@@ -1853,7 +1891,7 @@ Parse_DoVar(char *line, GNode *ctxt)
* XXX Rather than counting () and {} we should look for $ and
* then expand the variable.
*/
- for (depth = 0, cp = line + 1; depth != 0 || *cp != '='; cp++) {
+ for (depth = 0, cp = line + 1; depth > 0 || *cp != '='; cp++) {
if (*cp == '(' || *cp == '{') {
depth++;
continue;
@@ -1944,7 +1982,7 @@ Parse_DoVar(char *line, GNode *ctxt)
if (!Var_Exists(line, ctxt))
Var_Set(line, "", ctxt, 0);
- cp = Var_Subst(NULL, cp, ctxt, FALSE);
+ cp = Var_Subst(NULL, cp, ctxt, VARF_WANTRES|VARF_ASSIGN);
oldVars = oldOldVars;
freeCp = TRUE;
@@ -1959,7 +1997,7 @@ Parse_DoVar(char *line, GNode *ctxt)
* expansion on the whole thing. The resulting string will need
* freeing when we're done, so set freeCmd to TRUE.
*/
- cp = Var_Subst(NULL, cp, VAR_CMD, TRUE);
+ cp = Var_Subst(NULL, cp, VAR_CMD, VARF_UNDEFERR|VARF_WANTRES);
freeCp = TRUE;
}
@@ -2151,7 +2189,7 @@ Parse_AddIncludeDir(char *dir)
*/
static void
-Parse_include_file(char *file, Boolean isSystem, int silent)
+Parse_include_file(char *file, Boolean isSystem, Boolean depinc, int silent)
{
struct loadedfile *lf;
char *fullname; /* full pathname of file */
@@ -2251,6 +2289,8 @@ Parse_include_file(char *file, Boolean isSystem, int silent)
/* Start reading from this file next */
Parse_SetInput(fullname, 0, -1, loadedfile_nextbuf, lf);
curFile->lf = lf;
+ if (depinc)
+ doing_depend = depinc; /* only turn it on */
}
static void
@@ -2298,9 +2338,9 @@ ParseDoInclude(char *line)
* Substitute for any variables in the file name before trying to
* find the thing.
*/
- file = Var_Subst(NULL, file, VAR_CMD, FALSE);
+ file = Var_Subst(NULL, file, VAR_CMD, VARF_WANTRES);
- Parse_include_file(file, endc == '>', silent);
+ Parse_include_file(file, endc == '>', (*line == 'd'), silent);
free(file);
}
@@ -2335,10 +2375,8 @@ ParseSetIncludedFile(void)
fprintf(debug_file, "%s: ${.INCLUDEDFROMDIR} = `%s' "
"${.INCLUDEDFROMFILE} = `%s'\n", __func__, pd, pf);
- if (fp)
- free(fp);
- if (dp)
- free(dp);
+ free(fp);
+ free(dp);
}
/*-
*---------------------------------------------------------------------
@@ -2390,15 +2428,19 @@ static void
ParseTrackInput(const char *name)
{
char *old;
+ char *ep;
char *fp = NULL;
size_t name_len = strlen(name);
old = Var_Value(MAKE_MAKEFILES, VAR_GLOBAL, &fp);
if (old) {
+ ep = old + strlen(old) - name_len;
/* does it contain name? */
for (; old != NULL; old = strchr(old, ' ')) {
if (*old == ' ')
old++;
+ if (old >= ep)
+ break; /* cannot contain name */
if (memcmp(old, name, name_len) == 0
&& (old[name_len] == 0 || old[name_len] == ' '))
goto cleanup;
@@ -2464,6 +2506,7 @@ Parse_SetInput(const char *name, int line, int fd,
curFile->nextbuf = nextbuf;
curFile->nextbuf_arg = arg;
curFile->lf = NULL;
+ curFile->depending = doing_depend; /* restore this on EOF */
assert(nextbuf != NULL);
@@ -2484,8 +2527,73 @@ Parse_SetInput(const char *name, int line, int fd,
ParseSetParseFile(name);
}
+/*-
+ *-----------------------------------------------------------------------
+ * IsInclude --
+ * Check if the line is an include directive
+ *
+ * Results:
+ * TRUE if it is.
+ *
+ * Side Effects:
+ * None
+ *
+ *-----------------------------------------------------------------------
+ */
+static Boolean
+IsInclude(const char *line, Boolean sysv)
+{
+ static const char inc[] = "include";
+ static const size_t inclen = sizeof(inc) - 1;
+
+ // 'd' is not valid for sysv
+ int o = strchr(&("ds-"[sysv]), *line) != NULL;
+
+ if (strncmp(line + o, inc, inclen) != 0)
+ return FALSE;
+
+ // Space is not mandatory for BSD .include
+ return !sysv || isspace((unsigned char)line[inclen + o]);
+}
+
+
#ifdef SYSVINCLUDE
/*-
+ *-----------------------------------------------------------------------
+ * IsSysVInclude --
+ * Check if the line is a SYSV include directive
+ *
+ * Results:
+ * TRUE if it is.
+ *
+ * Side Effects:
+ * None
+ *
+ *-----------------------------------------------------------------------
+ */
+static Boolean
+IsSysVInclude(const char *line)
+{
+ const char *p;
+
+ if (!IsInclude(line, TRUE))
+ return FALSE;
+
+ /* Avoid interpeting a dependency line as an include */
+ for (p = line; (p = strchr(p, ':')) != NULL;) {
+ if (*++p == '\0') {
+ /* end of line -> dependency */
+ return FALSE;
+ }
+ if (*p == ':' || isspace((unsigned char)*p)) {
+ /* :: operator or ': ' -> dependency */
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+/*-
*---------------------------------------------------------------------
* ParseTraditionalInclude --
* Push to another file.
@@ -2524,12 +2632,12 @@ ParseTraditionalInclude(char *line)
* Substitute for any variables in the file name before trying to
* find the thing.
*/
- all_files = Var_Subst(NULL, file, VAR_CMD, FALSE);
+ all_files = Var_Subst(NULL, file, VAR_CMD, VARF_WANTRES);
if (*file == '\0') {
Parse_Error(PARSE_FATAL,
"Filename missing from \"include\"");
- return;
+ goto out;
}
for (file = all_files; !done; file = cp + 1) {
@@ -2542,8 +2650,9 @@ ParseTraditionalInclude(char *line)
else
done = 1;
- Parse_include_file(file, FALSE, silent);
+ Parse_include_file(file, FALSE, FALSE, silent);
}
+out:
free(all_files);
}
#endif
@@ -2592,8 +2701,9 @@ ParseGmakeExport(char *line)
/*
* Expand the value before putting it in the environment.
*/
- value = Var_Subst(NULL, value, VAR_CMD, FALSE);
+ value = Var_Subst(NULL, value, VAR_CMD, VARF_WANTRES);
setenv(variable, value, 1);
+ free(value);
}
#endif
@@ -2620,6 +2730,7 @@ ParseEOF(void)
assert(curFile->nextbuf != NULL);
+ doing_depend = curFile->depending; /* restore this */
/* get next input buffer, if any */
ptr = curFile->nextbuf(curFile->nextbuf_arg, &len);
curFile->P_ptr = ptr;
@@ -2981,9 +3092,7 @@ Parse_File(const char *name, int fd)
for (cp = line + 1; isspace((unsigned char)*cp); cp++) {
continue;
}
- if (strncmp(cp, "include", 7) == 0 ||
- ((cp[0] == 's' || cp[0] == '-') &&
- strncmp(&cp[1], "include", 7) == 0)) {
+ if (IsInclude(cp, FALSE)) {
ParseDoInclude(cp);
continue;
}
@@ -3045,12 +3154,7 @@ Parse_File(const char *name, int fd)
}
#ifdef SYSVINCLUDE
- if (((strncmp(line, "include", 7) == 0 &&
- isspace((unsigned char) line[7])) ||
- ((line[0] == 's' || line[0] == '-') &&
- strncmp(&line[1], "include", 7) == 0 &&
- isspace((unsigned char) line[8]))) &&
- strchr(line, ':') == NULL) {
+ if (IsSysVInclude(line)) {
/*
* It's an S3/S5-style "include".
*/
@@ -3141,7 +3245,7 @@ Parse_File(const char *name, int fd)
* variables expanded before being parsed. Tell the variable
* module to complain if some variable is undefined...
*/
- line = Var_Subst(NULL, line, VAR_CMD, TRUE);
+ line = Var_Subst(NULL, line, VAR_CMD, VARF_UNDEFERR|VARF_WANTRES);
/*
* Need a non-circular list for the target nodes