• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  Author: Marcus Boerger <helly@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 
mbo_opt_error(int argc,char * const * argv,int oint,int optchr,int err,int show_err)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 
mbo_getopt(int argc,char * const * argv,const mbo_opt_struct opts[],char ** optarg,int * optind,int show_err)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