ref: 157fda2bc85b54a608bdb0cf5149c8a01046c51a
dir: /src/link/main.c/
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "asmotor.h"
#include "link/object.h"
#include "link/output.h"
#include "link/assign.h"
#include "link/patch.h"
#include "link/mylink.h"
#include "link/mapfile.h"
#include "link/main.h"
#include "link/library.h"
// Quick and dirty...but it works
#ifdef __GNUC__
#define strcmpi strcasecmp
#endif
enum eBlockType {
BLOCK_COMMENT,
BLOCK_OBJECTS,
BLOCK_LIBRARIES,
BLOCK_OUTPUT
};
SLONG options = 0;
SLONG fillchar = 0;
enum eOutputType outputtype = OUTPUT_GBROM;
char smartlinkstartsymbol[256];
/*
* Print the usagescreen
*
*/
static void
usage(void)
{
printf("xLink v" LINK_VERSION " (part of ASMotor " ASMOTOR_VERSION
")\n\n");
printf("usage: xlink [m mapfile] [-n symfile] [-s symbol] [-tg | -ts | -tp]\n");
printf("\t [-z pad_value] linkfile\n");
exit(0);
}
/*
* Parse the linkfile and load all the objectfiles
*
*/
void
ProcessLinkfile(char *tzLinkfile)
{
FILE *pLinkfile;
enum eBlockType CurrentBlock = BLOCK_COMMENT;
pLinkfile = fopen(tzLinkfile, "rt");
if (!pLinkfile) {
errx(5, "Unable to find linkfile '%s'", tzLinkfile);
}
while (!feof(pLinkfile)) {
char tzLine[256];
fscanf(pLinkfile, "%s\n", tzLine);
if (tzLine[0] != '#') {
if (tzLine[0] == '['
&& tzLine[strlen(tzLine) - 1] == ']') {
if (strcmpi("[objects]", tzLine) == 0)
CurrentBlock = BLOCK_OBJECTS;
else if (strcmpi("[output]", tzLine) ==
0)
CurrentBlock = BLOCK_OUTPUT;
else if (strcmpi("[libraries]", tzLine)
== 0)
CurrentBlock = BLOCK_LIBRARIES;
else if (strcmpi("[comment]", tzLine) ==
0)
CurrentBlock = BLOCK_COMMENT;
else {
fclose(pLinkfile);
errx(5,
"Unknown block '%s'",
tzLine);
}
} else {
switch (CurrentBlock) {
case BLOCK_COMMENT:
break;
case BLOCK_OBJECTS:
obj_Readfile(tzLine);
break;
case BLOCK_LIBRARIES:
lib_Readfile(tzLine);
break;
case BLOCK_OUTPUT:
out_Setname(tzLine);
break;
}
}
}
}
fclose(pLinkfile);
}
/*
* The main routine
*
*/
int
main(int argc, char *argv[])
{
int ch;
char *ep;
SLONG argn = 0;
if (argc == 1)
usage();
while ((ch = getopt(argc, argv, "m:n:s:t:z:")) != -1) {
switch (ch) {
case 'm':
SetMapfileName(optarg);
break;
case 'n':
SetSymfileName(optarg);
break;
case 's':
options |= OPT_SMART_C_LINK;
strcpy(smartlinkstartsymbol, optarg);
break;
case 't':
switch (optarg[0]) {
case 'g':
outputtype = OUTPUT_GBROM;
break;
case 's':
outputtype = OUTPUT_GBROM;
options |= OPT_SMALL;
break;
case 'p':
outputtype = OUTPUT_PSION2;
break;
default:
errx(5, "Invalid argument to option t");
break;
}
break;
case 'z':
if (optarg[0] == '?')
fillchar = -1;
else {
fillchar = strtoul(optarg, &ep, 0);
if (optarg[0] == '\0' || *ep != '\0')
errx(5, "Invalid argument for option 'z'");
if (fillchar < 0 || fillchar > 0xFF)
errx(5, "Argument for option 'z' must be between 0 and 0xFF");
}
break;
default:
usage();
/* NOTREACHED */
}
}
argc -= optind;
argv += optind;
if (argc == 1) {
ProcessLinkfile(argv[argc - 1]);
AddNeededModules();
AssignSections();
CreateSymbolTable();
Patch();
Output();
CloseMapfile();
} else
usage();
return (0);
}