diff options
Diffstat (limited to 'builtins/bashgetopt.c')
-rw-r--r-- | builtins/bashgetopt.c | 65 |
1 files changed, 51 insertions, 14 deletions
diff --git a/builtins/bashgetopt.c b/builtins/bashgetopt.c index 95dcaac..72ac900 100644 --- a/builtins/bashgetopt.c +++ b/builtins/bashgetopt.c @@ -18,10 +18,17 @@ You should have received a copy of the GNU General Public License along with Bash; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include <config.h> + +#if defined (HAVE_UNISTD_H) +# include <unistd.h> +#endif + +#include "../bashansi.h" #include <errno.h> -#include "shell.h" -#include "bashansi.h" +#include "../shell.h" +#include "common.h" #define ERR(S, C) builtin_error("%s%c", (S), (C)) @@ -41,14 +48,21 @@ char *opts; { register int c; register char *cp; + int plus; /* nonzero means to handle +option */ - if (!list) { + if (*opts == '+') { + plus = 1; + opts++; + } else + plus = 0; + + if (list == 0) { list_optarg = (char *)NULL; loptend = (WORD_LIST *)NULL; /* No non-option arguments */ return -1; } - if (list != lhead || !lhead) { + if (list != lhead || lhead == 0) { /* Hmmm.... called with a different word list. Reset. */ sp = 1; lcurrent = lhead = list; @@ -56,7 +70,7 @@ char *opts; } if (sp == 1) { - if (!lcurrent || + if (lcurrent == 0 || (lcurrent->word->word[0] != '-' || lcurrent->word->word[1] == '\0')) { lhead = (WORD_LIST *)NULL; loptend = lcurrent; @@ -84,23 +98,46 @@ char *opts; return('?'); } - if (*++cp == ':') { - /* Option requires an argument. */ + if (*++cp == ':' || *cp == ';') { + /* `:': Option requires an argument. */ + /* `;': option argument may be missing */ /* We allow -l2 as equivalent to -l 2 */ - if (lcurrent->word->word[sp+1] != '\0') { - list_optarg = &(lcurrent->word->word[sp+1]); + if (lcurrent->word->word[sp+1]) { + list_optarg = lcurrent->word->word + sp + 1; + lcurrent = lcurrent->next; + /* If the specifier is `;', don't set optarg if the next + argument looks like another option. */ + } else if (lcurrent->next && (*cp == ':' || lcurrent->next->word->word[0] != '-')) { + lcurrent = lcurrent->next; + list_optarg = lcurrent->word->word; + lcurrent = lcurrent->next; + } else if (*cp == ';') { + list_optarg = (char *)NULL; lcurrent = lcurrent->next; - } else if (lcurrent->next == NULL) { + } else { /* lcurrent->next == NULL */ ERR("option requires an argument: -", c); sp = 1; list_optarg = (char *)NULL; return('?'); - } else { - lcurrent = lcurrent->next; - list_optarg = lcurrent->word->word; - lcurrent = lcurrent->next; } sp = 1; + } else if (*cp == '#') { + /* optional numeric argument */ + if (lcurrent->word->word[sp+1]) { + if (digit(lcurrent->word->word[sp+1])) { + list_optarg = lcurrent->word->word + sp + 1; + lcurrent = lcurrent->next; + } else + list_optarg = (char *)NULL; + } else { + if (lcurrent->next && legal_number(lcurrent->next->word->word, (long *)0)) { + lcurrent = lcurrent->next; + list_optarg = lcurrent->word->word; + lcurrent = lcurrent->next; + } else + list_optarg = (char *)NULL; + } + } else { /* No argument, just return the option. */ if (lcurrent->word->word[++sp] == '\0') { |