1 /* WORK IN PROGRESS: do not watch this if you don't have the legal
2 age in your country to watch this.
5 /* This program is distributed in the hope that it will be useful,
6 * but WITHOUT ANY WARRANTY; without even the implied warranty of
7 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8 * GNU General Public License for more details.
10 * You should have received a copy of the GNU General Public License
11 * along with this program; if not, write to the Free Software
12 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 /* This is a cheap hack. The xa51 has a couple of ways to scramble
16 relocation info into it's opcode that the standard linker can't
19 The relocatable format looks like the known one, BUT ISN'T.
21 The only things that are handled now are:
23 "SDCCXA rel, version %f" must be the first line, sort of MAGIC word
24 "H %d areas %d global symbols" defines the # of areas and globals
25 "S <symbol> [Ref0000 | DefXXXX]" Def's are supposed to be defined in
26 their own area/segment
27 "A <seg> size %d flags %d" switch to another segment. this can happen
28 multiple times and should be equal. flags is ignored for now
29 "T xx xx bb bb ..." where xx xx is the address within the current segment
31 "R xx <how> <symbol>" the relocation info. xx is the offset within the
32 previous "T .." line. <how> could be something like REL_FF, REL_FFFF,
33 ABS_F0FF. symbol is the (previous) defined symbol it refers to
35 So, this is not a standalone linker. It will only link files generated
36 by xa_asm, which will only process files generated by the xa51 sdcc
45 #include "xa_version.h"
60 } segments[MAX_SEGMENTS]={
72 static char outFileName[PATH_MAX];
74 void syntaxError (char *err) {
75 fprintf (stderr, "error while parsing '%s'\n", err);
79 void baseName(char *name, char*base) {
82 // find the last path seperator in name
83 for (first=strlen(name)-1;
84 (name[first]!='/' && name[first]!='\\') && first;
86 if (name[first]=='/' || name[first]=='\\') {
90 // find the last ext seperator in name
91 for (last=strlen(name)-1;
92 (name[last]!='.' && last);
98 fprintf (stderr, "baseName: %s %d %d\n", name, first, last);
99 // fill the base with the baseName
100 for (i=first; i<last; i++) {
101 base[i-first]=name[i];
106 void readModule(char *module) {
111 if ((relModule=fopen(module, "r"))==NULL) {
115 printf ("ReadModule: %s\n", module);
117 // first we need to check if this is a valid file
118 if (sscanf(fgets(line, 132, relModule),
119 "SDCCXA rel, version %lf", &hisVersion)!=1) {
120 fprintf (stderr, "%s is not a valid input file\n", module);
123 if (hisVersion!=version) {
124 fprintf (stderr, "WARNING: version conflict; "
125 "we(%1.1f) != %s(%1.1f)\n",
126 version, module, hisVersion);
130 fprintf (stderr, "Wow! This seems a nice module: v %1.1f.\n", hisVersion);
131 // that's all for now, thanks for watching */
136 fprintf (stderr, "WriteModule: %s\n", outFileName);
137 // oops, forgot something :) */
143 void usage (char * progName, int errNo) {
144 fprintf (stderr, "usage: %s lnkCmdFile\n", progName);
150 int main(int argc, char **argv) {
151 FILE *linkCommandsFile;
152 char linkCommandsPath[PATH_MAX];
153 char linkCommand[PATH_MAX];
159 // read in the commands
160 sprintf (linkCommandsPath, "%s.lnk", argv[1]);
161 if (!(linkCommandsFile=fopen(linkCommandsPath, "r"))) {
162 perror(linkCommandsPath);
165 while (fgets(linkCommand, PATH_MAX, linkCommandsFile)) {
166 linkCommand[strlen(linkCommand)-1]='\0';
174 if (*linkCommand=='-') {
175 switch (linkCommand[1])
178 // probably -muxi, ignore for now
181 // -e, always in the last line, ignore for now
185 // a segment start address like: "-b XSEG = 0x4000"
187 char *seg=strtok(&linkCommand[3], " \t");
188 for (s=0; s<MAX_SEGMENTS; s++) {
189 if (strcmp(segments[s].name, seg)==0) {
190 strtok(NULL, " \t"); // skip the '='
191 if (sscanf(strtok(NULL, " \t"), "%x",
192 &segments[s].start)!=1) {
193 syntaxError(linkCommand);
198 if (s==MAX_SEGMENTS) {
199 syntaxError(linkCommand);
204 // a lib path like: "-k /usr/local/share/sdcc/lib/xa51"; one/line
205 libPaths[nlibPaths++]=strdup(&linkCommand[3]);
208 // a lib file like: "-l libsdcc"; one/line
209 libFiles[nlibFiles++]=strdup(&linkCommand[3]);
212 syntaxError(linkCommand);
215 // not a switch, must be an inputfile; one/line
216 readModule(linkCommand);