usr.bin/make/parse.c
/*-
 *---------------------------------------------------------------------
 * 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
 *---------------------------------------------------------------------
 */
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).

A line w/o its newline

Side Effects:
Only those associated with reading a character
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 ) . A line w / o its newline Side Effects : Only those associated with reading a character
static char *
ParseReadLine ()
{
    Buffer  	  buf;	    	
    register int  c;	      	
    register int  lastc;    	
    Boolean	  semiNL;     	
    Boolean	  ignDepOp;   	
    Boolean 	  ignComment;	
    char 	  *line;    	
    char          *ep;		
    int	    	  lineLength;	
    semiNL = FALSE;
    ignDepOp = FALSE;
    ignComment = FALSE;
    for (;;) {
	c = ParseReadc();
	if (c == '\t') {
	    ignComment = ignDepOp = TRUE;
	    break;
	} else if (c == '\n') {
	    lineno++;
	} else if (c == '#') {
	    ParseUnreadc(c);
	    break;
	} else {
	    break;
	}
    }
    if (c != EOF) {
	lastc = c;
	buf = Buf_Init(MAKE_BSIZE);
	while (((c = ParseReadc ()) != '\n' || (lastc == '\\')) &&
	       (c != EOF))
	{
test_char:
	    switch(c) {
	    case '\n':
		lineno++;
		lastc = ' ';
		while ((c = ParseReadc ()) == ' ' || c == '\t') {
		    continue;
		}
		if (c == EOF || c == '\n') {
		    goto line_read;
		} else {
		    goto test_char;
		}
		break;
	    case ';':
		if (semiNL) {
		    ParseUnreadc('\t');
		    goto line_read;
		} 
		break;
	    case '=':
		if (!semiNL) {
		    ignDepOp = TRUE;
		} else if (lastc == ':' || lastc == '!') {
		    ignDepOp = TRUE; semiNL = FALSE;
		}
		break;
	    case '#':
		if (!ignComment) {
		    if (compatMake && (lastc != '\\')) {
			do {
			    c = ParseReadc();
			} while ((c != '\n') && (c != EOF));
			goto line_read;
		    } else {
			lastc = c;
			continue;
		    }
		}
		break;
	    case ':':
	    case '!':
		if (!ignDepOp && (c == ':' || c == '!')) {
		    semiNL = TRUE;
		}
		break;
	    }
	    Buf_AddByte (buf, (Byte)lastc);
	    lastc = c;
	}
    line_read:
	lineno++;
	if (lastc != '\0') {
	    Buf_AddByte (buf, (Byte)lastc);
	}
	Buf_AddByte (buf, (Byte)'\0');
	line = (char *)Buf_GetAll (buf, &lineLength);
	Buf_Destroy (buf, FALSE);
	ep = line;
	while (*ep)
	    ++ep;
	while (ep > line && (ep[-1] == ' ' || ep[-1] == '\t')) {
	    if (ep > line + 1 && ep[-2] == '\\')
		break;
	    --ep;
	}
	*ep = 0;
	if (line[0] == '.') {
	    switch (Cond_Eval (line)) {
	    case COND_SKIP:
		do {
		    free (line);
		    line = ParseSkipLine(1);
		} while (line && Cond_Eval(line) != COND_PARSE);
		if (line == NULL)
		    break;
	    case COND_PARSE:
		free ((Address) line);
		line = ParseReadLine();
		break;
	    case COND_INVALID:
		if (For_Eval(line)) {
		    int ok;
		    free(line);
		    do {
			line = ParseSkipLine(0);
			if (line == NULL) {
			    Parse_Error (PARSE_FATAL, 
				     "Unexpected end of file in for loop.\n");
			    break;
			}
			ok = For_Eval(line);
			free(line);
		    }
		    while (ok);
		    if (line != NULL)
			For_Run();
		    line = ParseReadLine();
		}
		break;
	    }
	}
	return (line);
    } else {
	return((char *)NULL);
    }
}
static char * ParseReadLine ( ) { Buffer buf ; register int c ; register int lastc ; Boolean semiNL ; Boolean ignDepOp ; Boolean ignComment ; char * line ; char * ep ; int lineLength ; semiNL = FALSE ; ignDepOp = FALSE ; ignComment = FALSE ; for ( ; ; ) { c = ParseReadc ( ) ; if ( c == ' \t ' ) { ignComment = ignDepOp = TRUE ; break ; } else if ( c == ' \n ' ) { lineno ++ ; } else if ( c == ' ' ) { ParseUnreadc ( c ) ; break ; } else { break ; } } if ( c != EOF ) { lastc = c ; buf = Buf_Init ( MAKE_BSIZE ) ; while ( ( ( c = ParseReadc ( ) ) != ' \n ' || ( lastc == ' \\ ' ) ) && ( c != EOF ) ) { test_char : switch ( c ) { case ' \n ' : lineno ++ ; lastc = ' ' ; while ( ( c = ParseReadc ( ) ) == ' ' || c == ' \t ' ) { continue ; } if ( c == EOF || c == ' \n ' ) { goto line_read ; } else { goto test_char ; } break ; case ' ' : if ( semiNL ) { ParseUnreadc ( ' \t ' ) ; goto line_read ; } break ; case ' ' : if ( ! semiNL ) { ignDepOp = TRUE ; } else if ( lastc == ' ' || lastc == ' ' ) { ignDepOp = TRUE ; semiNL = FALSE ; } break ; case ' ' : if ( ! ignComment ) { if ( compatMake && ( lastc != ' \\ ' ) ) { do { c = ParseReadc ( ) ; } while ( ( c != ' \n ' ) && ( c != EOF ) ) ; goto line_read ; } else { lastc = c ; continue ; } } break ; case ' ' : case ' ' : if ( ! ignDepOp && ( c == ' ' || c == ' ' ) ) { semiNL = TRUE ; } break ; } Buf_AddByte ( buf , ( Byte ) lastc ) ; lastc = c ; } line_read : lineno ++ ; if ( lastc != ' \0 ' ) { Buf_AddByte ( buf , ( Byte ) lastc ) ; } Buf_AddByte ( buf , ( Byte ) ' \0 ' ) ; line = ( char * ) Buf_GetAll ( buf , & lineLength ) ; Buf_Destroy ( buf , FALSE ) ; ep = line ; while ( * ep ) ++ ep ; while ( ep > line && ( ep [ -1 ] == ' ' || ep [ -1 ] == ' \t ' ) ) { if ( ep > line + 1 && ep [ -2 ] == ' \\ ' ) break ; -- ep ; } * ep = 0 ; if ( line [ 0 ] == ' ' ) { switch ( Cond_Eval ( line ) ) { case COND_SKIP : do { free ( line ) ; line = ParseSkipLine ( 1 ) ; } while ( line && Cond_Eval ( line ) != COND_PARSE ) ; if ( line == NULL ) break ; case COND_PARSE : free ( ( Address ) line ) ; line = ParseReadLine ( ) ; break ; case COND_INVALID : if ( For_Eval ( line ) ) { int ok ; free ( line ) ; do { line = ParseSkipLine ( 0 ) ; if ( line == NULL ) { Parse_Error ( PARSE_FATAL , " \n " ) ; break ; } ok = For_Eval ( line ) ; free ( line ) ; } while ( ok ) ; if ( line != NULL ) For_Run ( ) ; line = ParseReadLine ( ) ; } break ; } } return ( line ) ; } else { return ( ( char * ) NULL ) ; } }
ParseReadLine
      Read an entire line from the input file.
ParseReadLine Read an entire line from the input file .
/* Buffer for current line */ /* the current character */ /* The most-recent character */ /* treat semi-colons as newlines */ /* TRUE if should ignore dependency operators
				 * for the purposes of setting semiNL */ /* TRUE if should ignore comments (in a
				 * shell command */ /* Result */ /* to strip trailing blanks */ /* Length of result */ /*
     * 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.
     */ /*
	     * Anything else breaks out without doing anything
	     */ /*
		 * 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...
		 */ /*
		     * Check for comments, semiNL's, etc. -- easier than
		     * ParseUnreadc(c); continue;
		     */ /*NOTREACHED*/ /*
		 * Semi-colon: Need to see if it should be interpreted as a
		 * newline
		 */ /*
		     * 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.
		     */ /*
		     * Haven't seen a dependency operator before this, so this
		     * must be a variable assignment -- don't pay attention to
		     * dependency operators after this.
		     */ /*
		     * 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?
		     */ /*
			 * 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.
			 */ /*
			 * Don't add the backslash. Just let the # get copied
			 * over.
			 */ /*
		     * A semi-colon is recognized as a newline only on
		     * dependency lines. Dependency lines are lines with a
		     * colon or an exclamation point. Ergo...
		     */ /*
	     * Copy in the previous character and save this one in lastc.
	     */ /*
	 * Strip trailing blanks and tabs from the line.
	 * Do not strip a blank or tab that is preceeded by
	 * a '\'
	 */ /*
	     * The line might be a conditional. Ask the conditional module
	     * about it and act accordingly
	     */ /*
		 * Skip to next conditional that evaluates to COND_PARSE.
		 */ /*FALLTHRU*/ /*
			 * Skip after the matching end
			 */ /*
	 * Hit end-of-file, so return a NULL line to indicate this.
	 */