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
);