[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.90 and 1.91

version 1.90, 2007/09/17 11:14:37 version 1.91, 2007/09/17 11:32:25
Line 218 
Line 218 
 static bool handle_for_loop(Buffer, const char *);  static bool handle_for_loop(Buffer, const char *);
 static bool handle_undef(const char *);  static bool handle_undef(const char *);
 #define ParseReadLoopLine(linebuf) Parse_ReadUnparsedLine(linebuf, "for loop")  #define ParseReadLoopLine(linebuf) Parse_ReadUnparsedLine(linebuf, "for loop")
 static void ParseFinishDependency(void);  
 static bool handle_bsd_command(Buffer, Buffer, const char *);  static bool handle_bsd_command(Buffer, Buffer, const char *);
 static char *strip_comments(Buffer, const char *);  static char *strip_comments(Buffer, const char *);
 static char *resolve_include_filename(const char *, bool);  static char *resolve_include_filename(const char *, bool);
Line 227 
Line 226 
 static void lookup_sysv_style_include(const char *, const char *, bool);  static void lookup_sysv_style_include(const char *, const char *, bool);
 static void lookup_sysv_include(const char *, const char *);  static void lookup_sysv_include(const char *, const char *);
 static void lookup_conditional_include(const char *, const char *);  static void lookup_conditional_include(const char *, const char *);
   static bool parse_as_special_line(Buffer, Buffer, const char *);
   static void parse_target_line(struct growableArray *, const char *,
       const char *);
   
 static void ParseDoCommands(const char *);  
   
 /*-  /*-
  *----------------------------------------------------------------------   *----------------------------------------------------------------------
  * ParseFindKeyword --   * ParseFindKeyword --
Line 1121 
Line 1121 
   
   
   
   /* Strip comments from line. Build a copy in buffer if necessary, */
   static char *
   strip_comments(Buffer copy, const char *line)
   {
           const char *comment;
           const char *p;
   
           comment = strchr(line, '#');
           assert(comment != line);
           if (comment == NULL)
                   return (char *)line;
           else {
                   Buf_Reset(copy);
   
                   for (p = line; *p != '\0'; p++) {
                           if (*p == '\\') {
                                   if (p[1] == '#') {
                                           Buf_Addi(copy, line, p);
                                           Buf_AddChar(copy, '#');
                                           line = p+2;
                                   }
                                   if (p[1] != '\0')
                                           p++;
                           } else if (*p == '#')
                                   break;
                   }
                   Buf_Addi(copy, line, p);
                   Buf_KillTrailingSpaces(copy);
                   return Buf_Retrieve(copy);
           }
   }
   
   
   
 /***  /***
  *** Support for various include constructs   *** Support for various include constructs
  ***/   ***/
Line 1290 
Line 1324 
 }  }
   
   
   /***
    ***   BSD-specific . constructs
    ***   They all follow the same pattern:
    ***    if the syntax matches BSD stuff, then we're committed to handle
    ***   them and report fatal errors (like, include file not existing)
    ***    otherwise, we return false, and hope somebody else will handle it.
    ***/
   
 static bool  static bool
 handle_poison(const char *line)  handle_poison(const char *line)
 {  {
Line 1357 
Line 1399 
         }          }
 }  }
   
   
 /* Strip comments from the line. Build a copy in buffer if necessary, */  
 static char *  
 strip_comments(Buffer copy, const char *line)  
 {  
         const char *comment;  
         const char *p;  
   
         comment = strchr(line, '#');  
         assert(comment != line);  
         if (comment == NULL)  
                 return (char *)line;  
         else {  
                 Buf_Reset(copy);  
   
                 for (p = line; *p != '\0'; p++) {  
                         if (*p == '\\') {  
                                 if (p[1] == '#') {  
                                         Buf_Addi(copy, line, p);  
                                         Buf_AddChar(copy, '#');  
                                         line = p+2;  
                                 }  
                                 if (p[1] != '\0')  
                                         p++;  
                         } else if (*p == '#')  
                                 break;  
                 }  
                 Buf_Addi(copy, line, p);  
                 Buf_KillTrailingSpaces(copy);  
                 return Buf_Retrieve(copy);  
         }  
 }  
   
 static bool  static bool
 handle_for_loop(Buffer linebuf, const char *line)  handle_for_loop(Buffer linebuf, const char *line)
 {  {
         For *loop;          For *loop;
   
         loop = For_Eval(line+3);          loop = For_Eval(line);
         if (loop != NULL) {          if (loop != NULL) {
                 bool ok;                  bool ok;
                 do {                  do {
Line 1435 
Line 1444 
         while (isspace(*line))          while (isspace(*line))
                 line++;                  line++;
   
         /* The line might be a conditional. Ask the conditional module          /* delegate basic classification to the conditional module */
          * about it and act accordingly.  */  
         switch (Cond_Eval(line)) {          switch (Cond_Eval(line)) {
         case COND_SKIP:          case COND_SKIP:
                 /* Skip to next conditional that evaluates to COND_PARSE.  */                  /* Skip to next conditional that evaluates to COND_PARSE.  */
Line 1452 
Line 1460 
         case COND_PARSE:          case COND_PARSE:
                 return true;                  return true;
         case COND_ISFOR:          case COND_ISFOR:
                 return handle_for_loop(linebuf, line);                  return handle_for_loop(linebuf, line + 3);
         case COND_ISINCLUDE:          case COND_ISINCLUDE:
                 return lookup_bsd_include(line + 7);                  return lookup_bsd_include(line + 7);
         case COND_ISPOISON:          case COND_ISPOISON:
                 return handle_poison(line+6);                  return handle_poison(line + 6);
         case COND_ISUNDEF:          case COND_ISUNDEF:
                 return handle_undef(line + 5);                  return handle_undef(line + 5);
         default:          default:
Line 1466 
Line 1474 
         return false;          return false;
 }  }
   
 /*-  /***
  *-----------------------------------------------------------------------   *** handle a group of commands
  * ParseFinishDependency --   ***/
  *      Handle the end of a dependency group.  
  *  
  * Side Effects:  
  *      'targets' list destroyed.  
  *  
  *-----------------------------------------------------------------------  
  */  
 static void  static void
 ParseFinishDependency(void)  finish_commands(struct growableArray *targets)
 {  {
         Array_Every(&gtargets, Suff_EndTransform);          Array_Every(targets, Suff_EndTransform);
         Array_Every(&gtargets, ParseHasCommands);          Array_Every(targets, ParseHasCommands);
         Array_Reset(&gtargets);          Array_Reset(targets);
 }  }
   
 static void  static void
 ParseDoCommands(const char *line)  parse_commands(struct growableArray *targets, const char *line)
 {  {
         /* add the command to the list of          /* add the command to the list of
          * commands of all targets in the dependency spec */           * commands of all targets in the dependency spec */
         char *cmd = estrdup(line);          char *cmd = estrdup(line);
   
         Array_ForEach(&gtargets, ParseAddCmd, cmd);          Array_ForEach(targets, ParseAddCmd, cmd);
 #ifdef CLEANUP  #ifdef CLEANUP
         Lst_AtEnd(&targCmds, cmd);          Lst_AtEnd(&targCmds, cmd);
 #endif  #endif
 }  }
   
 void  static bool
 Parse_File(  parse_as_special_line(Buffer buf, Buffer copy, const char *line)
     const char    *name,        /* the name of the file being read */  
     FILE          *stream)      /* Stream open to makefile to parse */  
 {  {
     char          *cp,          /* pointer into the line */          if (*line == '.' && handle_bsd_command(buf, copy, line+1))
                   *line;        /* the line we're working on */                  return true;
     bool          inDependency; /* true if currently in a dependency          if (FEATURES(FEATURE_SYSVINCLUDE) &&
                                  * line or its commands */              strncmp(line, "include", 7) == 0 &&
               isspace(line[7]) &&
               strchr(line, ':') == NULL) {
               /* It's an S3/S5-style "include".  */
                   lookup_sysv_include(line + 7, "include");
                   return true;
           }
           if (FEATURES(FEATURE_CONDINCLUDE) &&
               strncmp(line, "sinclude", 8) == 0 &&
               isspace(line[8]) &&
               strchr(line, ':') == NULL) {
                   lookup_conditional_include(line+8, "sinclude");
                   return true;
           }
           if (FEATURES(FEATURE_CONDINCLUDE) &&
               strncmp(line, "-include", 8) == 0 &&
               isspace(line[8]) &&
               strchr(line, ':') == NULL) {
                   lookup_conditional_include(line+8, "-include");
                   return true;
           }
           return false;
   }
   
     BUFFER        buf;  static void
     BUFFER        copy;  parse_target_line(struct growableArray *targets, const char *line,
       const char *stripped)
   {
           size_t pos;
           char *end;
           char *cp;
           char *dep;
   
     Buf_Init(&buf, MAKE_BSIZE);          /* let's start a new set of commands */
     Buf_Init(&copy, MAKE_BSIZE);          Array_Reset(targets);
     inDependency = false;  
     Parse_FromFile(name, stream);  
   
     do {          /* XXX this is a dirty heuristic to handle target: dep ; commands */
         while ((line = Parse_ReadNormalLine(&buf)) != NULL) {          dep = NULL;
             if (*line == '\t') {          /* First we need to find eventual dependencies */
                 if (inDependency)          pos = strcspn(stripped, ":!");
                     ParseDoCommands(line+1);          /* go over :!, and find ;  */
           if (stripped[pos] != '\0' &&
               (end = strchr(stripped+pos+1, ';')) != NULL) {
                   if (line != stripped)
                           /* find matching ; in original... The
                            * original might be slightly longer.  */
                           dep = strchr(line+(end-stripped), ';');
                 else                  else
                     Parse_Error(PARSE_FATAL,                          dep = end;
                         "Unassociated shell command \"%s\"",                  /* kill end of line. */
                          line);                  *end = '\0';
             } else {          }
                 char *stripped;          /* We now know it's a dependency line so it needs to
                 stripped = strip_comments(&copy, line);           * have all variables expanded before being parsed.
                 if (*stripped == '.' && handle_bsd_command(&buf, &copy,           */
                     stripped+1))          cp = Var_Subst(stripped, NULL, false);
                         ;          ParseDoDependency(cp);
                 else if (FEATURES(FEATURE_SYSVINCLUDE) &&          free(cp);
                     strncmp(stripped, "include", 7) == 0 &&  
                     isspace(stripped[7]) &&  
                     strchr(stripped, ':') == NULL) {  
                     /* It's an S3/S5-style "include".  */  
                         lookup_sysv_include(stripped + 7, "include");  
                 } else if (FEATURES(FEATURE_CONDINCLUDE) &&  
                     strncmp(stripped, "sinclude", 8) == 0 &&  
                     isspace(stripped[8]) &&  
                     strchr(stripped, ':') == NULL) {  
                         lookup_conditional_include(stripped+8, "sinclude");  
                 } else if (FEATURES(FEATURE_CONDINCLUDE) &&  
                     strncmp(stripped, "-include", 8) == 0 &&  
                     isspace(stripped[8]) &&  
                     strchr(stripped, ':') == NULL) {  
                         lookup_conditional_include(stripped+8, "-include");  
                 } else {  
                     char *dep;  
   
                     if (inDependency)          /* Parse dependency if it's not empty. */
                         ParseFinishDependency();          if (dep != NULL) {
                     if (Parse_As_Var_Assignment(stripped))                  do {
                         inDependency = false;                          dep++;
                     else {                  } while (isspace(*dep));
                         size_t pos;                  if (*dep != '\0')
                         char *end;                          parse_commands(targets, dep);
           }
   }
   
                         /* Need a new list for the target nodes.  */  void
                         Array_Reset(&gtargets);  Parse_File(const char *filename, FILE *stream)
                         inDependency = true;  {
           char *line;
           bool expectingCommands = false;
   
                         dep = NULL;          /* somewhat permanent spaces to shave time */
                         /* First we need to find eventual dependencies */          BUFFER buf;
                         pos = strcspn(stripped, ":!");          BUFFER copy;
                         /* go over :!, and find ;  */  
                         if (stripped[pos] != '\0' &&          Buf_Init(&buf, MAKE_BSIZE);
                             (end = strchr(stripped+pos+1, ';')) != NULL) {          Buf_Init(&copy, MAKE_BSIZE);
                                 if (line != stripped)  
                                     /* find matching ; in original... The          Parse_FromFile(filename, stream);
                                      * original might be slightly longer.  */          do {
                                     dep = strchr(line+(end-stripped), ';');                  while ((line = Parse_ReadNormalLine(&buf)) != NULL) {
                           if (*line == '\t') {
                                   if (expectingCommands)
                                           parse_commands(&gtargets, line+1);
                                 else                                  else
                                     dep = end;                                          Parse_Error(PARSE_FATAL,
                                 /* kill end of line. */                                              "Unassociated shell command \"%s\"",
                                 *end = '\0';                                               line);
                           } else {
                                   const char *stripped = strip_comments(&copy,
                                       line);
                                   if (!parse_as_special_line(&buf, &copy,
                                       stripped)) {
                                           if (expectingCommands)
                                                   finish_commands(&gtargets);
                                           if (Parse_As_Var_Assignment(stripped))
                                                   expectingCommands = false;
                                           else {
                                                   parse_target_line(&gtargets,
                                                       line, stripped);
                                                   expectingCommands = true;
                                           }
                                   }
                         }                          }
                         /* We now know it's a dependency line so it needs to  
                          * have all variables expanded before being parsed.  
                          * Tell the variable module to complain if some  
                          * variable is undefined... */  
                         cp = Var_Subst(stripped, NULL, true);  
                         ParseDoDependency(cp);  
                         free(cp);  
   
                         /* Parse dependency if it's not empty. */  
                         if (dep != NULL) {  
                             do {  
                                 dep++;  
                             } while (isspace(*dep));  
                             if (*dep != '\0')  
                                 ParseDoCommands(dep);  
                         }  
                     }  
                 }                  }
             }          } while (Parse_NextFile());
         }  
     } while (Parse_NextFile());  
   
     if (inDependency)          if (expectingCommands)
         ParseFinishDependency();                  finish_commands(&gtargets);
     /* Make sure conditionals are clean.  */          /* Make sure conditionals are clean.  */
     Cond_End();          Cond_End();
   
     Parse_ReportErrors();          Parse_ReportErrors();
     Buf_Destroy(&buf);          Buf_Destroy(&buf);
     Buf_Destroy(&copy);          Buf_Destroy(&copy);
 }  }
   
 void  void

Legend:
Removed from v.1.90  
changed lines
  Added in v.1.91