diff options
author | Marc Espie <espie@cvs.openbsd.org> | 2000-06-23 16:39:46 +0000 |
---|---|---|
committer | Marc Espie <espie@cvs.openbsd.org> | 2000-06-23 16:39:46 +0000 |
commit | 43e184c8683ee4a828d2175e016b583f0b9dd036 (patch) | |
tree | ebf397bd390fda96e8cf0c874747501b7a065a50 /usr.bin/make | |
parent | 3be881f38f781744cfe617c28ce0fad7f282d1fe (diff) |
This patch is worth a lot, speed-wise.
This does introduce a proper stack of IFiles to handle included files:
instead of having the current file be a special case, it's also an IFile.
The corresponding code is slightly unobfuscated, removing the error-prone
ParseEOF function, freeing the filename systematically (thus, main.c needs
to strdup stdin), and merging both include functions lookup into one.
The speed gain comes from changing the IFile structure to merge with
fgetln seamlessly.
The low-level parse code is mostly moved to a new file, lowparse.c, to
make things easier to read (see next patch as well).
Accordingly, util.c gains a fgetln.
Note the interaction between Parse_File, Dir_FindFile, and ReadMakefile in
main.c. This patch closes a subtle memory hole (only the Makefile names,
so rather small).
Reviewed by miod@.
Diffstat (limited to 'usr.bin/make')
-rw-r--r-- | usr.bin/make/Makefile | 6 | ||||
-rw-r--r-- | usr.bin/make/lowparse.c | 292 | ||||
-rw-r--r-- | usr.bin/make/lowparse.h | 55 | ||||
-rw-r--r-- | usr.bin/make/main.c | 6 | ||||
-rw-r--r-- | usr.bin/make/parse.c | 666 | ||||
-rw-r--r-- | usr.bin/make/util.c | 31 |
6 files changed, 488 insertions, 568 deletions
diff --git a/usr.bin/make/Makefile b/usr.bin/make/Makefile index 6dcd9b96d87..59e56229621 100644 --- a/usr.bin/make/Makefile +++ b/usr.bin/make/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.17 2000/06/23 16:27:29 espie Exp $ +# $OpenBSD: Makefile,v 1.18 2000/06/23 16:39:45 espie Exp $ PROG= make CFLAGS+= -I${.OBJDIR} -I${.CURDIR} -Wall -Wno-char-subscripts -Wno-unused -Wstrict-prototypes#-Wmissing-prototypes -Wstrict-prototypes @@ -7,8 +7,8 @@ CFLAGS+= -I${.OBJDIR} -I${.CURDIR} -Wall -Wno-char-subscripts -Wno-unused -Wstri CFLAGS+=-O0 .endif -SRCS= arch.c buf.c compat.c cond.c dir.c error.c for.c hash.c job.c main.c \ - make.c parse.c str.c suff.c targ.c var.c #util.c +SRCS= arch.c buf.c compat.c cond.c dir.c error.c for.c hash.c job.c lowparse.c \ + main.c make.c parse.c str.c suff.c targ.c var.c #util.c SRCS+= lstAppend.c lstAtEnd.c lstAtFront.c lstClose.c lstConcat.c \ lstConcatDestroy.c lstDeQueue.c lstDestroy.c lstDupl.c lstEnQueue.c \ lstFindFrom.c lstForEachFrom.c \ diff --git a/usr.bin/make/lowparse.c b/usr.bin/make/lowparse.c new file mode 100644 index 00000000000..3c1faeee0dc --- /dev/null +++ b/usr.bin/make/lowparse.c @@ -0,0 +1,292 @@ +/* $OpenBSD: lowparse.c,v 1.1 2000/06/23 16:39:45 espie Exp $ */ + +/* low-level parsing functions. */ + +/* + * Copyright (c) 1999,2000 Marc Espie. + * + * Extensive code changes for the OpenBSD project. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD + * PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdarg.h> +#include <stdio.h> +#include <assert.h> +#include "make.h" +#include "buf.h" +#include "lowparse.h" + +#ifdef CLEANUP +static LIST fileNames; /* file names to free at end */ +#endif + +static LIST includes; /* stack of IFiles generated by + * #includes */ + +static IFile *new_ifile __P((char *, FILE *)); +static IFile *new_istring __P((char *, char *, unsigned long)); +static void free_ifile __P((IFile *)); +static void ParseVErrorInternal __P((char *, unsigned long, int, char *, va_list)); +static int skiptoendofline __P((void)); +static int ParseSkipEmptyLines __P((Buffer)); +static int fatals = 0; + +/*- + * ParseVErrorInternal -- + * Error message abort function for parsing. Prints out the context + * of the error (line number and file) as well as the message with + * two optional arguments. + * + * Side Effects: + * "fatals" is incremented if the level is PARSE_FATAL. + */ +/* VARARGS */ +static void +#ifdef __STDC__ +ParseVErrorInternal(char *cfname, unsigned long clineno, int type, char *fmt, + va_list ap) +#else +ParseVErrorInternal(va_alist) + va_dcl +#endif +{ + (void)fprintf(stderr, "\"%s\", line %lu: ", cfname, clineno); + if (type == PARSE_WARNING) + (void)fprintf(stderr, "warning: "); + (void)vfprintf(stderr, fmt, ap); + va_end(ap); + (void)fprintf(stderr, "\n"); + if (type == PARSE_FATAL) + fatals ++; +} + +/*- + * Parse_Error -- + * External interface to ParseVErrorInternal; uses the default filename + * Line number. + */ +/* VARARGS */ +void +#ifdef __STDC__ +Parse_Error(int type, char *fmt, ...) +#else +Parse_Error(va_alist) + va_dcl +#endif +{ + va_list ap; +#ifdef __STDC__ + va_start(ap, fmt); +#else + int type; /* Error type (PARSE_WARNING, PARSE_FATAL) */ + char *fmt; + + va_start(ap); + type = va_arg(ap, int); + fmt = va_arg(ap, char *); +#endif + + ParseVErrorInternal(current->fname, current->lineno, type, fmt, ap); +} + +static IFile * +new_ifile(name, stream) + char *name; + FILE *stream; +{ + IFile *ifile; +#ifdef CLEANUP + Lst_AtEnd(&fileNames, name); +#endif + + ifile = emalloc(sizeof(*ifile)); + ifile->fname = name; + /* Naturally enough, we start reading at line 0 */ + ifile->lineno = 0; + ifile->F = stream; + ifile->ptr = ifile->end = NULL; + return ifile; +} + +static void +free_ifile(ifile) + IFile *ifile; +{ + if (ifile->F) + (void)fclose(ifile->F); + else + free(ifile->str); + /* Note we can't free the file names yet, as they are embedded in GN for + * error reports. */ + free(ifile); +} + +static IFile * +new_istring(str, name, lineno) + char *str; + char *name; + unsigned long lineno; +{ + IFile *ifile; + + ifile = emalloc(sizeof(*ifile)); + ifile->fname = name; + ifile->F = NULL; + /* Strings are used from for loops... */ + ifile->lineno = lineno; + ifile->ptr = ifile->str = str; + ifile->end = str + strlen(str); + return ifile; +} + + +/*- + *--------------------------------------------------------------------- + * Parse_FromString -- + * Start Parsing from the given string + * + * Side Effects: + * A structure is added to the includes Lst and readProc, lineno, + * fname and curFILE are altered for the new file + *--------------------------------------------------------------------- + */ +void +Parse_FromString(str, lineno) + char *str; + unsigned long lineno; +{ + if (DEBUG(FOR)) + (void)fprintf(stderr, "%s\n----\n", str); + + if (current != NULL) + Lst_AtFront(&includes, current); + current = new_istring(str, current->fname, lineno); +} + + +void +Parse_FromFile(name, stream) + char *name; + FILE *stream; +{ + if (current != NULL) + Lst_AtFront(&includes, current); + current = new_ifile(name, stream); +} + +/*- + *--------------------------------------------------------------------- + * Parse_NextFile -- + * Called when EOF is reached in the current file. If we were reading + * an include file, the includes stack is popped and things set up + * to go back to reading the previous file at the previous location. + * + * Results: + * CONTINUE if there's more to do. DONE if not. + * + * Side Effects: + * The old curFILE, is closed. The includes list is shortened. + * lineno, curFILE, and fname are changed if CONTINUE is returned. + *--------------------------------------------------------------------- + */ +Boolean +Parse_NextFile() +{ + IFile *next; + + next = (IFile *)Lst_DeQueue(&includes); + if (next != NULL) { + if (current != NULL) + free_ifile(current); + current = next; + return TRUE; + } else + return FALSE; +} + + +int +newline() +{ + size_t len; + + if (current->F) { + current->ptr = fgetln(current->F, &len); + if (current->ptr) { + current->end = current->ptr + len; + return *current->ptr++; + } else { + current->end = NULL; + } + } + return EOF; +} + +void +ParseUnreadc(c) + char c; +{ + current->ptr--; + *current->ptr = c; +} + +unsigned long +Parse_Getlineno() +{ + return current->lineno; +} + +const char * +Parse_Getfilename() +{ + return current->fname; +} + +#ifdef CLEANUP +void +LowParse_Init() +{ + Lst_Init(&includes); + current = NULL; +} + +void +LowParse_End() +{ + Lst_Destroy(&includes, NOFREE); /* Should be empty now */ +} +#endif + + +void +Finish_Errors() +{ + if (current != NULL) { + free_ifile(current); + current = NULL; + } + if (fatals) { + fprintf(stderr, "Fatal errors encountered -- cannot continue\n"); + exit(1); + } +} diff --git a/usr.bin/make/lowparse.h b/usr.bin/make/lowparse.h new file mode 100644 index 00000000000..317de41774a --- /dev/null +++ b/usr.bin/make/lowparse.h @@ -0,0 +1,55 @@ +/* $OpenBSD: lowparse.h,v 1.1 2000/06/23 16:39:45 espie Exp $ */ + +/* + * Copyright (c) 1999 Marc Espie. + * + * Extensive code changes for the OpenBSD project. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD + * PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef LOWPARSE_H +#define LOWPARSE_H +extern void Parse_FromFile __P((char *, FILE *)); +extern Boolean Parse_NextFile __P((void)); +#ifdef CLEANUP +extern void LowParse_Init __P((void)); +extern void LowParse_End __P((void)); +#endif +extern void Finish_Errors __P((void)); +extern void ParseUnreadc __P((char)); + +/* Definitions for handling #include specifications */ +typedef struct IFile_ { + char *fname; /* name of file */ + unsigned long lineno; /* line number */ + FILE *F; /* open stream */ + char *str; /* read from char area */ + char *ptr; /* where we are */ + char *end; /* don't overdo it */ +} IFile; + +IFile *current; + +int newline __P((void)); +#define ParseReadc() current->ptr < current->end ? *current->ptr++ : newline() + +#endif diff --git a/usr.bin/make/main.c b/usr.bin/make/main.c index f8d93eca666..95ec5f71af8 100644 --- a/usr.bin/make/main.c +++ b/usr.bin/make/main.c @@ -1,4 +1,4 @@ -/* $OpenBSD: main.c,v 1.36 2000/06/23 16:23:26 espie Exp $ */ +/* $OpenBSD: main.c,v 1.37 2000/06/23 16:39:45 espie Exp $ */ /* $NetBSD: main.c,v 1.34 1997/03/24 20:56:36 gwr Exp $ */ /* @@ -49,7 +49,7 @@ static char copyright[] = #if 0 static char sccsid[] = "@(#)main.c 8.3 (Berkeley) 3/19/94"; #else -static char rcsid[] = "$OpenBSD: main.c,v 1.36 2000/06/23 16:23:26 espie Exp $"; +static char rcsid[] = "$OpenBSD: main.c,v 1.37 2000/06/23 16:39:45 espie Exp $"; #endif #endif /* not lint */ @@ -877,7 +877,7 @@ ReadMakefile(p, q) char *name, path[MAXPATHLEN + 1]; if (!strcmp(fname, "-")) { - Parse_File("(stdin)", stdin); + Parse_File(estrdup("(stdin)"), stdin); Var_Set("MAKEFILE", "", VAR_GLOBAL); } else { if ((stream = fopen(fname, "r")) != NULL) diff --git a/usr.bin/make/parse.c b/usr.bin/make/parse.c index a9904b811ec..bb9f0cdc3c7 100644 --- a/usr.bin/make/parse.c +++ b/usr.bin/make/parse.c @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.c,v 1.49 2000/06/23 16:23:26 espie Exp $ */ +/* $OpenBSD: parse.c,v 1.50 2000/06/23 16:39:45 espie Exp $ */ /* $NetBSD: parse.c,v 1.29 1997/03/10 21:20:04 christos Exp $ */ /* @@ -43,7 +43,7 @@ #if 0 static char sccsid[] = "@(#)parse.c 8.3 (Berkeley) 3/19/94"; #else -static char rcsid[] = "$OpenBSD: parse.c,v 1.49 2000/06/23 16:23:26 espie Exp $"; +static char rcsid[] = "$OpenBSD: parse.c,v 1.50 2000/06/23 16:39:45 espie Exp $"; #endif #endif /* not lint */ @@ -103,52 +103,17 @@ static char rcsid[] = "$OpenBSD: parse.c,v 1.49 2000/06/23 16:23:26 espie Exp $" #include "job.h" #include "buf.h" #include "pathnames.h" +#include "lowparse.h" -#ifdef CLEANUP -static LIST fileNames; /* file names to free at end */ -#endif - -/* - * 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 LIST targets; /* targets we're working on */ #ifdef CLEANUP static LIST targCmds; /* command lines for targets */ #endif static Boolean inLine; /* true if currently in a dependency * line or its commands */ -typedef struct { - char *str; - char *ptr; -} PTR; - -static char *fname; /* name of current file (for errors) */ -static unsigned long lineno; /* line number in current file */ -static FILE *curFILE = NULL; /* current makefile */ - -static PTR *curPTR = NULL; /* current makefile */ - -static int fatals = 0; - static GNode *mainNode; /* The main target to create. This is the * first target on the first dependency * line in the first makefile */ -/* - * Definitions for handling #include specifications - */ -typedef struct IFile { - char *fname; /* name of previous file */ - unsigned long lineno; /* saved line number */ - FILE *F; /* the open stream */ - PTR *p; /* the char pointer */ -} IFile; - -static LIST includes; /* stack of IFiles generated by - * #includes */ LIST parseIncPath; /* list of directories for "..." includes */ LIST sysIncPath; /* list of directories for <...> includes */ @@ -245,8 +210,6 @@ static struct { { ".WAIT", Wait, 0 }, }; -static void ParseErrorInternal __P((char *, unsigned long, int, char *, ...)); -static void ParseVErrorInternal __P((char *, unsigned long, int, char *, va_list)); static int ParseFindKeyword __P((char *)); static void ParseLinkSrc __P((void *, void *)); static int ParseDoOp __P((void *, void *)); @@ -258,13 +221,12 @@ static void ParseClearPath __P((void *)); static void ParseDoDependency __P((char *)); static void ParseAddCmd __P((void *, void *)); static int __inline ParseReadc __P((void)); -static void ParseUnreadc __P((int)); static void ParseHasCommands __P((void *)); static void ParseDoInclude __P((char *)); #ifdef SYSVINCLUDE static void ParseTraditionalInclude __P((char *)); #endif -static int ParseEOF __P((int)); +static void ParseLookupIncludeFile __P((char *, char *, Boolean)); static char *ParseReadLine __P((void)); static char *ParseSkipLine __P((int)); static void ParseFinishLine __P((void)); @@ -309,113 +271,6 @@ ParseFindKeyword (str) } /*- - * ParseVErrorInternal -- - * Error message abort function for parsing. Prints out the context - * of the error (line number and file) as well as the message with - * two optional arguments. - * - * Results: - * None - * - * Side Effects: - * "fatals" is incremented if the level is PARSE_FATAL. - */ -/* VARARGS */ -static void -#ifdef __STDC__ -ParseVErrorInternal(char *cfname, unsigned long clineno, int type, char *fmt, - va_list ap) -#else -ParseVErrorInternal(va_alist) - va_dcl -#endif -{ - (void)fprintf(stderr, "\"%s\", line %lu: ", cfname, clineno); - if (type == PARSE_WARNING) - (void)fprintf(stderr, "warning: "); - (void)vfprintf(stderr, fmt, ap); - va_end(ap); - (void)fprintf(stderr, "\n"); - (void)fflush(stderr); - if (type == PARSE_FATAL) - fatals += 1; -} - -/*- - * ParseErrorInternal -- - * Error function - * - * Results: - * None - * - * Side Effects: - * None - */ -/* VARARGS */ -static void -#ifdef __STDC__ -ParseErrorInternal(char *cfname, unsigned long clineno, int type, char *fmt, ...) -#else -ParseErrorInternal(va_alist) - va_dcl -#endif -{ - va_list ap; -#ifdef __STDC__ - va_start(ap, fmt); -#else - int type; /* Error type (PARSE_WARNING, PARSE_FATAL) */ - char *fmt; - char *cfname; - unsigned long clineno; - - va_start(ap); - cfname = va_arg(ap, char *); - clineno = va_arg(ap, unsigned long); - type = va_arg(ap, int); - fmt = va_arg(ap, char *); -#endif - - ParseVErrorInternal(cfname, clineno, type, fmt, ap); - va_end(ap); -} - -/*- - * Parse_Error -- - * External interface to ParseErrorInternal; uses the default filename - * Line number. - * - * Results: - * None - * - * Side Effects: - * None - */ -/* VARARGS */ -void -#ifdef __STDC__ -Parse_Error(int type, char *fmt, ...) -#else -Parse_Error(va_alist) - va_dcl -#endif -{ - va_list ap; -#ifdef __STDC__ - va_start(ap, fmt); -#else - int type; /* Error type (PARSE_WARNING, PARSE_FATAL) */ - char *fmt; - - va_start(ap); - type = va_arg(ap, int); - fmt = va_arg(ap, char *); -#endif - - ParseVErrorInternal(fname, lineno, type, fmt, ap); -} - -/*- *--------------------------------------------------------------------- * ParseLinkSrc -- * Link the parent node to its new child. Used in a Lst_ForEach by @@ -1628,42 +1483,32 @@ Parse_AddIncludeDir(dir) * The latter in . and the directories specified by -I command line * options * - * Results: - * None - * * Side Effects: - * A structure is added to the includes Lst and readProc, lineno, - * fname and curFILE are altered for the new file + * old parse context is pushed on the stack, new file becomes + * current context. *--------------------------------------------------------------------- */ static void -ParseDoInclude (file) +ParseDoInclude(file) char *file; /* file specification */ { - char *fullname; /* full pathname of file */ - IFile *oldFile; /* state associated with current file */ char endc; /* the character which ends the file spec */ char *cp; /* current position in file spec */ Boolean isSystem; /* TRUE if makefile is a system makefile */ - /* - * Skip to delimiter character so we know where to look - */ - while ((*file == ' ') || (*file == '\t')) { + /* Skip to delimiter character so we know where to look */ + while (*file == ' ' || *file == '\t') file++; - } - if ((*file != '"') && (*file != '<')) { + if (*file != '"' && *file != '<') { Parse_Error (PARSE_FATAL, ".include filename must be delimited by '\"' or '<'"); return; } - /* - * Set the search path on which to find the include file based on the + /* Set the search path on which to find the include file based on the * characters which bracket its name. Angle-brackets imply it's - * a system Makefile while double-quotes imply it's a user makefile - */ + * a system Makefile while double-quotes imply it's a user makefile */ if (*file == '<') { isSystem = TRUE; endc = '>'; @@ -1672,175 +1517,18 @@ ParseDoInclude (file) endc = '"'; } - /* - * Skip to matching delimiter - */ + /* Skip to matching delimiter */ for (cp = ++file; *cp && *cp != endc; cp++) { - continue; - } - - if (*cp != endc) { - Parse_Error (PARSE_FATAL, + if (*cp == '\0') { + Parse_Error(PARSE_FATAL, "Unclosed %cinclude filename. '%c' expected", '.', endc); - return; - } - *cp = '\0'; - - /* - * Substitute for any variables in the file name before trying to - * find the thing. - */ - file = Var_Subst(file, NULL, FALSE); - - /* - * Now we know the file's name and its search path, we attempt to - * find the durn thing. A return of NULL indicates the file don't - * exist. - */ - if (!isSystem) { - /* - * Include files contained in double-quotes are first searched for - * relative to the including file's location. We don't want to - * cd there, of course, so we just tack on the old file's - * leading path components and call Dir_FindFile to see if - * we can locate the beast. - */ - char *prefEnd, *Fname; - - /* Make a temporary copy of this, to be safe. */ - Fname = estrdup(fname); - - prefEnd = strrchr (Fname, '/'); - if (prefEnd != (char *)NULL) { - char *newName; - - *prefEnd = '\0'; - if (file[0] == '/') - newName = estrdup(file); - else - newName = str_concat (Fname, file, STR_ADDSLASH); - fullname = Dir_FindFile(newName, &parseIncPath); - if (fullname == (char *)NULL) { - fullname = Dir_FindFile(newName, &dirSearchPath); - } - free (newName); - *prefEnd = '/'; - } else { - fullname = (char *)NULL; - } - free (Fname); - } else { - fullname = (char *)NULL; - } - - if (fullname == (char *)NULL) { - /* - * System makefile or makefile wasn't found in same directory as - * included makefile. Search for it first on the -I search path, - * then on the .PATH search path, if not found in a -I directory. - * XXX: Suffix specific? - */ - fullname = Dir_FindFile(file, &parseIncPath); - if (fullname == (char *)NULL) { - fullname = Dir_FindFile(file, &dirSearchPath); + return; } } - - if (fullname == (char *)NULL) { - /* - * Still haven't found the makefile. Look for it on the system - * path as a last resort. - */ - fullname = Dir_FindFile(file, &sysIncPath); - } - - if (fullname == (char *) NULL) { - *cp = endc; - Parse_Error (PARSE_FATAL, "Could not find %s", file); - return; - } - - free(file); - - /* - * Once we find the absolute path to the file, we get to save all the - * state from the current file before we can start reading this - * include file. The state is stored in an IFile structure which - * is placed on a list with other IFile structures. The list makes - * a very nice stack to track how we got here... - */ - oldFile = (IFile *) emalloc (sizeof (IFile)); - oldFile->fname = fname; - - oldFile->F = curFILE; - oldFile->p = curPTR; - oldFile->lineno = lineno; - - Lst_AtFront(&includes, oldFile); - - /* - * Once the previous state has been saved, we can get down to reading - * the new file. We set up the name of the file to be the absolute - * name of the include file so error messages refer to the right - * place. Naturally enough, we start reading at line number 0. - */ - fname = fullname; -#ifdef CLEANUP - Lst_AtEnd(&fileNames, fname); -#endif - lineno = 0; - - curFILE = fopen (fullname, "r"); - curPTR = NULL; - if (curFILE == (FILE * ) NULL) { - Parse_Error (PARSE_FATAL, "Cannot open %s", fullname); - /* - * Pop to previous file - */ - (void) ParseEOF(0); - } -} - - -/*- - *--------------------------------------------------------------------- - * Parse_FromString -- - * Start Parsing from the given string - * - * Results: - * None - * - * Side Effects: - * A structure is added to the includes Lst and readProc, lineno, - * fname and curFILE are altered for the new file - *--------------------------------------------------------------------- - */ -void -Parse_FromString(str, newlineno) - char *str; - unsigned long newlineno; -{ - IFile *oldFile; /* state associated with this file */ - - if (DEBUG(FOR)) - (void) fprintf(stderr, "%s\n----\n", str); - - oldFile = (IFile *) emalloc (sizeof (IFile)); - oldFile->lineno = lineno; - oldFile->fname = fname; - oldFile->F = curFILE; - oldFile->p = curPTR; - - Lst_AtFront(&includes, oldFile); - - curFILE = NULL; - curPTR = (PTR *) emalloc (sizeof (PTR)); - curPTR->str = curPTR->ptr = str; - lineno = newlineno; + ParseLookupIncludeFile(file, cp, isSystem); } - #ifdef SYSVINCLUDE /*- *--------------------------------------------------------------------- @@ -1850,29 +1538,20 @@ Parse_FromString(str, newlineno) * The input is the line minus the "include". The file name is * the string following the "include". * - * Results: - * None - * * Side Effects: - * A structure is added to the includes Lst and readProc, lineno, - * fname and curFILE are altered for the new file + * old parse context is pushed on the stack, new file becomes + * current context. *--------------------------------------------------------------------- */ static void -ParseTraditionalInclude (file) +ParseTraditionalInclude(file) char *file; /* file specification */ { - char *fullname; /* full pathname of file */ - IFile *oldFile; /* state associated with current file */ char *cp; /* current position in file spec */ - char *prefEnd; - /* - * Skip over whitespace - */ - while ((*file == ' ') || (*file == '\t')) { + /* Skip over whitespace */ + while (*file == ' ' || *file == '\t') file++; - } if (*file == '\0') { Parse_Error (PARSE_FATAL, @@ -1880,198 +1559,93 @@ ParseTraditionalInclude (file) return; } - /* - * Skip to end of line or next whitespace - */ - for (cp = file; *cp && *cp != '\n' && *cp != '\t' && *cp != ' '; cp++) { - continue; - } - - *cp = '\0'; + /* Skip to end of line or next whitespace */ + for (cp = file; *cp != '\0' && !isspace(*cp);) + cp++; - /* - * Substitute for any variables in the file name before trying to - * find the thing. - */ - file = Var_Subst(file, NULL, FALSE); - - /* - * Now we know the file's name, we attempt to find the durn thing. - * A return of NULL indicates the file don't exist. - * - * Include files are first searched for relative to the including - * file's location. We don't want to cd there, of course, so we - * just tack on the old file's leading path components and call - * Dir_FindFile to see if we can locate the beast. - * XXX - this *does* search in the current directory, right? - */ + ParseLookupIncludeFile(file, cp, TRUE); +} +#endif - prefEnd = strrchr (fname, '/'); - if (prefEnd != (char *)NULL) { - char *newName; - - *prefEnd = '\0'; - newName = str_concat (fname, file, STR_ADDSLASH); - fullname = Dir_FindFile(newName, &parseIncPath); - if (fullname == NULL) - fullname = Dir_FindFile(newName, &dirSearchPath); - free (newName); - *prefEnd = '/'; - } else { - fullname = (char *)NULL; +/* Common part to lookup and read an include file. */ +static void +ParseLookupIncludeFile(spec, endSpec, isSystem) + char *spec; + char *endSpec; + Boolean isSystem; +{ + char *file; + char *fullname; + char endc; + + /* Substitute for any variables in the file name before trying to + * find the thing. */ + endc = *endSpec; + *endSpec = '\0'; + file = Var_Subst(spec, NULL, FALSE); + *endSpec = endc; + + /* Now that we know the file name and its search path, we attempt to + * find the durn thing. NULL indicates the file still hasn't been + * found. */ + fullname = NULL; + + /* Handle non-system non-absolute files... */ + if (!isSystem && file[0] != '/') { + /* ... by first searching relative to the including file's + * location. We don't want to cd there, of course, so we + * just tack on the old file's leading path components + * and call Dir_FindFile to see if we can locate the beast. */ + char *slash; + + slash = strrchr(Parse_Getfilename(), '/'); + if (slash != NULL) { + char *base, *newName; + + base = interval_dup(Parse_Getfilename(), slash); + newName = str_concat(base, file, STR_ADDSLASH); + free(base); + fullname = Dir_FindFile(newName, &parseIncPath); + if (fullname == NULL) + fullname = Dir_FindFile(newName, &dirSearchPath); + free(newName); + } } - if (fullname == (char *)NULL) { - /* - * System makefile or makefile wasn't found in same directory as - * included makefile. Search for it first on the -I search path, - * then on the .PATH search path, if not found in a -I directory. - * XXX: Suffix specific? - */ + /* Now look first on the -I search path, then on the .PATH + * search path, if not found in a -I directory. + * XXX: Suffix specific? */ + if (fullname == NULL) fullname = Dir_FindFile(file, &parseIncPath); - if (fullname == NULL) - fullname = Dir_FindFile(file, &dirSearchPath); - } + if (fullname == NULL) + fullname = Dir_FindFile(file, &dirSearchPath); - if (fullname == (char *)NULL) { - /* - * Still haven't found the makefile. Look for it on the system - * path as a last resort. - */ + /* Still haven't found the makefile. Look for it on the system + * path as a last resort. */ + if (fullname == NULL) fullname = Dir_FindFile(file, &sysIncPath); - } - - if (fullname == (char *) NULL) { - Parse_Error (PARSE_FATAL, "Could not find %s", file); - return; - } - - /* - * Once we find the absolute path to the file, we get to save all the - * state from the current file before we can start reading this - * include file. The state is stored in an IFile structure which - * is placed on a list with other IFile structures. The list makes - * a very nice stack to track how we got here... - */ - oldFile = (IFile *) emalloc (sizeof (IFile)); - oldFile->fname = fname; - oldFile->F = curFILE; - oldFile->p = curPTR; - oldFile->lineno = lineno; + if (fullname == NULL) + Parse_Error(PARSE_FATAL, "Could not find %s", file); - Lst_AtFront(&includes, oldFile); - - /* - * Once the previous state has been saved, we can get down to reading - * the new file. We set up the name of the file to be the absolute - * name of the include file so error messages refer to the right - * place. Naturally enough, we start reading at line number 0. - */ - fname = fullname; -#ifdef CLEANUP - Lst_AtEnd(&fileNames, fname); -#endif - lineno = 0; - - curFILE = fopen (fullname, "r"); - curPTR = NULL; - if (curFILE == (FILE * ) NULL) { - Parse_Error (PARSE_FATAL, "Cannot open %s", fullname); - /* - * Pop to previous file - */ - (void) ParseEOF(1); - } -} -#endif - -/*- - *--------------------------------------------------------------------- - * ParseEOF -- - * Called when EOF is reached in the current file. If we were reading - * an include file, the includes stack is popped and things set up - * to go back to reading the previous file at the previous location. - * - * Results: - * CONTINUE if there's more to do. DONE if not. - * - * Side Effects: - * The old curFILE, is closed. The includes list is shortened. - * lineno, curFILE, and fname are changed if CONTINUE is returned. - *--------------------------------------------------------------------- - */ -static int -ParseEOF (opened) - int opened; -{ - IFile *ifile; /* the state on the top of the includes stack */ - - if ((ifile = (IFile *)Lst_DeQueue(&includes)) == NULL) - return DONE; - fname = ifile->fname; - lineno = ifile->lineno; - if (opened && curFILE) - (void) fclose (curFILE); - if (curPTR) { - free(curPTR->str); - free(curPTR); - } - curFILE = ifile->F; - curPTR = ifile->p; - free(ifile); - return (CONTINUE); -} - -/*- - *--------------------------------------------------------------------- - * ParseReadc -- - * Read a character from the current file - * - * Results: - * The character that was read - * - * Side Effects: - *--------------------------------------------------------------------- - */ -static int __inline -ParseReadc() -{ - if (curFILE) - return fgetc(curFILE); - - if (curPTR && *curPTR->ptr) - return *curPTR->ptr++; - return EOF; -} + free(file); + if (fullname != NULL) { + FILE *f; -/*- - *--------------------------------------------------------------------- - * ParseUnreadc -- - * Put back a character to the current file - * - * Results: - * None. - * - * Side Effects: - *--------------------------------------------------------------------- - */ -static void -ParseUnreadc(c) - int c; -{ - if (curFILE) { - ungetc(c, curFILE); - return; - } - if (curPTR) { - *--(curPTR->ptr) = c; - return; + f = fopen(fullname, "r"); + if (f == NULL) { + Parse_Error(PARSE_FATAL, "Cannot open %s", fullname); + } else { + /* Once we find the absolute path to the file, we push the current + * stream to the includes stack, and start reading from the new + * file. We set up the file name to be its absolute name so that + * error messages are informative. */ + Parse_FromFile(fullname, f); + } } } - /* ParseSkipLine(): * Grab the next line */ @@ -2093,7 +1667,7 @@ ParseSkipLine(skip) && c != EOF) { if (c == '\n') { Buf_ReplaceLastChar(&buf, ' '); - lineno++; + current->lineno++; while ((c = ParseReadc()) == ' ' || c == '\t'); @@ -2106,7 +1680,7 @@ ParseSkipLine(skip) } line = Buf_Retrieve(&buf); - lineno++; + current->lineno++; /* allow for non-newline terminated lines while skipping */ if (line[0] == '.') break; @@ -2174,7 +1748,7 @@ ParseReadLine () ignComment = ignDepOp = TRUE; break; } else if (c == '\n') { - lineno++; + current->lineno++; } else if (c == '#') { ParseUnreadc(c); break; @@ -2204,7 +1778,7 @@ test_char: * semi-colon and semiNL is TRUE, it will be recognized as a * newline in the code below this... */ - lineno++; + current->lineno++; lastc = ' '; while ((c = ParseReadc ()) == ' ' || c == '\t') { continue; @@ -2307,7 +1881,7 @@ test_char: } line_read: - lineno++; + current->lineno++; if (lastc != '\0') Buf_AddChar(&buf, lastc); @@ -2432,14 +2006,7 @@ Parse_File(name, stream) *line; /* the line we're working on */ inLine = FALSE; - fname = estrdup(name); -#ifdef CLEANUP - Lst_AtEnd(&fileNames, fname); -#endif - curFILE = stream; - lineno = 0; - fatals = 0; - + Parse_FromFile(name, stream); do { while ((line = ParseReadLine ()) != NULL) { if (*line == '.') { @@ -2580,20 +2147,12 @@ Parse_File(name, stream) free (line); } - /* - * Reached EOF, but it may be just EOF of an include file... - */ - } while (ParseEOF(1) == CONTINUE); + } while (Parse_NextFile()); - /* - * Make sure conditionals are clean - */ + /* Make sure conditionals are clean */ Cond_End(); - if (fatals) { - fprintf (stderr, "Fatal errors encountered -- cannot continue\n"); - exit (1); - } + Finish_Errors(); } /*- @@ -2611,9 +2170,9 @@ Parse_Init() mainNode = NULL; Lst_Init(&parseIncPath); Lst_Init(&sysIncPath); - Lst_Init(&includes); Lst_Init(&targets); #ifdef CLEANUP + LowParse_Init(); Lst_Init(&targCmds); Lst_Init(&fileNames); #endif @@ -2628,7 +2187,7 @@ Parse_End() Lst_Delete(&targets, NOFREE); Lst_Destroy(&sysIncPath, Dir_Destroy); Lst_Destroy(&parseIncPath, Dir_Destroy); - Lst_Destroy(&includes, NOFREE); /* Should be empty now */ + LowParse_End(); #endif } @@ -2659,16 +2218,3 @@ Parse_MainName(listmain) else Lst_AtEnd(listmain, mainNode); } - -unsigned long -Parse_Getlineno() -{ - return lineno; -} - -const char * -Parse_Getfilename() -{ - return fname; -} - diff --git a/usr.bin/make/util.c b/usr.bin/make/util.c index 2cb48a7603a..17a3713abac 100644 --- a/usr.bin/make/util.c +++ b/usr.bin/make/util.c @@ -1,4 +1,4 @@ -/* $OpenBSD: util.c,v 1.11 1999/11/11 11:35:17 espie Exp $ */ +/* $OpenBSD: util.c,v 1.12 2000/06/23 16:39:45 espie Exp $ */ /* $NetBSD: util.c,v 1.10 1996/12/31 17:56:04 christos Exp $ */ /* @@ -6,7 +6,7 @@ */ #ifndef lint -static char rcsid[] = "$OpenBSD: util.c,v 1.11 1999/11/11 11:35:17 espie Exp $"; +static char rcsid[] = "$OpenBSD: util.c,v 1.12 2000/06/23 16:39:45 espie Exp $"; #endif #include <stdio.h> @@ -450,3 +450,30 @@ strstr(string, substring) return NULL; } #endif + +#ifdef NEED_FGETLN +char * +fgetln(stream, len) + FILE *stream; + size_t *len; +{ + static char *buffer = NULL; + static size_t buflen = 0; + + if (buflen == 0) { + buflen = 512; + buffer = emalloc(buflen+1); + } + if (fgets(buffer, buflen+1, stream) == NULL) + return NULL; + *len = strlen(buffer); + while (*len == buflen && buffer[*len-1] != '\n') { + buffer = erealloc(buffer, 2*buflen + 1); + if (fgets(buffer + buflen, buflen + 1, stream) == NULL) + return NULL; + *len += strlen(buffer + buflen); + buflen *= 2; + } + return buffer; +} +#endif |