summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.bin/make/lowparse.c333
-rw-r--r--usr.bin/make/lowparse.h21
-rw-r--r--usr.bin/make/parse.c320
3 files changed, 337 insertions, 337 deletions
diff --git a/usr.bin/make/lowparse.c b/usr.bin/make/lowparse.c
index 3c1faeee0dc..e265093ceab 100644
--- a/usr.bin/make/lowparse.c
+++ b/usr.bin/make/lowparse.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: lowparse.c,v 1.1 2000/06/23 16:39:45 espie Exp $ */
+/* $OpenBSD: lowparse.c,v 1.2 2000/06/23 16:40:50 espie Exp $ */
/* low-level parsing functions. */
@@ -40,6 +40,20 @@
static LIST fileNames; /* file names to free at end */
#endif
+/* 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;
+
+static IFile *current;
+
+
+
static LIST includes; /* stack of IFiles generated by
* #includes */
@@ -48,6 +62,9 @@ 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 newline __P((void));
+#define ParseReadc() current->ptr < current->end ? *current->ptr++ : newline()
+static void ParseUnreadc __P((char));
static int ParseSkipEmptyLines __P((Buffer));
static int fatals = 0;
@@ -250,6 +267,320 @@ ParseUnreadc(c)
*current->ptr = c;
}
+/* ParseSkipLine():
+ * Grab the next line
+ */
+char *
+ParseSkipLine(skip)
+ int skip; /* Skip lines that don't start with . */
+{
+ char *line;
+ int c, lastc;
+ BUFFER buf;
+
+ Buf_Init(&buf, MAKE_BSIZE);
+
+ for (;;) {
+ Buf_Reset(&buf);
+ lastc = '\0';
+
+ while (((c = ParseReadc()) != '\n' || lastc == '\\')
+ && c != EOF) {
+ if (c == '\n') {
+ Buf_ReplaceLastChar(&buf, ' ');
+ current->lineno++;
+
+ while ((c = ParseReadc()) == ' ' || c == '\t');
+
+ if (c == EOF)
+ break;
+ }
+
+ Buf_AddChar(&buf, c);
+ lastc = c;
+ }
+
+ line = Buf_Retrieve(&buf);
+ current->lineno++;
+ /* allow for non-newline terminated lines while skipping */
+ if (line[0] == '.')
+ break;
+
+ if (c == EOF) {
+ Parse_Error(PARSE_FATAL, "Unclosed conditional/for loop");
+ Buf_Destroy(&buf);
+ return NULL;
+ }
+ if (skip == 0)
+ break;
+
+ }
+
+ return line;
+}
+
+
+/*-
+ *---------------------------------------------------------------------
+ * ParseReadLine --
+ * Read an entire line from the input file. Called only by Parse_File.
+ * To facilitate escaped newlines and what have you, a character is
+ * buffered in 'lastc', which is '\0' when no characters have been
+ * read. When we break out of the loop, c holds the terminating
+ * character and lastc holds a character that should be added to
+ * the line (unless we don't read anything but a terminator).
+ *
+ * Results:
+ * A line w/o its newline
+ *
+ * Side Effects:
+ * Only those associated with reading a character
+ *---------------------------------------------------------------------
+ */
+char *
+ParseReadLine ()
+{
+ BUFFER buf; /* Buffer for current line */
+ register int c; /* the current character */
+ register int lastc; /* The most-recent character */
+ Boolean semiNL; /* treat semi-colons as newlines */
+ Boolean ignDepOp; /* TRUE if should ignore dependency operators
+ * for the purposes of setting semiNL */
+ Boolean ignComment; /* TRUE if should ignore comments (in a
+ * shell command */
+ char *line; /* Result */
+ char *ep; /* to strip trailing blanks */
+
+ semiNL = FALSE;
+ ignDepOp = FALSE;
+ ignComment = FALSE;
+
+ /*
+ * Handle special-characters at the beginning of the line. Either a
+ * leading tab (shell command) or pound-sign (possible conditional)
+ * forces us to ignore comments and dependency operators and treat
+ * semi-colons as semi-colons (by leaving semiNL FALSE). This also
+ * discards completely blank lines.
+ */
+ for (;;) {
+ c = ParseReadc();
+
+ if (c == '\t') {
+ ignComment = ignDepOp = TRUE;
+ break;
+ } else if (c == '\n') {
+ current->lineno++;
+ } else if (c == '#') {
+ ParseUnreadc(c);
+ break;
+ } else {
+ /*
+ * Anything else breaks out without doing anything
+ */
+ break;
+ }
+ }
+
+ if (c != EOF) {
+ lastc = c;
+ Buf_Init(&buf, MAKE_BSIZE);
+
+ while (((c = ParseReadc ()) != '\n' || (lastc == '\\')) &&
+ (c != EOF))
+ {
+test_char:
+ switch(c) {
+ case '\n':
+ /*
+ * Escaped newline: read characters until a non-space or an
+ * unescaped newline and replace them all by a single space.
+ * This is done by storing the space over the backslash and
+ * dropping through with the next nonspace. If it is a
+ * semi-colon and semiNL is TRUE, it will be recognized as a
+ * newline in the code below this...
+ */
+ current->lineno++;
+ lastc = ' ';
+ while ((c = ParseReadc ()) == ' ' || c == '\t') {
+ continue;
+ }
+ if (c == EOF || c == '\n') {
+ goto line_read;
+ } else {
+ /*
+ * Check for comments, semiNL's, etc. -- easier than
+ * ParseUnreadc(c); continue;
+ */
+ goto test_char;
+ }
+ /*NOTREACHED*/
+ break;
+
+ case ';':
+ /*
+ * Semi-colon: Need to see if it should be interpreted as a
+ * newline
+ */
+ if (semiNL) {
+ /*
+ * To make sure the command that may be following this
+ * semi-colon begins with a tab, we push one back into the
+ * input stream. This will overwrite the semi-colon in the
+ * buffer. If there is no command following, this does no
+ * harm, since the newline remains in the buffer and the
+ * whole line is ignored.
+ */
+ ParseUnreadc('\t');
+ goto line_read;
+ }
+ break;
+ case '=':
+ if (!semiNL) {
+ /*
+ * Haven't seen a dependency operator before this, so this
+ * must be a variable assignment -- don't pay attention to
+ * dependency operators after this.
+ */
+ ignDepOp = TRUE;
+ } else if (lastc == ':' || lastc == '!') {
+ /*
+ * Well, we've seen a dependency operator already, but it
+ * was the previous character, so this is really just an
+ * expanded variable assignment. Revert semi-colons to
+ * being just semi-colons again and ignore any more
+ * dependency operators.
+ *
+ * XXX: Note that a line like "foo : a:=b" will blow up,
+ * but who'd write a line like that anyway?
+ */
+ ignDepOp = TRUE; semiNL = FALSE;
+ }
+ break;
+ case '#':
+ if (!ignComment) {
+ if (
+#if 0
+ compatMake &&
+#endif
+ (lastc != '\\')) {
+ /*
+ * If the character is a hash mark and it isn't escaped
+ * (or we're being compatible), the thing is a comment.
+ * Skip to the end of the line.
+ */
+ do {
+ c = ParseReadc();
+ } while ((c != '\n') && (c != EOF));
+ goto line_read;
+ } else {
+ /*
+ * Don't add the backslash. Just let the # get copied
+ * over.
+ */
+ lastc = c;
+ continue;
+ }
+ }
+ break;
+ case ':':
+ case '!':
+ if (!ignDepOp && (c == ':' || c == '!')) {
+ /*
+ * A semi-colon is recognized as a newline only on
+ * dependency lines. Dependency lines are lines with a
+ * colon or an exclamation point. Ergo...
+ */
+ semiNL = TRUE;
+ }
+ break;
+ }
+ /*
+ * Copy in the previous character and save this one in lastc.
+ */
+ Buf_AddChar(&buf, lastc);
+ lastc = c;
+
+ }
+ line_read:
+ current->lineno++;
+
+ if (lastc != '\0')
+ Buf_AddChar(&buf, lastc);
+ line = Buf_Retrieve(&buf);
+
+ /*
+ * Strip trailing blanks and tabs from the line.
+ * Do not strip a blank or tab that is preceeded by
+ * a '\'
+ */
+ ep = line;
+ while (*ep)
+ ++ep;
+ while (ep > line + 1 && (ep[-1] == ' ' || ep[-1] == '\t')) {
+ if (ep > line + 1 && ep[-2] == '\\')
+ break;
+ --ep;
+ }
+ *ep = 0;
+
+ if (line[0] == '.') {
+ /*
+ * The line might be a conditional. Ask the conditional module
+ * about it and act accordingly
+ */
+ switch (Cond_Eval (line)) {
+ case COND_SKIP:
+ /*
+ * Skip to next conditional that evaluates to COND_PARSE.
+ */
+ do {
+ free (line);
+ line = ParseSkipLine(1);
+ } while (line && Cond_Eval(line) != COND_PARSE);
+ if (line == NULL)
+ break;
+ /*FALLTHRU*/
+ case COND_PARSE:
+ free(line);
+ line = ParseReadLine();
+ break;
+ case COND_INVALID:
+ {
+ For *loop;
+
+ loop = For_Eval(line);
+ if (loop != NULL) {
+ Boolean ok;
+
+ free(line);
+ do {
+ /* Find the matching endfor. */
+ line = ParseSkipLine(0);
+ if (line == NULL) {
+ Parse_Error(PARSE_FATAL,
+ "Unexpected end of file in for loop.\n");
+ return line;
+ }
+ ok = For_Accumulate(loop, line);
+ free(line);
+ } while (ok);
+ For_Run(loop);
+ line = ParseReadLine();
+ }
+ break;
+ }
+ }
+ }
+ return (line);
+
+ } else {
+ /*
+ * Hit end-of-file, so return a NULL line to indicate this.
+ */
+ return((char *)NULL);
+ }
+}
+
unsigned long
Parse_Getlineno()
{
diff --git a/usr.bin/make/lowparse.h b/usr.bin/make/lowparse.h
index 317de41774a..0ceb3939218 100644
--- a/usr.bin/make/lowparse.h
+++ b/usr.bin/make/lowparse.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: lowparse.h,v 1.1 2000/06/23 16:39:45 espie Exp $ */
+/* $OpenBSD: lowparse.h,v 1.2 2000/06/23 16:40:50 espie Exp $ */
/*
* Copyright (c) 1999 Marc Espie.
@@ -34,22 +34,7 @@ extern Boolean Parse_NextFile __P((void));
extern void LowParse_Init __P((void));
extern void LowParse_End __P((void));
#endif
+extern char *ParseReadLine __P((void));
+extern char *ParseSkipLine __P((int));
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/parse.c b/usr.bin/make/parse.c
index bb9f0cdc3c7..a13b4e90935 100644
--- a/usr.bin/make/parse.c
+++ b/usr.bin/make/parse.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.c,v 1.50 2000/06/23 16:39:45 espie Exp $ */
+/* $OpenBSD: parse.c,v 1.51 2000/06/23 16:40:50 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.50 2000/06/23 16:39:45 espie Exp $";
+static char rcsid[] = "$OpenBSD: parse.c,v 1.51 2000/06/23 16:40:50 espie Exp $";
#endif
#endif /* not lint */
@@ -227,8 +227,6 @@ static void ParseDoInclude __P((char *));
static void ParseTraditionalInclude __P((char *));
#endif
static void ParseLookupIncludeFile __P((char *, char *, Boolean));
-static char *ParseReadLine __P((void));
-static char *ParseSkipLine __P((int));
static void ParseFinishLine __P((void));
/*-
@@ -1646,320 +1644,6 @@ ParseLookupIncludeFile(spec, endSpec, isSystem)
}
}
-/* ParseSkipLine():
- * Grab the next line
- */
-static char *
-ParseSkipLine(skip)
- int skip; /* Skip lines that don't start with . */
-{
- char *line;
- int c, lastc;
- BUFFER buf;
-
- Buf_Init(&buf, MAKE_BSIZE);
-
- for (;;) {
- Buf_Reset(&buf);
- lastc = '\0';
-
- while (((c = ParseReadc()) != '\n' || lastc == '\\')
- && c != EOF) {
- if (c == '\n') {
- Buf_ReplaceLastChar(&buf, ' ');
- current->lineno++;
-
- while ((c = ParseReadc()) == ' ' || c == '\t');
-
- if (c == EOF)
- break;
- }
-
- Buf_AddChar(&buf, c);
- lastc = c;
- }
-
- line = Buf_Retrieve(&buf);
- current->lineno++;
- /* allow for non-newline terminated lines while skipping */
- if (line[0] == '.')
- break;
-
- if (c == EOF) {
- Parse_Error(PARSE_FATAL, "Unclosed conditional/for loop");
- Buf_Destroy(&buf);
- return NULL;
- }
- if (skip == 0)
- break;
-
- }
-
- return line;
-}
-
-
-/*-
- *---------------------------------------------------------------------
- * ParseReadLine --
- * Read an entire line from the input file. Called only by Parse_File.
- * To facilitate escaped newlines and what have you, a character is
- * buffered in 'lastc', which is '\0' when no characters have been
- * read. When we break out of the loop, c holds the terminating
- * character and lastc holds a character that should be added to
- * the line (unless we don't read anything but a terminator).
- *
- * Results:
- * A line w/o its newline
- *
- * Side Effects:
- * Only those associated with reading a character
- *---------------------------------------------------------------------
- */
-static char *
-ParseReadLine ()
-{
- BUFFER buf; /* Buffer for current line */
- register int c; /* the current character */
- register int lastc; /* The most-recent character */
- Boolean semiNL; /* treat semi-colons as newlines */
- Boolean ignDepOp; /* TRUE if should ignore dependency operators
- * for the purposes of setting semiNL */
- Boolean ignComment; /* TRUE if should ignore comments (in a
- * shell command */
- char *line; /* Result */
- char *ep; /* to strip trailing blanks */
-
- semiNL = FALSE;
- ignDepOp = FALSE;
- ignComment = FALSE;
-
- /*
- * Handle special-characters at the beginning of the line. Either a
- * leading tab (shell command) or pound-sign (possible conditional)
- * forces us to ignore comments and dependency operators and treat
- * semi-colons as semi-colons (by leaving semiNL FALSE). This also
- * discards completely blank lines.
- */
- for (;;) {
- c = ParseReadc();
-
- if (c == '\t') {
- ignComment = ignDepOp = TRUE;
- break;
- } else if (c == '\n') {
- current->lineno++;
- } else if (c == '#') {
- ParseUnreadc(c);
- break;
- } else {
- /*
- * Anything else breaks out without doing anything
- */
- break;
- }
- }
-
- if (c != EOF) {
- lastc = c;
- Buf_Init(&buf, MAKE_BSIZE);
-
- while (((c = ParseReadc ()) != '\n' || (lastc == '\\')) &&
- (c != EOF))
- {
-test_char:
- switch(c) {
- case '\n':
- /*
- * Escaped newline: read characters until a non-space or an
- * unescaped newline and replace them all by a single space.
- * This is done by storing the space over the backslash and
- * dropping through with the next nonspace. If it is a
- * semi-colon and semiNL is TRUE, it will be recognized as a
- * newline in the code below this...
- */
- current->lineno++;
- lastc = ' ';
- while ((c = ParseReadc ()) == ' ' || c == '\t') {
- continue;
- }
- if (c == EOF || c == '\n') {
- goto line_read;
- } else {
- /*
- * Check for comments, semiNL's, etc. -- easier than
- * ParseUnreadc(c); continue;
- */
- goto test_char;
- }
- /*NOTREACHED*/
- break;
-
- case ';':
- /*
- * Semi-colon: Need to see if it should be interpreted as a
- * newline
- */
- if (semiNL) {
- /*
- * To make sure the command that may be following this
- * semi-colon begins with a tab, we push one back into the
- * input stream. This will overwrite the semi-colon in the
- * buffer. If there is no command following, this does no
- * harm, since the newline remains in the buffer and the
- * whole line is ignored.
- */
- ParseUnreadc('\t');
- goto line_read;
- }
- break;
- case '=':
- if (!semiNL) {
- /*
- * Haven't seen a dependency operator before this, so this
- * must be a variable assignment -- don't pay attention to
- * dependency operators after this.
- */
- ignDepOp = TRUE;
- } else if (lastc == ':' || lastc == '!') {
- /*
- * Well, we've seen a dependency operator already, but it
- * was the previous character, so this is really just an
- * expanded variable assignment. Revert semi-colons to
- * being just semi-colons again and ignore any more
- * dependency operators.
- *
- * XXX: Note that a line like "foo : a:=b" will blow up,
- * but who'd write a line like that anyway?
- */
- ignDepOp = TRUE; semiNL = FALSE;
- }
- break;
- case '#':
- if (!ignComment) {
- if (
-#if 0
- compatMake &&
-#endif
- (lastc != '\\')) {
- /*
- * If the character is a hash mark and it isn't escaped
- * (or we're being compatible), the thing is a comment.
- * Skip to the end of the line.
- */
- do {
- c = ParseReadc();
- } while ((c != '\n') && (c != EOF));
- goto line_read;
- } else {
- /*
- * Don't add the backslash. Just let the # get copied
- * over.
- */
- lastc = c;
- continue;
- }
- }
- break;
- case ':':
- case '!':
- if (!ignDepOp && (c == ':' || c == '!')) {
- /*
- * A semi-colon is recognized as a newline only on
- * dependency lines. Dependency lines are lines with a
- * colon or an exclamation point. Ergo...
- */
- semiNL = TRUE;
- }
- break;
- }
- /*
- * Copy in the previous character and save this one in lastc.
- */
- Buf_AddChar(&buf, lastc);
- lastc = c;
-
- }
- line_read:
- current->lineno++;
-
- if (lastc != '\0')
- Buf_AddChar(&buf, lastc);
- line = Buf_Retrieve(&buf);
-
- /*
- * Strip trailing blanks and tabs from the line.
- * Do not strip a blank or tab that is preceeded by
- * a '\'
- */
- ep = line;
- while (*ep)
- ++ep;
- while (ep > line + 1 && (ep[-1] == ' ' || ep[-1] == '\t')) {
- if (ep > line + 1 && ep[-2] == '\\')
- break;
- --ep;
- }
- *ep = 0;
-
- if (line[0] == '.') {
- /*
- * The line might be a conditional. Ask the conditional module
- * about it and act accordingly
- */
- switch (Cond_Eval (line)) {
- case COND_SKIP:
- /*
- * Skip to next conditional that evaluates to COND_PARSE.
- */
- do {
- free (line);
- line = ParseSkipLine(1);
- } while (line && Cond_Eval(line) != COND_PARSE);
- if (line == NULL)
- break;
- /*FALLTHRU*/
- case COND_PARSE:
- free(line);
- line = ParseReadLine();
- break;
- case COND_INVALID:
- {
- For *loop;
-
- loop = For_Eval(line);
- if (loop != NULL) {
- Boolean ok;
-
- free(line);
- do {
- /* Find the matching endfor. */
- line = ParseSkipLine(0);
- if (line == NULL) {
- Parse_Error(PARSE_FATAL,
- "Unexpected end of file in for loop.\n");
- return line;
- }
- ok = For_Accumulate(loop, line);
- free(line);
- } while (ok);
- For_Run(loop);
- line = ParseReadLine();
- }
- break;
- }
- }
- }
- return (line);
-
- } else {
- /*
- * Hit end-of-file, so return a NULL line to indicate this.
- */
- return((char *)NULL);
- }
-}
-
/*-
*-----------------------------------------------------------------------
* ParseFinishLine --