[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.8 and 1.9

version 1.8, 2001/05/14 12:55:48 version 1.9, 2001/05/23 12:34:45
Line 30 
Line 30 
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */   */
   
 #include <stdarg.h>  
 #include <stdio.h>  
 #include <assert.h>  #include <assert.h>
 #include "make.h"  #include <stddef.h>
   #include <stdio.h>
   #include <unistd.h>
   #include "config.h"
   #include "defines.h"
 #include "buf.h"  #include "buf.h"
 #include "lowparse.h"  #include "lowparse.h"
   #include "error.h"
   #include "lst.h"
   #include "memory.h"
   
 #ifdef CLEANUP  /* XXX check whether we can free filenames at the end, for a proper
    * definition of `end'. */
   
   #if 0
 static LIST         fileNames;  /* file names to free at end */  static LIST         fileNames;  /* file names to free at end */
 #endif  #endif
   
 /* Definitions for handling #include specifications */  /* Input stream structure, file or string. */
 typedef struct IFile_ {  typedef struct {
     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 */      FILE                *F;     /* Open stream, or NULL if pure string. */
     char                *str;   /* read from char area */      char                *str;   /* Input string, if F == NULL. */
     char                *ptr;   /* where we are */  
     char                *end;   /* don't overdo it */      /* Line buffer. */
       char                *ptr;   /* Where we are. */
       char                *end;   /* Don't overdo it. */
 } IFile;  } IFile;
   
 static IFile    *current;  static IFile    *current;       /* IFile being parsed. */
   
 static LIST     includes;       /* stack of IFiles generated by  static LIST     input_stack;    /* Stack of IFiles waiting to be parsed
                                  * #includes */                                   * (includes and loop reparses) */
   
 static IFile *new_ifile(char *, FILE *);  /* IFile ctors.
 static IFile *new_istring(char *, char *, unsigned long);   *
    * obj = new_ifile(filename, filehandle);
    *      Create input object from filename, filehandle. */
   static IFile *new_ifile(const char *, FILE *);
   /* obj = new_istring(str, filename, lineno);
    *      Create input object from str, filename, lineno. */
   static IFile *new_istring(char *, const char *, unsigned long);
   /* free_ifile(obj);
    *      Discard consumed input object, closing streams, freeing memory.  */
 static void free_ifile(IFile *);  static void free_ifile(IFile *);
 static void ParseVErrorInternal(char *, unsigned long, int, char *, va_list);  
   
   /* Handling basic character reading.
    * c = ParseReadc();
    *      New character c from current input stream, or EOF at end of stream. */
   #define ParseReadc()    current->ptr < current->end ? *current->ptr++ : newline()
   /* len = newline();
    *      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
    *      stream.  */
 static int newline(void);  static int newline(void);
   /* c = skiptoendofline();
    *      Skips to the end of the current line, returns either '\n' or EOF.  */
 static int skiptoendofline(void);  static int skiptoendofline(void);
 static void ParseFoldLF(Buffer, int);  
 static int ParseSkipEmptyLines(Buffer);  
 static int          fatals = 0;  
   
 /*-  
  * ParseVErrorInternal  --  
  *      Error message abort function for parsing. Prints out the context  
  *      of the error (line number and file) as well as the message with  
  *      two optional arguments.  
  *  
  * Side Effects:  
  *      "fatals" is incremented if the level is PARSE_FATAL.  
  */  
 /* VARARGS */  
 static void  
 #ifdef __STDC__  
 ParseVErrorInternal(char *cfname, unsigned long clineno, int type, char *fmt,  
     va_list ap)  
 #else  
 ParseVErrorInternal(va_alist)  
         va_dcl  
 #endif  
 {  
         (void)fprintf(stderr, "\"%s\", line %lu: ", cfname, clineno);  
         if (type == PARSE_WARNING)  
                 (void)fprintf(stderr, "warning: ");  
         (void)vfprintf(stderr, fmt, ap);  
         va_end(ap);  
         (void)fprintf(stderr, "\n");  
         if (type == PARSE_FATAL)  
                 fatals ++;  
 }  
   
 /*-  /* Helper functions to handle basic parsing. */
  * Parse_Error  --  /* ParseFoldLF(buffer, firstchar);
  *      External interface to ParseVErrorInternal; uses the default filename   *      Grabs logical line into buffer, the first character has already been
  *      Line number.   *      read into firstchar.  */
  */  static void ParseFoldLF(Buffer, int);
 /* VARARGS */  
 void  
 #ifdef __STDC__  
 Parse_Error(int type, char *fmt, ...)  
 #else  
 Parse_Error(va_alist)  
         va_dcl  
 #endif  
 {  
         va_list ap;  
 #ifdef __STDC__  
         va_start(ap, fmt);  
 #else  
         int type;               /* Error type (PARSE_WARNING, PARSE_FATAL) */  
         char *fmt;  
   
         va_start(ap);  /* firstchar = ParseSkipEmptyLines(buffer);
         type = va_arg(ap, int);   *      Scans lines, skipping empty lines. May put some characters into
         fmt = va_arg(ap, char *);   *      buffer, returns the first character useful to continue parsing
 #endif   *      (e.g., not a backslash or a space. */
   static int ParseSkipEmptyLines(Buffer);
   
         ParseVErrorInternal(current->fname, current->lineno, type, fmt, ap);  
 }  
   
 static IFile *  static IFile *
 new_ifile(name, stream)  new_ifile(name, stream)
     char *name;      const char *name;
     FILE *stream;      FILE *stream;
 {  {
     IFile *ifile;      IFile *ifile;
 #ifdef CLEANUP  #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;
Line 159 
Line 140 
 static IFile *  static IFile *
 new_istring(str, name, lineno)  new_istring(str, name, lineno)
     char *str;      char *str;
     char *name;      const char *name;
     unsigned long lineno;      unsigned long lineno;
 {  {
     IFile *ifile;      IFile *ifile;
Line 168 
Line 149 
     /* 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 from for loops... */      /* Strings are used in for loops, so we need to reset the line counter
        * 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);
Line 176 
Line 158 
 }  }
   
   
 /*-  
  *---------------------------------------------------------------------  
  * Parse_FromString  --  
  *      Start Parsing from the given string  
  *  
  * Side Effects:  
  *      A structure is added to the includes Lst and readProc, lineno,  
  *      fname and curFILE are altered for the new file  
  *---------------------------------------------------------------------  
  */  
 void  void
 Parse_FromString(str, lineno)  Parse_FromString(str, lineno)
     char                *str;      char                *str;
Line 195 
Line 167 
         (void)fprintf(stderr, "%s\n----\n", str);          (void)fprintf(stderr, "%s\n----\n", str);
   
     if (current != NULL)      if (current != NULL)
         Lst_AtFront(&includes, current);          Lst_Push(&input_stack, current);
     current = new_istring(str, current->fname, lineno);      current = new_istring(str, current->fname, lineno);
 }  }
   
   
 void  void
 Parse_FromFile(name, stream)  Parse_FromFile(name, stream)
     char                *name;      const char          *name;
     FILE                *stream;      FILE                *stream;
 {  {
     if (current != NULL)      if (current != NULL)
         Lst_AtFront(&includes, current);          Lst_Push(&input_stack, current);
     current = new_ifile(name, stream);      current = new_ifile(name, stream);
 }  }
   
 /*-  bool
  *---------------------------------------------------------------------  
  * Parse_NextFile --  
  *      Called when EOF is reached in the current file. If we were reading  
  *      an include file, the includes stack is popped and things set up  
  *      to go back to reading the previous file at the previous location.  
  *  
  * Results:  
  *      CONTINUE if there's more to do. DONE if not.  
  *  
  * Side Effects:  
  *      The old curFILE, is closed. The includes list is shortened.  
  *      lineno, curFILE, and fname are changed if CONTINUE is returned.  
  *---------------------------------------------------------------------  
  */  
 Boolean  
 Parse_NextFile()  Parse_NextFile()
 {  {
     IFile *next;      if (current != NULL)
           free_ifile(current);
     next = (IFile *)Lst_DeQueue(&includes);      current = (IFile *)Lst_Pop(&input_stack);
     if (next != NULL) {      return current != NULL;
         if (current != NULL)  
             free_ifile(current);  
         current = next;  
         return TRUE;  
     } else  
         return FALSE;  
 }  }
   
 /* guts for ParseReadc. Grab a new line off fgetln when we hit "\n" */  
 static int  static int
 newline()  newline()
 {  {
Line 258 
Line 208 
     return EOF;      return EOF;
 }  }
   
 #define ParseReadc()    current->ptr < current->end ? *current->ptr++ : newline()  
   
 /* Take advantage of fgetln: we don't have to scan a whole line to skip it.  
  */  
 static int  static int
 skiptoendofline()  skiptoendofline()
 {  {
Line 282 
Line 228 
 }  }
   
   
 /* ParseSkipGetLine():  
  *      Return the first logical line that starts with '.'  
  */  
 char *  char *
 ParseSkipGetLine(linebuf)  Parse_ReadNextConditionalLine(linebuf)
     Buffer linebuf;      Buffer linebuf;
 {  {
     int c;      int c;
Line 308 
Line 251 
     }      }
   
         /* This is the line we need to copy */          /* This is the line we need to copy */
     return ParseGetLine(linebuf, "conditional");      return Parse_ReadUnparsedLine(linebuf, "conditional");
 }  }
   
 /* Grab logical line into linebuf.  
  * The first character is already in c. */  
 static void  static void
 ParseFoldLF(linebuf, c)  ParseFoldLF(linebuf, c)
     Buffer linebuf;      Buffer linebuf;
Line 347 
Line 288 
     }      }
 }  }
   
 /* ParseGetLine:  
  *      Simply get line, no parsing beyond \  
  */  
 char *  char *
 ParseGetLine(linebuf, type)  Parse_ReadUnparsedLine(linebuf, type)
     Buffer      linebuf;      Buffer      linebuf;
     const char  *type;      const char  *type;
 {  {
Line 386 
Line 324 
     return Buf_Retrieve(linebuf);      return Buf_Retrieve(linebuf);
 }  }
   
 /* Skip all empty lines, and return the first `useful' character.  /* This is a fairly complex function, but without it, we could not skip
  * (This does skip blocks of comments at high speed, which justifies   * blocks of comments without reading them. */
  * the complexity of the function.)  
  */  
 static int  static int
 ParseSkipEmptyLines(linebuf)  ParseSkipEmptyLines(linebuf)
     Buffer      linebuf;      Buffer      linebuf;
Line 462 
Line 398 
     }      }
 }  }
   
 /*-  /* Parse_ReadNormalLine removes beginning and trailing blanks (but keeps
  *---------------------------------------------------------------------   * the first tab), handles escaped newlinews, and skip over uninteresting
  * ParseReadLine --   * lines.
  *      Read an entire line from the input file.  
  *   *
  * Results:   * The line number is advanced, which implies that continuation
  *      A line without a new line, or NULL at EOF.   * lines are numbered with the last line no (we could do better, at a
    * price).
  *   *
  * Notes:   * Trivial comments are also removed, but we can't do more, as
  *      Removes beginning and trailing blanks (but keeps first tab).   * we don't know which lines are shell commands or not.  */
  *      Updates line numbers, handles escaped newlines, and skip over  
  *      uninteresting lines.  
  *      All but trivial comments can't be handled at this point, because we  
  *      don't know yet which lines are shell commands or not.  
  *---------------------------------------------------------------------  
  */  
 char *  char *
 ParseReadLine(linebuf)  Parse_ReadNormalLine(linebuf)
     Buffer      linebuf;      Buffer      linebuf;
 {  {
     int         c;              /* the current character */      int         c;              /* the current character */
Line 511 
Line 441 
 void  void
 LowParse_Init()  LowParse_Init()
 {  {
     Lst_Init(&includes);      Lst_Init(&input_stack);
     current = NULL;      current = NULL;
 }  }
   
 void  void
 LowParse_End()  LowParse_End()
 {  {
     Lst_Destroy(&includes, NOFREE);     /* Should be empty now */      Lst_Destroy(&input_stack, NOFREE);  /* Should be empty now */
   #ifdef 0
       Lst_Destroy(&fileNames, (SimpleProc)free);
   #endif
 }  }
 #endif  #endif
   
   
 void  void
 Finish_Errors()  Parse_ReportErrors()
 {  {
     if (current != NULL) {      if (fatal_errors) {
         free_ifile(current);  #ifdef CLEANUP
         current = NULL;          while (Parse_NextFile())
     }                  ;
     if (fatals) {  #endif
         fprintf(stderr, "Fatal errors encountered -- cannot continue\n");          fprintf(stderr, "Fatal errors encountered -- cannot continue\n");
         exit(1);          exit(1);
     }      } else
           assert(current == NULL);
 }  }

Legend:
Removed from v.1.8  
changed lines
  Added in v.1.9