[BACK]Return to parse.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / make

Diff for /src/usr.bin/make/parse.c between version 1.50 and 1.51

version 1.50, 2000/06/23 16:39:45 version 1.51, 2000/06/23 16:40:50
Line 227 
Line 227 
 static void ParseTraditionalInclude __P((char *));  static void ParseTraditionalInclude __P((char *));
 #endif  #endif
 static void ParseLookupIncludeFile __P((char *, char *, Boolean));  static void ParseLookupIncludeFile __P((char *, char *, Boolean));
 static char *ParseReadLine __P((void));  
 static char *ParseSkipLine __P((int));  
 static void ParseFinishLine __P((void));  static void ParseFinishLine __P((void));
   
 /*-  /*-
Line 1643 
Line 1641 
              * error messages are informative.  */               * error messages are informative.  */
             Parse_FromFile(fullname, f);              Parse_FromFile(fullname, f);
         }          }
     }  
 }  
   
 /* 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);  
     }      }
 }  }
   

Legend:
Removed from v.1.50  
changed lines
  Added in v.1.51