summaryrefslogtreecommitdiff
path: root/devel/bmake/files/parse.c
diff options
context:
space:
mode:
authorbsiegert <bsiegert@pkgsrc.org>2011-06-18 22:17:41 +0000
committerbsiegert <bsiegert@pkgsrc.org>2011-06-18 22:17:41 +0000
commit7cb16bb66575467ac59352068eaec344242b439a (patch)
treec8f5dd7d540977ec601c02e7d04c13e80115f641 /devel/bmake/files/parse.c
parent92219014db9b676e01e78bbe73c3877f94f2a471 (diff)
downloadpkgsrc-7cb16bb66575467ac59352068eaec344242b439a.tar.gz
Import bmake-20110606. Many changes, among them:
- unit-tests/modts now works on MirBSD - meta mode - ApplyModifiers: when we parse a variable which is not the entire modifier string, or not followed by ':', do not consider it as containing modifiers. - when long modifiers fail to match, check sysV style. - :hash - cheap 32bit hash of value - :localtime, :gmtime - use value as format string for strftime. - fix for use after free() in CondDoExists(). - boot-strap (TOOL_DIFF): aparently at least on linux distro formats the output of 'type' differently - so eat any "()" - correct sysV substitution handling of empty lhs and variable - correct exists() check for dir with trailing / - correct handling of modifiers for non-existant variables during evaluation of conditionals. - fix for incorrect .PARSEDIR when .OBJDIR is re-computed after makefiles have been read. - fix example of :? modifier in man page. - sigcompat.c: convert to ansi so we can use higher warning levels. - parse.c: SunOS 5.8 at least does not have MAP_FILE - use mmap(2) if available, for reading makefiles - to ensure unit-tests results match, need to control LC_ALL as well as LANG. - if stale dependency is an IMPSRC, search via .PATH - machine.sh: like os.sh, allow for uname -p producing useless drivel - boot-strap: document configure knobs for meta and filemon.
Diffstat (limited to 'devel/bmake/files/parse.c')
-rw-r--r--devel/bmake/files/parse.c522
1 files changed, 382 insertions, 140 deletions
diff --git a/devel/bmake/files/parse.c b/devel/bmake/files/parse.c
index 5e549f0c6c4..40a14cba1a6 100644
--- a/devel/bmake/files/parse.c
+++ b/devel/bmake/files/parse.c
@@ -1,4 +1,4 @@
-/* $NetBSD: parse.c,v 1.1.1.8 2010/09/07 14:12:02 joerg Exp $ */
+/* $NetBSD: parse.c,v 1.1.1.9 2011/06/18 22:18:06 bsiegert Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -69,14 +69,14 @@
*/
#ifndef MAKE_NATIVE
-static char rcsid[] = "$NetBSD: parse.c,v 1.1.1.8 2010/09/07 14:12:02 joerg Exp $";
+static char rcsid[] = "$NetBSD: parse.c,v 1.1.1.9 2011/06/18 22:18:06 bsiegert 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.8 2010/09/07 14:12:02 joerg Exp $");
+__RCSID("$NetBSD: parse.c,v 1.1.1.9 2011/06/18 22:18:06 bsiegert Exp $");
#endif
#endif /* not lint */
#endif
@@ -123,12 +123,22 @@ __RCSID("$NetBSD: parse.c,v 1.1.1.8 2010/09/07 14:12:02 joerg Exp $");
* Parse_MainName Returns a Lst of the main target to create.
*/
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdio.h>
+#ifndef MAP_FILE
+#define MAP_FILE 0
+#endif
+#ifndef MAP_COPY
+#define MAP_COPY MAP_PRIVATE
+#endif
+
#include "make.h"
#include "hash.h"
#include "dir.h"
@@ -136,56 +146,47 @@ __RCSID("$NetBSD: parse.c,v 1.1.1.8 2010/09/07 14:12:02 joerg Exp $");
#include "buf.h"
#include "pathnames.h"
-/*
- * These values are returned by ParseEOF to tell Parse_File whether to
- * CONTINUE parsing, i.e. it had only reached the end of an include file,
- * or if it's DONE.
- */
-#define CONTINUE 1
-#define DONE 0
-static Lst targets; /* targets we're working on */
-#ifdef CLEANUP
-static Lst targCmds; /* command lines for targets */
+#ifdef HAVE_MMAP
+#include <sys/mman.h>
+
+#ifndef MAP_COPY
+#define MAP_COPY MAP_PRIVATE
#endif
-static Boolean inLine; /* true if currently in a dependency
- * line or its commands */
-static int fatals = 0;
+#ifndef MAP_FILE
+#define MAP_FILE 0
+#endif
+#endif
+
+////////////////////////////////////////////////////////////
+// types and constants
-static GNode *mainNode; /* The main target to create. This is the
- * first target on the first dependency
- * line in the first makefile */
+/*
+ * Structure for a file being read ("included file")
+ */
typedef struct IFile {
const char *fname; /* name of file */
int lineno; /* current line number in file */
int first_lineno; /* line number of start of text */
- int fd; /* the open file */
int cond_depth; /* 'if' nesting when file opened */
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 */
- int P_buflen; /* current size of file buffer */
- char *(*nextbuf)(void *); /* Function to get more data */
+ char *(*nextbuf)(void *, size_t *); /* Function to get more data */
void *nextbuf_arg; /* Opaque arg for nextbuf() */
+ struct loadedfile *lf; /* loadedfile object, if any */
} IFile;
-#define IFILE_BUFLEN 0x8000
-static IFile *curFile;
-
/*
- * Definitions for handling #include specifications
+ * These values are returned by ParseEOF to tell Parse_File whether to
+ * CONTINUE parsing, i.e. it had only reached the end of an include file,
+ * or if it's DONE.
*/
+#define CONTINUE 1
+#define DONE 0
-static Lst includes; /* stack of IFiles generated by .includes */
-Lst parseIncPath; /* list of directories for "..." includes */
-Lst sysIncPath; /* list of directories for <...> includes */
-Lst defIncPath; /* default directories for <...> includes */
-
-/*-
- * specType contains the SPECial TYPE of the current target. It is
- * Not if the target is unspecial. If it *is* special, however, the children
- * are linked as children of the parent but not vice versa. This variable is
- * set in ParseDoDependency
+/*
+ * Tokens for target attributes
*/
typedef enum {
Begin, /* .BEGIN */
@@ -196,10 +197,13 @@ typedef enum {
Includes, /* .INCLUDES */
Interrupt, /* .INTERRUPT */
Libs, /* .LIBS */
+ Meta, /* .META */
MFlags, /* .MFLAGS or .MAKEFLAGS */
Main, /* .MAIN and we don't have anything user-specified to
* make */
NoExport, /* .NOEXPORT */
+ NoMeta, /* .NOMETA */
+ NoMetaCmp, /* .NOMETA_CMP */
NoPath, /* .NOPATH */
Not, /* Not special */
NotParallel, /* .NOTPARALLEL */
@@ -221,16 +225,74 @@ typedef enum {
Attribute /* Generic attribute */
} ParseSpecial;
+/*
+ * Other tokens
+ */
+#define LPAREN '('
+#define RPAREN ')'
+
+
+////////////////////////////////////////////////////////////
+// result data
+
+/*
+ * The main target to create. This is the first target on the first
+ * dependency line in the first makefile.
+ */
+static GNode *mainNode;
+
+////////////////////////////////////////////////////////////
+// eval state
+
+/* targets we're working on */
+static Lst targets;
+
+#ifdef CLEANUP
+/* command lines for targets */
+static Lst targCmds;
+#endif
+
+/*
+ * specType contains the SPECial TYPE of the current target. It is
+ * Not if the target is unspecial. If it *is* special, however, the children
+ * are linked as children of the parent but not vice versa. This variable is
+ * set in ParseDoDependency
+ */
static ParseSpecial specType;
-#define LPAREN '('
-#define RPAREN ')'
/*
* Predecessor node for handling .ORDER. Initialized to NULL when .ORDER
* seen, then set to each successive source on the line.
*/
static GNode *predecessor;
+////////////////////////////////////////////////////////////
+// parser state
+
+/* true if currently in a dependency line or its commands */
+static Boolean inLine;
+
+/* number of fatal errors */
+static int fatals = 0;
+
+/*
+ * Variables for doing includes
+ */
+
+/* current file being read */
+static IFile *curFile;
+
+/* stack of IFiles generated by .includes */
+static Lst includes;
+
+/* include paths (lists of directories) */
+Lst parseIncPath; /* dirs for "..." includes */
+Lst sysIncPath; /* dirs for <...> includes */
+Lst defIncPath; /* default for sysIncPath */
+
+////////////////////////////////////////////////////////////
+// parser tables
+
/*
* The parseKeywords table is searched using binary search when deciding
* if a target or source is special. The 'spec' field is the ParseSpecial
@@ -238,7 +300,7 @@ static GNode *predecessor;
* the 'op' field is the operator to apply to the list of targets if the
* keyword is used as a source ("0" if the keyword isn't special as a source)
*/
-static struct {
+static const struct {
const char *name; /* Name of keyword */
ParseSpecial spec; /* Type when used as a target */
int op; /* Operator when used as a source */
@@ -258,7 +320,10 @@ static struct {
{ ".MAIN", Main, 0 },
{ ".MAKE", Attribute, OP_MAKE },
{ ".MAKEFLAGS", MFlags, 0 },
+{ ".META", Meta, OP_META },
{ ".MFLAGS", MFlags, 0 },
+{ ".NOMETA", NoMeta, OP_NOMETA },
+{ ".NOMETA_CMP", NoMetaCmp, OP_NOMETA_CMP },
{ ".NOPATH", NoPath, OP_NOPATH },
{ ".NOTMAIN", Attribute, OP_NOTMAIN },
{ ".NOTPARALLEL", NotParallel, 0 },
@@ -284,6 +349,9 @@ static struct {
{ ".WAIT", Wait, 0 },
};
+////////////////////////////////////////////////////////////
+// local functions
+
static int ParseIsEscaped(const char *, const char *);
static void ParseErrorInternal(const char *, size_t, int, const char *, ...)
__attribute__((__format__(__printf__, 4, 5)));
@@ -309,8 +377,216 @@ static char *ParseReadLine(void);
static void ParseFinishLine(void);
static void ParseMark(GNode *);
-extern int maxJobs;
+////////////////////////////////////////////////////////////
+// file loader
+struct loadedfile {
+ const char *path; /* name, for error reports */
+ char *buf; /* contents buffer */
+ size_t len; /* length of contents */
+ size_t maplen; /* length of mmap area, or 0 */
+ Boolean used; /* XXX: have we used the data yet */
+};
+
+/*
+ * Constructor/destructor for loadedfile
+ */
+static struct loadedfile *
+loadedfile_create(const char *path)
+{
+ struct loadedfile *lf;
+
+ lf = bmake_malloc(sizeof(*lf));
+ lf->path = (path == NULL ? "(stdin)" : path);
+ lf->buf = NULL;
+ lf->len = 0;
+ lf->maplen = 0;
+ lf->used = FALSE;
+ return lf;
+}
+
+static void
+loadedfile_destroy(struct loadedfile *lf)
+{
+ if (lf->buf != NULL) {
+ if (lf->maplen > 0) {
+#ifdef HAVE_MMAP
+ munmap(lf->buf, lf->maplen);
+#endif
+ } else {
+ free(lf->buf);
+ }
+ }
+ free(lf);
+}
+
+/*
+ * nextbuf() operation for loadedfile, as needed by the weird and twisted
+ * logic below. Once that's cleaned up, we can get rid of lf->used...
+ */
+static char *
+loadedfile_nextbuf(void *x, size_t *len)
+{
+ struct loadedfile *lf = x;
+
+ if (lf->used) {
+ return NULL;
+ }
+ lf->used = TRUE;
+ *len = lf->len;
+ return lf->buf;
+}
+
+/*
+ * Try to get the size of a file.
+ */
+static ReturnStatus
+load_getsize(int fd, size_t *ret)
+{
+ struct stat st;
+
+ if (fstat(fd, &st) < 0) {
+ return FAILURE;
+ }
+
+ if (!S_ISREG(st.st_mode)) {
+ return FAILURE;
+ }
+
+ /*
+ * st_size is an off_t, which is 64 bits signed; *ret is
+ * size_t, which might be 32 bits unsigned or 64 bits
+ * unsigned. Rather than being elaborate, just punt on
+ * files that are more than 2^31 bytes. We should never
+ * see a makefile that size in practice...
+ *
+ * While we're at it reject negative sizes too, just in case.
+ */
+ if (st.st_size < 0 || st.st_size > 0x7fffffff) {
+ return FAILURE;
+ }
+
+ *ret = (size_t) st.st_size;
+ return SUCCESS;
+}
+
+/*
+ * Read in a file.
+ *
+ * Until the path search logic can be moved under here instead of
+ * being in the caller in another source file, we need to have the fd
+ * passed in already open. Bleh.
+ *
+ * If the path is NULL use stdin and (to insure against fd leaks)
+ * assert that the caller passed in -1.
+ */
+static struct loadedfile *
+loadfile(const char *path, int fd)
+{
+ struct loadedfile *lf;
+#ifdef HAVE_MMAP
+ long pagesize;
+#endif
+ ssize_t result;
+ size_t bufpos;
+
+ lf = loadedfile_create(path);
+
+ if (path == NULL) {
+ assert(fd == -1);
+ fd = STDIN_FILENO;
+ } else {
+#if 0 /* notyet */
+ fd = open(path, O_RDONLY);
+ if (fd < 0) {
+ ...
+ Error("%s: %s", path, strerror(errno));
+ exit(1);
+ }
+#endif
+ }
+
+#ifdef HAVE_MMAP
+ if (load_getsize(fd, &lf->len) == SUCCESS) {
+ /* found a size, try mmap */
+ pagesize = sysconf(_SC_PAGESIZE);
+ if (pagesize <= 0) {
+ pagesize = 0x1000;
+ }
+ /* round size up to a page */
+ lf->maplen = pagesize * ((lf->len + pagesize - 1)/pagesize);
+
+ /*
+ * XXX hack for dealing with empty files; remove when
+ * we're no longer limited by interfacing to the old
+ * logic elsewhere in this file.
+ */
+ if (lf->maplen == 0) {
+ lf->maplen = pagesize;
+ }
+
+ /*
+ * FUTURE: remove PROT_WRITE when the parser no longer
+ * needs to scribble on the input.
+ */
+ lf->buf = mmap(NULL, lf->maplen, PROT_READ|PROT_WRITE,
+ MAP_FILE|MAP_COPY, fd, 0);
+ if (lf->buf != MAP_FAILED) {
+ /* succeeded */
+ if (lf->len == lf->maplen && lf->buf[lf->len - 1] != '\n') {
+ char *b = malloc(lf->len + 1);
+ b[lf->len] = '\n';
+ memcpy(b, lf->buf, lf->len++);
+ munmap(lf->buf, lf->maplen);
+ lf->maplen = 0;
+ lf->buf = b;
+ }
+ goto done;
+ }
+ }
+#endif
+ /* cannot mmap; load the traditional way */
+
+ lf->maplen = 0;
+ lf->len = 1024;
+ lf->buf = bmake_malloc(lf->len);
+
+ bufpos = 0;
+ while (1) {
+ assert(bufpos <= lf->len);
+ if (bufpos == lf->len) {
+ lf->len *= 2;
+ lf->buf = bmake_realloc(lf->buf, lf->len);
+ }
+ result = read(fd, lf->buf + bufpos, lf->len - bufpos);
+ if (result < 0) {
+ Error("%s: read error: %s", path, strerror(errno));
+ exit(1);
+ }
+ if (result == 0) {
+ break;
+ }
+ bufpos += result;
+ }
+ assert(bufpos <= lf->len);
+ lf->len = bufpos;
+
+ /* truncate malloc region to actual length (maybe not useful) */
+ if (lf->len > 0) {
+ lf->buf = bmake_realloc(lf->buf, lf->len);
+ }
+
+#ifdef HAVE_MMAP
+done:
+#endif
+ if (path != NULL) {
+ close(fd);
+ }
+ return lf;
+}
+
+////////////////////////////////////////////////////////////
+// old code
/*-
*----------------------------------------------------------------------
@@ -404,7 +680,7 @@ ParseVErrorInternal(FILE *f, const char *cfname, size_t clineno, int type,
const char *dir;
/*
- * Nothing is more anoying than not knowing
+ * Nothing is more annoying than not knowing
* which Makefile is the culprit.
*/
dir = Var_Value(".PARSEDIR", VAR_GLOBAL, &cp);
@@ -1786,6 +2062,7 @@ Parse_AddIncludeDir(char *dir)
static void
Parse_include_file(char *file, Boolean isSystem, int silent)
{
+ struct loadedfile *lf;
char *fullname; /* full pathname of file */
char *newName;
char *prefEnd, *incdir;
@@ -1876,8 +2153,12 @@ Parse_include_file(char *file, Boolean isSystem, int silent)
return;
}
+ /* load it */
+ lf = loadfile(fullname, fd);
+
/* Start reading from this file next */
- Parse_SetInput(fullname, 0, fd, NULL, NULL);
+ Parse_SetInput(fullname, 0, -1, loadedfile_nextbuf, lf);
+ curFile->lf = lf;
}
static void
@@ -1955,7 +2236,7 @@ ParseSetParseFile(const char *filename)
slash = strrchr(filename, '/');
if (slash == NULL) {
- Var_Set(".PARSEDIR", ".", VAR_GLOBAL, 0);
+ Var_Set(".PARSEDIR", curdir, VAR_GLOBAL, 0);
Var_Set(".PARSEFILE", filename, VAR_GLOBAL, 0);
} else {
len = slash - filename;
@@ -2014,9 +2295,11 @@ ParseTrackInput(const char *name)
*---------------------------------------------------------------------
*/
void
-Parse_SetInput(const char *name, int line, int fd, char *(*nextbuf)(void *), void *arg)
+Parse_SetInput(const char *name, int line, int fd,
+ char *(*nextbuf)(void *, size_t *), void *arg)
{
char *buf;
+ size_t len;
if (name == NULL)
name = curFile->fname;
@@ -2047,33 +2330,22 @@ Parse_SetInput(const char *name, int line, int fd, char *(*nextbuf)(void *), voi
curFile->fname = name;
curFile->lineno = line;
curFile->first_lineno = line;
- curFile->fd = fd;
curFile->nextbuf = nextbuf;
curFile->nextbuf_arg = arg;
+ curFile->lf = NULL;
- if (nextbuf == NULL) {
- /*
- * Allocate a 32k data buffer (as stdio seems to).
- * Set pointers so that first ParseReadc has to do a file read.
- */
- buf = bmake_malloc(IFILE_BUFLEN);
- buf[0] = 0;
- curFile->P_str = buf;
- curFile->P_ptr = buf;
- curFile->P_end = buf;
- curFile->P_buflen = IFILE_BUFLEN;
- } else {
- /* Get first block of input data */
- buf = curFile->nextbuf(curFile->nextbuf_arg);
- if (buf == NULL) {
- /* Was all a waste of time ... */
- free(curFile);
- return;
- }
- curFile->P_str = buf;
- curFile->P_ptr = buf;
- curFile->P_end = NULL;
+ assert(nextbuf != NULL);
+
+ /* Get first block of input data */
+ buf = curFile->nextbuf(curFile->nextbuf_arg, &len);
+ if (buf == NULL) {
+ /* Was all a waste of time ... */
+ free(curFile);
+ return;
}
+ curFile->P_str = buf;
+ curFile->P_ptr = buf;
+ curFile->P_end = buf+len;
curFile->cond_depth = Cond_save_depth();
ParseSetParseFile(name);
@@ -2162,26 +2434,31 @@ static int
ParseEOF(void)
{
char *ptr;
-
- if (curFile->nextbuf != NULL) {
- /* eg .for loop data, get next iteration */
- ptr = curFile->nextbuf(curFile->nextbuf_arg);
- curFile->P_ptr = ptr;
- curFile->P_str = ptr;
- curFile->lineno = curFile->first_lineno;
- if (ptr != NULL) {
- /* Iterate again */
- return CONTINUE;
- }
+ size_t len;
+
+ assert(curFile->nextbuf != NULL);
+
+ /* get next input buffer, if any */
+ ptr = curFile->nextbuf(curFile->nextbuf_arg, &len);
+ curFile->P_ptr = ptr;
+ curFile->P_str = ptr;
+ curFile->P_end = ptr + len;
+ curFile->lineno = curFile->first_lineno;
+ if (ptr != NULL) {
+ /* Iterate again */
+ return CONTINUE;
}
/* Ensure the makefile (or loop) didn't have mismatched conditionals */
Cond_restore_depth(curFile->cond_depth);
+ if (curFile->lf != NULL) {
+ loadedfile_destroy(curFile->lf);
+ curFile->lf = NULL;
+ }
+
/* Dispose of curFile info */
/* Leak curFile->fname because all the gnodes have pointers to it */
- if (curFile->fd != -1)
- close(curFile->fd);
free(curFile->P_str);
free(curFile);
@@ -2195,8 +2472,8 @@ ParseEOF(void)
}
if (DEBUG(PARSE))
- fprintf(debug_file, "ParseEOF: returning to file %s, line %d, fd %d\n",
- curFile->fname, curFile->lineno, curFile->fd);
+ fprintf(debug_file, "ParseEOF: returning to file %s, line %d\n",
+ curFile->fname, curFile->lineno);
/* Restore the PARSEDIR/PARSEFILE variables */
ParseSetParseFile(curFile->fname);
@@ -2217,7 +2494,6 @@ ParseGetLine(int flags, int *length)
char *escaped;
char *comment;
char *tp;
- int len, dist;
/* Loop through blank lines and comment lines */
for (;;) {
@@ -2228,67 +2504,25 @@ ParseGetLine(int flags, int *length)
escaped = NULL;
comment = NULL;
for (;;) {
+ if (cf->P_end != NULL && ptr == cf->P_end) {
+ /* end of buffer */
+ ch = 0;
+ break;
+ }
ch = *ptr;
if (ch == 0 || (ch == '\\' && ptr[1] == 0)) {
if (cf->P_end == NULL)
/* End of string (aka for loop) data */
break;
- /* End of data read from file, read more data */
- if (ptr != cf->P_end && (ch != '\\' || ptr + 1 != cf->P_end)) {
- Parse_Error(PARSE_FATAL, "Zero byte read from file");
- return NULL;
- }
- /* Move existing data to (near) start of file buffer */
- len = cf->P_end - cf->P_ptr;
- tp = cf->P_str + 32;
- memmove(tp, cf->P_ptr, len);
- dist = cf->P_ptr - tp;
- /* Update all pointers to reflect moved data */
- ptr -= dist;
- line -= dist;
- line_end -= dist;
- if (escaped)
- escaped -= dist;
- if (comment)
- comment -= dist;
- cf->P_ptr = tp;
- tp += len;
- cf->P_end = tp;
- /* Try to read more data from file into buffer space */
- len = cf->P_str + cf->P_buflen - tp - 32;
- if (len <= 0) {
- /* We need a bigger buffer to hold this line */
- tp = bmake_realloc(cf->P_str, cf->P_buflen + IFILE_BUFLEN);
- cf->P_ptr = cf->P_ptr - cf->P_str + tp;
- cf->P_end = cf->P_end - cf->P_str + tp;
- ptr = ptr - cf->P_str + tp;
- line = line - cf->P_str + tp;
- line_end = line_end - cf->P_str + tp;
- if (escaped)
- escaped = escaped - cf->P_str + tp;
- if (comment)
- comment = comment - cf->P_str + tp;
- cf->P_str = tp;
- tp = cf->P_end;
- len += IFILE_BUFLEN;
- cf->P_buflen += IFILE_BUFLEN;
- }
- len = read(cf->fd, tp, len);
- if (len <= 0) {
- if (len < 0) {
- Parse_Error(PARSE_FATAL, "Makefile read error: %s",
- strerror(errno));
- return NULL;
- }
- /* End of file */
+ if (cf->nextbuf != NULL) {
+ /*
+ * End of this buffer; return EOF and outer logic
+ * will get the next one. (eww)
+ */
break;
}
- /* 0 terminate the data, and update end pointer */
- tp += len;
- cf->P_end = tp;
- *tp = 0;
- /* Process newly read characters */
- continue;
+ Parse_Error(PARSE_FATAL, "Zero byte read from file");
+ return NULL;
}
if (ch == '\\') {
@@ -2459,7 +2693,7 @@ ParseReadLine(void)
line = ParseGetLine(PARSE_RAW, &lineLength);
if (line == NULL) {
Parse_Error(PARSE_FATAL,
- "Unexpected end of file in for loop.\n");
+ "Unexpected end of file in for loop.");
break;
}
} while (For_Accum(line));
@@ -2522,11 +2756,19 @@ Parse_File(const char *name, int fd)
{
char *cp; /* pointer into the line */
char *line; /* the line we're working on */
+ struct loadedfile *lf;
+
+ lf = loadfile(name, fd);
inLine = FALSE;
fatals = 0;
- Parse_SetInput(name, 0, fd, NULL, NULL);
+ if (name == NULL) {
+ name = "(stdin)";
+ }
+
+ Parse_SetInput(name, 0, -1, loadedfile_nextbuf, lf);
+ curFile->lf = lf;
do {
for (; (line = ParseReadLine()) != NULL; ) {
@@ -2719,7 +2961,7 @@ Parse_File(const char *name, int fd)
if (fatals) {
(void)fflush(stdout);
(void)fprintf(stderr,
- "%s: Fatal errors encountered -- cannot continue\n",
+ "%s: Fatal errors encountered -- cannot continue",
progname);
PrintOnError(NULL, NULL);
exit(1);