]>
git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/alpha/vms-ld.c
2 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002
3 Free Software Foundation, Inc.
4 Contributed by Douglas B. Rupp (rupp@gnat.com).
6 This file is part of GNU CC.
8 GNU CC 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 2, or (at your option)
13 GNU CC 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 GNU CC; see the file COPYING. If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
23 /* This program is a wrapper around the VMS linker.
24 It translates Unix style command line options into corresponding
25 VMS style qualifiers and then spawns the VMS linker. */
29 #include "coretypes.h"
32 typedef struct dsc
{unsigned short len
, mbz
; char *adr
; } Descr
;
35 #undef PATH_SEPARATOR_STR
36 #define PATH_SEPARATOR ','
37 #define PATH_SEPARATOR_STR ","
39 /* Local variable declarations. */
41 /* File specification for vms-dwarf2.o. */
42 static char *vmsdwarf2spec
= 0;
44 /* File specification for vms-dwarf2eh.o. */
45 static char *vmsdwarf2ehspec
= 0;
47 /* verbose = 1 if -v passed. */
48 static int verbose
= 0;
50 /* save_temps = 1 if -save-temps passed. */
51 static int save_temps
= 0;
53 /* By default don't generate executable file if there are errors
54 in the link. Override with --noinhibit-exec. */
55 static int inhibit_exec
= 1;
57 /* debug = 1 if -g passed. */
60 /* By default prefer to link with shareable image libraries.
61 Override with -static. */
62 static int staticp
= 0;
64 /* By default generate an executable, not a shareable image library.
65 Override with -shared. */
68 /* Remember if IDENTIFICATION given on command line. */
71 /* Keep track of arg translations. */
72 static int link_arg_max
= -1;
73 static const char **link_args
= 0;
74 static int link_arg_index
= -1;
76 /* Keep track of filenames */
77 static char optfilefullname
[267];
78 static char *sharefilename
= 0;
79 static char *exefilename
= 0;
81 /* System search dir list. Leave blank since link handles this
83 static char *system_search_dirs
= "";
85 /* Search dir list passed on command line (with -L). */
86 static char *search_dirs
;
88 /* Local function declarations. */
90 /* Add STR to the list of arguments to pass to the linker. Expand the list as
91 necessary to accommodate. */
92 static void addarg
PARAMS ((const char *));
94 /* Check to see if NAME is a regular file, i.e. not a directory */
95 static int is_regular_file
PARAMS ((char *));
97 /* Translate a Unix syntax file specification FILESPEC into VMS syntax.
98 If indicators of VMS syntax found, return input string. */
99 static char *to_host_file_spec
PARAMS ((char *));
101 /* Locate the library named LIB_NAME in the set of paths PATH_VAL. */
102 static char *locate_lib
PARAMS ((char *, char *));
104 /* Given a library name NAME, i.e. foo, Look for libfoo.lib and then
105 libfoo.a in the set of directories we are allowed to search in. */
106 static const char *expand_lib
PARAMS ((char *));
108 /* Preprocess the number of args P_ARGC in ARGV.
109 Look for special flags, etc. that must be handled first. */
110 static void preprocess_args
PARAMS ((int *, char **));
112 /* Preprocess the number of args P_ARGC in ARGV. Look for
113 special flags, etc. that must be handled for the VMS linker. */
114 static void process_args
PARAMS ((int *, char **));
116 /* Action routine called by decc$to_vms. NAME is a file name or
117 directory name. TYPE is unused. */
118 static int translate_unix
PARAMS ((char *, int));
120 int main
PARAMS ((int, char **));
128 if (++link_arg_index
>= link_arg_max
)
130 const char **new_link_args
131 = (const char **) xcalloc (link_arg_max
+ 1000, sizeof (char *));
133 for (i
= 0; i
<= link_arg_max
; i
++)
134 new_link_args
[i
] = link_args
[i
];
139 link_arg_max
+= 1000;
140 link_args
= new_link_args
;
143 link_args
[link_arg_index
] = str
;
147 locate_lib (lib_name
, path_val
)
151 int lib_len
= strlen (lib_name
);
154 for (sptr
= path_val
; *sptr
; sptr
= eptr
)
158 while (*sptr
== PATH_SEPARATOR
)
161 eptr
= strchr (sptr
, PATH_SEPARATOR
);
163 eptr
= strchr (sptr
, 0);
165 buf
= alloca ((eptr
-sptr
) + lib_len
+ 4 + 2);
166 strncpy (buf
, sptr
, eptr
-sptr
);
169 strcat (buf
, lib_name
);
170 ptr
= strchr (buf
, 0);
172 if (debug
|| staticp
)
174 /* For debug or static links, look for shareable image libraries
177 if (is_regular_file (buf
))
178 return xstrdup (to_host_file_spec (buf
));
180 strcpy (ptr
, ".olb");
181 if (is_regular_file (buf
))
182 return xstrdup (to_host_file_spec (buf
));
184 strcpy (ptr
, ".exe");
185 if (is_regular_file (buf
))
186 return xstrdup (to_host_file_spec (buf
));
190 /* Otherwise look for shareable image libraries first. */
191 strcpy (ptr
, ".exe");
192 if (is_regular_file (buf
))
193 return xstrdup (to_host_file_spec (buf
));
196 if (is_regular_file (buf
))
197 return xstrdup (to_host_file_spec (buf
));
199 strcpy (ptr
, ".olb");
200 if (is_regular_file (buf
))
201 return xstrdup (to_host_file_spec (buf
));
212 char *lib
, *lib_path
;
214 if (strcmp (name
, "c") == 0)
215 /* IEEE VAX C compatible library for non-prefixed (e.g. no DECC$)
217 return "sys$library:vaxcrtltx.olb";
219 else if (strcmp (name
, "m") == 0)
220 /* No separate library for math functions */
225 lib
= xmalloc (strlen (name
) + 14);
229 lib_path
= locate_lib (lib
, search_dirs
);
236 "Couldn't locate library: lib%s.exe, lib%s.a or lib%s.olb\n",
243 is_regular_file (name
)
249 ret
= stat (name
, &statbuf
);
250 return !ret
&& S_ISREG (statbuf
.st_mode
);
254 preprocess_args (p_argc
, argv
)
260 for (i
= 1; i
< *p_argc
; i
++)
261 if (strlen (argv
[i
]) >= 6 && strncmp (argv
[i
], "-shared", 7) == 0)
264 for (i
= 1; i
< *p_argc
; i
++)
265 if (strcmp (argv
[i
], "-o") == 0)
272 ptr
= to_host_file_spec (argv
[i
]);
273 exefilename
= xstrdup (ptr
);
274 out_len
= strlen (ptr
);
275 buff
= xmalloc (out_len
+ 18);
278 strcpy (buff
, "/share=");
280 strcpy (buff
, "/exe=");
287 sharefilename
= xmalloc (out_len
+5);
288 if (ptr
== strchr (argv
[i
], ']'))
289 strcpy (sharefilename
, ++ptr
);
290 else if (ptr
== strchr (argv
[i
], ':'))
291 strcpy (sharefilename
, ++ptr
);
292 else if (ptr
== strrchr (argv
[i
], '/'))
293 strcpy (sharefilename
, ++ptr
);
295 strcpy (sharefilename
, argv
[i
]);
297 len
= strlen (sharefilename
);
298 if (strncasecmp (&sharefilename
[len
-4], ".exe", 4) == 0)
299 sharefilename
[len
-4] = 0;
301 for (ptr
= sharefilename
; *ptr
; ptr
++)
302 *ptr
= TOUPPER (*ptr
);
308 process_args (p_argc
, argv
)
314 for (i
= 1; i
< *p_argc
; i
++)
316 if (strlen (argv
[i
]) < 2)
319 if (strncmp (argv
[i
], "-L", 2) == 0)
322 int new_len
, search_dirs_len
;
325 new_len
= strlen (ptr
);
326 search_dirs_len
= strlen (search_dirs
);
328 nbuff
= xmalloc (new_len
+ 1);
331 /* Remove trailing slashes. */
332 while (new_len
> 1 && nbuff
[new_len
- 1] == '/')
334 nbuff
[new_len
- 1] = 0;
338 search_dirs
= xrealloc (search_dirs
, search_dirs_len
+ new_len
+ 2);
339 if (search_dirs_len
> 0)
340 strcat (search_dirs
, PATH_SEPARATOR_STR
);
342 strcat (search_dirs
, nbuff
);
346 /* -v turns on verbose option here and is passed on to gcc. */
347 else if (strcmp (argv
[i
], "-v") == 0)
349 else if (strcmp (argv
[i
], "-g0") == 0)
350 addarg ("/notraceback");
351 else if (strncmp (argv
[i
], "-g", 2) == 0)
356 else if (strcmp (argv
[i
], "-static") == 0)
358 else if (strcmp (argv
[i
], "-map") == 0)
362 buff
= xmalloc (strlen (exefilename
) + 5);
363 strcpy (buff
, exefilename
);
364 ptr
= strchr (buff
, '.');
368 strcat (buff
, ".map");
373 else if (strcmp (argv
[i
], "-save-temps") == 0)
375 else if (strcmp (argv
[i
], "--noinhibit-exec") == 0)
380 /* The main program. Spawn the VMS linker after fixing up the Unix-like flags
381 and args to be what the VMS linker wants. */
389 char cwdev
[128], *devptr
;
393 char *cwd
= getcwd (0, 1024);
396 devptr
= strchr (cwd
, ':');
397 devlen
= (devptr
- cwd
) + 1;
398 strncpy (cwdev
, cwd
, devlen
);
399 cwdev
[devlen
] = '\0';
401 search_dirs
= xstrdup (system_search_dirs
);
405 /* Pass to find args that have to be append first. */
406 preprocess_args (&argc
, argv
);
408 /* Pass to find the rest of the args. */
409 process_args (&argc
, argv
);
411 /* Create a temp file to hold args, otherwise we can easily exceed the VMS
412 command line length limits. */
413 optfilename
= alloca (strlen ("LDXXXXXX") + 1);
414 strcpy (optfilename
, "LDXXXXXX");
415 optfd
= mkstemp (optfilename
);
416 getcwd (optfilefullname
, 256, 1); /* VMS style cwd. */
417 strcat (optfilefullname
, optfilename
);
418 strcat (optfilefullname
, ".");
419 optfile
= fdopen (optfd
, "w");
421 /* Write out the IDENTIFICATION argument first so that it can be overridden
422 by an options file. */
423 for (i
= 1; i
< argc
; i
++)
425 int arg_len
= strlen (argv
[i
]);
427 if (arg_len
> 6 && strncasecmp (argv
[i
], "IDENT=", 6) == 0)
429 /* Comes from command line. If present will always appear before
430 IDENTIFICATION=... and will override. */
435 else if (arg_len
> 15
436 && strncasecmp (argv
[i
], "IDENTIFICATION=", 15) == 0)
438 /* Comes from pragma Ident (). */
442 fprintf (optfile
, "case_sensitive=yes\n");
443 fprintf (optfile
, "IDENTIFICATION=\"%15.15s\"\n", &argv
[i
][15]);
444 fprintf (optfile
, "case_sensitive=NO\n");
450 for (i
= 1; i
< argc
; i
++)
452 int arg_len
= strlen (argv
[i
]);
454 if (strcmp (argv
[i
], "-o") == 0)
456 else if (arg_len
> 2 && strncmp (argv
[i
], "-l", 2) == 0)
458 const char *libname
= expand_lib (&argv
[i
][2]);
462 if ((len
= strlen (libname
)) > 0)
466 if (len
> 4 && strcasecmp (&libname
[len
-4], ".exe") == 0)
471 if (libname
[0] == '[')
472 sprintf (buff
, "%s%s", cwdev
, libname
);
474 sprintf (buff
, "%s", libname
);
476 fprintf (optfile
, "%s%s\n", buff
, ext
);
480 else if (strcmp (argv
[i
], "-v" ) == 0
481 || strncmp (argv
[i
], "-g", 2 ) == 0
482 || strcmp (argv
[i
], "-static" ) == 0
483 || strcmp (argv
[i
], "-map" ) == 0
484 || strcmp (argv
[i
], "-save-temps") == 0
485 || strcmp (argv
[i
], "--noinhibit-exec") == 0
486 || (arg_len
> 2 && strncmp (argv
[i
], "-L", 2) == 0)
487 || (arg_len
>= 6 && strncmp (argv
[i
], "-share", 6) == 0))
489 else if (arg_len
> 1 && argv
[i
][0] == '@')
497 if (stat (&argv
[i
][1], &statbuf
))
499 fprintf (stderr
, "Couldn't open linker response file: %s\n",
504 buff
= xmalloc (statbuf
.st_size
+ 1);
505 atfile
= fopen (&argv
[i
][1], "r");
506 fgets (buff
, statbuf
.st_size
+ 1, atfile
);
510 if (buff
[len
- 1] == '\n')
520 ptr1
= strchr (ptr
, ' ');
523 ptr
= to_host_file_spec (ptr
);
525 fprintf (optfile
, "%s%s\n", cwdev
, ptr
);
527 fprintf (optfile
, "%s\n", ptr
);
532 /* Unix style file specs and VMS style switches look alike, so assume an
533 arg consisting of one and only one slash, and that being first, is
535 else if ((argv
[i
][0] == '/') && (strchr (&argv
[i
][1], '/') == 0))
538 && strncasecmp (&argv
[i
][arg_len
-4], ".OPT", 4) == 0)
543 optfile1
= fopen (argv
[i
], "r");
544 while (fgets (buff
, 256, optfile1
))
545 fputs (buff
, optfile
);
549 else if (arg_len
> 7 && strncasecmp (argv
[i
], "GSMATCH", 7) == 0)
550 fprintf (optfile
, "%s\n", argv
[i
]);
551 else if (arg_len
> 6 && strncasecmp (argv
[i
], "IDENT=", 6) == 0)
553 /* Comes from command line and will override pragma. */
554 fprintf (optfile
, "case_sensitive=yes\n");
555 fprintf (optfile
, "IDENT=\"%15.15s\"\n", &argv
[i
][6]);
556 fprintf (optfile
, "case_sensitive=NO\n");
559 else if (arg_len
> 15
560 && strncasecmp (argv
[i
], "IDENTIFICATION=", 15) == 0)
564 /* Assume filename arg. */
565 const char *addswitch
= "";
570 argv
[i
] = to_host_file_spec (argv
[i
]);
571 arg_len
= strlen (argv
[i
]);
573 if (arg_len
> 4 && strcasecmp (&argv
[i
][arg_len
-4], ".exe") == 0)
574 addswitch
= "/shareable";
576 if (arg_len
> 4 && strcasecmp (&argv
[i
][arg_len
-4], ".cld") == 0)
578 addswitch
= "/shareable";
582 if (arg_len
> 2 && strcasecmp (&argv
[i
][arg_len
-2], ".a") == 0)
585 if (arg_len
> 4 && strcasecmp (&argv
[i
][arg_len
-4], ".olb") == 0)
588 if (argv
[i
][0] == '[')
589 sprintf (buff
, "%s%s%s\n", cwdev
, argv
[i
], addswitch
);
590 else if (strchr (argv
[i
], ':'))
591 sprintf (buff
, "%s%s\n", argv
[i
], addswitch
);
593 sprintf (buff
, "%s%s%s\n", cwd
, argv
[i
], addswitch
);
595 buff_len
= strlen (buff
);
598 && strcasecmp (&buff
[buff_len
- 15], "vms-dwarf2eh.o\n") == 0)
599 vmsdwarf2ehspec
= xstrdup (buff
);
600 else if (buff_len
>= 13
601 && strcasecmp (&buff
[buff_len
- 13],"vms-dwarf2.o\n") == 0)
602 vmsdwarf2spec
= xstrdup (buff
);
609 fprintf (optfile
, buff
);
615 fprintf (optfile
, "symbol_vector=(main=procedure)\n");
620 fprintf (optfile
, "case_sensitive=yes\n");
621 fprintf (optfile
, "cluster=DWARF2eh,,,%s", vmsdwarf2ehspec
);
622 fprintf (optfile
, "collect=DWARF2eh,eh_frame\n");
623 fprintf (optfile
, "case_sensitive=NO\n");
626 if (debug
&& vmsdwarf2spec
)
628 fprintf (optfile
, "case_sensitive=yes\n");
629 fprintf (optfile
, "cluster=DWARF2debug,,,%s", vmsdwarf2spec
);
630 fprintf (optfile
, "collect=DWARF2debug,debug_abbrev,debug_aranges,-\n");
631 fprintf (optfile
, " debug_frame,debug_info,debug_line,debug_loc,-\n");
632 fprintf (optfile
, " debug_macinfo,debug_pubnames,debug_str,-\n");
633 fprintf (optfile
, " debug_zzzzzz\n");
634 fprintf (optfile
, "case_sensitive=NO\n");
639 fprintf (optfile
, "case_sensitive=yes\n");
640 fprintf (optfile
, "symbol_vector=(-\n");
642 "%s$DWARF2.DEBUG_ABBREV/$dwarf2.debug_abbrev=DATA,-\n",
645 "%s$DWARF2.DEBUG_ARANGES/$dwarf2.debug_aranges=DATA,-\n",
647 fprintf (optfile
, "%s$DWARF2.DEBUG_FRAME/$dwarf2.debug_frame=DATA,-\n",
649 fprintf (optfile
, "%s$DWARF2.DEBUG_INFO/$dwarf2.debug_info=DATA,-\n",
651 fprintf (optfile
, "%s$DWARF2.DEBUG_LINE/$dwarf2.debug_line=DATA,-\n",
653 fprintf (optfile
, "%s$DWARF2.DEBUG_LOC/$dwarf2.debug_loc=DATA,-\n",
656 "%s$DWARF2.DEBUG_MACINFO/$dwarf2.debug_macinfo=DATA,-\n",
659 "%s$DWARF2.DEBUG_PUBNAMES/$dwarf2.debug_pubnames=DATA,-\n",
661 fprintf (optfile
, "%s$DWARF2.DEBUG_STR/$dwarf2.debug_str=DATA,-\n",
663 fprintf (optfile
, "%s$DWARF2.DEBUG_ZZZZZZ/$dwarf2.debug_zzzzzz=DATA)\n",
665 fprintf (optfile
, "case_sensitive=NO\n");
669 addarg (optfilefullname
);
678 for (i
= 0; i
< link_arg_index
; i
++)
679 printf ("%s ", link_args
[i
]);
687 for (i
= 0; link_args
[i
]; i
++)
688 len
= len
+ strlen (link_args
[i
]) + 1;
691 char *allargs
= (char *) alloca (len
+ 1);
696 for (i
= 0; i
< len
+ 1; i
++)
699 for (i
= 0; link_args
[i
]; i
++)
701 strcat (allargs
, link_args
[i
]);
702 strcat (allargs
, " ");
709 i
= LIB$
SPAWN (&cmd
, 0, 0, 0, 0, 0, &status
);
718 strcpy (allargs
, "@gnu:[bin]set_exe ");
719 strcat (allargs
, exefilename
);
720 strcat (allargs
, " /nodebug /silent");
721 len
= strlen (allargs
);
729 i
= LIB$
SPAWN (&cmd
, 0, 0, 0, 0, 0, &status1
);
739 remove (optfilefullname
);
741 if ((status
& 1) == 1 && (status1
& 1) == 1)
744 if (exefilename
&& inhibit_exec
== 1)
745 remove (exefilename
);
752 static char new_host_filespec
[255];
753 static char filename_buff
[256];
756 translate_unix (name
, type
)
758 int type ATTRIBUTE_UNUSED
;
760 strcpy (filename_buff
, name
);
765 to_host_file_spec (filespec
)
768 strcpy (new_host_filespec
, "");
769 if (strchr (filespec
, ']') || strchr (filespec
, ':'))
770 strcpy (new_host_filespec
, filespec
);
773 decc$
to_vms (filespec
, translate_unix
, 1, 1);
774 strcpy (new_host_filespec
, filename_buff
);
777 return new_host_filespec
;