#include <stdio.h>
+#include "../common/xmalloc.h"
#include "../common/xsprintf.h"
#include "error.h"
-#include "mem.h"
#include "asmline.h"
#include <string.h>
#include "../common/version.h"
+#include "../common/xmalloc.h"
#include "asmcode.h"
#include "asmlabel.h"
#include "global.h"
#include "io.h"
#include "litpool.h"
-#include "mem.h"
#include "optimize.h"
#include "util.h"
#include "codegen.h"
ldaconst (offs); /* Load A with offset value */
AddCodeLine ("\tjsr\tleaasp"); /* Load effective address */
} else {
- ldaconst (offs);
- AddCodeLine ("\tclc");
- AddCodeLine ("\tldx\tsp+1");
- AddCodeLine ("\tadc\tsp");
- AddCodeLine ("\tbcc\t*+3");
- AddCodeLine ("\tinx");
- AddCodeHint ("x:!"); /* Invalidate X */
+ if (CPU == CPU_65C02 && offs == 1) {
+ AddCodeLine ("\tlda\tsp");
+ AddCodeLine ("\tldx\tsp+1");
+ AddCodeLine ("\tina");
+ AddCodeLine ("\tbne\t*+3");
+ AddCodeLine ("\tinx");
+ AddCodeHint ("x:!"); /* Invalidate X */
+ } else {
+ ldaconst (offs);
+ AddCodeLine ("\tclc");
+ AddCodeLine ("\tldx\tsp+1");
+ AddCodeLine ("\tadc\tsp");
+ AddCodeLine ("\tbcc\t*+3");
+ AddCodeLine ("\tinx");
+ AddCodeHint ("x:!"); /* Invalidate X */
+ }
}
}
}
AddCodeLine ("\tjsr\tpushax"); /* Push the address */
push (flags); /* Correct the internal sp */
g_getind (flags, offs); /* Fetch the value */
- g_inc (flags, val); /* Increment value in primary */
+ g_inc (flags, val); /* Increment value in primary */
g_putind (flags, offs); /* Store the value back */
break;
AddCodeLine ("\t.res\t%u,$00", n);
}
-
+
/*****************************************************************************/
/* Inlined known functions */
static void Parse (void)
-/* Process all input text.
- * At this level, only static declarations, defines, includes, and function
- * definitions are legal....
- */
+/* Top level parser routine. */
{
int comma;
SymEntry* Entry;
/* Setup variables */
- filetab[0].f_iocb = inp;
LiteralLabel = GetLabel ();
/* Add some standard paths to the include search path */
#include <string.h>
+#include "../common/xmalloc.h"
+
#include "check.h"
#include "codegen.h"
#include "datatype.h"
#include "error.h"
#include "funcdesc.h"
#include "global.h"
-#include "mem.h"
#include "util.h"
#include "symtab.h"
#include <errno.h>
#include <ctype.h>
+#include "../common/xmalloc.h"
+
#include "anonname.h"
#include "codegen.h"
#include "datatype.h"
#include "function.h"
#include "global.h"
#include "litpool.h"
-#include "mem.h"
#include "pragma.h"
#include "scanner.h"
#include "symtab.h"
#include <stdarg.h>
#include "global.h"
+#include "input.h"
#include "io.h"
#include "scanner.h"
#include "stmt.h"
va_list ap;
if (!NoWarn) {
- fprintf (stderr, "%s(%u): Warning #%u: ", fin, curpos, WarnNum);
+ fprintf (stderr, "%s(%u): Warning #%u: ",
+ GetCurrentFile(), curpos, WarnNum);
va_start (ap, WarnNum);
vfprintf (stderr, WarnMsg [WarnNum-1], ap);
va_list ap;
if (!NoWarn) {
- fprintf (stderr, "%s(%u): Warning #%u: ", fin, ln, WarnNum);
+ fprintf (stderr, "%s(%u): Warning #%u: ",
+ GetCurrentFile(), GetCurrentLine(), WarnNum);
va_start (ap, WarnNum);
vfprintf (stderr, WarnMsg [WarnNum-1], ap);
{
va_list ap;
- fprintf (stderr, "%s(%u): Error #%u: ", fin, curpos, ErrNum);
+ fprintf (stderr, "%s(%u): Error #%u: ",
+ GetCurrentFile(), curpos, ErrNum);
va_start (ap, ErrNum);
vfprintf (stderr, ErrMsg [ErrNum-1], ap);
{
va_list ap;
- fprintf (stderr, "%s(%u): Error #%u: ", fin, ln, ErrNum);
+ fprintf (stderr, "%s(%u): Error #%u: ",
+ GetCurrentFile(), GetCurrentLine(), ErrNum);
va_start (ap, ErrNum);
vfprintf (stderr, ErrMsg [ErrNum-1], ap);
{
va_list ap;
- fprintf (stderr, "%s(%u): Fatal #%u: ", fin, curpos, FatNum);
+ fprintf (stderr, "%s(%u): Fatal #%u: ",
+ GetCurrentFile(), curpos, FatNum);
va_start (ap, FatNum);
vfprintf (stderr, FatMsg [FatNum-1], ap);
{
va_list ap;
- fprintf (stderr, "%s(%u): Internal compiler error:\n", fin, curpos);
+ fprintf (stderr, "%s(%u): Internal compiler error:\n",
+ GetCurrentFile(), curpos);
va_start (ap, Format);
vfprintf (stderr, Format, ap);
+
#include <stdlib.h>
#include <string.h>
+#include "../common/xmalloc.h"
+
#include "asmcode.h"
#include "asmlabel.h"
#include "check.h"
#include "io.h"
#include "litpool.h"
#include "macrotab.h"
-#include "mem.h"
#include "preproc.h"
#include "scanner.h"
#include "stdfunc.h"
-#include "mem.h"
+#include "../common/xmalloc.h"
+
#include "funcdesc.h"
+#include "../common/xmalloc.h"
+
#include "asmcode.h"
#include "asmlabel.h"
#include "codegen.h"
#include "funcdesc.h"
#include "litpool.h"
#include "locals.h"
-#include "mem.h"
#include "scanner.h"
#include "stmt.h"
#include "symtab.h"
# include <unistd.h>
#endif
-#include "mem.h"
+#include "../common/xmalloc.h"
+
#include "incpath.h"
--- /dev/null
+/*****************************************************************************/
+/* */
+/* input.c */
+/* */
+/* Input file handling */
+/* */
+/* */
+/* */
+/* (C) 2000 Ullrich von Bassewitz */
+/* Wacholderweg 14 */
+/* D-70597 Stuttgart */
+/* EMail: uz@musoftware.de */
+/* */
+/* */
+/* This software is provided 'as-is', without any expressed or implied */
+/* warranty. In no event will the authors be held liable for any damages */
+/* arising from the use of this software. */
+/* */
+/* Permission is granted to anyone to use this software for any purpose, */
+/* including commercial applications, and to alter it and redistribute it */
+/* freely, subject to the following restrictions: */
+/* */
+/* 1. The origin of this software must not be misrepresented; you must not */
+/* claim that you wrote the original software. If you use this software */
+/* in a product, an acknowledgment in the product documentation would be */
+/* appreciated but is not required. */
+/* 2. Altered source versions must be plainly marked as such, and must not */
+/* be misrepresented as being the original software. */
+/* 3. This notice may not be removed or altered from any source */
+/* distribution. */
+/* */
+/*****************************************************************************/
+
+
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include "../common/xmalloc.h"
+
+#include "asmcode.h"
+#include "check.h"
+#include "error.h"
+#include "global.h"
+#include "incpath.h"
+#include "io.h"
+#include "input.h"
+
+
+
+/*****************************************************************************/
+/* Data */
+/*****************************************************************************/
+
+
+
+/* Maximum count of nested includes */
+#define MAX_INC_NESTING 16
+
+/* Struct that describes an input file */
+typedef struct IFile IFile;
+struct IFile {
+ IFile* Next; /* Next file in single linked list */
+ IFile* Active; /* Next file in list of active includes */
+ unsigned Index; /* File index */
+ unsigned Line; /* Line number for this file */
+ FILE* F; /* Input file stream */
+ char Name[1]; /* Name of file (dynamically allocated) */
+};
+
+/* List of input files */
+static unsigned IFileTotal = 0; /* Total number of files */
+static IFile* IFileList = 0; /* Single linked list of all files */
+static unsigned IFileCount = 0; /* Number of active input files */
+static IFile* Input = 0; /* Single linked list of active files */
+
+
+
+/*****************************************************************************/
+/* struct IFile */
+/*****************************************************************************/
+
+
+
+static IFile* NewIFile (const char* Name, FILE* F)
+/* Create and return a new IFile */
+{
+ /* Get the length of the name */
+ unsigned Len = strlen (Name);
+
+ /* Allocate a IFile structure */
+ IFile* IF = xmalloc (sizeof (IFile) + Len);
+
+ /* Initialize the fields */
+ IF->Index = ++IFileTotal;
+ IF->Line = 0;
+ IF->F = F;
+ memcpy (IF->Name, Name, Len+1);
+
+ /* Insert the structure into both lists */
+ IF->Next = IFileList;
+ IFileList = IF;
+ IF->Active = Input;
+ Input = IF;
+ ++IFileCount;
+
+ /* Return the new struct */
+ return IF;
+}
+
+
+
+/*****************************************************************************/
+/* Code */
+/*****************************************************************************/
+
+
+
+void OpenMainFile (const char* Name)
+/* Open the main file. Will call Fatal() in case of failures. */
+{
+ /* Open the file for reading */
+ FILE* F = fopen (Name, "r");
+ if (F == 0) {
+ /* Cannot open */
+ Fatal (FAT_CANNOT_OPEN_INPUT, strerror (errno));
+ }
+
+ /* Setup a new IFile structure */
+ NewIFile (Name, F);
+}
+
+
+
+void OpenIncludeFile (const char* Name, unsigned DirSpec)
+/* Open an include file and insert it into the tables. */
+{
+ char* N;
+ FILE* F;
+
+ /* Check for the maximum include nesting */
+ if (IFileCount > MAX_INC_NESTING) {
+ PPError (ERR_INCLUDE_NESTING);
+ return;
+ }
+
+ /* Search for the file */
+ N = FindInclude (Name, DirSpec);
+ if (N == 0) {
+ PPError (ERR_INCLUDE_NOT_FOUND, Name);
+ return;
+ }
+
+ /* Open the file */
+ F = fopen (N, "r");
+ if (F == 0) {
+ /* Error opening the file */
+ PPError (ERR_INCLUDE_OPEN_FAILURE, N);
+ xfree (N);
+ return;
+ }
+
+ /* Allocate a new IFile structure */
+ NewIFile (N, F);
+
+ /* We don't need the full name any longer */
+ xfree (N);
+}
+
+
+
+static void CloseIncludeFile (void)
+/* Close an include file and switch to the higher level file. Set Input to
+ * NULL if this was the main file.
+ */
+{
+ /* Must have an input file when called */
+ PRECONDITION (Input != 0);
+
+ /* Close the current input file (we're just reading so no error check) */
+ fclose (Input->F);
+
+ /* Make this file inactive and the last one active again */
+ Input = Input->Active;
+}
+
+
+
+int NextLine (void)
+/* Get a line from the current input. Returns 0 on end of file. */
+{
+ unsigned Len;
+ unsigned Part;
+ unsigned Start;
+ int Done;
+
+ /* Setup the line */
+ kill ();
+
+ /* If there is no file open, bail out */
+ if (Input == 0) {
+ return 0;
+ }
+
+ /* Read lines until we get one with real contents */
+ Len = 0;
+ Done = 0;
+ while (!Done && Len < LINESIZE) {
+
+ while (fgets (line + Len, LINESIZE - Len, Input->F) == 0) {
+
+ /* eof */
+ kill ();
+
+ /* Leave the current file */
+ CloseIncludeFile ();
+
+ /* If this was the last file, bail out */
+ if (Input == 0) {
+ return 0;
+ }
+ }
+
+ /* We got a new line */
+ ++Input->Line;
+
+ /* Remove the trailing newline if we have one */
+ Part = strlen (line + Len);
+ Start = Len;
+ Len += Part;
+ while (Len > 0 && line [Len-1] == '\n') {
+ --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.
+ */
+ if (Len > 0 && line[Len-1] == '\\') {
+ line[Len-1] = '\n'; /* Replace by newline */
+ } else {
+ Done = 1;
+ }
+ }
+
+ /* Got a line */
+ return 1;
+}
+
+
+
+const char* GetCurrentFile (void)
+/* Return the name of the current input file */
+{
+ if (Input == 0) {
+ return "(outside file scope)";
+ } else {
+ return Input->Name;
+ }
+}
+
+
+
+unsigned GetCurrentLine (void)
+/* Return the line number in the current input file */
+{
+ return Input? Input->Line : 0;
+}
+
+
+
--- /dev/null
+/*****************************************************************************/
+/* */
+/* input.h */
+/* */
+/* Input file handling */
+/* */
+/* */
+/* */
+/* (C) 2000 Ullrich von Bassewitz */
+/* Wacholderweg 14 */
+/* D-70597 Stuttgart */
+/* EMail: uz@musoftware.de */
+/* */
+/* */
+/* This software is provided 'as-is', without any expressed or implied */
+/* warranty. In no event will the authors be held liable for any damages */
+/* arising from the use of this software. */
+/* */
+/* Permission is granted to anyone to use this software for any purpose, */
+/* including commercial applications, and to alter it and redistribute it */
+/* freely, subject to the following restrictions: */
+/* */
+/* 1. The origin of this software must not be misrepresented; you must not */
+/* claim that you wrote the original software. If you use this software */
+/* in a product, an acknowledgment in the product documentation would be */
+/* appreciated but is not required. */
+/* 2. Altered source versions must be plainly marked as such, and must not */
+/* be misrepresented as being the original software. */
+/* 3. This notice may not be removed or altered from any source */
+/* distribution. */
+/* */
+/*****************************************************************************/
+
+
+
+#ifndef INPUT_H
+#define INPUT_H
+
+
+
+/*****************************************************************************/
+/* Code */
+/*****************************************************************************/
+
+
+
+void OpenMainFile (const char* Name);
+/* Open the main file. Will call Fatal() in case of failures. */
+
+void OpenIncludeFile (const char* Name, unsigned DirSpec);
+/* Open an include file and insert it into the tables. */
+
+int NextLine (void);
+/* Get a line from the current input. Returns 0 on end of file. */
+
+const char* GetCurrentFile (void);
+/* Return the name of the current input file */
+
+unsigned GetCurrentLine (void);
+/* Return the line number in the current input file */
+
+
+
+/* End of input.h */
+#endif
+
+
+
/* C I/O functions */
-#include <stdio.h>
-#include <stdarg.h>
-#include <string.h>
-#include <errno.h>
-
-#include "asmcode.h"
#include "global.h"
-#include "error.h"
-#include "mem.h"
-#include "codegen.h"
-#include "optimize.h"
#include "io.h"
char* line = linebuf;
char* lptr = 0;
-/* Input file table and number of open input files */
-struct filent filetab[MAXFILES];
-int ifile = 0;
-
-/* Current input file stream data */
-FILE* inp = 0;
-char* fin = 0;
-unsigned ln = 0;
-
/*****************************************************************************/
-static void CloseInclude (void)
-/* Close an include file and switch to the higher level file. Set inp to NULL
- * if this was the main file.
- */
-{
- struct filent* pftab;
-
- /* Close the file */
- fclose(inp);
-
- /* Leave the include file */
- if (ifile > 0) {
- xfree (fin);
- inp = (pftab = &filetab[--ifile])->f_iocb;
- ln = pftab->f_ln;
- fin = pftab->f_name;
- } else {
- inp = 0;
- }
-}
-
-
-
-int NextLine (void)
-/* Get a line from the current input. Returns -1 on end of file. */
-{
- unsigned Len;
- unsigned Part;
- unsigned Start;
- int Done;
-
- /* Setup the line */
- kill ();
-
- /* If there is no file open, bail out */
- if (inp == 0) {
- return 0;
- }
-
- /* Read lines until we get one with real contents */
- Len = 0;
- Done = 0;
- while (!Done && Len < LINESIZE) {
-
- while (fgets (line + Len, LINESIZE - Len, inp) == 0) {
-
- /* eof */
- kill ();
-
- /* Leave the current file */
- CloseInclude ();
-
- /* If this was the last file, bail out */
- if (inp == 0) {
- return 0;
- }
- }
-
- /* We got a new line */
- ++ln;
-
- /* Remove the trailing newline if we have one */
- Part = strlen (line + Len);
- Start = Len;
- Len += Part;
- while (Len > 0 && line [Len-1] == '\n') {
- --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.
- */
- if (Len > 0 && line[Len-1] == '\\') {
- line[Len-1] = '\n'; /* Replace by newline */
- } else {
- Done = 1;
- }
- }
-
- /* Got a line */
- return 1;
-}
-
-
-
int f_ln;
};
-/* Input file table and number of open input files */
-extern struct filent filetab[MAXFILES];
-extern int ifile;
-
-/* Current input file stream data */
-extern FILE* inp; /* Input file stream */
-extern char* fin; /* Input file name */
-extern unsigned ln; /* Line number */
-
/*****************************************************************************/
* pointer (no end of line check is performed).
*/
-int NextLine (void);
-/* Get a line from the current input. Returns -1 on end of file. */
-
/* End of io.h */
+#include "../common/xmalloc.h"
+
#include "anonname.h"
#include "asmlabel.h"
#include "codegen.h"
#include "expr.h"
#include "function.h"
#include "global.h"
-#include "mem.h"
#include "symtab.h"
#include "locals.h"
+#include "../common/xmalloc.h"
+
#include "error.h"
-#include "mem.h"
#include "loop.h"
#include <string.h>
#include "../common/hashstr.h"
+#include "../common/xmalloc.h"
#include "error.h"
-#include "mem.h"
#include "macrotab.h"
#include "../common/cmdline.h"
#include "../common/fname.h"
#include "../common/version.h"
+#include "../common/xmalloc.h"
#include "asmcode.h"
#include "compile.h"
#include "error.h"
#include "global.h"
#include "incpath.h"
-#include "io.h"
+#include "input.h"
#include "macrotab.h"
-#include "mem.h"
#include "optimize.h"
#include "scanner.h"
/* Initialize the output file name */
const char* OutputFile = 0;
-
- fin = NULL;
+ const char* InputFile = 0;
/* Initialize the cmdline module */
InitCmdLine (argc, argv, "cc65");
case 'h':
case '?':
- OptHelp (Arg, 0);
+ OptHelp (Arg, 0);
break;
case 'g':
case 'j':
OptSignedChars (Arg, 0);
- break;
+ break;
case 'o':
OutputFile = GetArg (&I, 2);
case 'f':
sscanf (P, "%lx", (long*) &OptDisable);
break;
- case 'i':
- FavourSize = 0;
- break;
- case 'r':
- EnableRegVars = 1;
- break;
- case 's':
- InlineStdFuncs = 1;
- break;
- }
- }
- break;
-
- case 'T':
- OptAddSource (Arg, 0);
- break;
-
- case 'V':
- OptVersion (Arg, 0);
- break;
-
- case 'W':
- NoWarn = 1;
- break;
-
- default:
+ case 'i':
+ FavourSize = 0;
+ break;
+ case 'r':
+ EnableRegVars = 1;
+ break;
+ case 's':
+ InlineStdFuncs = 1;
+ break;
+ }
+ }
+ break;
+
+ case 'T':
+ OptAddSource (Arg, 0);
+ break;
+
+ case 'V':
+ OptVersion (Arg, 0);
+ break;
+
+ case 'W':
+ NoWarn = 1;
+ break;
+
+ default:
UnknownOption (Arg);
- break;
+ break;
}
} else {
- if (fin) {
- fprintf (stderr, "additional file specs ignored\n");
+ if (InputFile) {
+ fprintf (stderr, "additional file specs ignored\n");
} else {
- fin = xstrdup (Arg);
- inp = fopen (fin, "r");
- if (inp == 0) {
- Fatal (FAT_CANNOT_OPEN_INPUT, strerror (errno));
- }
+ InputFile = Arg;
}
}
}
/* Did we have a file spec on the command line? */
- if (!fin) {
+ if (InputFile == 0) {
fprintf (stderr, "%s: No input files\n", argv [0]);
exit (EXIT_FAILURE);
}
+ /* Open the input file */
+ OpenMainFile (InputFile);
+
/* Create the output file name if it was not explicitly given */
if (OutputFile == 0) {
- OutputFile = MakeFilename (fin, ".s");
+ OutputFile = MakeFilename (InputFile, ".s");
}
/* Go! */
goto.o \
ident.o \
incpath.o \
+ input.o \
io.o \
litpool.o \
locals.o \
loop.o \
macrotab.o \
main.o \
- mem.o \
optimize.o \
preproc.o \
pragma.o \
goto.obj \
ident.obj \
incpath.obj \
+ input.obj \
io.obj \
litpool.obj \
locals.obj \
loop.obj \
macrotab.obj \
main.obj \
- mem.obj \
optimize.obj \
pragma.obj \
preproc.obj \
FILE goto.obj
FILE ident.obj
FILE incpath.obj
+FILE input.obj
FILE io.obj
FILE litpool.obj
FILE locals.obj
FILE loop.obj
FILE macrotab.obj
FILE main.obj
-FILE mem.obj
FILE optimize.obj
FILE pragma.obj
FILE preproc.obj
+++ /dev/null
-/*****************************************************************************/
-/* */
-/* MEMCHECK.CC */
-/* */
-/* (C) 1995 Ullrich von Bassewitz */
-/* Zwehrenbuehlstrasse 33 */
-/* D-72070 Tuebingen */
-/* EMail: uz@ibb.schwaben.com */
-/* */
-/*****************************************************************************/
-
-
-
-// Poor man's memory checker. Overloads the global operators new and delete
-// and does some additional checks if the variable MemCheck is set to true:
-//
-// * Check if an allocated block is already allocated (heap corrupt)
-// * Check if a block that should be freed is allocated
-// * Check if there have been writes outside the blocks bounds (by
-// adding a signature to the end)
-// * Check if new does not provide a NULL pointer.
-
-
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
-#if defined(__WATCOMC__) || defined(_MSC_VER)
-# include <malloc.h>
-#endif
-
-#include "check.h"
-
-
-
-/*****************************************************************************/
-/* Data */
-/*****************************************************************************/
-
-
-
-typedef unsigned long u32;
-
-
-
-// Signature of a memory block
-static u32 MemSig = 0x12785634;
-
-// Switch memory checking on or off
-int MemCheck = 0;
-
-// Switch memory filling on or off
-int MemFill = 0;
-
-// Validation on each call?
-int MemValidate = 0;
-
-// Don't really free blocks
-int MemDontFree = 0;
-
-// Logfile for allocations/deallocations
-static const char* MemLogFile = 0;
-static FILE* LogFile = 0;
-
-// Statistics
-u32 MemNewCount = 0;
-u32 MemDelCount = 0;
-u32 MemDelNULLCount = 0;
-u32 MemNewCheckCount = 0;
-u32 MemDelCheckCount = 0;
-u32 MemLargestBlock = 0;
-u32 MemUsage = 0;
-u32 MemMaxUsage = 0;
-
-// This is the fill value for memory blocks if MemFill is true. On intel
-// architectures, this is the code for "INT 3", an instruction that is
-// often used by debuggers as a breakpoint.
-unsigned char FillVal = 0xCC;
-
-
-
-/*****************************************************************************/
-/* struct BlockInfo */
-/*****************************************************************************/
-
-
-
-typedef struct {
- unsigned char* Ptr;
- u32 Size;
-} BlockInfo;
-
-//
-const int FirstChunk = 2000;
-const int Delta = 1000;
-
-// Variables needed
-static int IsInitialized = 0;
-static int BlockCount = 0;
-static int BlockLimit = 0;
-static BlockInfo* Blocks = 0;
-
-
-
-/*****************************************************************************/
-/* class BlockInfoColl */
-/*****************************************************************************/
-
-
-
-static void MemSetCount (int NewCount)
-// Make shure, there is space for NewSize blocks in Blocks
-{
- if (NewCount > BlockLimit) {
- // OOPS, need realloc
- if (BlockLimit == 0 && NewCount <= FirstChunk) {
- BlockLimit = FirstChunk;
- } else {
- BlockLimit = ((NewCount / Delta) + 1) * Delta;
- }
- Blocks = (BlockInfo*) realloc (Blocks, BlockLimit * sizeof (BlockInfo));
- }
- BlockCount = NewCount;
-}
-
-
-
-static int MemSearch (const unsigned char* Ptr, int* Index)
-// Search for the block. Return 1 if the block is found (Index holds the
-// block index in this case). Return 0 if the block is not found and return
-// in Index the index where the block should be inserted.
-{
- // do a binary search
- int First = 0;
- int Last = BlockCount - 1;
- int Current;
- int S = 0;
-
- while (First <= Last) {
-
- // Set current to mid of range
- Current = (Last + First) / 2;
-
- // Do a compare
- if (Blocks [Current].Ptr < Ptr) {
- First = Current + 1;
- } else {
- Last = Current - 1;
- if (Blocks [Current].Ptr == Ptr) {
- // Found.
- S = 1; // function result
- // Set condition to terminate loop
- First = Current;
- }
- }
-
- }
-
- *Index = First;
- return S;
-}
-
-
-
-static void MemDelBlock (int Index)
-// Delete the block with the given index
-{
- BlockCount--;
- memmove (Blocks+Index, Blocks+Index+1, (BlockCount-Index) * sizeof (BlockInfo));
-}
-
-
-
-static void MemInsBlock (int Index, unsigned char* Ptr, u32 Size)
-{
- // Set the new size
- MemSetCount (BlockCount + 1);
-
- // We can insert the element. If the item is not inserted at the end
- // of the collection, we must create a "hole"
- if (Index != BlockCount - 1) {
- memmove (Blocks + Index + 1,
- Blocks + Index,
- (BlockCount - 1 - Index) * sizeof (BlockInfo));
- }
-
- // store the new data
- Blocks [Index].Ptr = Ptr;
- Blocks [Index].Size = Size;
-}
-
-
-
-u32 MemBlocksInUse ()
-{
- return (u32) BlockCount;
-}
-
-
-
-static void PrintContents (const void* B, unsigned Size, FILE* F)
-// Print the contents of the block
-{
- unsigned I;
- static const unsigned MaxPrint = 14;
-
- const unsigned char* P = (const unsigned char*) B;
- if (Size > MaxPrint) {
- Size = MaxPrint;
- }
-
- // Two characters space
- fprintf (F, " ");
-
- // Print the first few bytes in hex
- for (I = 0; I < Size; I++) {
- fprintf (F, "%02X ", P [I]);
- }
- fprintf (F, "%*s ", (MaxPrint-Size)*3, "");
-
- // Print the bytes again in ASCII
- for (I = 0; I < Size; I++) {
- unsigned char C = P [I];
- if (C < ' ' || C > 0x7E) {
- C = '.';
- }
- putc (C, F);
- }
-}
-
-
-
-void MemLogBlocksInUse (const char* Name)
-{
- BlockInfo* Block;
- int I;
-
- FILE* F = fopen (Name, "w+t");
- if (F == 0) {
- // This is a debug function, so ignore the error
- return;
- }
-
- // Get the block count and log some statistics
- fprintf (F, "Blocks currently in use: %8lu\n\n"
- "Calls to operator new: %8lu\n"
- "Calls to operator delete: %8lu\n"
- "Checked calls to new: %8lu\n"
- "Checked calls to delete: %8lu\n"
- "Calls to delete with a NULL arg: %8lu\n\n"
- "Largest block allocated: %8lu\n"
- "Maximum memory usage: %8lu\n\n",
- (unsigned long) BlockCount,
- (unsigned long) MemNewCount,
- (unsigned long) MemDelCount,
- (unsigned long) MemNewCheckCount,
- (unsigned long) MemDelCheckCount,
- (unsigned long) MemDelNULLCount,
- (unsigned long) MemLargestBlock,
- (unsigned long) MemMaxUsage);
-
- // Print a header
- fprintf (F, "Num Address Size Contents\n");
- fprintf (F, "----------------------------------------"
- "---------------------------------------\n");
-
- // Log the blocks
- Block = Blocks;
- for (I = 0; I < BlockCount; I++, Block++) {
-
- // Print a line describing the block (convert pointers to hex values)
- fprintf (F, "%-5u %08lX %5lu",
- I, (unsigned long) Block->Ptr, (unsigned long) Block->Size);
-
- // Print the first few bytes of the block
- PrintContents (Block->Ptr, Block->Size, F);
-
- // Check the block signature
- if (memcmp (Block->Ptr + Block->Size, &MemSig, sizeof (MemSig)) != 0) {
- // Signature overwritten
- fprintf (F, " *** Signature overwritten ***\n");
- } else {
- fprintf (F, "\n");
- }
-
- }
-
- // Close the file
- fclose (F);
-}
-
-
-
-static long MemValidateBlocks ()
-// Validate all memory blocks. Return the index of a block where the
-// validation failed, otherwise return -1.
-{
- // Validate the blocks
- long I;
- BlockInfo* Block = Blocks;
- for (I = 0; I < BlockCount; I++, Block++) {
-
- // Check the block signature
- if (memcmp (Block->Ptr + Block->Size, &MemSig, sizeof (MemSig)) != 0) {
- // Signature overwritten
- return I;
- }
- }
-
- // All is well...
- return -1;
-}
-
-
-
-static void MemDone ()
-// Log the memory blocks if requested. Does *not* delete the block array
-// since the startup code may release memory after calling the exit functions
-// and in this case we will work with a freed block, if we free the block
-// array here
-{
- // If the environment variable MEMLOGBLOCKS is set to something, use
- // this "something" as a filename to log a list of still allocated blocks
- const char* Name = getenv ("MEMLOGBLOCKS");
- if (Name) {
- MemLogBlocksInUse (Name);
- }
-}
-
-
-
-static void MemInit ()
-// Initialize the memory checker.
-{
- // Get the defaults for the memory checker
- const char* Fill;
- MemCheck = getenv ("MEMCHECK") != 0;
- MemValidate = getenv ("MEMVALIDATE") != 0;
- MemDontFree = getenv ("MEMDONTFREE") != 0;
- MemLogFile = getenv ("MEMLOGFILE");
- Fill = getenv ("MEMFILL");
- if (Fill) {
- MemFill = 1;
- if (isdigit (*Fill)) {
- FillVal = atoi (Fill);
- }
- }
-
- // Open the logfile if set
- if (MemLogFile) {
- LogFile = fopen (MemLogFile, "w+t");
- }
-
- // Register the exit function
- atexit (MemDone);
-
- // Initialized now (maybe set already)
- IsInitialized = 1;
-}
-
-
-
-/*****************************************************************************/
-/* Allocate/free blocks */
-/*****************************************************************************/
-
-
-
-static void* MemAlloc (size_t Size)
-{
- unsigned char* Ptr;
-
- // Last allocated block is remembered here
- static void* LastBlock = 0;
-
- // Initialize the memory checker on the first call
- if (IsInitialized == 0) {
- MemInit ();
- }
-
- // Count the calls to new
- MemNewCount++;
-
- // Update largest block info
- if (Size > MemLargestBlock) {
- MemLargestBlock = Size;
- }
- if (MemCheck) {
-
- int Index;
-
- // Count the checked calls
- MemNewCheckCount++;
-
- // If we need to validate all blocks, do that
- if (MemValidate) {
- long I = MemValidateBlocks ();
- if (I != -1) {
- // We have a problem. Be shure to switch of MemValidate before
- // calling FAIL, otherwise we will get an endless loop...
- MemValidate = 0;
- FAIL ("MemCheck: Block signature overwritten!");
- }
- }
-
- // Update memory usage
- MemUsage += Size;
- if (MemUsage > MemMaxUsage) {
- MemMaxUsage = MemUsage;
- }
-
- // Get a memory block
- Ptr = (unsigned char*) malloc (Size + sizeof (MemSig));
-
- // Make a signature at the end of the block
- memcpy (Ptr + Size, &MemSig, sizeof (MemSig));
-
- // Search for the block
- if (MemSearch (Ptr, &Index) != 0) {
- // An item with this key exists. This means that the heap is
- // corrupted
- FAIL ("MemCheck: Duplicate block!");
- } else {
- // The returned pointer is not in the collection of already
- // allocated blocks, but it may point inside of an already
- // allocated block. Check this.
- // Note: Index is the index of the item _before the given
- // pointer, so simply check the range of the entry with index
- // Index.
- if (Index > 0) {
- // There is a block that's memory address is less than the
- // one returned by malloc
- const BlockInfo* BB = Blocks + Index - 1;
- if (Ptr < BB->Ptr + BB->Size) {
- // Pointer points inside the block below - heap corrupted
- FAIL ("MemCheck: Heap corrupt!");
- }
- }
-
- // Heap ok, insert the new block
- MemInsBlock (Index, Ptr, Size);
- }
-
- } else {
-
- // No memory checking. Allocate a memory block, but beware: New is
- // defined so that "new char [0]" points to a distinct object every
- // time it is called, so one cannot return NULL for a size of 0!
- Ptr = (unsigned char*) malloc (Size ? Size : 1);
-
- }
-
- // Remember the last block
- LastBlock = Ptr;
-
- // Check if we got memory, fail otherwise
- if (Ptr == 0) {
- FAIL ("MemCheck: Out of memory");
- }
-
- // Fill the memory block if requested
- if (MemFill) {
- memset (Ptr, FillVal, Size);
- }
-
- // Log the allocation if requested
- if (LogFile) {
- // Print a line describing the block (convert pointers to hex values)
- fprintf (LogFile, "A %08lX %5lu",
- (unsigned long) Ptr, (unsigned long) Size);
-
- // Print the first few bytes of the block
- PrintContents (Ptr, Size, LogFile);
- fprintf (LogFile, "\n");
- }
-
- // Return a pointer to the memory block
- return Ptr;
-}
-
-
-
-static void MemFree (void* P)
-{
- // We cannot call delete if the memory system is not initialized
- if (IsInitialized == 0) {
- FAIL ("MemCheck: Trying to delete a block before the first call to new!");
- }
-
- // Count the calls to delete
- MemDelCount++;
-
- // Deleting NULL pointers is always ok, nothing has to be done
- if (P == 0) {
- MemDelNULLCount++;
- return;
- }
-
- if (MemCheck) {
-
- int Index;
- unsigned char* Ptr;
-
- // Count the calls
- MemDelCheckCount++;
-
- // If we need to validate all blocks, do that
- if (MemValidate) {
- long I = MemValidateBlocks ();
- if (I != -1) {
- // We have a problem. Be shure to switch of MemValidate before
- // calling FAIL, otherwise we will get an endless loop...
- MemValidate = 0;
- FAIL ("MemCheck: Block signature overwritten!");
- }
- }
-
- // Cast the pointer
- Ptr = (unsigned char*) P;
-
- // Search for the block
- if (MemSearch (Ptr, &Index) != 0) {
-
- // The block exists.
- BlockInfo* BI = Blocks + Index;
-
- // Log the deallocation if requested
- if (LogFile) {
- // Print a line describing the block (convert pointers to hex values)
- fprintf (LogFile, "D %08lX %5lu",
- (unsigned long) BI->Ptr, (unsigned long) BI->Size);
-
- // Print the first few bytes of the block
- PrintContents (BI->Ptr, BI->Size, LogFile);
- fprintf (LogFile, "\n");
- }
-
- // Check the signature
- if (memcmp (Ptr + BI->Size, &MemSig, sizeof (MemSig)) != 0) {
- // Signature overwritten
- FAIL ("MemCheck: Block signature overwritten");
- }
-
- // Fill the memory block if requested
- if (MemFill) {
- memset (Ptr, FillVal, BI->Size);
- }
-
- // Should the block really be freed?
- if (MemDontFree == 0) {
-
- // Update memory usage
- MemUsage -= BI->Size;
-
- // Delete the entry
- MemDelBlock (Index);
-
- // Delete the memory block
- free (P);
-
- }
-
- } else {
- // Trying to free a block that is not allocated
- FAIL ("MemCheck: Trying to free a block that is not allocated");
- }
- } else {
-
- // Free the block without checks
- free (P);
-
- }
-}
-
-
-
-/*****************************************************************************/
-/* Code */
-/*****************************************************************************/
-
-
-
-void* xmalloc (size_t Size)
-{
- return MemAlloc (Size);
-}
-
-
-
-void xfree (const void* P)
-{
- MemFree ((void*)P);
-}
-
-
-
-char* xstrdup (const char* S)
-{
- unsigned Len = strlen (S) + 1;
- return memcpy (xmalloc (Len), S, Len);
-}
-
-
-
+++ /dev/null
-/*****************************************************************************/
-/* */
-/* mem.h */
-/* */
-/* Safe memory allocation for the cc65 C compiler */
-/* */
-/* */
-/* */
-/* (C) 1998 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
-/* EMail: uz@musoftware.de */
-/* */
-/* */
-/* This software is provided 'as-is', without any expressed or implied */
-/* warranty. In no event will the authors be held liable for any damages */
-/* arising from the use of this software. */
-/* */
-/* Permission is granted to anyone to use this software for any purpose, */
-/* including commercial applications, and to alter it and redistribute it */
-/* freely, subject to the following restrictions: */
-/* */
-/* 1. The origin of this software must not be misrepresented; you must not */
-/* claim that you wrote the original software. If you use this software */
-/* in a product, an acknowledgment in the product documentation would be */
-/* appreciated but is not required. */
-/* 2. Altered source versions must be plainly marked as such, and must not */
-/* be misrepresented as being the original software. */
-/* 3. This notice may not be removed or altered from any source */
-/* distribution. */
-/* */
-/*****************************************************************************/
-
-
-
-#ifndef MEM_H
-#define MEM_H
-
-
-
-#include <stddef.h>
-
-
-
-/*****************************************************************************/
-/* data */
-/*****************************************************************************/
-
-
-
-extern size_t memmax;
-
-
-
-/*****************************************************************************/
-/* code */
-/*****************************************************************************/
-
-
-
-void* xmalloc (size_t size);
-/* Allocate memory, check for out of memory condition. Do some debugging */
-
-void xfree (const void* block);
-/* Free the block, do some debugging */
-
-char* xstrdup (const char* s);
-/* Duplicate a string on the heap. The function checks for out of memory */
-
-
-
-/* End of mem.h */
-#endif
-
-
-
#include <string.h>
#include <ctype.h>
+#include "../common/xmalloc.h"
+
#include "asmlabel.h"
#include "asmline.h"
#include "check.h"
#include "error.h"
#include "global.h"
#include "io.h"
-#include "mem.h"
#include "optimize.h"
* If the end of the lookahead is reached, all registers that are uncertain
* are marked as used.
* The result of the search is returned.
- */
+ */
{
unsigned R;
}
}
} else if (LineMatch (L, "\tadc\t")) {
+ if (CPU == CPU_65C02 && Y == 0 && L->Line[5] == '(' && IsYAddrMode(L)) {
+ L->Line[strlen(L->Line)-2] = '\0';
+ }
A = -1;
} else if (LineMatch (L, "\tand\t")) {
A = -1;
if (A != -1) {
A = (A << 1) & 0xFF;
}
- } else if (CPU == CPU_65C02 && LineFullMatch (L, "\tdea")) {
+ } else if (CPU == CPU_65C02 && Y == 0 && L->Line[5] == '(' && IsYAddrMode(L)) {
+ L->Line[strlen(L->Line)-2] = '\0';
+ } else if (CPU == CPU_65C02 && (LineFullMatch (L, "\tdea") ||
+ LineFullMatch (L, "\tdec\ta"))) {
DEC (A, 1);
} else if (LineFullMatch (L, "\tdex")) {
DEC (X, 1);
DEC (Y, 1);
} else if (LineMatch (L, "\teor")) {
A = -1;
- } else if (CPU == CPU_65C02 && LineFullMatch (L, "\tina")) {
+ } else if (CPU == CPU_65C02 && (LineFullMatch (L, "\tina") ||
+ LineFullMatch (L, "\tinc\ta"))) {
INC (A, 1);
} else if (LineFullMatch (L, "\tinx")) {
INC (X, 1);
} else if (LineFullMatch (L, "\trti")) {
A = X = Y = -1;
} else if (LineMatch (L, "\tsbc\t")) {
+ if (CPU == CPU_65C02 && Y == 0 && L->Line[5] == '(' && IsYAddrMode(L)) {
+ L->Line[strlen(L->Line)-2] = '\0';
+ }
A = -1;
} else if (CPU == CPU_65C02 && LineMatch (L, "\tst")) {
/* Try to replace by stz if possible */
/* Not indirect and not Y allowed */
if (L->Line[5] != '(' && !IsYAddrMode (L)) {
L->Line[3] = 'z';
- }
+ }
} else if (X == 0 && LineMatch (L, "\tstx\t")) {
/* absolute,y not allowed */
if (!IsYAddrMode (L)) {
#include <errno.h>
#include <ctype.h>
+#include "../common/xmalloc.h"
+
#include "codegen.h"
#include "error.h"
#include "expr.h"
#include "global.h"
#include "ident.h"
#include "incpath.h"
+#include "input.h"
#include "io.h"
#include "macrotab.h"
-#include "mem.h"
#include "scanner.h"
#include "util.h"
#include "preproc.h"
/*****************************************************************************/
-/* data */
+/* data */
/*****************************************************************************/
static void comment (void)
/* Remove comment from line. */
{
- unsigned StartingLine = ln;
+ unsigned StartingLine = GetCurrentLine();
gch ();
gch ();
++lptr;
}
}
- }
+ }
} else {
if (MaybeMacro(c)) {
done = 0;
skipblank ();
S = line;
while ((*S++ = *lptr++) != '\0') ;
- strcat (line, ";;");
+ strcpy (S-1, ";;");
lptr = line;
/* Switch into special preprocessing mode */
static void doinclude (void)
/* Open an include file. */
{
- char name [80];
- unsigned count;
- char term;
- char c;
- char *p;
+ unsigned Length;
+ char* End;
+ char* Name;
+ char RTerm;
+ unsigned DirSpec;
- if (ifile >= MAXFILES) {
- PPError (ERR_INCLUDE_NESTING);
- goto done;
- }
+
+ /* Skip blanks */
mptr = mline;
skipblank ();
- if (!strchr ("\"<", (term = cgch ()))) {
- PPError (ERR_INCLUDE_LTERM_EXPECTED);
- goto done;
- }
- if (term == '<') {
- term = '>'; /* get right terminator */
- }
- /* Get the name of the include file */
- count = 0;
- while ((c = *lptr) && (c != term) && count < sizeof (name)-1) {
- name [count++] = c;
- ++lptr;
- }
- if (c != term) {
- PPError (ERR_INCLUDE_RTERM_EXPECTED);
- goto done;
- }
- name [count] = '\0';
+ /* Get the next char and check for a valid file name terminator. Setup
+ * the include directory spec (SYS/USR) by looking at the terminator.
+ */
+ switch (cgch()) {
- /* Now search for the name */
- p = FindInclude (name, (term == '\"')? INC_USER : INC_SYS);
- if (p == 0) {
- PPError (ERR_INCLUDE_NOT_FOUND, name);
- goto done;
- }
+ case '\"':
+ RTerm = '\"';
+ DirSpec = INC_USER;
+ break;
- /* Save the existing file info */
- filetab[ifile].f_ln = ln;
- filetab[ifile].f_name = fin;
- filetab[ifile].f_iocb = inp;
- ++ifile;
+ case '<':
+ RTerm = '>';
+ DirSpec = INC_SYS;
+ break;
- /* Assign the name and output it */
- fin = p;
- if (Verbose) {
- printf ("including '%s'\n", fin);
+ default:
+ PPError (ERR_INCLUDE_LTERM_EXPECTED);
+ goto Done;
}
- /* Try to open the include file */
- if ((inp = fopen (fin, "r")) == 0) {
- /* oops! restore old file */
- PPError (ERR_INCLUDE_OPEN_FAILURE, fin);
- xfree (fin);
- --ifile;
- inp = filetab[ifile].f_iocb;
- fin = filetab[ifile].f_name;
- } else {
- ln = 0;
+ /* Search for the right terminator */
+ End = strchr (lptr, RTerm);
+ if (End == 0) {
+ /* No terminator found */
+ PPError (ERR_INCLUDE_RTERM_EXPECTED);
+ goto Done;
}
-done:
+ /* Create a temp copy of the filename */
+ Length = End - lptr;
+ Name = xmalloc (Length + 1);
+ memcpy (Name, lptr, Length);
+ Name[Length] = '\0';
+
+ /* Open the include file */
+ OpenIncludeFile (Name, DirSpec);
+
+ /* Delete the temp filename copy */
+ xfree (Name);
+
+Done:
/* clear rest of line so next read will come from new file (if open) */
kill ();
}
#include "function.h"
#include "global.h"
#include "ident.h"
+#include "input.h"
#include "io.h"
#include "litpool.h"
#include "preproc.h"
CurTok = NextTok;
/* Remember the starting position of the next token */
- NextTok.Pos = ln;
+ NextTok.Pos = GetCurrentLine();
/* Skip spaces and read the next line if needed */
if (skipwhite () == 0) {
if (token [0] == '_') {
/* Special symbols */
if (strcmp (token, "__FILE__") == 0) {
- nxtval = AddLiteral (fin);
+ nxtval = AddLiteral (GetCurrentFile());
nxttok = TOK_SCONST;
return;
} else if (strcmp (token, "__LINE__") == 0) {
nxttok = TOK_ICONST;
- nxtval = ln;
+ nxtval = GetCurrentLine();
nxttype = type_int;
return;
} else if (strcmp (token, "__fixargs__") == 0) {
#include <stdio.h>
#include <string.h>
+#include "../common/xmalloc.h"
+
#include "asmcode.h"
#include "asmlabel.h"
#include "codegen.h"
#include "litpool.h"
#include "locals.h"
#include "loop.h"
-#include "mem.h"
#include "pragma.h"
#include "scanner.h"
#include "symtab.h"
-#include "mem.h"
+#include "../common/xmalloc.h"
+
#include "symentry.h"
#include <string.h>
#include "../common/hashstr.h"
+#include "../common/xmalloc.h"
#include "asmcode.h"
#include "asmlabel.h"
#include "funcdesc.h"
#include "global.h"
#include "io.h"
-#include "mem.h"
#include "symentry.h"
#include "symtab.h"