Imported from ../bash-1.14.7.tar.gz.
[platform/upstream/bash.git] / builtins / bashgetopt.c
1 /* bashgetopt.c -- `getopt' for use by the builtins. */
2
3 /* Copyright (C) 1992 Free Software Foundation, Inc.
4
5 This file is part of GNU Bash, the Bourne Again SHell.
6
7 Bash is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 1, or (at your option) any later
10 version.
11
12 Bash is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License along
18 with Bash; see the file COPYING.  If not, write to the Free Software
19 Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20
21 #include <errno.h>
22 #include "shell.h"
23
24 #include "bashansi.h"
25
26 #define ERR(S, C)       builtin_error("%s%c", (S), (C))
27
28 static int      sp;
29
30 char    *list_optarg;
31 int     list_optopt;
32
33 static WORD_LIST *lhead = (WORD_LIST *)NULL;
34 WORD_LIST       *lcurrent = (WORD_LIST *)NULL;
35 WORD_LIST       *loptend;       /* Points to the first non-option argument in the list */
36
37 int
38 internal_getopt(list, opts)
39 WORD_LIST       *list;
40 char            *opts;
41 {
42         register int c;
43         register char *cp;
44
45         if (!list) {
46                 list_optarg = (char *)NULL;
47                 loptend = (WORD_LIST *)NULL;    /* No non-option arguments */
48                 return -1;
49         }
50
51         if (list != lhead || !lhead) {
52                 /* Hmmm.... called with a different word list.  Reset. */
53                 sp = 1;
54                 lcurrent = lhead = list;
55                 loptend = (WORD_LIST *)NULL;
56         }
57
58         if (sp == 1) {
59                 if (!lcurrent ||
60                     (lcurrent->word->word[0] != '-' || lcurrent->word->word[1] == '\0')) {
61                         lhead = (WORD_LIST *)NULL;
62                         loptend = lcurrent;
63                         return(-1);
64                 } else if (lcurrent->word->word[0] == '-' &&
65                            lcurrent->word->word[1] == '-' &&
66                            lcurrent->word->word[2] == 0) {
67                         lhead = (WORD_LIST *)NULL;
68                         loptend = lcurrent->next;
69                         return(-1);
70                 }
71         }
72
73         list_optopt = c = lcurrent->word->word[sp];
74
75         if (c == ':' || (cp = strchr(opts, c)) == NULL) {
76                 ERR("illegal option: -", c);
77                 if (lcurrent->word->word[++sp] == '\0') {
78                         lcurrent = lcurrent->next;
79                         sp = 1;
80                 }
81                 list_optarg = NULL;
82                 if (lcurrent)
83                         loptend = lcurrent->next;
84                 return('?');
85         }
86
87         if (*++cp == ':') {
88                 /* Option requires an argument. */
89                 /* We allow -l2 as equivalent to -l 2 */
90                 if (lcurrent->word->word[sp+1] != '\0') {
91                         list_optarg = &(lcurrent->word->word[sp+1]);
92                         lcurrent = lcurrent->next;
93                 } else if (lcurrent->next == NULL) {
94                         ERR("option requires an argument: -", c);
95                         sp = 1;
96                         list_optarg = (char *)NULL;
97                         return('?');
98                 } else {
99                         lcurrent = lcurrent->next;
100                         list_optarg = lcurrent->word->word;
101                         lcurrent = lcurrent->next;
102                 }
103                 sp = 1;
104         } else {
105                 /* No argument, just return the option. */
106                 if (lcurrent->word->word[++sp] == '\0') {
107                         sp = 1;
108                         lcurrent = lcurrent->next;
109                 }
110                 list_optarg = (char *)NULL;
111         }
112
113         return(c);
114 }
115
116 /*
117  * reset_internal_getopt -- force the in[ft]ernal getopt to reset
118  */
119
120 void
121 reset_internal_getopt ()
122 {
123         lhead = lcurrent = loptend = (WORD_LIST *)NULL;
124         sp = 1;
125 }
126
127 void
128 report_bad_option ()
129 {
130         char s[3];
131
132         s[0] = '-';
133         s[1] = list_optopt;
134         s[2] = '\0';
135         bad_option (s);
136 }