/* Parse options for the GNU linker.
- Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 98, 99, 2000
+ Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 98, 99, 2000, 2001
Free Software Foundation, Inc.
This file is part of GLD, the Gnu Linker.
#define OPTION_FINI (OPTION_INIT + 1)
#define OPTION_SECTION_START (OPTION_FINI + 1)
#define OPTION_UNIQUE (OPTION_SECTION_START + 1)
+#define OPTION_TARGET_HELP (OPTION_UNIQUE + 1)
+#define OPTION_ALLOW_SHLIB_UNDEFINED (OPTION_TARGET_HELP + 1)
/* The long options. This structure is used for both the option
parsing and the help text. */
-struct ld_option {
+struct ld_option
+{
/* The long option information. */
struct option opt;
/* The short option with the same meaning ('\0' if none). */
ONE_DASH,
/* Use two dashes before long option name. */
TWO_DASHES,
+ /* Only accept two dashes before the long option name.
+ This is an overloading of the use of this enum, since originally it
+ was only intended to tell the --help display function how to display
+ the long option name. This feature was added in order to resolve
+ the confusion about the -omagic command line switch. Is it setting
+ the output file name to "magic" or is it setting the NMAGIC flag on
+ the output ? It has been decided that it is setting the output file
+ name, and that if you want to set the NMAGIC flag you should use -N
+ or --omagic. */
+ EXACTLY_TWO_DASHES,
/* Don't mention this option in --help output. */
NO_HELP
} control;
};
-static const struct ld_option ld_options[] = {
+static const struct ld_option ld_options[] =
+{
{ {NULL, required_argument, NULL, '\0'},
'a', N_("KEYWORD"), N_("Shared library control for HP/UX compatibility"),
ONE_DASH },
'n', NULL, N_("Do not page align data"), TWO_DASHES },
{ {"omagic", no_argument, NULL, 'N'},
'N', NULL, N_("Do not page align data, do not make text readonly"),
- TWO_DASHES },
+ EXACTLY_TWO_DASHES },
{ {"output", required_argument, NULL, 'o'},
- 'o', N_("FILE"), N_("Set output file name"), TWO_DASHES },
+ 'o', N_("FILE"), N_("Set output file name"), EXACTLY_TWO_DASHES },
{ {NULL, required_argument, NULL, '\0'},
'O', NULL, N_("Optimize output file"), ONE_DASH },
{ {"Qy", no_argument, NULL, OPTION_IGNORE},
'T', N_("FILE"), N_("Read linker script"), TWO_DASHES },
{ {"undefined", required_argument, NULL, 'u'},
'u', N_("SYMBOL"), N_("Start with undefined reference to SYMBOL"), TWO_DASHES },
- { {"unique", no_argument, NULL, OPTION_UNIQUE},
- '\0', NULL, N_("Don't merge orphan sections with the same name"), TWO_DASHES },
+ { {"unique", optional_argument, NULL, OPTION_UNIQUE},
+ '\0', N_("[=SECTION]"), N_("Don't merge input [SECTION | orphan] sections"), TWO_DASHES },
{ {"Ur", no_argument, NULL, OPTION_UR},
'\0', NULL, N_("Build global constructor/destructor tables"), ONE_DASH },
{ {"version", no_argument, NULL, OPTION_VERSION},
'\0', NULL, N_("Use less memory and more disk I/O"), TWO_DASHES },
{ {"no-undefined", no_argument, NULL, OPTION_NO_UNDEFINED},
'\0', NULL, N_("Allow no undefined symbols"), TWO_DASHES },
+ { {"allow-shlib-undefined", no_argument, NULL, OPTION_ALLOW_SHLIB_UNDEFINED},
+ '\0', NULL, N_("Allow undefined symbols in shared objects"), TWO_DASHES },
{ {"no-warn-mismatch", no_argument, NULL, OPTION_NO_WARN_MISMATCH},
'\0', NULL, N_("Don't warn about mismatched input files"), TWO_DASHES},
{ {"no-whole-archive", no_argument, NULL, OPTION_NO_WHOLE_ARCHIVE},
{ {"noinhibit_exec", no_argument, NULL, OPTION_NOINHIBIT_EXEC},
'\0', NULL, NULL, NO_HELP },
{ {"oformat", required_argument, NULL, OPTION_OFORMAT},
- '\0', N_("TARGET"), N_("Specify target of output file"), TWO_DASHES },
+ '\0', N_("TARGET"), N_("Specify target of output file"), EXACTLY_TWO_DASHES },
{ {"qmagic", no_argument, NULL, OPTION_IGNORE},
'\0', NULL, N_("Ignored for Linux compatibility"), ONE_DASH },
{ {"relax", no_argument, NULL, OPTION_RELAX},
'\0', N_("[=COUNT]"), N_("Split output sections every COUNT relocs"), TWO_DASHES },
{ {"stats", no_argument, NULL, OPTION_STATS},
'\0', NULL, N_("Print memory usage statistics"), TWO_DASHES },
+ { {"target-help", no_argument, NULL, OPTION_TARGET_HELP},
+ '\0', NULL, N_("Display target specific options"), TWO_DASHES },
{ {"task-link", required_argument, NULL, OPTION_TASK_LINK},
'\0', N_("SYMBOL"), N_("Do task level linking"), TWO_DASHES },
{ {"traditional-format", no_argument, NULL, OPTION_TRADITIONAL_FORMAT},
'\0', N_("[=WORDS]"), N_("Modify problematic branches in last WORDS (1-10,\n\t\t\t\tdefault 5) words of a page"), TWO_DASHES }
};
-#define OPTION_COUNT ((int) (sizeof ld_options / sizeof ld_options[0]))
+#define OPTION_COUNT ARRAY_SIZE (ld_options)
/* Test STRING for containing a string of digits that form a number
between MIN and MAX. The return value is the number or ERR. */
void
parse_args (argc, argv)
- int argc;
+ unsigned argc;
char **argv;
{
- int i, is, il;
+ unsigned i;
+ int is, il, irl;
int ingroup = 0;
char *default_dirlist = NULL;
char shortopts[OPTION_COUNT * 3 + 2];
struct option longopts[OPTION_COUNT + 1];
+ struct option really_longopts[OPTION_COUNT + 1];
int last_optind;
/* Starting the short option string with '-' is for programs that
shortopts[0] = '-';
is = 1;
il = 0;
+ irl = 0;
for (i = 0; i < OPTION_COUNT; i++)
{
if (ld_options[i].shortopt != '\0')
}
if (ld_options[i].opt.name != NULL)
{
- longopts[il] = ld_options[i].opt;
- ++il;
+ if (ld_options[i].control == EXACTLY_TWO_DASHES)
+ {
+ really_longopts[irl] = ld_options[i].opt;
+ ++irl;
+ }
+ else
+ {
+ longopts[il] = ld_options[i].opt;
+ ++il;
+ }
}
}
shortopts[is] = '\0';
longopts[il].name = NULL;
+ really_longopts[irl].name = NULL;
/* The -G option is ambiguous on different platforms. Sometimes it
specifies the largest data size to put into the small data
/* getopt_long_only is like getopt_long, but '-' as well as '--'
can indicate a long option. */
+ opterr = 0;
optc = getopt_long_only (argc, argv, shortopts, longopts, &longind);
+ if (optc == '?')
+ {
+ --optind;
+ optc = getopt_long (argc, argv, shortopts, really_longopts, &longind);
+ }
if (optc == -1)
break;
+
switch (optc)
{
+ case '?':
+ fprintf (stderr, _("%s: unrecognized option '%s'\n"),
+ program_name, argv[optind - 1]);
default:
fprintf (stderr,
_("%s: use the --help option for usage information\n"),
case OPTION_NO_UNDEFINED:
link_info.no_undefined = true;
break;
+ case OPTION_ALLOW_SHLIB_UNDEFINED:
+ link_info.allow_shlib_undefined = true;
+ break;
case OPTION_NO_WARN_MISMATCH:
command_line.warn_mismatch = false;
break;
set_section_start (sec_name, optarg2);
}
break;
+ case OPTION_TARGET_HELP:
+ /* Mention any target specific options. */
+ ldemul_list_emulation_options (stdout);
+ exit (0);
case OPTION_TBSS:
set_section_start (".bss", optarg);
break;
ldlang_add_undef (optarg);
break;
case OPTION_UNIQUE:
- config.unique_orphan_sections = true;
+ if (optarg != NULL)
+ lang_add_unique (optarg);
+ else
+ config.unique_orphan_sections = true;
break;
case OPTION_VERBOSE:
ldversion (1);
case OPTION_VERSION:
/* This output is intended to follow the GNU standards document. */
printf ("GNU ld %s\n", ld_program_version);
- printf (_("Copyright 2000 Free Software Foundation, Inc.\n"));
+ printf (_("Copyright 2001 Free Software Foundation, Inc.\n"));
printf (_("\
This program is free software; you may redistribute it under the terms of\n\
the GNU General Public License. This program has absolutely no warranty.\n"));
static void
help ()
{
- int i;
+ unsigned i;
const char **targets, **pp;
printf (_("Usage: %s [options] file...\n"), program_name);
{
boolean comma;
int len;
- int j;
+ unsigned j;
printf (" ");
if (ld_options[j].opt.name != NULL
&& ld_options[j].control != NO_HELP)
{
+ int two_dashes =
+ (ld_options[j].control == TWO_DASHES
+ || ld_options[j].control == EXACTLY_TWO_DASHES);
+
printf ("%s-%s%s",
comma ? ", " : "",
- ld_options[j].control == TWO_DASHES ? "-" : "",
+ two_dashes ? "-" : "",
ld_options[j].opt.name);
len += ((comma ? 2 : 0)
+ 1
- + (ld_options[j].control == TWO_DASHES ? 1 : 0)
+ + (two_dashes ? 1 : 0)
+ strlen (ld_options[j].opt.name));
if (ld_options[j].arg != NULL)
{