* added compilers lcc and bcc (linux86)
[mascara-docs.git] / compilers / linux86-0.16.17 / ld / ld.c
blob1e9234fe31e20767aea3efa0f5f8a0791ff0007d
1 /* ld.c - linker for Introl format (6809 C) object files 6809/8086/80386 */
3 /* Copyright (C) 1994 Bruce Evans */
5 #include <errno.h>
7 #include "syshead.h"
8 #include "const.h"
9 #include "byteord.h"
10 #include "type.h"
11 #include "globvar.h"
13 #define MAX_LIBS (NR_STDLIBS + 5)
14 #ifdef MC6809
15 #define NR_STDLIBS 1
16 #else
17 #define NR_STDLIBS 0
18 #endif
20 PUBLIC bin_off_t text_base_value = 0; /* XXX */
21 PUBLIC bin_off_t data_base_value = 0; /* XXX */
22 PUBLIC bin_off_t heap_top_value = 0; /* XXX */
23 PUBLIC int headerless = 0;
24 #ifndef MSDOS
25 PUBLIC int cpm86 = 0;
26 #endif
27 PUBLIC char hexdigit[] = "0123456789abcdef";
29 PRIVATE bool_t flag[128];
30 PRIVATE char *libs[MAX_LIBS] = {
31 #ifdef MC6809
32 "/usr/local/lib/m09/",
33 #endif
36 PRIVATE int lastlib = NR_STDLIBS;
38 FORWARD char *buildname P((char *pre, char *mid, char *suf));
39 FORWARD char *expandlib P((char *fn));
41 PRIVATE char *buildname(pre, mid, suf)
42 char *pre;
43 char *mid;
44 char *suf;
46 char *name;
48 name = ourmalloc(strlen(pre) + strlen(mid) + strlen(suf) + 1);
49 strcpy(name, pre);
50 strcat(name, mid);
51 strcat(name, suf);
52 return name;
55 PRIVATE char *expandlib(fn)
56 char *fn;
58 char *path, *s;
59 int i;
61 for (i = lastlib - 1; i >= 0; --i)
63 path = ourmalloc(strlen(libs[i]) + strlen(fn) + 2);
64 strcpy(path, libs[i]);
65 s = path + strlen(path);
66 if (s!=path && s[-1] != '/') strcat(path, "/");
67 strcat(path, fn);
68 if (access(path, R_OK) == 0)
69 return path;
70 ourfree(path);
72 return NUL_PTR;
75 PUBLIC int main(argc, argv)
76 int argc;
77 char **argv;
79 register char *arg;
80 int argn;
81 static char crtprefix[] = "crt";
82 static char crtsuffix[] = ".o";
83 char *infilename;
84 static char libprefix[] = "lib";
85 static char libsuffix[] = ".a";
86 char *outfilename;
87 char *tfn;
88 int icount=0;
90 ioinit(argv[0]);
91 objinit();
92 syminit();
93 typeconv_init(INT_BIG_ENDIAN, LONG_BIG_ENDIAN);
94 #ifndef MC6809
95 flag['3'] = sizeof(char *) >= 4;
96 #endif
97 outfilename = NUL_PTR;
98 for (argn = 1; argn < argc; ++argn)
100 arg = argv[argn];
101 if (*arg != '-')
103 readsyms(arg, flag['t']);
104 icount++;
106 else
107 switch (arg[1])
109 case 'v':
110 version_msg();
111 case 'r': /* relocatable output */
112 case 't': /* trace modules linked */
113 if (icount > 0) usage();
114 #ifdef REL_OUTPUT
115 case 'B': /* Broken -r for dosemu. */
116 #endif
117 case '0': /* use 16-bit libraries */
118 case '3': /* use 32-bit libraries */
119 case 'M': /* print symbols linked */
120 case 'i': /* separate I & D output */
121 case 'm': /* print modules linked */
122 case 's': /* strip symbols */
123 case 'z': /* unmapped zero page */
124 case 'N': /* Native format a.out */
125 case 'd': /* Make a headerless outfile */
126 #ifndef MSDOS
127 case 'c': /* Write header in CP/M-86 format */
128 #endif
129 case 'y': /* Use a newer symbol table */
130 if (arg[2] == 0)
131 flag[(int) arg[1]] = TRUE;
132 else if (arg[2] == '-' && arg[3] == 0)
133 flag[(int) arg[1]] = FALSE;
134 else
135 usage();
136 if (arg[1] == '0') /* flag 0 is negative logic flag 3 */
137 flag['3'] = !flag['0'];
138 break;
139 case 'C': /* startfile name */
140 tfn = buildname(crtprefix, arg + 2, crtsuffix);
141 if ((infilename = expandlib(tfn)) == NUL_PTR)
142 infilename = tfn;
143 /*fatalerror(tfn); * XXX - need to describe failure */
144 readsyms(infilename, flag['t']);
145 icount++;
146 break;
147 case 'L': /* library path */
148 if (lastlib < MAX_LIBS)
149 libs[lastlib++] = arg + 2;
150 else
151 fatalerror("too many library paths");
152 break;
153 case 'O': /* library file name */
154 if ((infilename = expandlib(arg + 2)) == NUL_PTR)
155 infilename = arg+2;
156 /* fatalerror(arg); * XXX */
157 readsyms(infilename, flag['t']);
158 break;
159 case 'T': /* text base address */
160 if (arg[2] == 0 && ++argn >= argc)
161 usage();
162 errno = 0;
163 if (arg[2] == 0 )
164 text_base_value = strtoul(argv[argn], (char **)0, 16);
165 else
166 text_base_value = strtoul(arg+2, (char **)0, 16);
167 if (errno != 0)
168 use_error("invalid text address");
169 break;
170 case 'D': /* data base address */
171 if (arg[2] == 0 && ++argn >= argc)
172 usage();
173 errno = 0;
174 if (arg[2] == 0 )
175 data_base_value = strtoul(argv[argn], (char **)0, 16);
176 else
177 data_base_value = strtoul(arg+2, (char **)0, 16);
178 if (errno != 0)
179 use_error("invalid data address");
180 break;
181 case 'H': /* heap top address */
182 if (arg[2] == 0 && ++argn >= argc)
183 usage();
184 errno = 0;
185 if (arg[2] == 0 )
186 heap_top_value = strtoul(argv[argn], (char **)0, 16);
187 else
188 heap_top_value = strtoul(arg+2, (char **)0, 16);
189 if (errno != 0)
190 use_error("invalid heap top");
191 break;
192 case 'l': /* library name */
193 tfn = buildname(libprefix, arg + 2, libsuffix);
194 if ((infilename = expandlib(tfn)) == NUL_PTR)
195 infilename = tfn;
196 /* fatalerror(tfn); * XXX */
197 readsyms(infilename, flag['t']);
198 icount+=2;
199 break;
200 case 'o': /* output file name */
201 if (arg[2] != 0 || ++argn >= argc || outfilename != NUL_PTR)
202 usage();
203 outfilename = argv[argn];
204 break;
205 default:
206 usage();
209 if(icount==0) usage();
211 #ifdef BUGCOMPAT
212 if( icount==1 && ( flag['r'] && !flag['N'] ) ) {
213 flag['r'] = 0;
214 flag['B'] = 1;
216 #endif
218 #ifdef REL_OUTPUT
219 #ifndef MSDOS
220 if( flag['r'] && !flag['N'] )
222 /* Do a relocatable link -- actually fake it with 'ar.c' */
223 ld86r(argc, argv);
225 #endif
226 #endif
228 #ifdef MSDOS
229 /* MSDOS Native is special, we make a COM file */
230 if( flag['N'] )
232 flag['N'] = 0;
233 flag['d'] = 1;
234 text_base_value = 0x100;
236 #endif
238 /* Headerless executables can't use symbols. */
239 headerless = flag['d'];
240 if( headerless ) flag['s'] = 1;
242 #ifndef MSDOS
243 /* CP/M-86 executables can't use symbols. */
244 cpm86 = flag['c'];
245 if ( cpm86 ) flag['s'] = 1;
246 #endif
248 linksyms(flag['r'] | flag['B']);
249 if (outfilename == NUL_PTR)
250 outfilename = "a.out";
251 #ifndef MSDOS
252 if( flag['N'] )
253 writebin(outfilename, flag['i'], flag['3'], flag['s'],
254 flag['z'] & flag['3']);
255 else
256 #endif
257 if( flag['B'] )
258 write_dosemu(outfilename, flag['i'], flag['3'], flag['s'],
259 flag['z'] & flag['3']);
260 else
261 write_elks(outfilename, flag['i'], flag['3'], flag['s'],
262 flag['z'], flag['y']);
263 if (flag['m'])
264 dumpmods();
265 if (flag['M'])
266 dumpsyms();
267 flusherr();
268 return errcount ? 1 : 0;