Initial revision
[official-gcc.git] / gcc / config / winnt / ld.c
blob67d53e783214f98a3673b1d104cc262f735f21b4
1 /* Call Windows NT 3.x linker.
2 Copyright (C) 1994, 1995 Free Software Foundation, Inc.
3 Contributed by Douglas B. Rupp (drupp@cs.washington.edu).
5 This file is part of GNU CC.
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 #include "config.h"
23 #include <stdio.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <process.h>
30 static char *concat ();
31 static char *concat3 ();
33 /* These can be set by command line arguments */
34 char *linker_path = 0;
35 int verbose = 0;
36 int subsystem = 0;
37 int entry = 0;
39 int link_arg_max = -1;
40 char **link_args = (char **) 0;
41 int link_arg_index = -1;
43 char *search_dirs = ".";
45 static int is_regular_file (char *name);
47 /* Add the argument contained in STR to the list of arguments to pass to the
48 linker */
50 static void
51 addarg (str)
52 char *str;
54 int i;
56 if (++link_arg_index >= link_arg_max)
58 char **new_link_args
59 = (char **) calloc (link_arg_max + 1000, sizeof (char *));
61 for (i = 0; i <= link_arg_max; i++)
62 new_link_args [i] = link_args [i];
64 if (link_args)
65 free (link_args);
67 link_arg_max += 1000;
68 link_args = new_link_args;
71 link_args [link_arg_index] = str;
74 /* Locate the file named in FILE_NAME in the set of paths contained in
75 PATH_VAL */
77 static char *
78 locate_file (file_name, path_val)
79 char *file_name;
80 char *path_val;
82 char buf [1000];
83 int file_len = strlen (file_name);
84 char *end_path = path_val + strlen (path_val);
85 char *ptr;
87 /* Handle absolute pathnames */
88 if (file_name [0] == '/' || file_name [0] == DIR_SEPARATOR
89 || isalpha (file_name [0]) && file_name [1] == ':')
91 strncpy (buf, file_name, sizeof buf);
92 buf[sizeof buf - 1] = '\0';
93 if (is_regular_file (buf))
94 return strdup (buf);
95 else
96 return 0;
99 if (! path_val)
100 return 0;
102 for (;;)
104 for (; *path_val == PATH_SEPARATOR ; path_val++)
106 if (! *path_val)
107 return 0;
109 for (ptr = buf; *path_val && *path_val != PATH_SEPARATOR; )
110 *ptr++ = *path_val++;
112 ptr--;
113 if (*ptr != '/' && *ptr != DIR_SEPARATOR)
114 *++ptr = DIR_SEPARATOR;
116 strcpy (++ptr, file_name);
118 if (is_regular_file (buf))
119 return strdup (buf);
122 return 0;
125 /* Given a library name in NAME, i.e. foo. Look first for libfoo.lib and then
126 libfoo.a in the set of directories we are allowed to search in */
128 static char *
129 expand_lib (name)
130 char *name;
132 char *lib, *lib_path;
134 lib = malloc (strlen (name) + 8);
135 strcpy (lib, "lib");
136 strcat (lib, name);
137 strcat (lib, ".lib");
138 lib_path = locate_file (lib, search_dirs);
139 if (!lib_path)
141 strcpy (lib, "lib");
142 strcat (lib, name);
143 strcat (lib, ".a");
144 lib_path = locate_file (lib, search_dirs);
145 if (!lib_path)
147 fprintf
148 (stderr,
149 "Couldn't locate library: lib%s.a or lib%s.lib\n", name, name);
150 exit (1);
154 return lib_path;
157 /* Check to see if the file named in NAME is a regular file, i.e. not a
158 directory */
160 static int
161 is_regular_file (name)
162 char *name;
164 int ret;
165 struct stat statbuf;
167 ret = stat(name, &statbuf);
168 return !ret && S_ISREG (statbuf.st_mode);
171 /* Process the number of args in P_ARGC and contained in ARGV. Look for
172 special flags, etc. that must be handled for the Microsoft linker */
174 static void
175 process_args (p_argc, argv)
176 int *p_argc;
177 char *argv[];
179 int i, j;
181 for (i = 1; i < *p_argc; i++)
183 /* -v turns on verbose option here and is passed on to gcc */
184 if (! strcmp (argv [i], "-v"))
185 verbose = 1;
186 else if (! strncmp (argv [i], "-g", 2))
188 addarg ("-debugtype:coff -debug:full");
190 else if (! strncmp (argv [i], "-stack", 6))
192 i++;
193 addarg (concat ("-stack:",argv[i]));
195 else if (! strncmp (argv [i], "-subsystem", 10))
197 subsystem = 1;
198 i++;
199 addarg (concat ("-subsystem:",argv[i]));
201 else if (! strncmp (argv [i], "-e", 2))
203 entry = 1;
204 i++;
205 addarg (concat ("-entry:",&argv[i][1]));
210 /* The main program. Spawn the Microsoft linker after fixing up the
211 Unix-like flags and args to be what the Microsoft linker wants */
213 main (argc, argv)
214 int argc;
215 char *argv[];
217 int i;
218 int done_an_ali = 0;
219 int file_name_index;
220 char *pathval = getenv ("PATH");
221 char *spawn_args [5];
222 char *tmppathval = malloc (strlen (pathval) + 3);
224 strcpy (tmppathval, ".;");
225 pathval = strcat (tmppathval, pathval);
227 linker_path = locate_file ("link32.exe", pathval);
228 if (!linker_path)
230 linker_path = locate_file ("link.exe", pathval);
231 if (!linker_path)
233 fprintf (stderr, "Couldn't locate link32 or link\n");
234 exit (1);
238 addarg (linker_path);
240 process_args (&argc , argv);
241 if (! subsystem) addarg ("-subsystem:console");
242 if (! entry) addarg ("-entry:mainCRTStartup");
244 for (i = 1; i < argc; i++)
246 int arg_len = strlen (argv [i]);
248 if (!strcmp (argv [i], "-o"))
250 char *buff, *ptr;
251 int out_len;
253 i++;
254 out_len = strlen (argv[i]) + 10;
255 buff = malloc (out_len);
256 strcpy (buff, "-out:");
257 strcat (buff, argv[i]);
258 ptr = strstr (buff, ".exe");
259 if (ptr == NULL || strlen (ptr) != 4)
260 strcat (buff, ".exe");
261 addarg (buff);
263 else if (arg_len > 2 && !strncmp (argv [i], "-L", 2))
265 char *nbuff, *sdbuff;
266 int j, new_len, search_dirs_len;
268 new_len = strlen (&argv[i][2]);
269 search_dirs_len = strlen (search_dirs);
271 nbuff = malloc (new_len + 1);
272 strcpy (nbuff, &argv[i][2]);
274 for (j = 0; j < new_len; j++)
275 if (nbuff[j] == '/') nbuff[j] = DIR_SEPARATOR;
277 sdbuff = malloc (search_dirs_len + new_len + 2);
278 strcpy (sdbuff, search_dirs);
279 sdbuff[search_dirs_len] = PATH_SEPARATOR;
280 sdbuff[search_dirs_len+1] = 0;
281 strcat (sdbuff, nbuff);
283 search_dirs = sdbuff;
286 else if (arg_len > 2 && !strncmp (argv [i], "-l", 2))
288 addarg (expand_lib (&argv[i][2]));
290 else if (!strcmp (argv [i], "-v")
291 || !strcmp (argv [i], "-g")
292 || !strcmp (argv [i], "-noinhibit-exec"))
296 else if (!strcmp (argv [i], "-stack")
297 || !strcmp (argv [i], "-subsystem")
298 || !strcmp (argv [i], "-e"))
300 i++;
302 else
304 addarg (argv [i]);
308 addarg (NULL);
310 if (verbose)
312 int i;
314 for (i = 0; i < link_arg_index; i++)
315 printf ("%s ", link_args [i]);
316 putchar ('\n');
319 if (spawnvp (P_WAIT, linker_path, (const char * const *)link_args) != 0)
321 fprintf (stderr, "Error executing %s\n", link_args[0]);
322 exit (1);
325 exit (0);
328 static char *
329 concat (s1, s2)
330 char *s1, *s2;
332 int len1 = strlen (s1);
333 int len2 = strlen (s2);
334 char *result = malloc (len1 + len2 + 1);
336 strcpy (result, s1);
337 strcpy (result + len1, s2);
338 *(result + len1 + len2) = 0;
340 return result;
343 static char *
344 concat3 (s1, s2, s3)
345 char *s1, *s2, *s3;
347 return concat (concat (s1, s2), s3);