]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/vms/vms-ld.c
Update copyright years.
[thirdparty/gcc.git] / gcc / config / vms / vms-ld.c
CommitLineData
18a24fed 1/* VMS linker wrapper.
cbe34bb5 2 Copyright (C) 2011-2017 Free Software Foundation, Inc.
18a24fed
TG
3 Contributed by AdaCore
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 3, or (at your option)
10any later version.
11
12GCC is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GCC; see the file COPYING3. If not see
19<http://www.gnu.org/licenses/>. */
20
21/* This program is a wrapper around the VMS linker.
22 It translates Unix style command line options into corresponding
23 VMS style qualifiers and then spawns the VMS linker.
24
25 It is possible to build this program on UNIX but only for the purpose of
26 checking for errors. */
27
28#include <stdlib.h>
29#include <string.h>
30#include <unistd.h>
31#include <stdio.h>
32
33#include "libiberty.h"
34#include <safe-ctype.h>
35#include <sys/stat.h>
36
37/* Macro for logicals. */
38#define LNM__STRING 2
39#define LNM_C_NAMLENGTH 255
40#define PSL_C_SUPER 2
41#define PSL_C_USER 3
42
43/* Local variable declarations. */
44static int ld_nocall_debug = 0;
45static int ld_mkthreads = 0;
46static int ld_upcalls = 0;
47
48/* verbose = 1 if -v passed. */
49static int verbose = 0;
50
51/* save_temps = 1 if -save-temps passed. */
52static int save_temps = 0;
53
54/* By default don't generate executable file if there are errors
55 in the link. Override with --noinhibit-exec. */
56static int inhibit_exec = 1;
57
58/* debug = 1 if -g passed. */
59static int debug = 0;
60
61/* By default prefer to link with static libraries. */
62static int staticp = 1;
63
64/* By default generate an executable, not a shareable image library.
65 Override with -shared. */
66static int share = 0;
67
68/* Linker command line. */
69static int link_cmd_maxlen = 0;
70static char *link_cmd = 0;
71static int link_cmd_len = 0;
72
73/* Keep track of filenames. */
74static char *sharebasename;
75static const char *exefullfilename;
76static const char *exefilename;
77
78/* Search dir list passed on command line (with -L). */
79static const char **search_dirs;
80static int search_dirs_len;
81
82/* Local function declarations. */
83static void addarg (const char *);
84static int is_regular_file (char *);
85static char *to_host_file_spec (char *);
86static char *locate_lib (char *);
87static const char *expand_lib (char *);
88static void preprocess_args (int, char **);
89static void process_args (int, char **);
90static void maybe_set_link_compat (void);
91static int set_exe (const char *);
92#ifdef VMS
93static int translate_unix (char *, int);
94#endif
95\f
96
97/* Append STR to the command line to invoke the linker.
98 Expand the line as necessary to accommodate. */
99
100static void
101addarg (const char *str)
102{
103 int l = strlen (str);
104
105 /* Extend the line. */
106 if (link_cmd_len + l >= link_cmd_maxlen)
107 {
108 link_cmd_maxlen = link_cmd_len + l + 1024;
109 link_cmd = XRESIZEVEC (char, link_cmd, link_cmd_maxlen);
110 }
111
112 memcpy (link_cmd + link_cmd_len, str, l);
113 link_cmd_len += l;
114}
115
116/* Check to see if NAME is a regular file, i.e. not a directory. */
117
118static int
119is_regular_file (char *name)
120{
121 int ret;
122 struct stat statbuf;
123
124 ret = stat (name, &statbuf);
125 return !ret && S_ISREG (statbuf.st_mode);
126}
127
128#ifdef VMS
129static char new_host_filespec [255];
130static char filename_buff [256];
131
132/* Action routine called by decc$to_vms. NAME is a file name or
133 directory name. TYPE is unused. */
134
135static int
136translate_unix (char *name, int type ATTRIBUTE_UNUSED)
137{
138 strcpy (filename_buff, name);
139 return 0;
140}
141#endif
142
143/* Translate a Unix syntax file specification FILESPEC into VMS syntax.
144 If indicators of VMS syntax found, return input string.
145 Return a pointer to a static buffer. */
146
147static char *
148to_host_file_spec (char *filespec)
149{
150#ifdef VMS
151 if (strchr (filespec, ']') || strchr (filespec, ':'))
152 {
153 /* Looks like a VMS path. */
154 return filespec;
155 }
156 else
157 {
158
159 strcpy (filename_buff, filespec);
160 decc$to_vms (filespec, translate_unix, 1, 1);
161 strcpy (new_host_filespec, filename_buff);
162 return new_host_filespec;
163 }
164#else
165 return filespec;
166#endif
167}
168
169/* Locate library LIB_NAME on the library path. */
170
171static char *
172locate_lib (char *lib_name)
173{
174 int lib_len = strlen (lib_name);
175 const char *exts[3];
176 int i;
177
178 if (staticp)
179 {
180 /* For static links, look for shareable image libraries last. */
181 exts[0] = ".a";
182 exts[1] = ".olb";
183 exts[2] = ".exe";
184 }
185 else
186 {
187 exts[0] = ".exe";
188 exts[1] = ".a";
189 exts[2] = ".olb";
190 }
191
192 for (i = 0; i < search_dirs_len; i++)
193 {
194 char *buf;
195 int l;
196 int j;
197
198 l = strlen (search_dirs[i]);
199 buf = (char *)alloca (l + 4 + lib_len + 4 + 1);
200 /* Put PATH/libLIB. */
201 memcpy (buf, search_dirs[i], l);
202 memcpy (buf + l, "/lib", 4);
203 l += 4;
204 memcpy (buf + l, lib_name, lib_len);
205 l += lib_len;
206
207 /* Look for files with the extensions. */
208 for (j = 0; j < 3; j++)
209 {
210 strcpy (buf + l, exts[j]);
211 if (is_regular_file (buf))
212 return xstrdup (to_host_file_spec (buf));
213 }
214 }
215
216 return NULL;
217}
218
219/* Given a library name NAME, i.e. foo, Look for libfoo.lib and then
220 libfoo.a in the set of directories we are allowed to search in.
221 May return NULL if the library can be discarded. */
222
223static const char *
224expand_lib (char *name)
225{
226 char *lib_path;
227
228 /* Discard libc. */
229 if (strcmp (name, "c") == 0)
230 return NULL;
231
232 /* Discard libm. No separate library for math functions. */
233 if (strcmp (name, "m") == 0)
234 return NULL;
235
236 /* Search on path. */
237 lib_path = locate_lib (name);
238 if (lib_path)
239 return lib_path;
240
241 fprintf (stderr,
242 "Couldn't locate library: lib%s.exe, lib%s.a or lib%s.olb\n",
243 name, name, name);
244
245 exit (EXIT_FAILURE);
246}
247
248/* Preprocess the number of args P_ARGC in ARGV.
249 Look for special flags, etc. that must be handled first. */
250
251static void
252preprocess_args (int argc, char **argv)
253{
254 int i;
255
256 /* Scan for -shared. */
257 for (i = 1; i < argc; i++)
258 if (strcmp (argv[i], "-shared") == 0)
259 {
260 share = 1;
261 break;
262 }
263
264 for (i = 1; i < argc; i++)
265 if (strcmp (argv[i], "-o") == 0)
266 {
267 int len;
268
269 i++;
270 exefilename = lbasename (argv[i]);
271 exefullfilename = xstrdup (to_host_file_spec (argv[i]));
272
273 if (share)
274 addarg(" /share=");
275 else
276 addarg (" /exe=");
277 addarg (exefullfilename);
278
279 if (share)
280 {
281 char *ptr;
282
283 /* Extract the basename. */
284 ptr = strchr (argv[i], ']');
285 if (ptr == NULL)
286 ptr = strchr (argv[i], ':');
287 if (ptr == NULL)
288 ptr = strchr (argv[i], '/');
289 if (ptr == NULL)
290 sharebasename = xstrdup (argv[i]);
291 else
292 sharebasename = xstrdup (ptr + 1);
293
294 len = strlen (sharebasename);
295 if (strncasecmp (&sharebasename[len-4], ".exe", 4) == 0)
296 sharebasename[len - 4] = 0;
297
298 /* Convert to uppercase. */
299 for (ptr = sharebasename; *ptr; ptr++)
300 *ptr = TOUPPER (*ptr);
301 }
302 }
303
304 if (exefullfilename == NULL && !share)
305 {
306 exefilename = "a_out.exe";
307 exefullfilename = "a_out.exe";
308 addarg (xstrdup (" /exe=a_out.exe"));
309 }
310}
311
312/* Preprocess the number of args ARGC in ARGV. Look for
313 special flags, etc. that must be handled for the VMS linker. */
314
315static void
316process_args (int argc, char **argv)
317{
318 int i;
319
320 for (i = 1; i < argc; i++)
321 {
322 if (strncmp (argv[i], "-L", 2) == 0)
323 {
324 search_dirs = XRESIZEVEC(const char *, search_dirs,
325 search_dirs_len + 1);
326 search_dirs[search_dirs_len++] = &argv[i][2];
327 }
328
329 /* -v turns on verbose option here and is passed on to gcc. */
330 else if (strcmp (argv[i], "-v") == 0)
331 verbose++;
332 else if (strcmp (argv[i], "--version") == 0)
333 {
334 fprintf (stdout, "VMS Linker\n");
335 exit (EXIT_SUCCESS);
336 }
337 else if (strcmp (argv[i], "--help") == 0)
338 {
339 fprintf (stdout, "VMS Linker\n");
340 exit (EXIT_SUCCESS);
341 }
342 else if (strcmp (argv[i], "-g0") == 0)
343 addarg ("/notraceback");
344 else if (strncmp (argv[i], "-g", 2) == 0)
345 {
346 addarg ("/debug");
347 debug = 1;
348 }
349 else if (strcmp (argv[i], "-static") == 0)
350 staticp = 1;
351 else if (strcmp (argv[i], "-map") == 0)
352 {
353 char *buff, *ptr;
354
355 buff = (char *) xstrdup (exefullfilename);
356 ptr = strrchr (buff, '.');
357 if (ptr)
358 *ptr = 0;
359
360 strcat (buff, ".map");
361 addarg ("/map=");
362 addarg (buff);
363 addarg (".map");
364 addarg ("/full");
365
366 free (buff);
367 }
368 else if (strcmp (argv[i], "-save-temps") == 0)
369 save_temps = 1;
370 else if (strcmp (argv[i], "--noinhibit-exec") == 0)
371 inhibit_exec = 0;
372 }
373}
374
375#ifdef VMS
376typedef struct dsc
377{
378 unsigned short len, mbz;
379 const char *adr;
380} Descriptor;
381
382struct lst
383{
384 unsigned short buflen, item_code;
385 const void *bufaddr;
386 void *retlenaddr;
387};
388
389static struct
390{
391 struct lst items [1];
392 unsigned int terminator;
393} item_lst1;
394
395static struct
396{
397 struct lst items [2];
398 unsigned int terminator;
399} item_lst2;
400
401/* Checks if logical names are defined for setting system library path and
402 linker program to enable compatibility with earlier VMS versions. */
403
404static void
405maybe_set_link_compat (void)
406{
407 char lnm_buff [LNM_C_NAMLENGTH];
408 unsigned int lnm_buff_len;
409 int status;
410 Descriptor tabledsc, linkdsc;
411
412 tabledsc.adr = "LNM$JOB";
413 tabledsc.len = strlen (tabledsc.adr);
414 tabledsc.mbz = 0;
415
416 linkdsc.adr = "GCC_LD_SYS$LIBRARY";
417 linkdsc.len = strlen (linkdsc.adr);
418 linkdsc.mbz = 0;
419
420 item_lst1.items[0].buflen = LNM_C_NAMLENGTH;
421 item_lst1.items[0].item_code = LNM__STRING;
422 item_lst1.items[0].bufaddr = lnm_buff;
423 item_lst1.items[0].retlenaddr = &lnm_buff_len;
424 item_lst1.terminator = 0;
425
426 status = SYS$TRNLNM
427 (0, /* attr */
428 &tabledsc, /* tabnam */
429 &linkdsc, /* lognam */
430 0, /* acmode */
431 &item_lst1);
432
433 /* If GCC_LD_SYS$LIBRARY is defined, redefine SYS$LIBRARY to search
434 the equivalence name first for system libraries, then the default
435 system library directory */
436
437 if ((status & 1) == 1)
438 {
439 unsigned char acmode = PSL_C_USER; /* Don't retain after image exit */
440 const char *syslib = "SYS$SYSROOT:[SYSLIB]"; /* Default SYS$LIBRARY */
441
442 /* Only visible to current and child processes */
443 tabledsc.adr = "LNM$PROCESS";
444 tabledsc.len = strlen (tabledsc.adr);
445 tabledsc.mbz = 0;
446
447 linkdsc.adr = "SYS$LIBRARY";
448 linkdsc.len = strlen (linkdsc.adr);
449 linkdsc.mbz = 0;
450
451 item_lst2.items[0].buflen = lnm_buff_len;
452 item_lst2.items[0].item_code = LNM__STRING;
453 item_lst2.items[0].bufaddr = lnm_buff;
454 item_lst2.items[0].retlenaddr = 0;
455
456 item_lst2.items[1].buflen = strlen (syslib);
457 item_lst2.items[1].item_code = LNM__STRING;
458 item_lst2.items[1].bufaddr = syslib;
459 item_lst2.items[1].retlenaddr = 0;
460 item_lst2.terminator = 0;
461
462 status = SYS$CRELNM
463 (0, /* attr */
464 &tabledsc, /* tabnam */
465 &linkdsc, /* lognam */
466 &acmode, /* acmode */
467 &item_lst2);
468
469 }
470
471 tabledsc.adr = "LNM$JOB";
472 tabledsc.len = strlen (tabledsc.adr);
473 tabledsc.mbz = 0;
474
475 linkdsc.adr = "GCC_LD_LINK";
476 linkdsc.len = strlen (linkdsc.adr);
477 linkdsc.mbz = 0;
478
479 item_lst1.items[0].buflen = LNM_C_NAMLENGTH;
480 item_lst1.items[0].item_code = LNM__STRING;
481 item_lst1.items[0].bufaddr = lnm_buff;
482 item_lst1.items[0].retlenaddr = &lnm_buff_len;
483 item_lst1.terminator = 0;
484
485 status = SYS$TRNLNM
486 (0, /* attr */
487 &tabledsc, /* tabnam */
488 &linkdsc, /* lognam */
489 0, /* acmode */
490 &item_lst1);
491
492 /* If GCC_LD_LINK is defined, redefine LINK to use the equivalence name
493 (sometimes the LINK program version is used by VMS to determine
494 compatibility). */
495
496 if ((status & 1) == 1)
497 {
498 unsigned char acmode = PSL_C_USER; /* Don't retain after image exit. */
499
500 /* Only visible to current and child processes. */
501 tabledsc.adr = "LNM$PROCESS";
502 tabledsc.len = strlen (tabledsc.adr);
503 tabledsc.mbz = 0;
504
505 linkdsc.adr = "LINK";
506 linkdsc.len = strlen (linkdsc.adr);
507 linkdsc.mbz = 0;
508
509 item_lst1.items[0].buflen = lnm_buff_len;
510 item_lst1.items[0].item_code = LNM__STRING;
511 item_lst1.items[0].bufaddr = lnm_buff;
512 item_lst1.items[0].retlenaddr = 0;
513 item_lst1.terminator = 0;
514
515 status = SYS$CRELNM
516 (0, /* attr */
517 &tabledsc, /* tabnam */
518 &linkdsc, /* lognam */
519 &acmode, /* acmode */
520 &item_lst1);
521 }
522}
523#else
524static void
525maybe_set_link_compat (void)
526{
527}
528#endif
529
530/* Set environment defined executable attributes. */
531
532static int
533set_exe (const char *arg)
534{
535 char allargs [1024];
536 int res;
537
538 snprintf (allargs, sizeof (allargs),
539 "$@gnu:[bin]set_exe %s %s", exefullfilename, arg);
540 if (verbose)
541 printf ("%s\n", allargs);
542
543 res = system (allargs);
544 if (verbose > 1)
545 printf ("$!status = %d\n", res);
546
547 if ((res & 1) != 1)
548 {
549 fprintf (stderr, "ld error: popen set_exe\n");
550 return 1;
551 }
552 return 0;
553}
554
555/* The main program. Spawn the VMS linker after fixing up the Unix-like flags
556 and args to be what the VMS linker wants. */
557
558int
559main (int argc, char **argv)
560{
561 /* File specification for vms-dwarf2.o. */
562 char *vmsdwarf2spec = 0;
563
564 /* File specification for vms-dwarf2eh.o. */
565 char *vmsdwarf2ehspec = 0;
566
567 int i;
568 char cwdev[128], *devptr;
569 int cwdevlen;
570 FILE *optfile;
571 char *cwd, *ptr;
572 char *optfilename;
573 int status = 0;
574
575 /* Some linker options can be set with logicals. */
576 if (getenv ("GNAT$LD_NOCALL_DEBUG"))
577 ld_nocall_debug = 1;
578 if (getenv ("GNAT$LD_MKTHREADS"))
579 ld_mkthreads = 1;
580 if (getenv ("GNAT$LD_UPCALLS"))
581 ld_upcalls = 1;
582 if (getenv ("GNAT$LD_SHARED_LIBS"))
583 staticp = 0;
584
585 /* Get current dir. */
586#ifdef VMS
587 cwd = getcwd (0, 1024, 1);
588#else
589 cwd = getcwd (0, 1024);
590 strcat (cwd, "/");
591#endif
592
593 /* Extract device part of the path. */
594 devptr = strchr (cwd, ':');
595 if (devptr)
596 cwdevlen = (devptr - cwd) + 1;
597 else
598 cwdevlen = 0;
599 memcpy (cwdev, cwd, cwdevlen);
600 cwdev [cwdevlen] = '\0';
601
602 maybe_set_link_compat ();
603
604 /* Linker command starts with the command name. */
605 addarg ("$ link");
606
607 /* Pass to find args that have to be append first. */
608 preprocess_args (argc , argv);
609
610 /* Pass to find the rest of the args. */
611 process_args (argc , argv);
612
613 if (!verbose)
614 addarg ("/noinform");
615
616 /* Create a temp file to hold args, otherwise we can easily exceed the VMS
617 command line length limits. */
618 optfilename = (char *) xmalloc (strlen (exefilename) + 13);
619 strcpy (optfilename, exefilename);
620 ptr = strrchr (optfilename, '.');
621 if (ptr)
622 *ptr = 0;
623 strcat (optfilename, ".opt_tmpfile");
624 optfile = fopen (optfilename, "w");
625
626 /* Write out the IDENTIFICATION argument first so that it can be overridden
627 by an options file. */
628 for (i = 1; i < argc; i++)
629 {
630 int arg_len = strlen (argv[i]);
631
632 if (arg_len > 6 && strncasecmp (argv[i], "IDENT=", 6) == 0)
633 {
634 /* Comes from command line. If present will always appear before
635 --identification=... and will override. */
636 break;
637 }
638 else if (arg_len > 17
639 && strncasecmp (argv[i], "--identification=", 17) == 0)
640 {
641 /* Comes from pragma Ident (). */
642 fprintf (optfile, "case_sensitive=yes\n");
c2885517 643 fprintf (optfile, "IDENTIFICATION=\"%-.15s\"\n", &argv[i][17]);
18a24fed
TG
644 fprintf (optfile, "case_sensitive=NO\n");
645 }
646 }
647
648 for (i = 1; i < argc; i++)
649 {
650 int arg_len = strlen (argv[i]);
651
652 if (strcmp (argv[i], "-o") == 0)
653 {
654 /* Already handled. */
655 i++;
656 }
657 else if (arg_len > 2 && strncmp (argv[i], "-l", 2) == 0)
658 {
659 const char *libname;
660
661 libname = expand_lib (&argv[i][2]);
662 if (libname != NULL)
663 {
664 int len = strlen (libname);
665 const char *ext;
666
667 if (len > 4 && strcasecmp (&libname [len-4], ".exe") == 0)
668 ext = "/shareable";
669 else
670 ext = "/library";
671
672 if (libname[0] == '[')
673 fprintf (optfile, "%s%s%s\n", cwdev, libname, ext);
674 else
675 fprintf (optfile, "%s%s\n", libname, ext);
676 }
677 }
678 else if (strcmp (argv[i], "-v" ) == 0
679 || strncmp (argv[i], "-g", 2 ) == 0
680 || strcmp (argv[i], "-static" ) == 0
681 || strcmp (argv[i], "-map" ) == 0
682 || strcmp (argv[i], "-save-temps") == 0
683 || strcmp (argv[i], "--noinhibit-exec") == 0
684 || (arg_len > 2 && strncmp (argv[i], "-L", 2) == 0)
685 || (arg_len >= 6 && strncmp (argv[i], "-share", 6) == 0))
686 {
687 /* Already handled. */
688 }
689 else if (strncmp (argv[i], "--opt=", 6) == 0)
690 fprintf (optfile, "%s\n", argv[i] + 6);
691 else if (arg_len > 1 && argv[i][0] == '@')
692 {
693 /* Read response file (in fact a single line of filenames). */
694 FILE *atfile;
695 char *ptr, *ptr1;
696 struct stat statbuf;
697 char *buff;
698 int len;
699
700 if (stat (&argv[i][1], &statbuf))
701 {
702 fprintf (stderr, "Couldn't open linker response file: %s\n",
703 &argv[i][1]);
704 exit (EXIT_FAILURE);
705 }
706
707 /* Read the line. */
708 buff = (char *) xmalloc (statbuf.st_size + 1);
709 atfile = fopen (&argv[i][1], "r");
710 fgets (buff, statbuf.st_size + 1, atfile);
711 fclose (atfile);
712
713 /* Remove trailing \n. */
714 len = strlen (buff);
715 if (buff [len - 1] == '\n')
716 {
717 buff [len - 1] = 0;
718 len--;
719 }
720
721 /* Put the filenames to the opt file. */
722 ptr = buff;
723 do
724 {
725 ptr1 = strchr (ptr, ' ');
726 if (ptr1)
727 *ptr1 = 0;
728
729 /* Add device name if a path is present. */
730 ptr = to_host_file_spec (ptr);
731 if (ptr[0] == '[')
732 fprintf (optfile, "%s%s\n", cwdev, ptr);
733 else
734 fprintf (optfile, "%s\n", ptr);
735
736 ptr = ptr1 + 1;
737 }
738 while (ptr1);
739 }
740 else if ((argv[i][0] == '/') && (strchr (&argv[i][1], '/') == 0))
741 {
742 /* Unix style file specs and VMS style switches look alike,
743 so assume an arg consisting of one and only one slash,
744 and that being first, is really a switch. */
745 addarg (argv[i]);
746 }
747 else if (arg_len > 4
748 && strncasecmp (&argv[i][arg_len-4], ".opt", 4) == 0)
749 {
750 /* Read option file. */
751 FILE *optfile1;
752 char buff[256];
753
754 /* Disable __UNIX_FOPEN redefinition in case user supplied .opt
755 file is not stream oriented. */
756
757 optfile1 = (fopen) (argv[i], "r");
758 if (optfile1 == 0)
759 {
760 perror (argv[i]);
761 status = 1;
762 goto cleanup_and_exit;
763 }
764
765 while (fgets (buff, sizeof (buff), optfile1))
766 fputs (buff, optfile);
767
768 fclose (optfile1);
769 }
770 else if (arg_len > 7 && strncasecmp (argv[i], "GSMATCH", 7) == 0)
771 fprintf (optfile, "%s\n", argv[i]);
772 else if (arg_len > 6 && strncasecmp (argv[i], "IDENT=", 6) == 0)
773 {
774 /* Comes from command line and will override pragma. */
775 fprintf (optfile, "case_sensitive=yes\n");
776 fprintf (optfile, "IDENT=\"%15.15s\"\n", &argv[i][6]);
777 fprintf (optfile, "case_sensitive=NO\n");
778 }
779 else if (arg_len > 17
780 && strncasecmp (argv[i], "--identification=", 17) == 0)
781 {
782 /* Already handled. */
783 }
784 else
785 {
786 /* Assume filename arg. */
787 const char *file;
788 const char *addswitch = NULL;
789 char *buff;
790 int buff_len;
791 int is_cld = 0;
792
793 file = to_host_file_spec (argv[i]);
794 arg_len = strlen (file);
795
796 /* Handle shareable image libraries. */
797 if (arg_len > 4 && strcasecmp (&file[arg_len - 4], ".exe") == 0)
798 addswitch = "/shareable";
799 else if (arg_len > 4 && strcasecmp (&file[arg_len - 4], ".cld") == 0)
800 {
801 addswitch = "/shareable";
802 is_cld = 1;
803 }
804
805 /* Handle object libraries. */
806 else if (arg_len > 2 && strcasecmp (&file[arg_len - 2], ".a") == 0)
807 addswitch = "/lib";
808 else if (arg_len > 4 && strcasecmp (&file[arg_len - 4], ".olb") == 0)
809 addswitch = "/lib";
810
811 /* Absolutize file location. */
812 if (file[0] == '[')
813 {
814 buff = (char *) xmalloc (cwdevlen + arg_len + 1);
815 sprintf (buff, "%s%s", cwdev, file);
816 }
817 else if (strchr (file, ':'))
818 {
819 buff = xstrdup (file);
820 }
821 else
822 {
823 buff = (char *) xmalloc (strlen (cwd) + arg_len + 1);
824 sprintf (buff, "%s%s", cwd, file);
825 }
826
827 buff_len = strlen (buff);
828
829 if (buff_len >= 15
830 && strcasecmp (&buff[buff_len - 14], "vms-dwarf2eh.o") == 0)
831 {
832 /* Remind of it. */
833 vmsdwarf2ehspec = xstrdup (buff);
834 }
835 else if (buff_len >= 13
836 && strcasecmp (&buff[buff_len - 12], "vms-dwarf2.o") == 0)
837 {
838 /* Remind of it. */
839 vmsdwarf2spec = xstrdup (buff);
840 }
841 else if (is_cld)
842 {
843 /* Command line definition file. */
844 addarg (buff);
845 addarg (addswitch);
846 addarg (",");
847 }
848 else
849 {
850 fprintf (optfile, "%s%s\n",
851 buff, addswitch != NULL ? addswitch : "");
852 }
853 free (buff);
854 }
855 }
856
857 if (vmsdwarf2ehspec)
858 {
859 /* Sequentialize exception handling info. */
860
861 fprintf (optfile, "case_sensitive=yes\n");
862 fprintf (optfile, "cluster=DWARF2eh,,,%s\n", vmsdwarf2ehspec);
863 fprintf (optfile, "collect=DWARF2eh,eh_frame\n");
864 fprintf (optfile, "case_sensitive=NO\n");
865 }
866
867 if (debug && vmsdwarf2spec)
868 {
869 /* Sequentialize the debug info. */
870
871 fprintf (optfile, "case_sensitive=yes\n");
872 fprintf (optfile, "cluster=DWARF2debug,,,%s\n", vmsdwarf2spec);
873 fprintf (optfile, "collect=DWARF2debug,debug_abbrev,debug_aranges,-\n");
874 fprintf (optfile, " debug_frame,debug_info,debug_line,debug_loc,-\n");
875 fprintf (optfile, " debug_macinfo,debug_pubnames,debug_str,-\n");
876 fprintf (optfile, " debug_zzzzzz\n");
877 fprintf (optfile, "case_sensitive=NO\n");
878 }
879
880 if (debug && share && vmsdwarf2spec)
881 {
882 /* Sequentialize the shared library debug info. */
883
884 fprintf (optfile, "case_sensitive=yes\n");
885 fprintf (optfile, "symbol_vector=(-\n");
886 fprintf (optfile,
887 "%s$DWARF2.DEBUG_ABBREV/$dwarf2.debug_abbrev=DATA,-\n",
888 sharebasename);
889 fprintf (optfile,
890 "%s$DWARF2.DEBUG_ARANGES/$dwarf2.debug_aranges=DATA,-\n",
891 sharebasename);
892 fprintf (optfile, "%s$DWARF2.DEBUG_FRAME/$dwarf2.debug_frame=DATA,-\n",
893 sharebasename);
894 fprintf (optfile, "%s$DWARF2.DEBUG_INFO/$dwarf2.debug_info=DATA,-\n",
895 sharebasename);
896 fprintf (optfile, "%s$DWARF2.DEBUG_LINE/$dwarf2.debug_line=DATA,-\n",
897 sharebasename);
898 fprintf (optfile, "%s$DWARF2.DEBUG_LOC/$dwarf2.debug_loc=DATA,-\n",
899 sharebasename);
900 fprintf (optfile,
901 "%s$DWARF2.DEBUG_MACINFO/$dwarf2.debug_macinfo=DATA,-\n",
902 sharebasename);
903 fprintf (optfile,
904 "%s$DWARF2.DEBUG_PUBNAMES/$dwarf2.debug_pubnames=DATA,-\n",
905 sharebasename);
906 fprintf (optfile, "%s$DWARF2.DEBUG_STR/$dwarf2.debug_str=DATA,-\n",
907 sharebasename);
908 fprintf (optfile, "%s$DWARF2.DEBUG_ZZZZZZ/$dwarf2.debug_zzzzzz=DATA)\n",
909 sharebasename);
910 fprintf (optfile, "case_sensitive=NO\n");
911 }
912
913 fprintf (optfile, "PSECT_ATTR=LIB$INITIALIZE,GBL\n");
914 fclose (optfile);
915
916 /* Append opt file. */
917 addarg (" ");
918 addarg (optfilename);
919 addarg ("/opt");
920
921 if (verbose)
922 printf ("%s\n", link_cmd);
923
924 status = system (link_cmd);
925 if (verbose > 1)
926 printf ("$!status = %d\n", status);
927
928 if ((status & 1) != 1)
929 {
930 status = 1;
931 goto cleanup_and_exit;
932 }
933
934 if (debug && !share && ld_nocall_debug)
935 {
936 status = set_exe ("/flags=nocall_debug");
937 if (status != 0)
938 goto cleanup_and_exit;
939 }
940
941 if (!share && ld_mkthreads)
942 {
943 status = set_exe ("/flags=mkthreads");
944 if (status != 0)
945 goto cleanup_and_exit;
946 }
947
948 if (!share && ld_upcalls)
949 {
950 status = set_exe ("/flags=upcalls");
951 if (status != 0)
952 goto cleanup_and_exit;
953 }
954
955 status = 0;
956
957 cleanup_and_exit:
958 if (!save_temps)
959 remove (optfilename);
960
961 if (status == 0)
962 exit (EXIT_SUCCESS);
963
964 if (exefullfilename && inhibit_exec == 1)
965 remove (exefullfilename);
966
967 exit (EXIT_FAILURE);
968}