1 /* 2 Author: Marcus Boerger <helly (at) users.sourceforge.net> 3 */ 4 5 #include <stdio.h> 6 #include <string.h> 7 #include <assert.h> 8 #include <stdlib.h> 9 #include "mbo_getopt.h" 10 #define OPTERRCOLON (1) 11 #define OPTERRNF (2) 12 #define OPTERRARG (3) 13 14 static int mbo_opt_error(int argc, char * const *argv, int oint, int optchr, int err, int show_err) 15 { 16 if (show_err) 17 { 18 fprintf(stderr, "Error in argument %d, char %d: ", oint, optchr + 1); 19 20 switch (err) 21 { 22 23 case OPTERRCOLON: 24 fprintf(stderr, ": in flags\n"); 25 break; 26 27 case OPTERRNF: 28 fprintf(stderr, "option not found %c\n", argv[oint][optchr]); 29 break; 30 31 case OPTERRARG: 32 fprintf(stderr, "no argument for option %c\n", argv[oint][optchr]); 33 break; 34 35 default: 36 fprintf(stderr, "unknown\n"); 37 break; 38 } 39 } 40 41 return ('?'); 42 } 43 44 int mbo_getopt(int argc, char* const *argv, const mbo_opt_struct opts[], char **optarg, int *optind, int show_err) 45 { 46 static int optchr = 0; 47 static int dash = 0; /* have already seen the - */ 48 int arg_start = 2; 49 50 int opts_idx = -1; 51 52 if (*optind >= argc) 53 { 54 return (EOF); 55 } 56 57 if (!dash) 58 { 59 if ((argv[*optind][0] != '-')) 60 { 61 return (EOF); 62 } 63 else 64 { 65 if (!argv[*optind][1]) 66 { 67 /* 68 * use to specify stdin. Need to let pgm process this and 69 * the following args 70 */ 71 return (EOF); 72 } 73 } 74 } 75 76 if ((argv[*optind][0] == '-') && (argv[*optind][1] == '-')) 77 { 78 /* '--' indicates end of args if not followed by a known long option name */ 79 80 while (1) 81 { 82 opts_idx++; 83 84 if (opts[opts_idx].opt_char == '-') 85 { 86 (*optind)++; 87 return (EOF); 88 } 89 else if (opts[opts_idx].opt_name && !strcmp(&argv[*optind][2], opts[opts_idx].opt_name)) 90 { 91 break; 92 } 93 } 94 95 optchr = 0; 96 dash = 1; 97 arg_start = 2 + strlen(opts[opts_idx].opt_name); 98 } 99 100 if (!dash) 101 { 102 dash = 1; 103 optchr = 1; 104 } 105 106 /* Check if the guy tries to do a -: kind of flag */ 107 if (argv[*optind][optchr] == ':') 108 { 109 dash = 0; 110 (*optind)++; 111 return (mbo_opt_error(argc, argv, *optind - 1, optchr, OPTERRCOLON, show_err)); 112 } 113 114 if (opts_idx < 0) 115 { 116 while (1) 117 { 118 opts_idx++; 119 120 if (opts[opts_idx].opt_char == '-') 121 { 122 int errind = *optind; 123 int errchr = optchr; 124 125 if (!argv[*optind][optchr + 1]) 126 { 127 dash = 0; 128 (*optind)++; 129 } 130 else 131 { 132 optchr++; 133 } 134 135 return (mbo_opt_error(argc, argv, errind, errchr, OPTERRNF, show_err)); 136 } 137 else if (argv[*optind][optchr] == opts[opts_idx].opt_char) 138 { 139 break; 140 } 141 } 142 } 143 144 if (opts[opts_idx].need_param) 145 { 146 /* Check for cases where the value of the argument 147 is in the form -<arg> <val> or in the form -<arg><val> */ 148 dash = 0; 149 150 if (!argv[*optind][arg_start]) 151 { 152 (*optind)++; 153 154 if (*optind == argc) 155 { 156 return (mbo_opt_error(argc, argv, *optind - 1, optchr, OPTERRARG, show_err)); 157 } 158 159 *optarg = argv[(*optind)++]; 160 } 161 else 162 { 163 *optarg = &argv[*optind][arg_start]; 164 (*optind)++; 165 } 166 167 return opts[opts_idx].opt_char; 168 } 169 else 170 { 171 if (arg_start == 2) 172 { 173 if (!argv[*optind][optchr + 1]) 174 { 175 dash = 0; 176 (*optind)++; 177 } 178 else 179 { 180 optchr++; 181 } 182 } 183 else 184 { 185 (*optind)++; 186 } 187 188 return opts[opts_idx].opt_char; 189 } 190 191 assert(0); 192 return (0); /* never reached */ 193 } 194 195