#include #include #include #include #include #include #include extern char *optarg; extern int optind, opterr, optopt; static struct option long_options[] = { {"verbose", no_argument, 0, 'V'}, {"help", no_argument, 0, 'h'}, {"print-info", no_argument, 0, 'p'}, {"list-needed-libs", no_argument, 0, 'n'}, {"lookup", required_argument, 0, 'L'}, {0, 0, 0, 0}, }; /* This array must parallel long_options[] */ static const char *descriptions[] = { "print verbose output", "print help screen", "for each file, generate a listing of all dependencies that each symbol " "satisfies", "print out a list of needed libraries", "provide a directory for library lookup" }; void print_help(void) { fprintf(stdout, "invokation:\n" "\tlsd file1 [file2 file3 ... fileN] [-Ldir1 -Ldir2 ... -LdirN] " "[-Vpn]\n" "or\n" "\tlsd -h\n\n"); fprintf(stdout, "options:\n"); struct option *opt = long_options; const char **desc = descriptions; while (opt->name) { fprintf(stdout, "\t-%c\n" "\t--%-15s: %s\n", opt->val, opt->name, *desc); opt++; desc++; } } int get_options(int argc, char **argv, int *list_needed_libs, int *info, char ***dirs, int *num_dirs, int *verbose) { int c; ASSERT(list_needed_libs); *list_needed_libs = 0; ASSERT(info); *info = 0; ASSERT(verbose); *verbose = 0; ASSERT(dirs); *dirs = NULL; ASSERT(num_dirs); int size = 0; *num_dirs = 0; while (1) { /* getopt_long stores the option index here. */ int option_index = 0; c = getopt_long (argc, argv, "VhpnL:", 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 'h': print_help(); exit(1); break; case 'V': *verbose = 1; break; case 'p': *info = 1; break; case 'n': *list_needed_libs = 1; break; case 'L': { if (*num_dirs == size) { size += 10; *dirs = (char **)REALLOC(*dirs, size * sizeof(char *)); } SET_STRING_OPTION(((*dirs) + *num_dirs)); (*num_dirs)++; } break; case '?': /* getopt_long already printed an error message. */ break; #undef SET_STRING_OPTION default: FAILIF(1, "Unknown option"); } } return optind; }