]> git.sur5r.net Git - cc65/blobdiff - src/cc65/input.c
Removed (pretty inconsistently used) tab chars from source code base.
[cc65] / src / cc65 / input.c
index 7b6f808d6ec84a2496078465ab4c582b780543d0..a98c72e4f2e014a29e8c0e893e1699598d4396ea 100644 (file)
@@ -1,12 +1,12 @@
 /*****************************************************************************/
 /*                                                                           */
-/*                                 input.c                                  */
+/*                                  input.c                                  */
 /*                                                                           */
-/*                           Input file handling                            */
+/*                            Input file handling                            */
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2000-2010, Ullrich von Bassewitz                                      */
+/* (C) 2000-2012, Ullrich von Bassewitz                                      */
 /*                Roemerstrasse 52                                           */
 /*                D-70794 Filderstadt                                        */
 /* EMail:         uz@cc65.org                                                */
 #include <stdio.h>
 #include <string.h>
 #include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
 
 /* common */
 #include "check.h"
 #include "coll.h"
+#include "filestat.h"
+#include "fname.h"
 #include "print.h"
 #include "strbuf.h"
 #include "xmalloc.h"
 
 
 /*****************************************************************************/
-/*                                  Data                                    */
+/*                                   Data                                    */
 /*****************************************************************************/
 
 
 
-/* An enum that describes different types of input files. The members are
- * choosen so that it is possible to combine them to bitsets
- */
-typedef enum {
-    IT_MAIN     = 0x01,         /* Main input file */
-    IT_SYSINC   = 0x02,         /* System include file (using <>) */
-    IT_USERINC  = 0x04,         /* User include file (using "") */
-} InputType;
-
 /* The current input line */
 StrBuf* Line;
 
@@ -80,25 +71,26 @@ char CurC  = '\0';
 char NextC = '\0';
 
 /* Maximum count of nested includes */
-#define MAX_INC_NESTING        16
+#define MAX_INC_NESTING         16
 
 /* Struct that describes an input file */
 typedef struct IFile IFile;
 struct IFile {
-    unsigned       Index;      /* File index */
-    unsigned       Usage;      /* Usage counter */
+    unsigned        Index;      /* File index */
+    unsigned        Usage;      /* Usage counter */
     unsigned long   Size;       /* File size */
     unsigned long   MTime;      /* Time of last modification */
     InputType       Type;       /* Type of input file */
-    char                   Name[1];    /* Name of file (dynamically allocated) */
+    char            Name[1];    /* Name of file (dynamically allocated) */
 };
 
 /* Struct that describes an active input file */
 typedef struct AFile AFile;
 struct AFile {
-    unsigned   Line;           /* Line number for this file            */
-    FILE*      F;              /* Input file stream                    */
-    IFile*      Input;          /* Points to corresponding IFile        */
+    unsigned    Line;           /* Line number for this file */
+    FILE*       F;              /* Input file stream */
+    IFile*      Input;          /* Points to corresponding IFile */
+    int         SearchPath;     /* True if we've added a path for this file */
 };
 
 /* List of all input files */
@@ -113,7 +105,7 @@ static Collection InputStack = STATIC_COLLECTION_INITIALIZER;
 
 
 /*****************************************************************************/
-/*                              struct IFile                                */
+/*                               struct IFile                                */
 /*****************************************************************************/
 
 
@@ -145,14 +137,18 @@ static IFile* NewIFile (const char* Name, InputType Type)
 
 
 /*****************************************************************************/
-/*                              struct AFile                                */
+/*                               struct AFile                                */
 /*****************************************************************************/
 
 
 
 static AFile* NewAFile (IFile* IF, FILE* F)
-/* Create and return a new AFile */
+/* Create a new AFile, push it onto the stack, add the path of the file to
+ * the path search list, and finally return a pointer to the new AFile struct.
+ */
 {
+    StrBuf Path = AUTO_STRBUF_INITIALIZER;
+
     /* Allocate a AFile structure */
     AFile* AF = (AFile*) xmalloc (sizeof (AFile));
 
@@ -167,7 +163,7 @@ static AFile* NewAFile (IFile* IF, FILE* F)
      */
     if (IF->Usage++ == 0) {
 
-       /* Get file size and modification time. There a race condition here,
+        /* Get file size and modification time. There a race condition here,
          * since we cannot use fileno() (non standard identifier in standard
          * header file), and therefore not fstat. When using stat with the
          * file name, there's a risk that the file was deleted and recreated
@@ -175,21 +171,30 @@ static AFile* NewAFile (IFile* IF, FILE* F)
          * if a file has changed in the debugger, we will ignore this problem
          * here.
          */
-       struct stat Buf;
-       if (stat (IF->Name, &Buf) != 0) {
-           /* Error */
-           Fatal ("Cannot stat `%s': %s", IF->Name, strerror (errno));
-       }
-               IF->Size  = (unsigned long) Buf.st_size;
-       IF->MTime = (unsigned long) Buf.st_mtime;
-
-       /* Set the debug data */
-       g_fileinfo (IF->Name, IF->Size, IF->MTime);
+        struct stat Buf;
+        if (FileStat (IF->Name, &Buf) != 0) {
+            /* Error */
+            Fatal ("Cannot stat `%s': %s", IF->Name, strerror (errno));
+        }
+        IF->Size  = (unsigned long) Buf.st_size;
+        IF->MTime = (unsigned long) Buf.st_mtime;
+
+        /* Set the debug data */
+        g_fileinfo (IF->Name, IF->Size, IF->MTime);
     }
 
     /* Insert the new structure into the AFile collection */
     CollAppend (&AFiles, AF);
 
+    /* Get the path of this file and add it as an extra search path.
+     * To avoid file search overhead, we will add one path only once.
+     * This is checked by the PushSearchPath function.
+     */
+    SB_CopyBuf (&Path, IF->Name, FindName (IF->Name) - IF->Name);
+    SB_Terminate (&Path);
+    AF->SearchPath = PushSearchPath (UsrIncSearchPath, SB_GetConstBuf (&Path));
+    SB_Done (&Path);
+
     /* Return the new struct */
     return AF;
 }
@@ -205,7 +210,7 @@ static void FreeAFile (AFile* AF)
 
 
 /*****************************************************************************/
-/*                                  Code                                    */
+/*                                   Code                                    */
 /*****************************************************************************/
 
 
@@ -218,13 +223,13 @@ static IFile* FindFile (const char* Name)
 {
     unsigned I;
     for (I = 0; I < CollCount (&IFiles); ++I) {
-       /* Get the file struct */
-       IFile* IF = (IFile*) CollAt (&IFiles, I);
-       /* Check the name */
-       if (strcmp (Name, IF->Name) == 0) {
-           /* Found, return the struct */
-           return IF;
-               }
+        /* Get the file struct */
+        IFile* IF = (IFile*) CollAt (&IFiles, I);
+        /* Check the name */
+        if (strcmp (Name, IF->Name) == 0) {
+            /* Found, return the struct */
+            return IF;
+        }
     }
 
     /* Not found */
@@ -245,8 +250,8 @@ void OpenMainFile (const char* Name)
     /* Open the file for reading */
     FILE* F = fopen (Name, "r");
     if (F == 0) {
-               /* Cannot open */
-               Fatal ("Cannot open input file `%s': %s", Name, strerror (errno));
+        /* Cannot open */
+        Fatal ("Cannot open input file `%s': %s", Name, strerror (errno));
     }
 
     /* Allocate a new AFile structure for the file */
@@ -263,7 +268,7 @@ void OpenMainFile (const char* Name)
 
 
 
-void OpenIncludeFile (const char* Name, unsigned DirSpec)
+void OpenIncludeFile (const char* Name, InputType IT)
 /* Open an include file and insert it into the tables. */
 {
     char*  N;
@@ -272,15 +277,15 @@ void OpenIncludeFile (const char* Name, unsigned DirSpec)
 
     /* Check for the maximum include nesting */
     if (CollCount (&AFiles) > MAX_INC_NESTING) {
-       PPError ("Include nesting too deep");
-       return;
+        PPError ("Include nesting too deep");
+        return;
     }
 
     /* Search for the file */
-    N = FindInclude (Name, DirSpec);
+    N = SearchFile ((IT == IT_SYSINC)? SysIncSearchPath : UsrIncSearchPath, Name);
     if (N == 0) {
-       PPError ("Include file `%s' not found", Name);
-       return;
+        PPError ("Include file `%s' not found", Name);
+        return;
     }
 
     /* Search the list of all input files for this file. If we don't find
@@ -288,7 +293,7 @@ void OpenIncludeFile (const char* Name, unsigned DirSpec)
      */
     IF = FindFile (N);
     if (IF == 0) {
-       IF = NewIFile (N, (DirSpec == INC_SYS)? IT_SYSINC : IT_USERINC);
+        IF = NewIFile (N, IT);
     }
 
     /* We don't need N any longer, since we may now use IF->Name */
@@ -297,9 +302,9 @@ void OpenIncludeFile (const char* Name, unsigned DirSpec)
     /* Open the file */
     F = fopen (IF->Name, "r");
     if (F == 0) {
-       /* Error opening the file */
-       PPError ("Cannot open include file `%s': %s", IF->Name, strerror (errno));
-       return;
+        /* Error opening the file */
+        PPError ("Cannot open include file `%s': %s", IF->Name, strerror (errno));
+        return;
     }
 
     /* Debugging output */
@@ -333,6 +338,11 @@ static void CloseIncludeFile (void)
     /* Delete the last active file from the active file collection */
     CollDelete (&AFiles, AFileCount-1);
 
+    /* If we had added an extra search path for this AFile, remove it */
+    if (Input->SearchPath) {
+        PopSearchPath (UsrIncSearchPath);
+    }
+
     /* Delete the active file structure */
     FreeAFile (Input);
 }
@@ -428,14 +438,14 @@ StrBuf* InitLine (StrBuf* Buf)
 int NextLine (void)
 /* Get a line from the current input. Returns 0 on end of file. */
 {
-    AFile*             Input;
+    AFile*      Input;
 
     /* Clear the current line */
     ClearLine ();
 
     /* If there is no file open, bail out, otherwise get the current input file */
     if (CollCount (&AFiles) == 0) {
-       return 0;
+        return 0;
     }
     Input = CollLast (&AFiles);
 
@@ -454,8 +464,8 @@ int NextLine (void)
                 break;
             }
 
-           /* Leave the current file */
-           CloseIncludeFile ();
+            /* Leave the current file */
+            CloseIncludeFile ();
 
             /* If there is no file open, bail out, otherwise get the
              * previous input file and start over.
@@ -526,17 +536,17 @@ const char* GetCurrentFile (void)
 {
     unsigned AFileCount = CollCount (&AFiles);
     if (AFileCount > 0) {
-       const AFile* AF = (const AFile*) CollAt (&AFiles, AFileCount-1);
-       return AF->Input->Name;
+        const AFile* AF = (const AFile*) CollAt (&AFiles, AFileCount-1);
+        return AF->Input->Name;
     } else {
-       /* No open file. Use the main file if we have one. */
-       unsigned IFileCount = CollCount (&IFiles);
-       if (IFileCount > 0) {
-           const IFile* IF = (const IFile*) CollAt (&IFiles, 0);
-           return IF->Name;
-       } else {
-           return "(outside file scope)";
-       }
+        /* No open file. Use the main file if we have one. */
+        unsigned IFileCount = CollCount (&IFiles);
+        if (IFileCount > 0) {
+            const IFile* IF = (const IFile*) CollAt (&IFiles, 0);
+            return IF->Name;
+        } else {
+            return "(outside file scope)";
+        }
     }
 }
 
@@ -547,11 +557,26 @@ unsigned GetCurrentLine (void)
 {
     unsigned AFileCount = CollCount (&AFiles);
     if (AFileCount > 0) {
-       const AFile* AF = (const AFile*) CollAt (&AFiles, AFileCount-1);
-       return AF->Line;
+        const AFile* AF = (const AFile*) CollAt (&AFiles, AFileCount-1);
+        return AF->Line;
     } else {
-       /* No open file */
-       return 0;
+        /* No open file */
+        return 0;
+    }
+}
+
+
+
+static void WriteEscaped (FILE* F, const char* Name)
+/* Write a file name to a dependency file escaping spaces */
+{
+    while (*Name) {
+        if (*Name == ' ') {
+            /* Escape spaces */
+            fputc ('\\', F);
+        }
+        fputc (*Name, F);
+        ++Name;
     }
 }
 
@@ -566,21 +591,21 @@ static void WriteDep (FILE* F, InputType Types)
     unsigned FileCount = CollCount (&IFiles);
     for (I = 0; I < FileCount; ++I) {
 
-       /* Get the next input file */
-       const IFile* IF = (const IFile*) CollAt (&IFiles, I);
+        /* Get the next input file */
+        const IFile* IF = (const IFile*) CollAt (&IFiles, I);
 
         /* Ignore it if it is not of the correct type */
         if ((IF->Type & Types) == 0) {
             continue;
         }
 
-       /* If this is not the first file, add a space */
-               if (I > 0) {
+        /* If this is not the first file, add a space */
+        if (I > 0) {
             fputc (' ', F);
         }
 
-       /* Print the dependency */
-        fputs (IF->Name, F);
+        /* Print the dependency escaping spaces */
+        WriteEscaped (F, IF->Name);
     }
 }
 
@@ -590,24 +615,22 @@ static void CreateDepFile (const char* Name, InputType Types)
 /* Create a dependency file with the given name and place dependencies for
  * all files with the given types there.
  */
-{      
-    const char* Target;
-
+{
     /* Open the file */
     FILE* F = fopen (Name, "w");
     if (F == 0) {
-               Fatal ("Cannot open dependency file `%s': %s", Name, strerror (errno));
+        Fatal ("Cannot open dependency file `%s': %s", Name, strerror (errno));
     }
 
     /* If a dependency target was given, use it, otherwise use the output
      * file name as target, followed by a tab character.
      */
     if (SB_IsEmpty (&DepTarget)) {
-        Target = OutputFilename;
+        WriteEscaped (F, OutputFilename);
     } else {
-        Target = SB_GetConstBuf (&DepTarget);
+        WriteEscaped (F, SB_GetConstBuf (&DepTarget));
     }
-    fprintf (F, "%s:\t", Target);
+    fputs (":\t", F);
 
     /* Write out the dependencies for the output file */
     WriteDep (F, Types);
@@ -619,8 +642,8 @@ static void CreateDepFile (const char* Name, InputType Types)
 
     /* Close the file, check for errors */
     if (fclose (F) != 0) {
-       remove (Name);
-       Fatal ("Cannot write to dependeny file (disk full?)");
+        remove (Name);
+        Fatal ("Cannot write to dependeny file (disk full?)");
     }
 }
 
@@ -631,11 +654,11 @@ void CreateDependencies (void)
 {
     if (SB_NotEmpty (&DepName)) {
         CreateDepFile (SB_GetConstBuf (&DepName),
-                       IT_MAIN | IT_USERINC);
+                       IT_MAIN | IT_USRINC);
     }
     if (SB_NotEmpty (&FullDepName)) {
         CreateDepFile (SB_GetConstBuf (&FullDepName),
-                       IT_MAIN | IT_SYSINC | IT_USERINC);
+                       IT_MAIN | IT_SYSINC | IT_USRINC);
     }
 }