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)
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. */
24 #include <sys/types.h>
30 static char *concat ();
31 static char *concat3 ();
33 /* These can be set by command line arguments */
34 char *linker_path = 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
56 if (++link_arg_index >= link_arg_max)
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];
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
78 locate_file (file_name, path_val)
83 int file_len = strlen (file_name);
84 char *end_path = path_val + strlen (path_val);
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))
104 for (; *path_val == PATH_SEPARATOR ; path_val++)
109 for (ptr = buf; *path_val && *path_val != PATH_SEPARATOR; )
110 *ptr++ = *path_val++;
113 if (*ptr != '/' && *ptr != DIR_SEPARATOR)
114 *++ptr = DIR_SEPARATOR;
116 strcpy (++ptr, file_name);
118 if (is_regular_file (buf))
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 */
132 char *lib, *lib_path;
134 lib = malloc (strlen (name) + 8);
137 strcat (lib, ".lib");
138 lib_path = locate_file (lib, search_dirs);
144 lib_path = locate_file (lib, search_dirs);
149 "Couldn't locate library: lib%s.a or lib%s.lib\n", name, name);
157 /* Check to see if the file named in NAME is a regular file, i.e. not a
161 is_regular_file (name)
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 */
175 process_args (p_argc, argv)
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"))
186 else if (! strncmp (argv [i], "-g", 2))
188 addarg ("-debugtype:coff -debug:full");
190 else if (! strncmp (argv [i], "-stack", 6))
193 addarg (concat ("-stack:",argv[i]));
195 else if (! strncmp (argv [i], "-subsystem", 10))
199 addarg (concat ("-subsystem:",argv[i]));
201 else if (! strncmp (argv [i], "-e", 2))
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 */
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);
230 linker_path = locate_file ("link.exe", pathval);
233 fprintf (stderr, "Couldn't locate link32 or link\n");
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"))
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");
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"))
314 for (i = 0; i < link_arg_index; i++)
315 printf ("%s ", link_args [i]);
319 if (spawnvp (P_WAIT, linker_path, (const char * const *)link_args) != 0)
321 fprintf (stderr, "Error executing %s\n", link_args[0]);
332 int len1 = strlen (s1);
333 int len2 = strlen (s2);
334 char *result = malloc (len1 + len2 + 1);
337 strcpy (result + len1, s2);
338 *(result + len1 + len2) = 0;
347 return concat (concat (s1, s2), s3);