Merge remote-tracking branch 'upstream/master' into a5200
This commit is contained in:
28
src/Makefile
28
src/Makefile
@@ -27,6 +27,17 @@ LD65_LIB = $(datadir)/lib
|
||||
LD65_OBJ = $(datadir)/lib
|
||||
LD65_CFG = $(datadir)/cfg
|
||||
|
||||
ifdef CMD_EXE
|
||||
NULLDEV = nul:
|
||||
DIRLIST = $(strip $(foreach dir,$1,$(wildcard $(dir))))
|
||||
MKDIR = mkdir $(subst /,\,$1)
|
||||
RMDIR = $(if $(DIRLIST),rmdir /s /q $(subst /,\,$(DIRLIST)))
|
||||
else
|
||||
NULLDEV = /dev/null
|
||||
MKDIR = mkdir -p $1
|
||||
RMDIR = $(RM) -r $1
|
||||
endif
|
||||
|
||||
CC = $(CROSS_COMPILE)gcc
|
||||
AR = $(CROSS_COMPILE)ar
|
||||
|
||||
@@ -39,13 +50,15 @@ ifdef USER_CFLAGS
|
||||
$(info USER_CFLAGS: $(USER_CFLAGS))
|
||||
endif
|
||||
|
||||
ifndef GIT_SHA
|
||||
GIT_SHA := $(if $(wildcard ../.git),$(shell git rev-parse --short HEAD))
|
||||
ifdef GIT_SHA
|
||||
$(info GIT_SHA: $(GIT_SHA))
|
||||
else
|
||||
GIT_SHA := $(shell git rev-parse --short HEAD 2>$(NULLDEV))
|
||||
ifneq ($(words $(GIT_SHA)),1)
|
||||
GIT_SHA := N/A
|
||||
$(info GIT_SHA: N/A)
|
||||
endif
|
||||
endif
|
||||
$(info GIT_SHA: $(GIT_SHA))
|
||||
|
||||
CFLAGS += -MMD -MP -O -I common \
|
||||
-Wall -Wextra -Wno-char-subscripts $(USER_CFLAGS) \
|
||||
@@ -62,15 +75,6 @@ ifdef CROSS_COMPILE
|
||||
EXE_SUFFIX=.exe
|
||||
endif
|
||||
|
||||
ifdef CMD_EXE
|
||||
DIRLIST = $(strip $(foreach dir,$1,$(wildcard $(dir))))
|
||||
MKDIR = mkdir $(subst /,\,$1)
|
||||
RMDIR = $(if $(DIRLIST),rmdir /s /q $(subst /,\,$(DIRLIST)))
|
||||
else
|
||||
MKDIR = mkdir -p $1
|
||||
RMDIR = $(RM) -r $1
|
||||
endif
|
||||
|
||||
all bin: $(PROGS)
|
||||
|
||||
mostlyclean:
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
|
||||
|
||||
#ifndef SHIFTEXPR_H
|
||||
#define SHIFTEXPT_H
|
||||
#define SHIFTEXPR_H
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -870,8 +870,8 @@ static char GetAddrSizeCode (unsigned char AddrSize)
|
||||
|
||||
|
||||
|
||||
void PrintExportMap (FILE* F)
|
||||
/* Print an export map to the given file */
|
||||
void PrintExportMapByName (FILE* F)
|
||||
/* Print an export map, sorted by symbol name, to the given file */
|
||||
{
|
||||
unsigned I;
|
||||
unsigned Count;
|
||||
@@ -902,6 +902,61 @@ void PrintExportMap (FILE* F)
|
||||
|
||||
|
||||
|
||||
static int CmpExpValue (const void* I1, const void* I2)
|
||||
/* Compare function for qsort */
|
||||
{
|
||||
long V1 = GetExportVal (ExpPool [*(unsigned *)I1]);
|
||||
long V2 = GetExportVal (ExpPool [*(unsigned *)I2]);
|
||||
|
||||
return V1 < V2 ? -1 : V1 == V2 ? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void PrintExportMapByValue (FILE* F)
|
||||
/* Print an export map, sorted by symbol value, to the given file */
|
||||
{
|
||||
unsigned I;
|
||||
unsigned Count;
|
||||
unsigned *ExpValXlat;
|
||||
|
||||
/* Create a translation table where the symbols are sorted by value. */
|
||||
ExpValXlat = xmalloc (ExpCount * sizeof (unsigned));
|
||||
for (I = 0; I < ExpCount; ++I) {
|
||||
/* Initialize table with current sort order. */
|
||||
ExpValXlat [I] = I;
|
||||
}
|
||||
|
||||
/* Sort them by value */
|
||||
qsort (ExpValXlat, ExpCount, sizeof (unsigned), CmpExpValue);
|
||||
|
||||
/* Print all exports */
|
||||
Count = 0;
|
||||
for (I = 0; I < ExpCount; ++I) {
|
||||
const Export* E = ExpPool [ExpValXlat [I]];
|
||||
|
||||
/* Print unreferenced symbols only if explictly requested */
|
||||
if (VerboseMap || E->ImpCount > 0 || SYM_IS_CONDES (E->Type)) {
|
||||
fprintf (F,
|
||||
"%-25s %06lX %c%c%c%c ",
|
||||
GetString (E->Name),
|
||||
GetExportVal (E),
|
||||
E->ImpCount? 'R' : ' ',
|
||||
SYM_IS_LABEL (E->Type)? 'L' : 'E',
|
||||
GetAddrSizeCode ((unsigned char) E->AddrSize),
|
||||
SYM_IS_CONDES (E->Type)? 'I' : ' ');
|
||||
if (++Count == 2) {
|
||||
Count = 0;
|
||||
fprintf (F, "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
fprintf (F, "\n");
|
||||
xfree (ExpValXlat);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void PrintImportMap (FILE* F)
|
||||
/* Print an import map to the given file */
|
||||
{
|
||||
|
||||
@@ -186,8 +186,11 @@ void CheckUnresolvedImports (ExpCheckFunc F, void* Data);
|
||||
* called (see the comments on ExpCheckFunc in the data section).
|
||||
*/
|
||||
|
||||
void PrintExportMap (FILE* F);
|
||||
/* Print an export map to the given file */
|
||||
void PrintExportMapByName (FILE* F);
|
||||
/* Print an export map to the given file (sorted by symbol name) */
|
||||
|
||||
void PrintExportMapByValue (FILE* F);
|
||||
/* Print an export map to the given file (sorted by export value) */
|
||||
|
||||
void PrintImportMap (FILE* F);
|
||||
/* Print an import map to the given file */
|
||||
|
||||
207
src/ld65/main.c
207
src/ld65/main.c
@@ -80,6 +80,24 @@
|
||||
static unsigned ObjFiles = 0; /* Count of object files linked */
|
||||
static unsigned LibFiles = 0; /* Count of library files linked */
|
||||
|
||||
/* struct InputFile.Type definitions */
|
||||
#define INPUT_FILES_FILE 0 /* Entry is a file (unknown type) */
|
||||
#define INPUT_FILES_FILE_OBJ 1 /* Entry is a object file */
|
||||
#define INPUT_FILES_FILE_LIB 2 /* Entry is a library file */
|
||||
#define INPUT_FILES_SGROUP 3 /* Entry is 'StartGroup' */
|
||||
#define INPUT_FILES_EGROUP 4 /* Entry is 'EndGroup' */
|
||||
|
||||
#define MAX_INPUTFILES 256
|
||||
|
||||
/* Array of inputs (libraries and object files) */
|
||||
static struct InputFile {
|
||||
const char *FileName;
|
||||
unsigned Type;
|
||||
} *InputFiles;
|
||||
static unsigned InputFilesCount = 0;
|
||||
static const char *CmdlineCfgFile = NULL,
|
||||
*CmdlineTarget = NULL;
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
@@ -390,7 +408,10 @@ static void OptHelp (const char* Opt attribute ((unused)),
|
||||
static void OptLib (const char* Opt attribute ((unused)), const char* Arg)
|
||||
/* Link a library */
|
||||
{
|
||||
LinkFile (Arg, FILETYPE_LIB);
|
||||
InputFiles[InputFilesCount].Type = INPUT_FILES_FILE_LIB;
|
||||
InputFiles[InputFilesCount].FileName = Arg;
|
||||
if (++InputFilesCount >= MAX_INPUTFILES)
|
||||
Error ("Too many input files");
|
||||
}
|
||||
|
||||
|
||||
@@ -406,6 +427,9 @@ static void OptLibPath (const char* Opt attribute ((unused)), const char* Arg)
|
||||
static void OptMapFile (const char* Opt attribute ((unused)), const char* Arg)
|
||||
/* Give the name of the map file */
|
||||
{
|
||||
if (MapFileName) {
|
||||
Error ("Cannot use -m twice");
|
||||
}
|
||||
MapFileName = Arg;
|
||||
}
|
||||
|
||||
@@ -426,7 +450,10 @@ static void OptModuleId (const char* Opt, const char* Arg)
|
||||
static void OptObj (const char* Opt attribute ((unused)), const char* Arg)
|
||||
/* Link an object file */
|
||||
{
|
||||
LinkFile (Arg, FILETYPE_OBJ);
|
||||
InputFiles[InputFilesCount].Type = INPUT_FILES_FILE_OBJ;
|
||||
InputFiles[InputFilesCount].FileName = Arg;
|
||||
if (++InputFilesCount >= MAX_INPUTFILES)
|
||||
Error ("Too many input files");
|
||||
}
|
||||
|
||||
|
||||
@@ -439,16 +466,14 @@ static void OptObjPath (const char* Opt attribute ((unused)), const char* Arg)
|
||||
|
||||
|
||||
|
||||
static void OptOutputName (const char* Opt, const char* Arg)
|
||||
static void OptOutputName (const char* Opt attribute ((unused)), const char* Arg)
|
||||
/* Give the name of the output file */
|
||||
{
|
||||
/* If the name of the output file has been used in the config before
|
||||
* (by using %O) we're actually changing it later, which - in most cases -
|
||||
* gives unexpected results, so emit a warning in this case.
|
||||
*/
|
||||
if (OutputNameUsed) {
|
||||
Warning ("Option `%s' should precede options `-t' or `-C'", Opt);
|
||||
static int OutputNameSeen = 0;
|
||||
if (OutputNameSeen) {
|
||||
Error ("Cannot use -o twice");
|
||||
}
|
||||
OutputNameSeen = 1;
|
||||
OutputName = Arg;
|
||||
}
|
||||
|
||||
@@ -457,6 +482,9 @@ static void OptOutputName (const char* Opt, const char* Arg)
|
||||
static void OptStartAddr (const char* Opt, const char* Arg)
|
||||
/* Set the default start address */
|
||||
{
|
||||
if (HaveStartAddr) {
|
||||
Error ("Cannot use -S twice");
|
||||
}
|
||||
StartAddr = CvtNumber (Opt, Arg);
|
||||
HaveStartAddr = 1;
|
||||
}
|
||||
@@ -520,16 +548,61 @@ static void OptVersion (const char* Opt attribute ((unused)),
|
||||
|
||||
|
||||
|
||||
int main (int argc, char* argv [])
|
||||
/* Assembler main program */
|
||||
static void CmdlOptStartGroup (const char* Opt attribute ((unused)),
|
||||
const char* Arg attribute ((unused)))
|
||||
/* Remember 'start group' occurrence in input files array */
|
||||
{
|
||||
InputFiles[InputFilesCount].Type = INPUT_FILES_SGROUP;
|
||||
InputFiles[InputFilesCount].FileName = Arg; /* Unused */
|
||||
if (++InputFilesCount >= MAX_INPUTFILES)
|
||||
Error ("Too many input files");
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void CmdlOptEndGroup (const char* Opt attribute ((unused)),
|
||||
const char* Arg attribute ((unused)))
|
||||
/* Remember 'end group' occurrence in input files array */
|
||||
{
|
||||
InputFiles[InputFilesCount].Type = INPUT_FILES_EGROUP;
|
||||
InputFiles[InputFilesCount].FileName = Arg; /* Unused */
|
||||
if (++InputFilesCount >= MAX_INPUTFILES)
|
||||
Error ("Too many input files");
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void CmdlOptConfig (const char* Opt attribute ((unused)), const char* Arg)
|
||||
/* Set 'config file' command line parameter */
|
||||
{
|
||||
if (CmdlineCfgFile || CmdlineTarget) {
|
||||
Error ("Cannot use -C/-t twice");
|
||||
}
|
||||
CmdlineCfgFile = Arg;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void CmdlOptTarget (const char* Opt attribute ((unused)), const char* Arg)
|
||||
/* Set 'target' command line parameter */
|
||||
{
|
||||
if (CmdlineCfgFile || CmdlineTarget) {
|
||||
Error ("Cannot use -C/-t twice");
|
||||
}
|
||||
CmdlineTarget = Arg;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void ParseCommandLine(void)
|
||||
{
|
||||
/* Program long options */
|
||||
static const LongOpt OptTab[] = {
|
||||
{ "--cfg-path", 1, OptCfgPath },
|
||||
{ "--config", 1, OptConfig },
|
||||
{ "--config", 1, CmdlOptConfig },
|
||||
{ "--dbgfile", 1, OptDbgFile },
|
||||
{ "--define", 1, OptDefine },
|
||||
{ "--end-group", 0, OptEndGroup },
|
||||
{ "--end-group", 0, CmdlOptEndGroup },
|
||||
{ "--force-import", 1, OptForceImport },
|
||||
{ "--help", 0, OptHelp },
|
||||
{ "--lib", 1, OptLib },
|
||||
@@ -539,27 +612,18 @@ int main (int argc, char* argv [])
|
||||
{ "--obj", 1, OptObj },
|
||||
{ "--obj-path", 1, OptObjPath },
|
||||
{ "--start-addr", 1, OptStartAddr },
|
||||
{ "--start-group", 0, OptStartGroup },
|
||||
{ "--target", 1, OptTarget },
|
||||
{ "--start-group", 0, CmdlOptStartGroup },
|
||||
{ "--target", 1, CmdlOptTarget },
|
||||
{ "--version", 0, OptVersion },
|
||||
};
|
||||
|
||||
unsigned I;
|
||||
unsigned MemoryAreaOverflows;
|
||||
unsigned LabelFileGiven = 0;
|
||||
|
||||
/* Initialize the cmdline module */
|
||||
InitCmdLine (&argc, &argv, "ld65");
|
||||
/* Allocate memory for input file array */
|
||||
InputFiles = xmalloc (MAX_INPUTFILES * sizeof (struct InputFile));
|
||||
|
||||
/* Initialize the input file search paths */
|
||||
InitSearchPaths ();
|
||||
|
||||
/* Initialize the string pool */
|
||||
InitStrPool ();
|
||||
|
||||
/* Initialize the type pool */
|
||||
InitTypePool ();
|
||||
|
||||
/* Check the parameters */
|
||||
/* Defer setting of config/target and input files until all options are parsed */
|
||||
I = 1;
|
||||
while (I < ArgCount) {
|
||||
|
||||
@@ -577,11 +641,11 @@ int main (int argc, char* argv [])
|
||||
break;
|
||||
|
||||
case '(':
|
||||
OptStartGroup (Arg, 0);
|
||||
CmdlOptStartGroup (Arg, 0);
|
||||
break;
|
||||
|
||||
case ')':
|
||||
OptEndGroup (Arg, 0);
|
||||
CmdlOptEndGroup (Arg, 0);
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
@@ -594,14 +658,11 @@ int main (int argc, char* argv [])
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
OptOutputName (Arg, GetArg (&I, 2));
|
||||
OptOutputName (NULL, GetArg (&I, 2));
|
||||
break;
|
||||
|
||||
case 't':
|
||||
if (CfgAvail ()) {
|
||||
Error ("Cannot use -C/-t twice");
|
||||
}
|
||||
OptTarget (Arg, GetArg (&I, 2));
|
||||
CmdlOptTarget (Arg, GetArg (&I, 2));
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
@@ -617,7 +678,7 @@ int main (int argc, char* argv [])
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
OptConfig (Arg, GetArg (&I, 2));
|
||||
CmdlOptConfig (Arg, GetArg (&I, 2));
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
@@ -626,9 +687,17 @@ int main (int argc, char* argv [])
|
||||
|
||||
case 'L':
|
||||
switch (Arg [2]) {
|
||||
/* ## The first one is obsolete and will go */
|
||||
case 'n': LabelFileName = GetArg (&I, 3); break;
|
||||
default: OptLibPath (Arg, GetArg (&I, 2)); break;
|
||||
case 'n':
|
||||
/* ## This one is obsolete and will go */
|
||||
if (LabelFileGiven) {
|
||||
Error ("Cannot use -Ln twice");
|
||||
}
|
||||
LabelFileGiven = 1;
|
||||
LabelFileName = GetArg (&I, 3);
|
||||
break;
|
||||
default:
|
||||
OptLibPath (Arg, GetArg (&I, 2));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -648,7 +717,10 @@ int main (int argc, char* argv [])
|
||||
} else {
|
||||
|
||||
/* A filename */
|
||||
LinkFile (Arg, FILETYPE_UNKNOWN);
|
||||
InputFiles[InputFilesCount].Type = INPUT_FILES_FILE;
|
||||
InputFiles[InputFilesCount].FileName = Arg;
|
||||
if (++InputFilesCount >= MAX_INPUTFILES)
|
||||
Error ("Too many input files");
|
||||
|
||||
}
|
||||
|
||||
@@ -656,6 +728,61 @@ int main (int argc, char* argv [])
|
||||
++I;
|
||||
}
|
||||
|
||||
if (CmdlineTarget) {
|
||||
OptTarget (NULL, CmdlineTarget);
|
||||
} else if (CmdlineCfgFile) {
|
||||
OptConfig (NULL, CmdlineCfgFile);
|
||||
}
|
||||
|
||||
/* Process input files */
|
||||
for (I = 0; I < InputFilesCount; ++I) {
|
||||
switch (InputFiles[I].Type) {
|
||||
case INPUT_FILES_FILE:
|
||||
LinkFile (InputFiles[I].FileName, FILETYPE_UNKNOWN);
|
||||
break;
|
||||
case INPUT_FILES_FILE_LIB:
|
||||
LinkFile (InputFiles[I].FileName, FILETYPE_LIB);
|
||||
break;
|
||||
case INPUT_FILES_FILE_OBJ:
|
||||
LinkFile (InputFiles[I].FileName, FILETYPE_OBJ);
|
||||
break;
|
||||
case INPUT_FILES_SGROUP:
|
||||
OptStartGroup (NULL, 0);
|
||||
break;
|
||||
case INPUT_FILES_EGROUP:
|
||||
OptEndGroup (NULL, 0);
|
||||
break;
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
/* Free memory used for input file array */
|
||||
xfree (InputFiles);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main (int argc, char* argv [])
|
||||
/* Linker main program */
|
||||
{
|
||||
unsigned MemoryAreaOverflows;
|
||||
|
||||
/* Initialize the cmdline module */
|
||||
InitCmdLine (&argc, &argv, "ld65");
|
||||
|
||||
/* Initialize the input file search paths */
|
||||
InitSearchPaths ();
|
||||
|
||||
/* Initialize the string pool */
|
||||
InitStrPool ();
|
||||
|
||||
/* Initialize the type pool */
|
||||
InitTypePool ();
|
||||
|
||||
/* Parse the command line */
|
||||
ParseCommandLine ();
|
||||
|
||||
/* Check if we had any object files */
|
||||
if (ObjFiles == 0) {
|
||||
Error ("No object files to link");
|
||||
|
||||
@@ -111,11 +111,17 @@ void CreateMapFile (int ShortMap)
|
||||
/* The remainder is not written for short map files */
|
||||
if (!ShortMap) {
|
||||
|
||||
/* Write the exports list */
|
||||
/* Write the exports list by name */
|
||||
fprintf (F, "\n\n"
|
||||
"Exports list:\n"
|
||||
"-------------\n");
|
||||
PrintExportMap (F);
|
||||
"Exports list by name:\n"
|
||||
"---------------------\n");
|
||||
PrintExportMapByName (F);
|
||||
|
||||
/* Write the exports list by value */
|
||||
fprintf (F, "\n\n"
|
||||
"Exports list by value:\n"
|
||||
"----------------------\n");
|
||||
PrintExportMapByValue (F);
|
||||
|
||||
/* Write the imports list */
|
||||
fprintf (F, "\n\n"
|
||||
|
||||
Reference in New Issue
Block a user