summaryrefslogtreecommitdiffstats
path: root/tools/soslim/cmdline.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/soslim/cmdline.c')
-rw-r--r--tools/soslim/cmdline.c141
1 files changed, 141 insertions, 0 deletions
diff --git a/tools/soslim/cmdline.c b/tools/soslim/cmdline.c
new file mode 100644
index 0000000..c2d5e71
--- /dev/null
+++ b/tools/soslim/cmdline.c
@@ -0,0 +1,141 @@
+#include <debug.h>
+#include <cmdline.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <string.h>
+#include <ctype.h>
+
+extern char *optarg;
+extern int optind, opterr, optopt;
+
+static struct option long_options[] =
+{
+ {"verbose", no_argument, 0, 'V'},
+ {"quiet", no_argument, 0, 'Q'},
+ {"shady", no_argument, 0, 'S'},
+ {"print", no_argument, 0, 'p'},
+ {"help", no_argument, 0, 'h'},
+ {"outfile", required_argument, 0, 'o'},
+ {"filter", required_argument, 0, 'f'},
+ {"dry", no_argument, 0, 'n'},
+ {"strip", no_argument, 0, 's'},
+ {0, 0, 0, 0},
+};
+
+/* This array must parallel long_options[] */
+static
+const char *descriptions[sizeof(long_options)/sizeof(long_options[0])] = {
+ "print verbose output",
+ "suppress errors and warnings",
+ "patch ABS symbols whose values coincide with section starts and ends",
+ "print the symbol table (if specified, only -V is allowed)",
+ "this help screen",
+ "specify an output file (if not provided, input file is modified)",
+ "specify a symbol-filter file",
+ "dry run (perform all calculations but do not modify the ELF file)",
+ "strip debug sections, if they are present"
+};
+
+void print_help(void)
+{
+ fprintf(stdout,
+ "invokation:\n"
+ "\tsoslim file1 [file2 file3 ... fileN] [-Ldir1 -Ldir2 ... -LdirN] "
+ "[-Vpn]\n"
+ "or\n"
+ "\tsoslim -h\n\n");
+ fprintf(stdout, "options:\n");
+ struct option *opt = long_options;
+ const char **desc = descriptions;
+ while (opt->name) {
+ fprintf(stdout, "\t-%c/--%-15s %s\n",
+ opt->val,
+ opt->name,
+ *desc);
+ opt++;
+ desc++;
+ }
+}
+
+int get_options(int argc, char **argv,
+ char **outfile,
+ char **symsfile,
+ int *print_symtab,
+ int *verbose,
+ int *quiet,
+ int *shady,
+ int *dry_run,
+ int *strip_debug)
+{
+ int c;
+
+ ASSERT(outfile);
+ *outfile = NULL;
+ ASSERT(symsfile);
+ *symsfile = NULL;
+ ASSERT(print_symtab);
+ *print_symtab = 0;
+ ASSERT(verbose);
+ *verbose = 0;
+ ASSERT(quiet);
+ *quiet = 0;
+ ASSERT(shady);
+ *shady = 0;
+ ASSERT(dry_run);
+ *dry_run = 0;
+ ASSERT(strip_debug);
+ *strip_debug = 0;
+
+ while (1) {
+ /* getopt_long stores the option index here. */
+ int option_index = 0;
+
+ c = getopt_long (argc, argv,
+ "QVSphi:o:y:Y:f:ns",
+ long_options,
+ &option_index);
+ /* Detect the end of the options. */
+ if (c == -1) break;
+
+ if (isgraph(c)) {
+ INFO ("option -%c with value `%s'\n", c, (optarg ?: "(null)"));
+ }
+
+#define SET_STRING_OPTION(name) do { \
+ ASSERT(optarg); \
+ *name = strdup(optarg); \
+} while(0)
+
+ switch (c) {
+ case 0:
+ /* If this option set a flag, do nothing else now. */
+ if (long_options[option_index].flag != 0)
+ break;
+ INFO ("option %s", long_options[option_index].name);
+ if (optarg)
+ INFO (" with arg %s", optarg);
+ INFO ("\n");
+ break;
+ case 'p': *print_symtab = 1; break;
+ case 'h': print_help(); exit(1); break;
+ case 'V': *verbose = 1; break;
+ case 'Q': *quiet = 1; break;
+ case 'S': *shady = 1; break;
+ case 'n': *dry_run = 1; break;
+ case 's': *strip_debug = 1; break;
+ case 'o': SET_STRING_OPTION(outfile); break;
+ case 'f': SET_STRING_OPTION(symsfile); break;
+ case '?':
+ /* getopt_long already printed an error message. */
+ break;
+
+#undef SET_STRING_OPTION
+
+ default:
+ FAILIF(1, "Unknown option");
+ }
+ }
+
+ return optind;
+}