root/src/jlog/getopt_long.c

Revision cc981f5c55100675865b6960135d70148d8585af, 5.9 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 3 years ago)

pull in jlog @ 52

  • Property mode set to 100644
Line 
1 /*
2  * Copyright (c) 2005-2008, Message Systems, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  *    * Redistributions of source code must retain the above copyright
10  *      notice, this list of conditions and the following disclaimer.
11  *    * Redistributions in binary form must reproduce the above
12  *      copyright notice, this list of conditions and the following
13  *      disclaimer in the documentation and/or other materials provided
14  *      with the distribution.
15  *    * Neither the name Message Systems, Inc. nor the names
16  *      of its contributors may be used to endorse or promote products
17  *      derived from this software without specific prior written
18  *      permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 #include "jlog_config.h"
34 #include "getopt_long.h"
35 #include <stdarg.h>
36 #include <stdio.h>
37
38 int optind = 1;
39 int opterr = 1;
40 char *optarg = NULL;
41
42 static void ec_error_func(const char *msg, ...) {
43   va_list arg;
44   va_start(arg, msg);
45   vfprintf(stderr, msg, arg);
46   va_end(arg);
47 }
48
49 getopt_error_func opterrfunc = ec_error_func;
50
51 static int _getopt_long(int my_argc,
52                 char * const *my_argv,
53                 const char *optstring,
54                 const struct option *longopts,
55                 int *longindex)
56 {
57   const char *cur = NULL;
58   const char *cur_longopt = NULL;
59   int cur_longopt_len;
60   char *argument = NULL;
61   int i;
62
63   cur = my_argv[optind];
64   cur_longopt = cur + 2;
65  
66   optind++;
67   /* check for options that have an embedded '=' in them */
68   if((argument = strchr(cur_longopt, '=')) != NULL) {
69     cur_longopt_len = argument - cur_longopt;
70     argument++;
71   } else {
72     cur_longopt_len = strlen(cur_longopt);
73   }
74   for(i = 0; longopts[i].name; i++) {
75     if(strlen(longopts[i].name) == cur_longopt_len &&
76        !strncmp(longopts[i].name, cur_longopt, cur_longopt_len))
77     {
78       switch(longopts[i].has_arg) {
79         case no_argument:
80           if(argument) {
81             /* error */
82             opterrfunc("argument --%.*s requires no arguments\n", cur_longopt_len, cur_longopt);
83             return GETOPT_INVALID_OPTION;
84           }
85           /* no break, we fall through */
86           break;
87         case required_argument:
88           optarg = argument?argument:my_argv[optind];
89           if(!optarg) {
90             /* error */
91             opterrfunc("argument %s requires an argument\n", cur);
92             return GETOPT_INVALID_OPTION;
93           }
94           if(!argument) optind++;
95           break;
96         case optional_argument:
97           optarg = argument;
98           break;
99       }
100       if(longindex) *longindex = i;
101       if(longopts[i].flag) {
102         *longopts[i].flag = longopts[i].val;
103         return 0;
104       } else {
105         return longopts[i].val;
106       }
107     }
108   }
109   /* we can only reach here if we have an unknown option */
110   opterrfunc("unknown long option %s\n", cur);
111   return GETOPT_INVALID_OPTION;
112 }
113
114 static int _getopt(int my_argc, char * const *my_argv, const char *optstring)
115 {
116   const char *cur;
117   char *optstring_off;
118   char cur_shortopt;
119
120   cur = my_argv[optind];
121   /* search simple option texts */
122   cur_shortopt = cur[1];
123   if(cur_shortopt == GETOPT_MISSING_OPTION ||
124      cur_shortopt == GETOPT_INVALID_OPTION ||
125      (optstring_off = strchr(optstring, cur_shortopt)) == NULL)
126   {
127     /* error case, none found */
128     opterrfunc("unknown option: %c\n", cur_shortopt);
129     return GETOPT_INVALID_OPTION;
130   }
131   optind++;
132   if(optstring_off[1] == ':') {
133     /* takes an option */
134     if(cur[2]) {
135       /* argument is concatenated with the option */
136       optarg = (char *) cur + 2;
137     } else {
138       if(optind >= my_argc) {
139         /* end of args */
140         opterrfunc("option %c requires an argument\n", cur_shortopt);
141         return GETOPT_INVALID_OPTION;
142       }
143       optarg = my_argv[optind];
144       optind++;
145     }
146   } else {
147     if(cur[2]) {
148       /* we have a concatenated argument, but our parameter takes no args */
149       opterrfunc("option %c does not take an argument\n", cur_shortopt);
150       return GETOPT_INVALID_OPTION;
151     }
152     /* does not take an option */
153   }
154   return cur_shortopt;
155 }
156
157 int getopt_long(int my_argc,
158                 char * const *my_argv,
159                 const char *optstring,
160                 const struct option *longopts,
161                 int *longindex)
162 {
163   const char *cur;
164
165   if(optind >= my_argc) {
166     /* end of args */
167     return -1;
168   }
169   cur = my_argv[optind];
170   if(cur[0] != '-' || (cur[1] == '-' && cur[2] == '\0')) {
171     /* end of args */
172     /* need to handle POSIXLY_CORRECT case */
173     return -1;
174   }
175   if(cur[1] == '-') {
176     /* this is a long option, dispatch appropriately */
177     return _getopt_long(my_argc, my_argv, optstring, longopts, longindex);
178   } else {
179     /* short opt */
180     return _getopt(my_argc, my_argv, optstring);
181   }
182 }
183
184 #if defined(_WIN32)
185 int getopt(int my_argc, char * const *my_argv, const char *optstring)
186 {
187   const char *cur;
188
189   if(optind >= my_argc) {
190     /* end of args */
191     return -1;
192   }
193   cur = my_argv[optind];
194   if(cur[0] != '-' || (cur[1] == '-' && cur[2] == '\0')) {
195     /* end of args */
196     /* need to handle POSIXLY_CORRECT case */
197     return -1;
198   }
199   return _getopt(my_argc, my_argv, optstring);
200 }
201 #endif
Note: See TracBrowser for help on using the browser.