/* parse command line & set command arguments. returns the index of * non-option arguments, -1 if there is an error. */ int parse_args(char **argv, int what, /* OF_CMDLINE or OF_SET */ int *setargsp) { static char cmd_opts[NELEM(options) + 3]; /* o:\0 */ static char set_opts[NELEM(options) + 5]; /* Ao;s\0 */ char *opts; char *array = (char *) 0; Getopt go; int i, optc, set, sortargs = 0, arrayset = 0; /* First call? Build option strings... */ if (cmd_opts[0] == '\0') { char *p, *q; /* see cmd_opts[] declaration */ strlcpy(cmd_opts, "o:", sizeof cmd_opts); p = cmd_opts + strlen(cmd_opts); /* see set_opts[] declaration */ strlcpy(set_opts, "A:o;s", sizeof set_opts); q = set_opts + strlen(set_opts); for (i = 0; i < NELEM(options); i++) { if (options[i].c) { if (options[i].flags & OF_CMDLINE) *p++ = options[i].c; if (options[i].flags & OF_SET) *q++ = options[i].c; } } *p = '\0'; *q = '\0'; } if (what == OF_CMDLINE) { opts = cmd_opts; } else opts = set_opts; ksh_getopt_reset(&go, GF_ERROR|GF_PLUSOPT); while ((optc = ksh_getopt(argv, &go, opts)) != -1) { set = (go.info & GI_PLUS) ? 0 : 1; switch (optc) { case 'A': arrayset = set ? 1 : -1; array = go.optarg; break; case 'o': if (go.optarg == (char *) 0) { /* lone -o: print options * * Note that on the command line, -o requires * an option (ie, can't get here if what is * OF_CMDLINE). */ printoptions(set); break; } i = option(go.optarg); if (i >= 0 && set == Flag(i)) /* Don't check the context if the flag * isn't changing - makes "set -o interactive" * work if you're already interactive. Needed * if the output of "set +o" is to be used. */ ; else if (i >= 0 && (options[i].flags & what)) change_flag((enum sh_flag) i, what, set); else { bi_errorf("%s: bad option", go.optarg); return -1; } break; case '?': return -1; default: /* -s: sort positional params (at&t ksh stupidity) */ if (what == OF_SET && optc == 's') { sortargs = 1; break; } for (i = 0; i < NELEM(options); i++) if (optc == options[i].c && (what & options[i].flags)) { change_flag((enum sh_flag) i, what, set); break; } if (i == NELEM(options)) { internal_errorf(1, "parse_args: `%c'", optc); return -1; /* not reached */ } } } if (!(go.info & GI_MINUSMINUS) && argv[go.optind] && (argv[go.optind][0] == '-' || argv[go.optind][0] == '+') && argv[go.optind][1] == '\0') { /* lone - clears -v and -x flags */ if (argv[go.optind][0] == '-' && !Flag(FPOSIX)) Flag(FVERBOSE) = Flag(FXTRACE) = 0; /* set skips lone - or + option */ go.optind++; } if (setargsp) /* -- means set $#/$* even if there are no arguments */ *setargsp = !arrayset && ((go.info & GI_MINUSMINUS) || argv[go.optind]); if (arrayset && (!*array || *skip_varname(array, false))) { bi_errorf("%s: is not an identifier", array); return -1; } if (sortargs) { for (i = go.optind; argv[i]; i++) ; qsortp((void **) &argv[go.optind], (size_t) (i - go.optind), xstrcmp); } if (arrayset) { set_array(array, arrayset, argv + go.optind); for (; argv[go.optind]; go.optind++) ; } return go.optind; }
static int x_command_glob(int flags, const char *str, int slen, char ***wordsp) { char *toglob; char *pat; char *fpath; int nwords; XPtrV w; struct block *l; if (slen < 0) return 0; toglob = add_glob(str, slen); /* Convert "foo*" (toglob) to a pattern for future use */ pat = evalstr(toglob, DOPAT|DOTILDE); afree(toglob, ATEMP); XPinit(w, 32); glob_table(pat, &w, &keywords); glob_table(pat, &w, &aliases); glob_table(pat, &w, &builtins); for (l = e->loc; l; l = l->next) glob_table(pat, &w, &l->funs); glob_path(flags, pat, &w, path); if ((fpath = str_val(global("FPATH"))) != null) glob_path(flags, pat, &w, fpath); nwords = XPsize(w); if (!nwords) { *wordsp = NULL; XPfree(w); return 0; } /* Sort entries */ if (flags & XCF_FULLPATH) { /* Sort by basename, then path order */ struct path_order_info *info; struct path_order_info *last_info = NULL; char **words = (char **) XPptrv(w); int path_order = 0; int i; info = areallocarray(NULL, nwords, sizeof(struct path_order_info), ATEMP); for (i = 0; i < nwords; i++) { info[i].word = words[i]; info[i].base = x_basename(words[i], NULL); if (!last_info || info[i].base != last_info->base || strncmp(words[i], last_info->word, info[i].base) != 0) { last_info = &info[i]; path_order++; } info[i].path_order = path_order; } qsort(info, nwords, sizeof(struct path_order_info), path_order_cmp); for (i = 0; i < nwords; i++) words[i] = info[i].word; afree(info, ATEMP); } else { /* Sort and remove duplicate entries */ char **words = (char **) XPptrv(w); int i, j; qsortp(XPptrv(w), (size_t) nwords, xstrcmp); for (i = j = 0; i < nwords - 1; i++) { if (strcmp(words[i], words[i + 1])) words[j++] = words[i]; else afree(words[i], ATEMP); } words[j++] = words[i]; nwords = j; w.cur = (void **) &words[j]; } XPput(w, NULL); *wordsp = (char **) XPclose(w); return nwords; }