]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - usr.bin/pr/egetopt.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / usr.bin / pr / egetopt.c
1 /*-
2  * Copyright (c) 1991 Keith Muller.
3  * Copyright (c) 1993
4  *      The Regents of the University of California.  All rights reserved.
5  *
6  * This code is derived from software contributed to Berkeley by
7  * Keith Muller of the University of California, San Diego.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *      This product includes software developed by the University of
20  *      California, Berkeley and its contributors.
21  * 4. Neither the name of the University nor the names of its contributors
22  *    may be used to endorse or promote products derived from this software
23  *    without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  */
37
38 #if 0
39 #ifndef lint
40 static char sccsid[] = "@(#)egetopt.c   8.1 (Berkeley) 6/6/93";
41 #endif /* not lint */
42 #endif
43
44 #include <sys/cdefs.h>
45 __FBSDID("$FreeBSD$");
46
47 #include <ctype.h>
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51
52 #include "extern.h"
53
54 /*
55  * egetopt:     get option letter from argument vector (an extended
56  *              version of getopt).
57  *
58  * Non standard additions to the ostr specs are:
59  * 1) '?': immediate value following arg is optional (no white space
60  *    between the arg and the value)
61  * 2) '#': +/- followed by a number (with an optional sign but
62  *    no white space between the arg and the number). The - may be
63  *    combined with other options, but the + cannot.
64  */
65
66 int     eopterr = 1;            /* if error message should be printed */
67 int     eoptind = 1;            /* index into parent argv vector */
68 int     eoptopt;                /* character checked for validity */
69 char    *eoptarg;               /* argument associated with option */
70
71 #define BADCH   (int)'?'
72
73 static char     emsg[] = "";
74
75 int
76 egetopt(int nargc, char * const *nargv, const char *ostr)
77 {
78         static char *place = emsg;      /* option letter processing */
79         char *oli;                      /* option letter list index */
80         static int delim;               /* which option delimeter */
81         char *p;
82         static char savec = '\0';
83
84         if (savec != '\0') {
85                 *place = savec;
86                 savec = '\0';
87         }
88
89         if (!*place) {
90                 /*
91                  * update scanning pointer
92                  */
93                 if ((eoptind >= nargc) ||
94                     ((*(place = nargv[eoptind]) != '-') && (*place != '+'))) {
95                         place = emsg;
96                         return (-1);
97                 }
98
99                 delim = (int)*place;
100                 if (place[1] && *++place == '-' && !place[1]) {
101                         /*
102                          * found "--"
103                          */
104                         ++eoptind;
105                         place = emsg;
106                         return (-1);
107                 }
108         }
109
110         /*
111          * check option letter
112          */
113         if ((eoptopt = (int)*place++) == (int)':' || (eoptopt == (int)'?') ||
114             !(oli = strchr(ostr, eoptopt))) {
115                 /*
116                  * if the user didn't specify '-' as an option,
117                  * assume it means -1 when by itself.
118                  */
119                 if ((eoptopt == (int)'-') && !*place)
120                         return (-1);
121                 if (strchr(ostr, '#') && (isdigit(eoptopt) ||
122                     (((eoptopt == (int)'-') || (eoptopt == (int)'+')) &&
123                       isdigit(*place)))) {
124                         /*
125                          * # option: +/- with a number is ok
126                          */
127                         for (p = place; *p != '\0'; ++p) {
128                                 if (!isdigit(*p))
129                                         break;
130                         }
131                         eoptarg = place-1;
132
133                         if (*p == '\0') {
134                                 place = emsg;
135                                 ++eoptind;
136                         } else {
137                                 place = p;
138                                 savec = *p;
139                                 *place = '\0';
140                         }
141                         return (delim);
142                 }
143
144                 if (!*place)
145                         ++eoptind;
146                 if (eopterr) {
147                         if (!(p = strrchr(*nargv, '/')))
148                                 p = *nargv;
149                         else
150                                 ++p;
151                         (void)fprintf(stderr, "%s: illegal option -- %c\n",
152                             p, eoptopt);
153                 }
154                 return (BADCH);
155         }
156         if (delim == (int)'+') {
157                 /*
158                  * '+' is only allowed with numbers
159                  */
160                 if (!*place)
161                         ++eoptind;
162                 if (eopterr) {
163                         if (!(p = strrchr(*nargv, '/')))
164                                 p = *nargv;
165                         else
166                                 ++p;
167                         (void)fprintf(stderr,
168                                 "%s: illegal '+' delimiter with option -- %c\n",
169                                 p, eoptopt);
170                 }
171                 return (BADCH);
172         }
173         ++oli;
174         if ((*oli != ':') && (*oli != '?')) {
175                 /*
176                  * don't need argument
177                  */
178                 eoptarg = NULL;
179                 if (!*place)
180                         ++eoptind;
181                 return (eoptopt);
182         }
183
184         if (*place) {
185                 /*
186                  * no white space
187                  */
188                 eoptarg = place;
189         } else if (*oli == '?') {
190                 /*
191                  * no arg, but NOT required
192                  */
193                 eoptarg = NULL;
194         } else if (nargc <= ++eoptind) {
195                 /*
196                  * no arg, but IS required
197                  */
198                 place = emsg;
199                 if (eopterr) {
200                         if (!(p = strrchr(*nargv, '/')))
201                                 p = *nargv;
202                         else
203                                 ++p;
204                         (void)fprintf(stderr,
205                             "%s: option requires an argument -- %c\n", p,
206                             eoptopt);
207                 }
208                 return (BADCH);
209         } else {
210                 /*
211                  * arg has white space
212                  */
213                 eoptarg = nargv[eoptind];
214         }
215         place = emsg;
216         ++eoptind;
217         return (eoptopt);
218 }