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

Diff for /src/usr.bin/make/lowparse.c between version 1.20 and 1.21

version 1.20, 2007/09/17 09:28:36 version 1.21, 2007/09/22 10:23:02
Line 53 
Line 53 
   
 /* Input stream structure, file or string. */  /* Input stream structure, file or string. */
 typedef struct {  typedef struct {
     const char          *fname; /* Name of file */          const char *fname;      /* Name of file */
     unsigned long       lineno; /* Line number */          unsigned long lineno;   /* Line number */
     FILE                *F;     /* Open stream, or NULL if pure string. */          FILE *F;                /* Open stream, or NULL if pure string. */
     char                *str;   /* Input string, if F == NULL. */          char *str;              /* Input string, if F == NULL. */
   
     /* Line buffer. */          /* Line buffer. */
     char                *ptr;   /* Where we are. */          char *ptr;              /* Where we are. */
     char                *end;   /* Don't overdo it. */          char *end;              /* Don't overdo it. */
 } IFile;  } IFile;
   
 static IFile    *current;       /* IFile being parsed. */  static IFile *current;          /* IFile being parsed. */
   
 static LIST     input_stack;    /* Stack of IFiles waiting to be parsed  static LIST input_stack;        /* Stack of IFiles waiting to be parsed
                                  * (includes and loop reparses) */                                   * (includes and loop reparses) */
   
 /* IFile ctors.  /* IFile ctors.
Line 84 
Line 84 
 /* Handling basic character reading.  /* Handling basic character reading.
  * c = ParseReadc();   * c = ParseReadc();
  *      New character c from current input stream, or EOF at end of stream. */   *      New character c from current input stream, or EOF at end of stream. */
 #define ParseReadc()    current->ptr < current->end ? *current->ptr++ : newline()  #define ParseReadc()    \
       current->ptr < current->end ? *current->ptr++ : newline()
 /* len = newline();  /* len = newline();
  *      Guts for ParseReadc. Grabs a new line off fgetln when we have   *      Guts for ParseReadc. Grabs a new line off fgetln when we have
  *      consumed the current line and returns its length. Or EOF at end of   *      consumed the current line and returns its length. Or EOF at end of
Line 110 
Line 111 
 static IFile *  static IFile *
 new_ifile(const char *name, FILE *stream)  new_ifile(const char *name, FILE *stream)
 {  {
     IFile *ifile;          IFile *ifile;
 #if 0  #if 0
     Lst_AtEnd(&fileNames, name);          Lst_AtEnd(&fileNames, name);
 #endif  #endif
   
     ifile = emalloc(sizeof(*ifile));          ifile = emalloc(sizeof(*ifile));
     ifile->fname = name;          ifile->fname = name;
     ifile->str = NULL;          ifile->str = NULL;
     /* Naturally enough, we start reading at line 0. */          /* Naturally enough, we start reading at line 0. */
     ifile->lineno = 0;          ifile->lineno = 0;
     ifile->F = stream;          ifile->F = stream;
     ifile->ptr = ifile->end = NULL;          ifile->ptr = ifile->end = NULL;
     return ifile;          return ifile;
 }  }
   
 static void  static void
 free_ifile(IFile *ifile)  free_ifile(IFile *ifile)
 {  {
     if (ifile->F && fileno(ifile->F) != STDIN_FILENO)          if (ifile->F && fileno(ifile->F) != STDIN_FILENO)
         (void)fclose(ifile->F);                  (void)fclose(ifile->F);
     free(ifile->str);          free(ifile->str);
     /* Note we can't free the file names yet, as they are embedded in GN for          /* Note we can't free the file names yet, as they are embedded in GN
      * error reports. */           * for error reports. */
     free(ifile);          free(ifile);
 }  }
   
 static IFile *  static IFile *
 new_istring(char *str, const char *name, unsigned long lineno)  new_istring(char *str, const char *name, unsigned long lineno)
 {  {
     IFile *ifile;          IFile *ifile;
   
     ifile = emalloc(sizeof(*ifile));          ifile = emalloc(sizeof(*ifile));
     /* No malloc, name is always taken from an already existing ifile */          /* No malloc, name is always taken from an already existing ifile */
     ifile->fname = name;          ifile->fname = name;
     ifile->F = NULL;          ifile->F = NULL;
     /* Strings are used in for loops, so we need to reset the line counter          /* Strings are used in for loops, so we need to reset the line counter
      * to an appropriate value. */           * to an appropriate value. */
     ifile->lineno = lineno;          ifile->lineno = lineno;
     ifile->ptr = ifile->str = str;          ifile->ptr = ifile->str = str;
     ifile->end = str + strlen(str);          ifile->end = str + strlen(str);
     return ifile;          return ifile;
 }  }
   
   
 void  void
 Parse_FromString(char *str, unsigned long lineno)  Parse_FromString(char *str, unsigned long lineno)
 {  {
     if (DEBUG(FOR))          if (DEBUG(FOR))
         (void)fprintf(stderr, "%s\n----\n", str);                  (void)fprintf(stderr, "%s\n----\n", str);
   
     if (current != NULL)          if (current != NULL)
         Lst_Push(&input_stack, current);                  Lst_Push(&input_stack, current);
     current = new_istring(str, current->fname, lineno);          current = new_istring(str, current->fname, lineno);
 }  }
   
   
 void  void
 Parse_FromFile(const char *name, FILE *stream)  Parse_FromFile(const char *name, FILE *stream)
 {  {
     if (current != NULL)          if (current != NULL)
         Lst_Push(&input_stack, current);                  Lst_Push(&input_stack, current);
     current = new_ifile(name, stream);          current = new_ifile(name, stream);
 }  }
   
 bool  bool
 Parse_NextFile(void)  Parse_NextFile(void)
 {  {
     if (current != NULL)          if (current != NULL)
         free_ifile(current);                  free_ifile(current);
     current = (IFile *)Lst_Pop(&input_stack);          current = (IFile *)Lst_Pop(&input_stack);
     return current != NULL;          return current != NULL;
 }  }
   
 static int  static int
 newline(void)  newline(void)
 {  {
     size_t len;          size_t len;
   
     if (current->F) {          if (current->F) {
         current->ptr = fgetln(current->F, &len);                  current->ptr = fgetln(current->F, &len);
         if (current->ptr) {                  if (current->ptr) {
             current->end = current->ptr + len;                          current->end = current->ptr + len;
             return *current->ptr++;                          return *current->ptr++;
         } else {                  } else {
             current->end = NULL;                          current->end = NULL;
                   }
         }          }
     }          return EOF;
     return EOF;  
 }  }
   
 static int  static int
 skiptoendofline(void)  skiptoendofline(void)
 {  {
     if (current->F) {          if (current->F) {
         if (current->end - current->ptr > 1)                  if (current->end - current->ptr > 1)
             current->ptr = current->end - 1;                          current->ptr = current->end - 1;
         if (*current->ptr == '\n')                  if (*current->ptr == '\n')
             return *current->ptr++;                          return *current->ptr++;
         return EOF;                  return EOF;
     } else {          } else {
         int c;                  int c;
   
         do {                  do {
             c = ParseReadc();                          c = ParseReadc();
         } while (c != '\n' && c != EOF);                  } while (c != '\n' && c != EOF);
         return c;                  return c;
     }          }
 }  }
   
   
 char *  char *
 Parse_ReadNextConditionalLine(Buffer linebuf)  Parse_ReadNextConditionalLine(Buffer linebuf)
 {  {
     int c;          int c;
   
         /* If first char isn't dot, skip to end of line, handling \ */          /* If first char isn't dot, skip to end of line, handling \ */
     while ((c = ParseReadc()) != '.') {          while ((c = ParseReadc()) != '.') {
         for (;c != '\n'; c = ParseReadc()) {                  for (;c != '\n'; c = ParseReadc()) {
             if (c == '\\') {                          if (c == '\\') {
                 c = ParseReadc();                                  c = ParseReadc();
                 if (c == '\n')                                  if (c == '\n')
                     current->lineno++;                                          current->lineno++;
             }                          }
             if (c == EOF) {                          if (c == EOF) {
                 Parse_Error(PARSE_FATAL, "Unclosed conditional");                                  Parse_Error(PARSE_FATAL,
                 return NULL;                                      "Unclosed conditional");
             }                                  return NULL;
                           }
                   }
                   current->lineno++;
         }          }
         current->lineno++;  
     }  
   
         /* This is the line we need to copy */          /* This is the line we need to copy */
     return Parse_ReadUnparsedLine(linebuf, "conditional");          return Parse_ReadUnparsedLine(linebuf, "conditional");
 }  }
   
 static void  static void
 ParseFoldLF(Buffer linebuf, int c)  ParseFoldLF(Buffer linebuf, int c)
 {  {
     for (;;) {          for (;;) {
         if (c == '\n') {                  if (c == '\n') {
             current->lineno++;                          current->lineno++;
             break;                          break;
         }  
         if (c == EOF)  
             break;  
         Buf_AddChar(linebuf, c);  
         c = ParseReadc();  
         while (c == '\\') {  
             c = ParseReadc();  
             if (c == '\n') {  
                 Buf_AddSpace(linebuf);  
                 current->lineno++;  
                 do {  
                     c = ParseReadc();  
                 } while (c == ' ' || c == '\t');  
             } else {  
                 Buf_AddChar(linebuf, '\\');  
                 if (c == '\\') {  
                     Buf_AddChar(linebuf, '\\');  
                     c = ParseReadc();  
                 }                  }
                 break;                  if (c == EOF)
             }                          break;
                   Buf_AddChar(linebuf, c);
                   c = ParseReadc();
                   while (c == '\\') {
                           c = ParseReadc();
                           if (c == '\n') {
                                   Buf_AddSpace(linebuf);
                                   current->lineno++;
                                   do {
                                           c = ParseReadc();
                                   } while (c == ' ' || c == '\t');
                           } else {
                                   Buf_AddChar(linebuf, '\\');
                                   if (c == '\\') {
                                           Buf_AddChar(linebuf, '\\');
                                           c = ParseReadc();
                                   }
                                   break;
                           }
                   }
         }          }
     }  
 }  }
   
 char *  char *
 Parse_ReadUnparsedLine(Buffer linebuf, const char *type)  Parse_ReadUnparsedLine(Buffer linebuf, const char *type)
 {  {
     int c;          int c;
   
     Buf_Reset(linebuf);          Buf_Reset(linebuf);
     c = ParseReadc();  
     if (c == EOF) {  
         Parse_Error(PARSE_FATAL, "Unclosed %s", type);  
         return NULL;  
     }  
   
     /* Handle '\' at beginning of line, since \\n needs special treatment */  
     while (c == '\\') {  
         c = ParseReadc();          c = ParseReadc();
         if (c == '\n') {          if (c == EOF) {
             current->lineno++;                  Parse_Error(PARSE_FATAL, "Unclosed %s", type);
             do {                  return NULL;
           }
   
           /* Handle '\' at beginning of line, since \\n needs special treatment */
           while (c == '\\') {
                 c = ParseReadc();                  c = ParseReadc();
             } while (c == ' ' || c == '\t');                  if (c == '\n') {
         } else {                          current->lineno++;
             Buf_AddChar(linebuf, '\\');                          do {
             if (c == '\\') {                                  c = ParseReadc();
                 Buf_AddChar(linebuf, '\\');                          } while (c == ' ' || c == '\t');
                 c = ParseReadc();                  } else {
             }                          Buf_AddChar(linebuf, '\\');
             break;                          if (c == '\\') {
                                   Buf_AddChar(linebuf, '\\');
                                   c = ParseReadc();
                           }
                           break;
                   }
         }          }
     }          ParseFoldLF(linebuf, c);
     ParseFoldLF(linebuf, c);  
   
     return Buf_Retrieve(linebuf);          return Buf_Retrieve(linebuf);
 }  }
   
 /* This is a fairly complex function, but without it, we could not skip  /* This is a fairly complex function, but without it, we could not skip
Line 316 
Line 318 
 static int  static int
 ParseSkipEmptyLines(Buffer linebuf)  ParseSkipEmptyLines(Buffer linebuf)
 {  {
     int         c;              /* the current character */          int c;          /* the current character */
   
     for (;;) {          for (;;) {
         Buf_Reset(linebuf);                  Buf_Reset(linebuf);
         c = ParseReadc();  
         /* Strip leading spaces, fold on '\n' */  
         if (c == ' ') {  
             do {  
                 c = ParseReadc();                  c = ParseReadc();
             } while (c == ' ' || c == '\t');                  /* Strip leading spaces, fold on '\n' */
             while (c == '\\') {                  if (c == ' ') {
                 c = ParseReadc();                          do {
                 if (c == '\n') {                                  c = ParseReadc();
                     current->lineno++;                          } while (c == ' ' || c == '\t');
                     do {                          while (c == '\\') {
                         c = ParseReadc();                                  c = ParseReadc();
                     } while (c == ' ' || c == '\t');                                  if (c == '\n') {
                 } else {                                          current->lineno++;
                     Buf_AddChar(linebuf, '\\');                                          do {
                     if (c == '\\') {                                                  c = ParseReadc();
                         Buf_AddChar(linebuf, '\\');                                          } while (c == ' ' || c == '\t');
                         c = ParseReadc();                                  } else {
                     }                                          Buf_AddChar(linebuf, '\\');
                     if (c == EOF)                                          if (c == '\\') {
                         return '\n';                                                  Buf_AddChar(linebuf, '\\');
                     else                                                  c = ParseReadc();
                         return c;                                          }
                                           if (c == EOF)
                                                   return '\n';
                                           else
                                                   return c;
                                   }
                           }
                           assert(c != '\t');
                 }                  }
             }                  if (c == '#')
             assert(c != '\t');                          c = skiptoendofline();
         }                  /* Almost identical to spaces, except this occurs after
         if (c == '#')                   * comments have been taken care of, and we keep the tab
             c = skiptoendofline();                   * itself.  */
         /* Almost identical to spaces, except this occurs after comments                  if (c == '\t') {
          * have been taken care of, and we keep the tab itself.  */                          Buf_AddChar(linebuf, '\t');
         if (c == '\t') {                          do {
             Buf_AddChar(linebuf, '\t');                                  c = ParseReadc();
             do {                          } while (c == ' ' || c == '\t');
                 c = ParseReadc();                          while (c == '\\') {
             } while (c == ' ' || c == '\t');                                  c = ParseReadc();
             while (c == '\\') {                                  if (c == '\n') {
                 c = ParseReadc();                                          current->lineno++;
                 if (c == '\n') {                                          do {
                     current->lineno++;                                                  c = ParseReadc();
                     do {                                          } while (c == ' ' || c == '\t');
                         c = ParseReadc();                                  } else {
                     } while (c == ' ' || c == '\t');                                          Buf_AddChar(linebuf, '\\');
                 } else {                                          if (c == '\\') {
                     Buf_AddChar(linebuf, '\\');                                                  Buf_AddChar(linebuf, '\\');
                     if (c == '\\') {                                                  c = ParseReadc();
                         Buf_AddChar(linebuf, '\\');                                          }
                         c = ParseReadc();                                          if (c == EOF)
                     }                                                  return '\n';
                     if (c == EOF)                                          else
                         return '\n';                                                  return c;
                     else                                  }
                         return c;                          }
                 }                  }
             }                  if (c == '\n')
                           current->lineno++;
                   else
                           return c;
         }          }
         if (c == '\n')  
             current->lineno++;  
         else  
             return c;  
     }  
 }  }
   
 /* Parse_ReadNormalLine removes beginning and trailing blanks (but keeps  /* Parse_ReadNormalLine removes beginning and trailing blanks (but keeps
Line 396 
Line 399 
 char *  char *
 Parse_ReadNormalLine(Buffer linebuf)  Parse_ReadNormalLine(Buffer linebuf)
 {  {
     int         c;              /* the current character */          int c;          /* the current character */
   
     c = ParseSkipEmptyLines(linebuf);          c = ParseSkipEmptyLines(linebuf);
   
     if (c == EOF)          if (c == EOF)
         return NULL;                  return NULL;
     else {          else {
         ParseFoldLF(linebuf, c);                  ParseFoldLF(linebuf, c);
         Buf_KillTrailingSpaces(linebuf);                  Buf_KillTrailingSpaces(linebuf);
         return Buf_Retrieve(linebuf);                  return Buf_Retrieve(linebuf);
     }          }
 }  }
   
 unsigned long  unsigned long
 Parse_Getlineno(void)  Parse_Getlineno(void)
 {  {
     return current ? current->lineno : 0;          return current ? current->lineno : 0;
 }  }
   
 const char *  const char *
 Parse_Getfilename(void)  Parse_Getfilename(void)
 {  {
     return current ? current->fname : NULL;          return current ? current->fname : NULL;
 }  }
   
 #ifdef CLEANUP  #ifdef CLEANUP
 void  void
 LowParse_Init(void)  LowParse_Init(void)
 {  {
     Static_Lst_Init(&input_stack);          Static_Lst_Init(&input_stack);
     current = NULL;          current = NULL;
 }  }
   
 void  void
 LowParse_End(void)  LowParse_End(void)
 {  {
     Lst_Destroy(&input_stack, NOFREE);  /* Should be empty now */          Lst_Destroy(&input_stack, NOFREE);      /* Should be empty now */
 #if 0  #if 0
     Lst_Destroy(&fileNames, (SimpleProc)free);          Lst_Destroy(&fileNames, (SimpleProc)free);
 #endif  #endif
 }  }
 #endif  #endif
Line 443 
Line 446 
 void  void
 Parse_ReportErrors(void)  Parse_ReportErrors(void)
 {  {
     if (fatal_errors) {          if (fatal_errors) {
 #ifdef CLEANUP  #ifdef CLEANUP
         while (Parse_NextFile())                  while (Parse_NextFile())
                 ;                          ;
 #endif  #endif
         fprintf(stderr, "Fatal errors encountered -- cannot continue\n");                  fprintf(stderr,
         exit(1);                      "Fatal errors encountered -- cannot continue\n");
     } else                  exit(1);
         assert(current == NULL);          } else
                   assert(current == NULL);
 }  }

Legend:
Removed from v.1.20  
changed lines
  Added in v.1.21