=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/make/parse.c,v retrieving revision 1.49 retrieving revision 1.50 diff -u -r1.49 -r1.50 --- src/usr.bin/make/parse.c 2000/06/23 16:23:26 1.49 +++ src/usr.bin/make/parse.c 2000/06/23 16:39:45 1.50 @@ -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 @@ #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 @@ { ".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 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 @@ } /*- - * 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 @@ * 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 @@ 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; + return; } - 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); - } - } - - 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); - } + ParseLookupIncludeFile(file, cp, isSystem); } - -/*- - *--------------------------------------------------------------------- - * 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; -} - - #ifdef SYSVINCLUDE /*- *--------------------------------------------------------------------- @@ -1850,29 +1538,20 @@ * 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 @@ return; } - /* - * Skip to end of line or next whitespace - */ - for (cp = file; *cp && *cp != '\n' && *cp != '\t' && *cp != ' '; cp++) { - continue; - } + /* Skip to end of line or next whitespace */ + for (cp = file; *cp != '\0' && !isspace(*cp);) + cp++; - *cp = '\0'; + ParseLookupIncludeFile(file, cp, TRUE); +} +#endif - /* - * Substitute for any variables in the file name before trying to - * find the thing. - */ - file = Var_Subst(file, NULL, FALSE); +/* 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; - /* - * 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? - */ + /* 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; - prefEnd = strrchr (fname, '/'); - if (prefEnd != (char *)NULL) { - char *newName; + /* 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; - *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; + /* 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; - } + if (fullname == NULL) + Parse_Error(PARSE_FATAL, "Could not find %s", 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; + free(file); - oldFile->F = curFILE; - oldFile->p = curPTR; - oldFile->lineno = lineno; + if (fullname != NULL) { + FILE *f; - 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); + 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); + } } } -#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; -} - - -/*- - *--------------------------------------------------------------------- - * 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; - } -} - - /* ParseSkipLine(): * Grab the next line */ @@ -2093,7 +1667,7 @@ && c != EOF) { if (c == '\n') { Buf_ReplaceLastChar(&buf, ' '); - lineno++; + current->lineno++; while ((c = ParseReadc()) == ' ' || c == '\t'); @@ -2106,7 +1680,7 @@ } line = Buf_Retrieve(&buf); - lineno++; + current->lineno++; /* allow for non-newline terminated lines while skipping */ if (line[0] == '.') break; @@ -2174,7 +1748,7 @@ ignComment = ignDepOp = TRUE; break; } else if (c == '\n') { - lineno++; + current->lineno++; } else if (c == '#') { ParseUnreadc(c); break; @@ -2204,7 +1778,7 @@ * 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 @@ } line_read: - lineno++; + current->lineno++; if (lastc != '\0') Buf_AddChar(&buf, lastc); @@ -2432,14 +2006,7 @@ *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 @@ 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 @@ 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 @@ 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 @@ else Lst_AtEnd(listmain, mainNode); } - -unsigned long -Parse_Getlineno() -{ - return lineno; -} - -const char * -Parse_Getfilename() -{ - return fname; -} -