diff options
Diffstat (limited to 'devel/bmake/files/parse.c')
-rw-r--r-- | devel/bmake/files/parse.c | 218 |
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 |