mirror of
https://github.com/cc65/cc65.git
synced 2025-02-03 22:32:24 +00:00
Use the xmalloc module from the common directory.
Rewrote the include file management, keeping a list of all include files and cleaning up the code while going. git-svn-id: svn://svn.cc65.org/cc65/trunk@82 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
d10bf32c4c
commit
aa8737733f
@ -35,10 +35,10 @@
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../common/xmalloc.h"
|
||||
#include "../common/xsprintf.h"
|
||||
|
||||
#include "error.h"
|
||||
#include "mem.h"
|
||||
#include "asmline.h"
|
||||
|
||||
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "../common/version.h"
|
||||
#include "../common/xmalloc.h"
|
||||
|
||||
#include "asmcode.h"
|
||||
#include "asmlabel.h"
|
||||
@ -46,7 +47,6 @@
|
||||
#include "global.h"
|
||||
#include "io.h"
|
||||
#include "litpool.h"
|
||||
#include "mem.h"
|
||||
#include "optimize.h"
|
||||
#include "util.h"
|
||||
#include "codegen.h"
|
||||
@ -946,13 +946,22 @@ void g_leasp (int offs)
|
||||
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 */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1764,7 +1773,7 @@ void g_addeqind (unsigned flags, unsigned offs, unsigned long val)
|
||||
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;
|
||||
|
||||
@ -3723,7 +3732,7 @@ void g_zerobytes (unsigned n)
|
||||
AddCodeLine ("\t.res\t%u,$00", n);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Inlined known functions */
|
||||
|
@ -61,10 +61,7 @@
|
||||
|
||||
|
||||
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;
|
||||
@ -253,7 +250,6 @@ void Compile (void)
|
||||
|
||||
|
||||
/* Setup variables */
|
||||
filetab[0].f_iocb = inp;
|
||||
LiteralLabel = GetLabel ();
|
||||
|
||||
/* Add some standard paths to the include search path */
|
||||
|
@ -35,13 +35,14 @@
|
||||
|
||||
#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"
|
||||
|
||||
|
@ -11,6 +11,8 @@
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "../common/xmalloc.h"
|
||||
|
||||
#include "anonname.h"
|
||||
#include "codegen.h"
|
||||
#include "datatype.h"
|
||||
@ -20,7 +22,6 @@
|
||||
#include "function.h"
|
||||
#include "global.h"
|
||||
#include "litpool.h"
|
||||
#include "mem.h"
|
||||
#include "pragma.h"
|
||||
#include "scanner.h"
|
||||
#include "symtab.h"
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "global.h"
|
||||
#include "input.h"
|
||||
#include "io.h"
|
||||
#include "scanner.h"
|
||||
#include "stmt.h"
|
||||
@ -185,7 +186,8 @@ void Warning (unsigned WarnNum, ...)
|
||||
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);
|
||||
@ -207,7 +209,8 @@ void PPWarning (unsigned WarnNum, ...)
|
||||
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);
|
||||
@ -224,7 +227,8 @@ void Error (unsigned ErrNum, ...)
|
||||
{
|
||||
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);
|
||||
@ -247,7 +251,8 @@ void PPError (unsigned ErrNum, ...)
|
||||
{
|
||||
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);
|
||||
@ -267,7 +272,8 @@ void Fatal (unsigned FatNum, ...)
|
||||
{
|
||||
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);
|
||||
@ -287,7 +293,8 @@ void Internal (char* Format, ...)
|
||||
{
|
||||
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);
|
||||
@ -310,3 +317,4 @@ void ErrorReport (void)
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -10,6 +10,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../common/xmalloc.h"
|
||||
|
||||
#include "asmcode.h"
|
||||
#include "asmlabel.h"
|
||||
#include "check.h"
|
||||
@ -23,7 +25,6 @@
|
||||
#include "io.h"
|
||||
#include "litpool.h"
|
||||
#include "macrotab.h"
|
||||
#include "mem.h"
|
||||
#include "preproc.h"
|
||||
#include "scanner.h"
|
||||
#include "stdfunc.h"
|
||||
|
@ -33,7 +33,8 @@
|
||||
|
||||
|
||||
|
||||
#include "mem.h"
|
||||
#include "../common/xmalloc.h"
|
||||
|
||||
#include "funcdesc.h"
|
||||
|
||||
|
||||
|
@ -33,6 +33,8 @@
|
||||
|
||||
|
||||
|
||||
#include "../common/xmalloc.h"
|
||||
|
||||
#include "asmcode.h"
|
||||
#include "asmlabel.h"
|
||||
#include "codegen.h"
|
||||
@ -40,7 +42,6 @@
|
||||
#include "funcdesc.h"
|
||||
#include "litpool.h"
|
||||
#include "locals.h"
|
||||
#include "mem.h"
|
||||
#include "scanner.h"
|
||||
#include "stmt.h"
|
||||
#include "symtab.h"
|
||||
|
@ -44,7 +44,8 @@
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "mem.h"
|
||||
#include "../common/xmalloc.h"
|
||||
|
||||
#include "incpath.h"
|
||||
|
||||
|
||||
|
279
src/cc65/input.c
Normal file
279
src/cc65/input.c
Normal file
@ -0,0 +1,279 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,15 +1,15 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* mem.h */
|
||||
/* input.h */
|
||||
/* */
|
||||
/* Safe memory allocation for the cc65 C compiler */
|
||||
/* Input file handling */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998 Ullrich von Bassewitz */
|
||||
/* Wacholderweg 14 */
|
||||
/* D-70597 Stuttgart */
|
||||
/* EMail: uz@musoftware.de */
|
||||
/* (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 */
|
||||
@ -33,43 +33,35 @@
|
||||
|
||||
|
||||
|
||||
#ifndef MEM_H
|
||||
#define MEM_H
|
||||
|
||||
|
||||
|
||||
#include <stddef.h>
|
||||
#ifndef INPUT_H
|
||||
#define INPUT_H
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* data */
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
extern size_t memmax;
|
||||
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 */
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* 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 */
|
||||
/* End of input.h */
|
||||
#endif
|
||||
|
||||
|
112
src/cc65/io.c
112
src/cc65/io.c
@ -1,17 +1,7 @@
|
||||
|
||||
/* 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"
|
||||
|
||||
|
||||
@ -27,15 +17,6 @@ char linebuf [LINESIZE];
|
||||
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;
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -89,96 +70,3 @@ void kill (void)
|
||||
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -40,15 +40,6 @@ struct filent {
|
||||
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 */
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -73,9 +64,6 @@ int gch (void);
|
||||
* 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 */
|
||||
|
@ -33,6 +33,8 @@
|
||||
|
||||
|
||||
|
||||
#include "../common/xmalloc.h"
|
||||
|
||||
#include "anonname.h"
|
||||
#include "asmlabel.h"
|
||||
#include "codegen.h"
|
||||
@ -40,7 +42,6 @@
|
||||
#include "expr.h"
|
||||
#include "function.h"
|
||||
#include "global.h"
|
||||
#include "mem.h"
|
||||
#include "symtab.h"
|
||||
#include "locals.h"
|
||||
|
||||
|
@ -6,8 +6,9 @@
|
||||
|
||||
|
||||
|
||||
#include "../common/xmalloc.h"
|
||||
|
||||
#include "error.h"
|
||||
#include "mem.h"
|
||||
#include "loop.h"
|
||||
|
||||
|
||||
|
@ -37,9 +37,9 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "../common/hashstr.h"
|
||||
#include "../common/xmalloc.h"
|
||||
|
||||
#include "error.h"
|
||||
#include "mem.h"
|
||||
#include "macrotab.h"
|
||||
|
||||
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include "../common/cmdline.h"
|
||||
#include "../common/fname.h"
|
||||
#include "../common/version.h"
|
||||
#include "../common/xmalloc.h"
|
||||
|
||||
#include "asmcode.h"
|
||||
#include "compile.h"
|
||||
@ -49,9 +50,8 @@
|
||||
#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"
|
||||
|
||||
@ -379,8 +379,7 @@ int main (int argc, char* argv[])
|
||||
|
||||
/* Initialize the output file name */
|
||||
const char* OutputFile = 0;
|
||||
|
||||
fin = NULL;
|
||||
const char* InputFile = 0;
|
||||
|
||||
/* Initialize the cmdline module */
|
||||
InitCmdLine (argc, argv, "cc65");
|
||||
@ -409,7 +408,7 @@ int main (int argc, char* argv[])
|
||||
|
||||
case 'h':
|
||||
case '?':
|
||||
OptHelp (Arg, 0);
|
||||
OptHelp (Arg, 0);
|
||||
break;
|
||||
|
||||
case 'g':
|
||||
@ -418,7 +417,7 @@ int main (int argc, char* argv[])
|
||||
|
||||
case 'j':
|
||||
OptSignedChars (Arg, 0);
|
||||
break;
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
OutputFile = GetArg (&I, 2);
|
||||
@ -463,44 +462,40 @@ int main (int argc, char* argv[])
|
||||
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 'i':
|
||||
FavourSize = 0;
|
||||
break;
|
||||
case 'r':
|
||||
EnableRegVars = 1;
|
||||
break;
|
||||
case 's':
|
||||
InlineStdFuncs = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'T':
|
||||
OptAddSource (Arg, 0);
|
||||
break;
|
||||
case 'T':
|
||||
OptAddSource (Arg, 0);
|
||||
break;
|
||||
|
||||
case 'V':
|
||||
OptVersion (Arg, 0);
|
||||
break;
|
||||
case 'V':
|
||||
OptVersion (Arg, 0);
|
||||
break;
|
||||
|
||||
case 'W':
|
||||
NoWarn = 1;
|
||||
break;
|
||||
case 'W':
|
||||
NoWarn = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -509,14 +504,17 @@ int main (int argc, char* argv[])
|
||||
}
|
||||
|
||||
/* 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! */
|
||||
|
@ -28,13 +28,13 @@ OBJS = anonname.o \
|
||||
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 \
|
||||
|
@ -82,13 +82,13 @@ OBJS = anonname.obj \
|
||||
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 \
|
||||
@ -139,13 +139,13 @@ FILE global.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
|
||||
|
605
src/cc65/mem.c
605
src/cc65/mem.c
@ -1,605 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* 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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -37,6 +37,8 @@
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "../common/xmalloc.h"
|
||||
|
||||
#include "asmlabel.h"
|
||||
#include "asmline.h"
|
||||
#include "check.h"
|
||||
@ -44,7 +46,6 @@
|
||||
#include "error.h"
|
||||
#include "global.h"
|
||||
#include "io.h"
|
||||
#include "mem.h"
|
||||
#include "optimize.h"
|
||||
|
||||
|
||||
@ -1218,7 +1219,7 @@ static unsigned RegValUsed (Line* Start)
|
||||
* 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;
|
||||
|
||||
@ -3635,6 +3636,9 @@ static Line* OptOneBlock (Line* L)
|
||||
}
|
||||
}
|
||||
} 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;
|
||||
@ -3642,7 +3646,10 @@ static Line* OptOneBlock (Line* L)
|
||||
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);
|
||||
@ -3650,7 +3657,8 @@ static Line* OptOneBlock (Line* L)
|
||||
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);
|
||||
@ -4092,6 +4100,9 @@ static Line* OptOneBlock (Line* L)
|
||||
} 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 */
|
||||
@ -4099,7 +4110,7 @@ static Line* OptOneBlock (Line* L)
|
||||
/* 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)) {
|
||||
|
@ -7,15 +7,17 @@
|
||||
#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"
|
||||
@ -33,7 +35,7 @@ static int Pass1 (char* from, char* to);
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* data */
|
||||
/* data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
@ -83,7 +85,7 @@ static void keepstr (const char* S)
|
||||
static void comment (void)
|
||||
/* Remove comment from line. */
|
||||
{
|
||||
unsigned StartingLine = ln;
|
||||
unsigned StartingLine = GetCurrentLine();
|
||||
|
||||
gch ();
|
||||
gch ();
|
||||
@ -438,7 +440,7 @@ static int Pass1 (char* from, char* to)
|
||||
++lptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (MaybeMacro(c)) {
|
||||
done = 0;
|
||||
@ -576,7 +578,7 @@ static int doiff (int skip)
|
||||
skipblank ();
|
||||
S = line;
|
||||
while ((*S++ = *lptr++) != '\0') ;
|
||||
strcat (line, ";;");
|
||||
strcpy (S-1, ";;");
|
||||
lptr = line;
|
||||
|
||||
/* Switch into special preprocessing mode */
|
||||
@ -623,70 +625,58 @@ static int doifdef (int skip, int flag)
|
||||
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 next char and check for a valid file name terminator. Setup
|
||||
* the include directory spec (SYS/USR) by looking at the terminator.
|
||||
*/
|
||||
switch (cgch()) {
|
||||
|
||||
case '\"':
|
||||
RTerm = '\"';
|
||||
DirSpec = INC_USER;
|
||||
break;
|
||||
|
||||
case '<':
|
||||
RTerm = '>';
|
||||
DirSpec = INC_SYS;
|
||||
break;
|
||||
|
||||
default:
|
||||
PPError (ERR_INCLUDE_LTERM_EXPECTED);
|
||||
goto Done;
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
/* Search for the right terminator */
|
||||
End = strchr (lptr, RTerm);
|
||||
if (End == 0) {
|
||||
/* No terminator found */
|
||||
PPError (ERR_INCLUDE_RTERM_EXPECTED);
|
||||
goto done;
|
||||
}
|
||||
name [count] = '\0';
|
||||
|
||||
/* Now search for the name */
|
||||
p = FindInclude (name, (term == '\"')? INC_USER : INC_SYS);
|
||||
if (p == 0) {
|
||||
PPError (ERR_INCLUDE_NOT_FOUND, name);
|
||||
goto done;
|
||||
goto Done;
|
||||
}
|
||||
|
||||
/* Save the existing file info */
|
||||
filetab[ifile].f_ln = ln;
|
||||
filetab[ifile].f_name = fin;
|
||||
filetab[ifile].f_iocb = inp;
|
||||
++ifile;
|
||||
/* Create a temp copy of the filename */
|
||||
Length = End - lptr;
|
||||
Name = xmalloc (Length + 1);
|
||||
memcpy (Name, lptr, Length);
|
||||
Name[Length] = '\0';
|
||||
|
||||
/* Assign the name and output it */
|
||||
fin = p;
|
||||
if (Verbose) {
|
||||
printf ("including '%s'\n", fin);
|
||||
}
|
||||
/* Open the include file */
|
||||
OpenIncludeFile (Name, DirSpec);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
/* Delete the temp filename copy */
|
||||
xfree (Name);
|
||||
|
||||
done:
|
||||
Done:
|
||||
/* clear rest of line so next read will come from new file (if open) */
|
||||
kill ();
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "function.h"
|
||||
#include "global.h"
|
||||
#include "ident.h"
|
||||
#include "input.h"
|
||||
#include "io.h"
|
||||
#include "litpool.h"
|
||||
#include "preproc.h"
|
||||
@ -355,7 +356,7 @@ void NextToken (void)
|
||||
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) {
|
||||
@ -476,12 +477,12 @@ void NextToken (void)
|
||||
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) {
|
||||
|
@ -11,6 +11,8 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../common/xmalloc.h"
|
||||
|
||||
#include "asmcode.h"
|
||||
#include "asmlabel.h"
|
||||
#include "codegen.h"
|
||||
@ -23,7 +25,6 @@
|
||||
#include "litpool.h"
|
||||
#include "locals.h"
|
||||
#include "loop.h"
|
||||
#include "mem.h"
|
||||
#include "pragma.h"
|
||||
#include "scanner.h"
|
||||
#include "symtab.h"
|
||||
|
@ -33,7 +33,8 @@
|
||||
|
||||
|
||||
|
||||
#include "mem.h"
|
||||
#include "../common/xmalloc.h"
|
||||
|
||||
#include "symentry.h"
|
||||
|
||||
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "../common/hashstr.h"
|
||||
#include "../common/xmalloc.h"
|
||||
|
||||
#include "asmcode.h"
|
||||
#include "asmlabel.h"
|
||||
@ -50,7 +51,6 @@
|
||||
#include "funcdesc.h"
|
||||
#include "global.h"
|
||||
#include "io.h"
|
||||
#include "mem.h"
|
||||
#include "symentry.h"
|
||||
#include "symtab.h"
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user