#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 "print.h"
#include "xmalloc.h"
/* cc65 */
#include "asmcode.h"
+#include "codegen.h"
#include "error.h"
-#include "global.h"
#include "incpath.h"
+#include "lineinfo.h"
#include "input.h"
/* Maximum count of nested includes */
#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 */
- 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 */
- const char* Name; /* Points to corresponding IFile name */
+ IFile* Input; /* Points to corresponding IFile */
};
/* List of all input files */
/*****************************************************************************/
-/* struct IFile */
+/* struct IFile */
/*****************************************************************************/
unsigned Len = strlen (Name);
/* Allocate a IFile structure */
- IFile* IF = xmalloc (sizeof (IFile) + Len);
+ IFile* IF = (IFile*) xmalloc (sizeof (IFile) + Len);
/* Initialize the fields */
IF->Index = CollCount (&IFiles) + 1;
IF->Usage = 0;
+ IF->Size = 0;
+ IF->MTime = 0;
memcpy (IF->Name, Name, Len+1);
/* Insert the new structure into the IFile collection */
/* Create and return a new AFile */
{
/* Allocate a AFile structure */
- AFile* AF = xmalloc (sizeof (AFile));
+ AFile* AF = (AFile*) xmalloc (sizeof (AFile));
/* Initialize the fields */
AF->Line = 0;
AF->F = F;
- AF->Name = IF->Name;
+ AF->Input = IF;
+
+ /* Increment the usage counter of the corresponding IFile. If this
+ * is the first use, set the file data and output debug info if
+ * requested.
+ */
+ if (IF->Usage++ == 0) {
- /* Increment the usage counter of the corresponding IFile */
- ++IF->Usage;
+ /* Get file size and modification time */
+ struct stat Buf;
+ if (fstat (fileno (F), &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);
unsigned I;
for (I = 0; I < CollCount (&IFiles); ++I) {
/* Get the file struct */
- IFile* IF = CollAt (&IFiles, I);
+ IFile* IF = (IFile*) CollAt (&IFiles, I);
/* Check the name */
if (strcmp (Name, IF->Name) == 0) {
/* Found, return the struct */
return;
}
+ /* Debugging output */
+ Print (stdout, 1, "Opened include file `%s'\n", IF->Name);
+
/* Allocate a new AFile structure */
(void) NewAFile (IF, F);
}
PRECONDITION (AFileCount > 0);
/* Get the current active input file */
- Input = CollLast (&AFiles);
+ Input = (AFile*) CollLast (&AFiles);
/* Close the current input file (we're just reading so no error check) */
fclose (Input->F);
if (CollCount (&AFiles) == 0) {
return 0;
}
- Input = CollLast (&AFiles);
+ Input = (AFile*) CollLast (&AFiles);
/* Read lines until we get one with real contents */
Len = 0;
if (CollCount (&AFiles) == 0) {
return 0;
}
- Input = CollLast (&AFiles);
+ Input = (AFile*) CollLast (&AFiles);
}
/* We got a new line */
++Input->Line;
- /* Remove the trailing newline if we have one */
+ /* Remove the trailing cr/lf if we have one. We will ignore both, cr
+ * and lf on all systems since this enables us to compile DOS/Windows
+ * stuff also on unix systems (where fgets does not remove the cr).
+ */
Part = strlen (line + Len);
Start = Len;
Len += Part;
- while (Len > 0 && line [Len-1] == '\n') {
+ while (Len > 0 && (line[Len-1] == '\n' || line[Len-1] == '\r')) {
--Len;
}
line [Len] = '\0';
- /* Output the source line in the generated assembler file
- * if requested.
- */
- if (AddSource && line[Start] != '\0') {
- AddCodeLine ("; %s", line+Start);
- }
-
/* Check if we have a line continuation character at the end. If not,
* we're done.
*/
/* Got a line. Initialize the current and next characters. */
InitLine (line);
+ /* Create line information for this line */
+ UpdateLineInfo (Input->Input, Input->Line, line);
+
/* Done */
return 1;
}
{
unsigned AFileCount = CollCount (&AFiles);
if (AFileCount > 0) {
- const AFile* AF = CollAt (&AFiles, AFileCount-1);
- return AF->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 = CollAt (&IFiles, 0);
+ const IFile* IF = (const IFile*) CollAt (&IFiles, 0);
return IF->Name;
} else {
return "(outside file scope)";
{
unsigned AFileCount = CollCount (&AFiles);
if (AFileCount > 0) {
- const AFile* AF = CollAt (&AFiles, AFileCount-1);
+ const AFile* AF = (const AFile*) CollAt (&AFiles, AFileCount-1);
return AF->Line;
} else {
/* No open file */
/* Loop over all files */
for (I = 0; I < IFileCount; ++I) {
/* Get the next input file */
- const IFile* IF = CollAt (&IFiles, I);
+ const IFile* IF = (const IFile*) CollAt (&IFiles, I);
/* If this is not the first file, add a space */
const char* Format = (I == 0)? "%s" : " %s";
/* Print the dependency */