Home | History | Annotate | Download | only in apriori
      1 #include <debug.h>
      2 #include <cmdline.h>
      3 #include <stdio.h>
      4 #include <stdlib.h>
      5 #include <getopt.h>
      6 #include <string.h>
      7 #include <ctype.h>
      8 
      9 extern char *optarg;
     10 extern int optind, opterr, optopt;
     11 
     12 static struct option long_options[] = {
     13     {"start-address", required_argument, 0, 's'},
     14     {"inc-address",   required_argument, 0, 'i'},
     15     {"locals-only",   no_argument,       0, 'l'},
     16     {"quiet",         no_argument,       0, 'Q'},
     17     {"noupdate",      no_argument,       0, 'n'},
     18     {"lookup",        required_argument, 0, 'L'},
     19     {"default",       required_argument, 0, 'D'},
     20     {"verbose",       no_argument,       0, 'V'},
     21     {"help",          no_argument,       0, 'h'},
     22 	{"mapfile",       required_argument, 0, 'M'},
     23 	{"output",        required_argument, 0, 'o'},
     24     {"prelinkmap",    required_argument, 0, 'p'},
     25     {0, 0, 0, 0},
     26 };
     27 
     28 /* This array must parallel long_options[] */
     29 static const char *descriptions[] = {
     30     "start address to prelink libraries to",
     31     "address increment for each library",
     32     "prelink local relocations only",
     33     "suppress informational and non-fatal error messages",
     34     "do a dry run--calculate the prelink info but do not update any files",
     35     "provide a directory for library lookup",
     36     "provide a default library or executable for symbol lookup",
     37     "print verbose output",
     38     "print help screen",
     39 	"print a list of prelink addresses to file (prefix filename with + to append instead of overwrite)",
     40     "specify an output directory (if multiple inputs) or file (is single input)",
     41     "specify a file with prelink addresses instead of a --start-address/--inc-address combination",
     42 };
     43 
     44 void print_help(const char *name) {
     45     fprintf(stdout,
     46             "invokation:\n"
     47             "\t%s file1 [file2 file3 ...] -Ldir1 [-Ldir2 ...] -saddr -iinc [-Vqn] [-M<logfile>]\n"
     48             "\t%s -l file [-Vqn] [-M<logfile>]\n"
     49             "\t%s -h\n\n", name, name, name);
     50     fprintf(stdout, "options:\n");
     51     struct option *opt = long_options;
     52     const char **desc = descriptions;
     53     while (opt->name) {
     54         fprintf(stdout, "\t-%c/--%s%s: %s\n",
     55                 opt->val,
     56                 opt->name,
     57                 (opt->has_arg ? " (argument)" : ""),
     58                 *desc);
     59         opt++;
     60         desc++;
     61     }
     62 }
     63 
     64 int get_options(int argc, char **argv,
     65                 int *start_addr,
     66                 int *inc_addr,
     67                 int *locals_only,
     68                 int *quiet,
     69                 int *dry_run,
     70                 char ***dirs,
     71                 int *num_dirs,
     72                 char ***defaults,
     73                 int *num_defaults,
     74                 int *verbose,
     75 				char **mapfile,
     76                 char **output,
     77                 char **prelinkmap) {
     78     int c;
     79 
     80     ASSERT(dry_run); *dry_run = 0;
     81     ASSERT(quiet); *quiet = 0;
     82     ASSERT(verbose); *verbose = 0;
     83     ASSERT(dirs); *dirs = NULL;
     84     ASSERT(num_dirs); *num_dirs = 0;
     85     ASSERT(defaults); *defaults = NULL;
     86     ASSERT(num_defaults); *num_defaults = 0;
     87     ASSERT(start_addr); *start_addr = -1;
     88     ASSERT(inc_addr); *inc_addr =   -1;
     89     ASSERT(locals_only); *locals_only = 0;
     90 	ASSERT(mapfile); *mapfile = NULL;
     91 	ASSERT(output); *output = NULL;
     92     ASSERT(prelinkmap); *prelinkmap = NULL;
     93     int dirs_size = 0;
     94     int defaults_size = 0;
     95 
     96     while (1) {
     97         /* getopt_long stores the option index here. */
     98         int option_index = 0;
     99 
    100         c = getopt_long (argc, argv,
    101                          "VhnQlL:D:s:i:M:o:p:",
    102                          long_options,
    103                          &option_index);
    104         /* Detect the end of the options. */
    105         if (c == -1) break;
    106 
    107         if (isgraph(c)) {
    108             INFO ("option -%c with value `%s'\n", c, (optarg ?: "(null)"));
    109         }
    110 
    111 #define SET_STRING_OPTION(name) do {                                   \
    112     ASSERT(optarg);                                                    \
    113     (*name) = strdup(optarg);                                          \
    114 } while(0)
    115 
    116 #define SET_REPEATED_STRING_OPTION(arr, num, size) do {                \
    117 	if (*num == size) {                                                \
    118 		size += 10;                                                    \
    119 		*arr = (char **)REALLOC(*arr, size * sizeof(char *));          \
    120 	}                                                                  \
    121 	SET_STRING_OPTION(((*arr) + *num));                                \
    122 	(*num)++;                                                          \
    123 } while(0)
    124 
    125 #define SET_INT_OPTION(val) do {                                       \
    126     ASSERT(optarg);                                                    \
    127 	if (strlen(optarg) >= 2 && optarg[0] == '0' && optarg[1] == 'x') { \
    128 			FAILIF(1 != sscanf(optarg+2, "%x", val),                   \
    129 				   "Expecting a hexadecimal argument!\n");             \
    130 	} else {                                                           \
    131 		FAILIF(1 != sscanf(optarg, "%d", val),                         \
    132 			   "Expecting a decimal argument!\n");                     \
    133 	}                                                                  \
    134 } while(0)
    135 
    136         switch (c) {
    137         case 0:
    138             /* If this option set a flag, do nothing else now. */
    139             if (long_options[option_index].flag != 0)
    140                 break;
    141             INFO ("option %s", long_options[option_index].name);
    142             if (optarg)
    143                 INFO (" with arg %s", optarg);
    144             INFO ("\n");
    145             break;
    146         case 'Q': *quiet = 1; break;
    147 		case 'n': *dry_run = 1; break;
    148 		case 'M':
    149 			SET_STRING_OPTION(mapfile);
    150 			break;
    151 		case 'o':
    152 			SET_STRING_OPTION(output);
    153 			break;
    154         case 'p':
    155             SET_STRING_OPTION(prelinkmap);
    156             break;
    157         case 's':
    158             SET_INT_OPTION(start_addr);
    159             break;
    160         case 'i':
    161             SET_INT_OPTION(inc_addr);
    162             break;
    163         case 'L':
    164             SET_REPEATED_STRING_OPTION(dirs, num_dirs, dirs_size);
    165             break;
    166         case 'D':
    167             SET_REPEATED_STRING_OPTION(defaults, num_defaults, defaults_size);
    168             break;
    169         case 'l': *locals_only = 1; break;
    170         case 'h': print_help(argv[0]); exit(1); break;
    171         case 'V': *verbose = 1; break;
    172         case '?':
    173             /* getopt_long already printed an error message. */
    174             break;
    175 
    176 #undef SET_STRING_OPTION
    177 #undef SET_REPEATED_STRING_OPTION
    178 #undef SET_INT_OPTION
    179 
    180         default:
    181             FAILIF(1, "Unknown option");
    182         }
    183     }
    184 
    185     return optind;
    186 }
    187