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 {"verbose", no_argument, 0, 'V'}, 14 {"help", no_argument, 0, 'h'}, 15 {"print-info", no_argument, 0, 'p'}, 16 {"list-needed-libs", no_argument, 0, 'n'}, 17 {"lookup", required_argument, 0, 'L'}, 18 {0, 0, 0, 0}, 19 }; 20 21 /* This array must parallel long_options[] */ 22 static const char *descriptions[] = { 23 "print verbose output", 24 "print help screen", 25 "for each file, generate a listing of all dependencies that each symbol " 26 "satisfies", 27 "print out a list of needed libraries", 28 "provide a directory for library lookup" 29 }; 30 31 void print_help(void) 32 { 33 fprintf(stdout, 34 "invokation:\n" 35 "\tlsd file1 [file2 file3 ... fileN] [-Ldir1 -Ldir2 ... -LdirN] " 36 "[-Vpn]\n" 37 "or\n" 38 "\tlsd -h\n\n"); 39 fprintf(stdout, "options:\n"); 40 struct option *opt = long_options; 41 const char **desc = descriptions; 42 while (opt->name) { 43 fprintf(stdout, "\t-%c\n" 44 "\t--%-15s: %s\n", 45 opt->val, 46 opt->name, 47 *desc); 48 opt++; 49 desc++; 50 } 51 } 52 53 int get_options(int argc, char **argv, 54 int *list_needed_libs, 55 int *info, 56 char ***dirs, 57 int *num_dirs, 58 int *verbose) 59 { 60 int c; 61 62 ASSERT(list_needed_libs); 63 *list_needed_libs = 0; 64 ASSERT(info); 65 *info = 0; 66 ASSERT(verbose); 67 *verbose = 0; 68 ASSERT(dirs); 69 *dirs = NULL; 70 ASSERT(num_dirs); 71 int size = 0; 72 *num_dirs = 0; 73 74 while (1) { 75 /* getopt_long stores the option index here. */ 76 int option_index = 0; 77 78 c = getopt_long (argc, argv, 79 "VhpnL:", 80 long_options, 81 &option_index); 82 /* Detect the end of the options. */ 83 if (c == -1) break; 84 85 if (isgraph(c)) { 86 INFO ("option -%c with value `%s'\n", c, (optarg ?: "(null)")); 87 } 88 89 #define SET_STRING_OPTION(name) do { \ 90 ASSERT(optarg); \ 91 (*name) = strdup(optarg); \ 92 } while(0) 93 94 switch (c) { 95 case 0: 96 /* If this option set a flag, do nothing else now. */ 97 if (long_options[option_index].flag != 0) 98 break; 99 INFO ("option %s", long_options[option_index].name); 100 if (optarg) 101 INFO (" with arg %s", optarg); 102 INFO ("\n"); 103 break; 104 case 'h': print_help(); exit(1); break; 105 case 'V': *verbose = 1; break; 106 case 'p': *info = 1; break; 107 case 'n': *list_needed_libs = 1; break; 108 case 'L': 109 { 110 if (*num_dirs == size) { 111 size += 10; 112 *dirs = (char **)REALLOC(*dirs, size * sizeof(char *)); 113 } 114 SET_STRING_OPTION(((*dirs) + *num_dirs)); 115 (*num_dirs)++; 116 } 117 break; 118 case '?': 119 /* getopt_long already printed an error message. */ 120 break; 121 122 #undef SET_STRING_OPTION 123 124 default: 125 FAILIF(1, "Unknown option"); 126 } 127 } 128 129 return optind; 130 } 131