1/* VMS linker wrapper. 2 Copyright (C) 2011-2015 Free Software Foundation, Inc. 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 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"); 643 fprintf (optfile, "IDENTIFICATION=\"%-.15s\"\n", &argv[i][17]); 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} 969