2 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2007
3 Free Software Foundation, Inc.
4 Contributed by Douglas B. Rupp (rupp@gnat.com).
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
13 GCC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
22 /* This program is a wrapper around the VMS linker.
23 It translates Unix style command line options into corresponding
24 VMS style qualifiers and then spawns the VMS linker. */
28 #include "coretypes.h"
31 typedef struct dsc
{unsigned short len
, mbz
; char *adr
; } Descr
;
34 #undef PATH_SEPARATOR_STR
35 #define PATH_SEPARATOR ','
36 #define PATH_SEPARATOR_STR ","
38 /* Local variable declarations. */
40 /* File specification for vms-dwarf2.o. */
41 static char *vmsdwarf2spec
= 0;
43 /* File specification for vms-dwarf2eh.o. */
44 static char *vmsdwarf2ehspec
= 0;
46 /* verbose = 1 if -v passed. */
47 static int verbose
= 0;
49 /* save_temps = 1 if -save-temps passed. */
50 static int save_temps
= 0;
52 /* By default don't generate executable file if there are errors
53 in the link. Override with --noinhibit-exec. */
54 static int inhibit_exec
= 1;
56 /* debug = 1 if -g passed. */
59 /* By default prefer to link with shareable image libraries.
60 Override with -static. */
61 static int staticp
= 0;
63 /* By default generate an executable, not a shareable image library.
64 Override with -shared. */
67 /* Remember if IDENTIFICATION given on command line. */
70 /* Keep track of arg translations. */
71 static int link_arg_max
= -1;
72 static const char **link_args
= 0;
73 static int link_arg_index
= -1;
75 /* Keep track of filenames */
76 static char optfilefullname
[267];
77 static char *sharefilename
= 0;
78 static char *exefilename
= 0;
80 /* System search dir list. Leave blank since link handles this
82 static char *system_search_dirs
= "";
84 /* Search dir list passed on command line (with -L). */
85 static char *search_dirs
;
87 /* Local function declarations. */
89 /* Add STR to the list of arguments to pass to the linker. Expand the list as
90 necessary to accommodate. */
91 static void addarg (const char *);
93 /* Check to see if NAME is a regular file, i.e. not a directory */
94 static int is_regular_file (char *);
96 /* Translate a Unix syntax file specification FILESPEC into VMS syntax.
97 If indicators of VMS syntax found, return input string. */
98 static char *to_host_file_spec (char *);
100 /* Locate the library named LIB_NAME in the set of paths PATH_VAL. */
101 static char *locate_lib (char *, char *);
103 /* Given a library name NAME, i.e. foo, Look for libfoo.lib and then
104 libfoo.a in the set of directories we are allowed to search in. */
105 static const char *expand_lib (char *);
107 /* Preprocess the number of args P_ARGC in ARGV.
108 Look for special flags, etc. that must be handled first. */
109 static void preprocess_args (int *, char **);
111 /* Preprocess the number of args P_ARGC in ARGV. Look for
112 special flags, etc. that must be handled for the VMS linker. */
113 static void process_args (int *, char **);
115 /* Action routine called by decc$to_vms. NAME is a file name or
116 directory name. TYPE is unused. */
117 static int translate_unix (char *, int);
119 int main (int, char **);
122 addarg (const char *str
)
126 if (++link_arg_index
>= link_arg_max
)
128 const char **new_link_args
129 = (const char **) xcalloc (link_arg_max
+ 1000, sizeof (char *));
131 for (i
= 0; i
<= link_arg_max
; i
++)
132 new_link_args
[i
] = link_args
[i
];
137 link_arg_max
+= 1000;
138 link_args
= new_link_args
;
141 link_args
[link_arg_index
] = str
;
145 locate_lib (char *lib_name
, char *path_val
)
147 int lib_len
= strlen (lib_name
);
150 for (sptr
= path_val
; *sptr
; sptr
= eptr
)
154 while (*sptr
== PATH_SEPARATOR
)
157 eptr
= strchr (sptr
, PATH_SEPARATOR
);
159 eptr
= strchr (sptr
, 0);
161 buf
= alloca ((eptr
-sptr
) + lib_len
+ 4 + 2);
162 strncpy (buf
, sptr
, eptr
-sptr
);
165 strcat (buf
, lib_name
);
166 ptr
= strchr (buf
, 0);
168 if (debug
|| staticp
)
170 /* For debug or static links, look for shareable image libraries
173 if (is_regular_file (buf
))
174 return xstrdup (to_host_file_spec (buf
));
176 strcpy (ptr
, ".olb");
177 if (is_regular_file (buf
))
178 return xstrdup (to_host_file_spec (buf
));
180 strcpy (ptr
, ".exe");
181 if (is_regular_file (buf
))
182 return xstrdup (to_host_file_spec (buf
));
186 /* Otherwise look for shareable image libraries first. */
187 strcpy (ptr
, ".exe");
188 if (is_regular_file (buf
))
189 return xstrdup (to_host_file_spec (buf
));
192 if (is_regular_file (buf
))
193 return xstrdup (to_host_file_spec (buf
));
195 strcpy (ptr
, ".olb");
196 if (is_regular_file (buf
))
197 return xstrdup (to_host_file_spec (buf
));
205 expand_lib (char *name
)
207 char *lib
, *lib_path
;
209 if (strcmp (name
, "c") == 0)
210 /* IEEE VAX C compatible library for non-prefixed (e.g. no DECC$)
212 return "sys$library:vaxcrtltx.olb";
214 else if (strcmp (name
, "m") == 0)
215 /* No separate library for math functions */
220 lib
= xmalloc (strlen (name
) + 14);
224 lib_path
= locate_lib (lib
, search_dirs
);
231 "Couldn't locate library: lib%s.exe, lib%s.a or lib%s.olb\n",
238 is_regular_file (char *name
)
243 ret
= stat (name
, &statbuf
);
244 return !ret
&& S_ISREG (statbuf
.st_mode
);
248 preprocess_args (int *p_argc
, char **argv
)
252 for (i
= 1; i
< *p_argc
; i
++)
253 if (strlen (argv
[i
]) >= 6 && strncmp (argv
[i
], "-shared", 7) == 0)
256 for (i
= 1; i
< *p_argc
; i
++)
257 if (strcmp (argv
[i
], "-o") == 0)
264 ptr
= to_host_file_spec (argv
[i
]);
265 exefilename
= xstrdup (ptr
);
266 out_len
= strlen (ptr
);
267 buff
= xmalloc (out_len
+ 18);
270 strcpy (buff
, "/share=");
272 strcpy (buff
, "/exe=");
279 sharefilename
= xmalloc (out_len
+5);
280 if (ptr
== strchr (argv
[i
], ']'))
281 strcpy (sharefilename
, ++ptr
);
282 else if (ptr
== strchr (argv
[i
], ':'))
283 strcpy (sharefilename
, ++ptr
);
284 else if (ptr
== strrchr (argv
[i
], '/'))
285 strcpy (sharefilename
, ++ptr
);
287 strcpy (sharefilename
, argv
[i
]);
289 len
= strlen (sharefilename
);
290 if (strncasecmp (&sharefilename
[len
-4], ".exe", 4) == 0)
291 sharefilename
[len
-4] = 0;
293 for (ptr
= sharefilename
; *ptr
; ptr
++)
294 *ptr
= TOUPPER (*ptr
);
300 process_args (int *p_argc
, char **argv
)
304 for (i
= 1; i
< *p_argc
; i
++)
306 if (strlen (argv
[i
]) < 2)
309 if (strncmp (argv
[i
], "-L", 2) == 0)
312 int new_len
, search_dirs_len
;
315 new_len
= strlen (ptr
);
316 search_dirs_len
= strlen (search_dirs
);
318 nbuff
= xmalloc (new_len
+ 1);
321 /* Remove trailing slashes. */
322 while (new_len
> 1 && nbuff
[new_len
- 1] == '/')
324 nbuff
[new_len
- 1] = 0;
328 search_dirs
= xrealloc (search_dirs
, search_dirs_len
+ new_len
+ 2);
329 if (search_dirs_len
> 0)
330 strcat (search_dirs
, PATH_SEPARATOR_STR
);
332 strcat (search_dirs
, nbuff
);
336 /* -v turns on verbose option here and is passed on to gcc. */
337 else if (strcmp (argv
[i
], "-v") == 0)
339 else if (strcmp (argv
[i
], "-g0") == 0)
340 addarg ("/notraceback");
341 else if (strncmp (argv
[i
], "-g", 2) == 0)
346 else if (strcmp (argv
[i
], "-static") == 0)
348 else if (strcmp (argv
[i
], "-map") == 0)
352 buff
= xmalloc (strlen (exefilename
) + 5);
353 strcpy (buff
, exefilename
);
354 ptr
= strchr (buff
, '.');
358 strcat (buff
, ".map");
363 else if (strcmp (argv
[i
], "-save-temps") == 0)
365 else if (strcmp (argv
[i
], "--noinhibit-exec") == 0)
370 /* The main program. Spawn the VMS linker after fixing up the Unix-like flags
371 and args to be what the VMS linker wants. */
374 main (int argc
, char **argv
)
377 char cwdev
[128], *devptr
;
381 char *cwd
= getcwd (0, 1024);
384 devptr
= strchr (cwd
, ':');
385 devlen
= (devptr
- cwd
) + 1;
386 strncpy (cwdev
, cwd
, devlen
);
387 cwdev
[devlen
] = '\0';
389 search_dirs
= xstrdup (system_search_dirs
);
393 /* Pass to find args that have to be append first. */
394 preprocess_args (&argc
, argv
);
396 /* Pass to find the rest of the args. */
397 process_args (&argc
, argv
);
399 /* Create a temp file to hold args, otherwise we can easily exceed the VMS
400 command line length limits. */
401 optfilename
= alloca (strlen ("LDXXXXXX") + 1);
402 strcpy (optfilename
, "LDXXXXXX");
403 optfd
= mkstemp (optfilename
);
404 getcwd (optfilefullname
, 256, 1); /* VMS style cwd. */
405 strcat (optfilefullname
, optfilename
);
406 strcat (optfilefullname
, ".");
407 optfile
= fdopen (optfd
, "w");
409 /* Write out the IDENTIFICATION argument first so that it can be overridden
410 by an options file. */
411 for (i
= 1; i
< argc
; i
++)
413 int arg_len
= strlen (argv
[i
]);
415 if (arg_len
> 6 && strncasecmp (argv
[i
], "IDENT=", 6) == 0)
417 /* Comes from command line. If present will always appear before
418 IDENTIFICATION=... and will override. */
423 else if (arg_len
> 15
424 && strncasecmp (argv
[i
], "IDENTIFICATION=", 15) == 0)
426 /* Comes from pragma Ident (). */
430 fprintf (optfile
, "case_sensitive=yes\n");
431 fprintf (optfile
, "IDENTIFICATION=\"%15.15s\"\n", &argv
[i
][15]);
432 fprintf (optfile
, "case_sensitive=NO\n");
438 for (i
= 1; i
< argc
; i
++)
440 int arg_len
= strlen (argv
[i
]);
442 if (strcmp (argv
[i
], "-o") == 0)
444 else if (arg_len
> 2 && strncmp (argv
[i
], "-l", 2) == 0)
446 const char *libname
= expand_lib (&argv
[i
][2]);
450 if ((len
= strlen (libname
)) > 0)
454 if (len
> 4 && strcasecmp (&libname
[len
-4], ".exe") == 0)
459 if (libname
[0] == '[')
460 sprintf (buff
, "%s%s", cwdev
, libname
);
462 sprintf (buff
, "%s", libname
);
464 fprintf (optfile
, "%s%s\n", buff
, ext
);
468 else if (strcmp (argv
[i
], "-v" ) == 0
469 || strncmp (argv
[i
], "-g", 2 ) == 0
470 || strcmp (argv
[i
], "-static" ) == 0
471 || strcmp (argv
[i
], "-map" ) == 0
472 || strcmp (argv
[i
], "-save-temps") == 0
473 || strcmp (argv
[i
], "--noinhibit-exec") == 0
474 || (arg_len
> 2 && strncmp (argv
[i
], "-L", 2) == 0)
475 || (arg_len
>= 6 && strncmp (argv
[i
], "-share", 6) == 0))
477 else if (arg_len
> 1 && argv
[i
][0] == '@')
485 if (stat (&argv
[i
][1], &statbuf
))
487 fprintf (stderr
, "Couldn't open linker response file: %s\n",
492 buff
= xmalloc (statbuf
.st_size
+ 1);
493 atfile
= fopen (&argv
[i
][1], "r");
494 fgets (buff
, statbuf
.st_size
+ 1, atfile
);
498 if (buff
[len
- 1] == '\n')
508 ptr1
= strchr (ptr
, ' ');
511 ptr
= to_host_file_spec (ptr
);
513 fprintf (optfile
, "%s%s\n", cwdev
, ptr
);
515 fprintf (optfile
, "%s\n", ptr
);
520 /* Unix style file specs and VMS style switches look alike, so assume an
521 arg consisting of one and only one slash, and that being first, is
523 else if ((argv
[i
][0] == '/') && (strchr (&argv
[i
][1], '/') == 0))
526 && strncasecmp (&argv
[i
][arg_len
-4], ".OPT", 4) == 0)
531 optfile1
= fopen (argv
[i
], "r");
532 while (fgets (buff
, 256, optfile1
))
533 fputs (buff
, optfile
);
537 else if (arg_len
> 7 && strncasecmp (argv
[i
], "GSMATCH", 7) == 0)
538 fprintf (optfile
, "%s\n", argv
[i
]);
539 else if (arg_len
> 6 && strncasecmp (argv
[i
], "IDENT=", 6) == 0)
541 /* Comes from command line and will override pragma. */
542 fprintf (optfile
, "case_sensitive=yes\n");
543 fprintf (optfile
, "IDENT=\"%15.15s\"\n", &argv
[i
][6]);
544 fprintf (optfile
, "case_sensitive=NO\n");
547 else if (arg_len
> 15
548 && strncasecmp (argv
[i
], "IDENTIFICATION=", 15) == 0)
552 /* Assume filename arg. */
553 const char *addswitch
= "";
558 argv
[i
] = to_host_file_spec (argv
[i
]);
559 arg_len
= strlen (argv
[i
]);
561 if (arg_len
> 4 && strcasecmp (&argv
[i
][arg_len
-4], ".exe") == 0)
562 addswitch
= "/shareable";
564 if (arg_len
> 4 && strcasecmp (&argv
[i
][arg_len
-4], ".cld") == 0)
566 addswitch
= "/shareable";
570 if (arg_len
> 2 && strcasecmp (&argv
[i
][arg_len
-2], ".a") == 0)
573 if (arg_len
> 4 && strcasecmp (&argv
[i
][arg_len
-4], ".olb") == 0)
576 if (argv
[i
][0] == '[')
577 sprintf (buff
, "%s%s%s\n", cwdev
, argv
[i
], addswitch
);
578 else if (strchr (argv
[i
], ':'))
579 sprintf (buff
, "%s%s\n", argv
[i
], addswitch
);
581 sprintf (buff
, "%s%s%s\n", cwd
, argv
[i
], addswitch
);
583 buff_len
= strlen (buff
);
586 && strcasecmp (&buff
[buff_len
- 15], "vms-dwarf2eh.o\n") == 0)
587 vmsdwarf2ehspec
= xstrdup (buff
);
588 else if (buff_len
>= 13
589 && strcasecmp (&buff
[buff_len
- 13],"vms-dwarf2.o\n") == 0)
590 vmsdwarf2spec
= xstrdup (buff
);
597 fprintf (optfile
, buff
);
603 fprintf (optfile
, "symbol_vector=(main=procedure)\n");
608 fprintf (optfile
, "case_sensitive=yes\n");
609 fprintf (optfile
, "cluster=DWARF2eh,,,%s", vmsdwarf2ehspec
);
610 fprintf (optfile
, "collect=DWARF2eh,eh_frame\n");
611 fprintf (optfile
, "case_sensitive=NO\n");
614 if (debug
&& vmsdwarf2spec
)
616 fprintf (optfile
, "case_sensitive=yes\n");
617 fprintf (optfile
, "cluster=DWARF2debug,,,%s", vmsdwarf2spec
);
618 fprintf (optfile
, "collect=DWARF2debug,debug_abbrev,debug_aranges,-\n");
619 fprintf (optfile
, " debug_frame,debug_info,debug_line,debug_loc,-\n");
620 fprintf (optfile
, " debug_macinfo,debug_pubnames,debug_str,-\n");
621 fprintf (optfile
, " debug_zzzzzz\n");
622 fprintf (optfile
, "case_sensitive=NO\n");
627 fprintf (optfile
, "case_sensitive=yes\n");
628 fprintf (optfile
, "symbol_vector=(-\n");
630 "%s$DWARF2.DEBUG_ABBREV/$dwarf2.debug_abbrev=DATA,-\n",
633 "%s$DWARF2.DEBUG_ARANGES/$dwarf2.debug_aranges=DATA,-\n",
635 fprintf (optfile
, "%s$DWARF2.DEBUG_FRAME/$dwarf2.debug_frame=DATA,-\n",
637 fprintf (optfile
, "%s$DWARF2.DEBUG_INFO/$dwarf2.debug_info=DATA,-\n",
639 fprintf (optfile
, "%s$DWARF2.DEBUG_LINE/$dwarf2.debug_line=DATA,-\n",
641 fprintf (optfile
, "%s$DWARF2.DEBUG_LOC/$dwarf2.debug_loc=DATA,-\n",
644 "%s$DWARF2.DEBUG_MACINFO/$dwarf2.debug_macinfo=DATA,-\n",
647 "%s$DWARF2.DEBUG_PUBNAMES/$dwarf2.debug_pubnames=DATA,-\n",
649 fprintf (optfile
, "%s$DWARF2.DEBUG_STR/$dwarf2.debug_str=DATA,-\n",
651 fprintf (optfile
, "%s$DWARF2.DEBUG_ZZZZZZ/$dwarf2.debug_zzzzzz=DATA)\n",
653 fprintf (optfile
, "case_sensitive=NO\n");
657 addarg (optfilefullname
);
666 for (i
= 0; i
< link_arg_index
; i
++)
667 printf ("%s ", link_args
[i
]);
675 for (i
= 0; link_args
[i
]; i
++)
676 len
= len
+ strlen (link_args
[i
]) + 1;
679 char *allargs
= (char *) alloca (len
+ 1);
684 for (i
= 0; i
< len
+ 1; i
++)
687 for (i
= 0; link_args
[i
]; i
++)
689 strcat (allargs
, link_args
[i
]);
690 strcat (allargs
, " ");
697 i
= LIB$
SPAWN (&cmd
, 0, 0, 0, 0, 0, &status
);
706 strcpy (allargs
, "@gnu:[bin]set_exe ");
707 strcat (allargs
, exefilename
);
708 strcat (allargs
, " /nodebug /silent");
709 len
= strlen (allargs
);
717 i
= LIB$
SPAWN (&cmd
, 0, 0, 0, 0, 0, &status1
);
727 remove (optfilefullname
);
729 if ((status
& 1) == 1 && (status1
& 1) == 1)
732 if (exefilename
&& inhibit_exec
== 1)
733 remove (exefilename
);
740 static char new_host_filespec
[255];
741 static char filename_buff
[256];
744 translate_unix (char *name
, int type ATTRIBUTE_UNUSED
)
746 strcpy (filename_buff
, name
);
751 to_host_file_spec (char *filespec
)
753 strcpy (new_host_filespec
, "");
754 if (strchr (filespec
, ']') || strchr (filespec
, ':'))
755 strcpy (new_host_filespec
, filespec
);
758 decc$
to_vms (filespec
, translate_unix
, 1, 1);
759 strcpy (new_host_filespec
, filename_buff
);
762 return new_host_filespec
;