summaryrefslogtreecommitdiffstats
path: root/tools/apriori/cmdline.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/apriori/cmdline.c')
-rw-r--r--tools/apriori/cmdline.c186
1 files changed, 186 insertions, 0 deletions
diff --git a/tools/apriori/cmdline.c b/tools/apriori/cmdline.c
new file mode 100644
index 0000000..95f112a
--- /dev/null
+++ b/tools/apriori/cmdline.c
@@ -0,0 +1,186 @@
+#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[] = {
+ {"start-address", required_argument, 0, 's'},
+ {"inc-address", required_argument, 0, 'i'},
+ {"locals-only", no_argument, 0, 'l'},
+ {"quiet", no_argument, 0, 'Q'},
+ {"noupdate", no_argument, 0, 'n'},
+ {"lookup", required_argument, 0, 'L'},
+ {"default", required_argument, 0, 'D'},
+ {"verbose", no_argument, 0, 'V'},
+ {"help", no_argument, 0, 'h'},
+ {"mapfile", required_argument, 0, 'M'},
+ {"output", required_argument, 0, 'o'},
+ {"prelinkmap", required_argument, 0, 'p'},
+ {0, 0, 0, 0},
+};
+
+/* This array must parallel long_options[] */
+static const char *descriptions[] = {
+ "start address to prelink libraries to",
+ "address increment for each library",
+ "prelink local relocations only",
+ "suppress informational and non-fatal error messages",
+ "do a dry run--calculate the prelink info but do not update any files",
+ "provide a directory for library lookup",
+ "provide a default library or executable for symbol lookup",
+ "print verbose output",
+ "print help screen",
+ "print a list of prelink addresses to file (prefix filename with + to append instead of overwrite)",
+ "specify an output directory (if multiple inputs) or file (is single input)",
+ "specify a file with prelink addresses instead of a --start-address/--inc-address combination",
+};
+
+void print_help(const char *name) {
+ fprintf(stdout,
+ "invokation:\n"
+ "\t%s file1 [file2 file3 ...] -Ldir1 [-Ldir2 ...] -saddr -iinc [-Vqn] [-M<logfile>]\n"
+ "\t%s -l file [-Vqn] [-M<logfile>]\n"
+ "\t%s -h\n\n", name, name, name);
+ fprintf(stdout, "options:\n");
+ struct option *opt = long_options;
+ const char **desc = descriptions;
+ while (opt->name) {
+ fprintf(stdout, "\t-%c/--%s%s: %s\n",
+ opt->val,
+ opt->name,
+ (opt->has_arg ? " (argument)" : ""),
+ *desc);
+ opt++;
+ desc++;
+ }
+}
+
+int get_options(int argc, char **argv,
+ int *start_addr,
+ int *inc_addr,
+ int *locals_only,
+ int *quiet,
+ int *dry_run,
+ char ***dirs,
+ int *num_dirs,
+ char ***defaults,
+ int *num_defaults,
+ int *verbose,
+ char **mapfile,
+ char **output,
+ char **prelinkmap) {
+ int c;
+
+ ASSERT(dry_run); *dry_run = 0;
+ ASSERT(quiet); *quiet = 0;
+ ASSERT(verbose); *verbose = 0;
+ ASSERT(dirs); *dirs = NULL;
+ ASSERT(num_dirs); *num_dirs = 0;
+ ASSERT(defaults); *defaults = NULL;
+ ASSERT(num_defaults); *num_defaults = 0;
+ ASSERT(start_addr); *start_addr = -1;
+ ASSERT(inc_addr); *inc_addr = -1;
+ ASSERT(locals_only); *locals_only = 0;
+ ASSERT(mapfile); *mapfile = NULL;
+ ASSERT(output); *output = NULL;
+ ASSERT(prelinkmap); *prelinkmap = NULL;
+ int dirs_size = 0;
+ int defaults_size = 0;
+
+ while (1) {
+ /* getopt_long stores the option index here. */
+ int option_index = 0;
+
+ c = getopt_long (argc, argv,
+ "VhnQlL:D:s:i:M:o:p:",
+ 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)
+
+#define SET_REPEATED_STRING_OPTION(arr, num, size) do { \
+ if (*num == size) { \
+ size += 10; \
+ *arr = (char **)REALLOC(*arr, size * sizeof(char *)); \
+ } \
+ SET_STRING_OPTION(((*arr) + *num)); \
+ (*num)++; \
+} while(0)
+
+#define SET_INT_OPTION(val) do { \
+ ASSERT(optarg); \
+ if (strlen(optarg) >= 2 && optarg[0] == '0' && optarg[1] == 'x') { \
+ FAILIF(1 != sscanf(optarg+2, "%x", val), \
+ "Expecting a hexadecimal argument!\n"); \
+ } else { \
+ FAILIF(1 != sscanf(optarg, "%d", val), \
+ "Expecting a decimal argument!\n"); \
+ } \
+} 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 'Q': *quiet = 1; break;
+ case 'n': *dry_run = 1; break;
+ case 'M':
+ SET_STRING_OPTION(mapfile);
+ break;
+ case 'o':
+ SET_STRING_OPTION(output);
+ break;
+ case 'p':
+ SET_STRING_OPTION(prelinkmap);
+ break;
+ case 's':
+ SET_INT_OPTION(start_addr);
+ break;
+ case 'i':
+ SET_INT_OPTION(inc_addr);
+ break;
+ case 'L':
+ SET_REPEATED_STRING_OPTION(dirs, num_dirs, dirs_size);
+ break;
+ case 'D':
+ SET_REPEATED_STRING_OPTION(defaults, num_defaults, defaults_size);
+ break;
+ case 'l': *locals_only = 1; break;
+ case 'h': print_help(argv[0]); exit(1); break;
+ case 'V': *verbose = 1; break;
+ case '?':
+ /* getopt_long already printed an error message. */
+ break;
+
+#undef SET_STRING_OPTION
+#undef SET_REPEATED_STRING_OPTION
+#undef SET_INT_OPTION
+
+ default:
+ FAILIF(1, "Unknown option");
+ }
+ }
+
+ return optind;
+}