示例#1
0
文件: expand.c 项目: att/ast
int path_expand(Shell_t *shp, const char *pattern, struct argnod **arghead) {
    glob_t gdata;
    struct argnod *ap;
    glob_t *gp = &gdata;
    int flags, extra = 0;
#if SHOPT_BASH
    int off;
    char *sp, *cp, *cp2;
#endif

    sh_stats(STAT_GLOBS);
    memset(gp, 0, sizeof(gdata));
    flags = GLOB_GROUP | GLOB_AUGMENTED | GLOB_NOCHECK | GLOB_NOSORT | GLOB_STACK | GLOB_LIST |
            GLOB_DISC;
    if (sh_isoption(shp, SH_MARKDIRS)) flags |= GLOB_MARK;
    if (sh_isoption(shp, SH_GLOBSTARS)) flags |= GLOB_STARSTAR;
#if SHOPT_BASH
#if 0
        if(sh_isoption(shp,SH_BASH) && !sh_isoption(shp,SH_EXTGLOB))
                flags &= ~GLOB_AUGMENTED;
#endif
    if (sh_isoption(shp, SH_NULLGLOB)) flags &= ~GLOB_NOCHECK;
    if (sh_isoption(shp, SH_NOCASEGLOB)) flags |= GLOB_ICASE;
#endif
    if (sh_isstate(shp, SH_COMPLETE)) {
        extra += scantree(shp, shp->alias_tree, pattern, arghead);
        extra += scantree(shp, shp->fun_tree, pattern, arghead);
        gp->gl_nextdir = nextdir;
        flags |= GLOB_COMPLETE;
        flags &= ~GLOB_NOCHECK;
    }
#if SHOPT_BASH
    off = stktell(shp->stk);
    if (off) sp = stkfreeze(shp->stk, 0);
    if (sh_isoption(shp, SH_BASH)) {
        // For bash, FIGNORE is a colon separated list of suffixes to ignore
        // when doing filename/command completion. GLOBIGNORE is similar to ksh
        // FIGNORE, but colon separated instead of being an augmented shell
        // pattern. Generate shell patterns out of those here.
        if (sh_isstate(shp, SH_FCOMPLETE)) {
            cp = nv_getval(sh_scoped(shp, FIGNORENOD));
        } else {
            static Namval_t *GLOBIGNORENOD;
            if (!GLOBIGNORENOD) GLOBIGNORENOD = nv_open("GLOBIGNORE", shp->var_tree, 0);
            cp = nv_getval(sh_scoped(shp, GLOBIGNORENOD));
        }
        if (cp) {
            flags |= GLOB_AUGMENTED;
            sfputr(shp->stk, "@(", -1);
            if (!sh_isstate(shp, SH_FCOMPLETE)) {
                sfputr(shp->stk, cp, -1);
                for (cp = stkptr(shp->stk, off); *cp; cp++) {
                    if (*cp == ':') *cp = '|';
                }
            } else {
                cp2 = strtok(cp, ":");
                if (!cp2) cp2 = cp;
                do {
                    sfputc(shp->stk, '*');
                    sfputr(shp->stk, cp2, -1);
                    cp2 = strtok(NULL, ":");
                    if (cp2) {
                        *(cp2 - 1) = ':';
                        sfputc(shp->stk, '|');
                    }
                } while (cp2);
            }
            sfputc(shp->stk, ')');
            gp->gl_fignore = stkfreeze(shp->stk, 1);
        } else if (!sh_isstate(shp, SH_FCOMPLETE) && sh_isoption(shp, SH_DOTGLOB)) {
            gp->gl_fignore = "";
        }
    } else
#endif
        gp->gl_fignore = nv_getval(sh_scoped(shp, FIGNORENOD));
    if (suflen) gp->gl_suffix = sufstr;
    gp->gl_intr = &shp->trapnote;
    suflen = 0;
    if (strncmp(pattern, "~(N", 3) == 0) flags &= ~GLOB_NOCHECK;
    ast_glob(pattern, flags, 0, gp);
#if SHOPT_BASH
    if (off) {
        stkset(shp->stk, sp, off);
    } else {
        stkseek(shp->stk, 0);
    }
#endif
    sh_sigcheck(shp);
    for (ap = (struct argnod *)gp->gl_list; ap; ap = ap->argnxt.ap) {
        ap->argchn.ap = ap->argnxt.ap;
        if (!ap->argnxt.ap) ap->argchn.ap = *arghead;
    }
    if (gp->gl_list) *arghead = (struct argnod *)gp->gl_list;
    return gp->gl_pathc + extra;
}
示例#2
0
int	b_hist(int argc,char *argv[], void *extra)
{
	register History_t *hp;
	register char *arg;
	register int flag,fdo;
	register Shell_t *shp = ((Shbltin_t*)extra)->shp;
	Sfio_t *outfile;
	char *fname;
	int range[2], incr, index2, indx= -1;
	char *edit = 0;		/* name of editor */
	char *replace = 0;		/* replace old=new */
	int lflag = 0, nflag = 0, rflag = 0;
#if SHOPT_HISTEXPAND
	int pflag = 0;
#endif
	Histloc_t location;
	NOT_USED(argc);
	if(!sh_histinit((void*)shp))
		errormsg(SH_DICT,ERROR_system(1),e_histopen);
	hp = shp->gd->hist_ptr;
	while((flag = optget(argv,sh_opthist))) switch(flag)
	{
	    case 'e':
		edit = opt_info.arg;
		break;
	    case 'n':
		nflag++;
		break;
	    case 'l':
		lflag++;
		break;
	    case 'r':
		rflag++;
		break;
	    case 's':
		edit = "-";
		break;
#if SHOPT_HISTEXPAND
	    case 'p':
		pflag++;
		break;
#endif
	    case 'N':
		if(indx<=0)
		{
			if((flag = hist_max(hp) - opt_info.num-1) < 0)
				flag = 1;
			range[++indx] = flag;
			break;
		}
	    case ':':
		errormsg(SH_DICT,2, "%s", opt_info.arg);
		break;
	    case '?':
		errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
		break;
	}
	if(error_info.errors)
		errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
	argv += (opt_info.index-1);
#if SHOPT_HISTEXPAND
	if(pflag)
	{
		hist_cancel(hp);
		pflag = 0;
		while(arg=argv[1])
		{
			flag = hist_expand(arg,&replace);
			if(!(flag & HIST_ERROR))
				sfputr(sfstdout, replace, '\n');
			else
				pflag = 1;
			if(replace)
				free(replace);
			argv++;
		}
		return pflag;
	}
#endif
	flag = indx;
	while(flag<1 && (arg=argv[1]))
	{
		/* look for old=new argument */
		if(!replace && strchr(arg+1,'='))
		{
			replace = arg;
			argv++;
			continue;
		}
		else if(isdigit(*arg) || *arg == '-')
		{
			/* see if completely numeric */
			do	arg++;
			while(isdigit(*arg));
			if(*arg==0)
			{
				arg = argv[1];
				range[++flag] = (int)strtol(arg, (char**)0, 10);
				if(*arg == '-')
					range[flag] += (hist_max(hp)-1);
				argv++;
				continue;
			}
		}
		/* search for last line starting with string */
		location = hist_find(hp,argv[1],hist_max(hp)-1,0,-1);
		if((range[++flag] = location.hist_command) < 0)
			errormsg(SH_DICT,ERROR_exit(1),e_found,argv[1]);
		argv++;
	}
	if(flag <0)
	{
		/* set default starting range */
		if(lflag)
		{
			flag = hist_max(hp)-16;
			if(flag<1)
				flag = 1;
		}
		else
			flag = hist_max(hp)-2;
		range[0] = flag;
		flag = 0;
	}
	index2 = hist_min(hp);
	if(range[0]<index2)
		range[0] = index2;
	if(flag==0)
		/* set default termination range */
		range[1] = ((lflag && !edit)?hist_max(hp)-1:range[0]);
	if(range[1]>=(flag=(hist_max(hp) - !lflag)))
		range[1] = flag;
	/* check for valid ranges */
	if(range[1]<index2 || range[0]>=flag)
		errormsg(SH_DICT,ERROR_exit(1),e_badrange,range[0],range[1]);
	if(edit && *edit=='-' && range[0]!=range[1])
		errormsg(SH_DICT,ERROR_exit(1),e_eneedsarg);
	/* now list commands from range[rflag] to range[1-rflag] */
	incr = 1;
	flag = rflag>0;
	if(range[1-flag] < range[flag])
		incr = -1;
	if(lflag)
	{
		outfile = sfstdout;
		arg = "\n\t";
	}
	else
	{
		if(!(fname=pathtmp(NIL(char*),0,0,NIL(int*))))
			errormsg(SH_DICT,ERROR_exit(1),e_create,"");
		if((fdo=open(fname,O_CREAT|O_RDWR,S_IRUSR|S_IWUSR)) < 0)
			errormsg(SH_DICT,ERROR_system(1),e_create,fname);
		outfile= sfnew(NIL(Sfio_t*),shp->outbuff,IOBSIZE,fdo,SF_WRITE);
		arg = "\n";
		nflag++;
	}
	while(1)
	{
		if(nflag==0)
			sfprintf(outfile,"%d\t",range[flag]);
		else if(lflag)
			sfputc(outfile,'\t');
		hist_list(shp->gd->hist_ptr,outfile,hist_tell(shp->gd->hist_ptr,range[flag]),0,arg);
		if(lflag)
			sh_sigcheck(shp);
		if(range[flag] == range[1-flag])
			break;
		range[flag] += incr;
	}
	if(lflag)
		return(0);
	sfclose(outfile);
	hist_eof(hp);
	arg = edit;
	if(!arg && !(arg=nv_getval(sh_scoped(shp,HISTEDIT))) && !(arg=nv_getval(sh_scoped(shp,FCEDNOD))))
		arg = (char*)e_defedit;
#ifdef apollo
	/*
	 * Code to support the FC using the pad editor.
	 * Exampled of how to use: HISTEDIT=pad
	 */
	if (strcmp (arg, "pad") == 0)
	{
		extern int pad_create(char*);
		sh_close(fdo);
		fdo = pad_create(fname);
		pad_wait(fdo);
		unlink(fname);
		strcat(fname, ".bak");
		unlink(fname);
		lseek(fdo,(off_t)0,SEEK_SET);
	}
	else
	{
#endif /* apollo */
	if(*arg != '-')
	{
		char *com[3];
		com[0] =  arg;
		com[1] =  fname;
		com[2] = 0;
		error_info.errors = sh_eval(sh_sfeval(com),0);
	}
	fdo = sh_chkopen(fname);
	unlink(fname);
	free((void*)fname);
#ifdef apollo
	}
#endif /* apollo */
	/* don't history fc itself unless forked */
	error_info.flags |= ERROR_SILENT;
	if(!sh_isstate(SH_FORKED))
		hist_cancel(hp);
	sh_onstate(SH_HISTORY);
	sh_onstate(SH_VERBOSE);	/* echo lines as read */
	if(replace)
		hist_subst(error_info.id,fdo,replace);
	else if(error_info.errors == 0)
	{
		char buff[IOBSIZE+1];
		Sfio_t *iop = sfnew(NIL(Sfio_t*),buff,IOBSIZE,fdo,SF_READ);
		/* read in and run the command */
		if(shp->hist_depth++ > HIST_RECURSE)
			errormsg(SH_DICT,ERROR_exit(1),e_toodeep,"history");
		sh_eval(iop,1);
		shp->hist_depth--;
	}
示例#3
0
文件: expand.c 项目: att/ast
int path_generate(Shell_t *shp, struct argnod *todo, struct argnod **arghead) {
    char *cp;
    int brace;
    struct argnod *ap;
    struct argnod *top = NULL;
    struct argnod *apin;
    char *pat, *rescan;
    char *format = NULL;
    char comma, range = 0;
    int first, last, incr, count = 0;
    char end_char;
    char tmp[32];

    if (!sh_isoption(shp, SH_BRACEEXPAND)) return path_expand(shp, todo->argval, arghead);
    todo->argchn.ap = NULL;
again:
    apin = ap = todo;
    todo = ap->argchn.ap;
    cp = ap->argval;
    range = comma = brace = 0;
    // First search for {...,...}.
    while (1) {
        switch (*cp++) {
            case '{': {
                if (brace++ == 0) pat = cp;
                break;
            }
            case '}': {
                if (--brace > 0) break;
                if (brace == 0 && comma && *cp != '(') goto endloop1;
                comma = brace = 0;
                break;
            }
            case '.': {
                if (brace != 1) break;
                if (*cp != '.') break;

                char *endc;
                incr = 1;
                if (isdigit(*pat) || *pat == '+' || *pat == '-') {
                    first = strtol(pat, &endc, 0);
                    if (endc == (cp - 1)) {
                        last = strtol(cp + 1, &endc, 0);
                        if (*endc == '.' && endc[1] == '.') {
                            incr = strtol(endc + 2, &endc, 0);
                        } else if (last < first) {
                            incr = -1;
                        }
                        if (incr) {
                            if (*endc == '%') {
                                Sffmt_t fmt;
                                memset(&fmt, 0, sizeof(fmt));
                                fmt.version = SFIO_VERSION;
                                fmt.form = endc;
                                fmt.extf = checkfmt;
                                sfprintf(sfstdout, "%!", &fmt);
                                if (!(fmt.flags & (SFFMT_LLONG | SFFMT_LDOUBLE))) {
                                    switch (fmt.fmt) {
                                        case 'c':
                                        case 'd':
                                        case 'i':
                                        case 'o':
                                        case 'u':
                                        case 'x':
                                        case 'X': {
                                            format = endc;
                                            endc = fmt.form;
                                            break;
                                        }
                                        default: { break; }
                                    }
                                }
                            } else {
                                format = "%d";
                            }
                            if (*endc == '}') {
                                cp = endc + 1;
                                range = 2;
                                goto endloop1;
                            }
                        }
                    }
                } else if ((cp[2] == '}' || (cp[2] == '.' && cp[3] == '.')) &&
                           ((*pat >= 'a' && *pat <= 'z' && cp[1] >= 'a' && cp[1] <= 'z') ||
                            (*pat >= 'A' && *pat <= 'Z' && cp[1] >= 'A' && cp[1] <= 'Z'))) {
                    first = *pat;
                    last = cp[1];
                    cp += 2;
                    if (*cp == '.') {
                        incr = strtol(cp + 2, &endc, 0);
                        cp = endc;
                    } else if (first > last) {
                        incr = -1;
                    }
                    if (incr && *cp == '}') {
                        cp++;
                        range = 1;
                        goto endloop1;
                    }
                }
                cp++;
                break;
            }
            case ',': {
                if (brace == 1) comma = 1;
                break;
            }
            case '\\': {
                cp++;
                break;
            }
            case 0: {  // insert on stack
                ap->argchn.ap = top;
                top = ap;
                if (todo) goto again;
                for (; ap; ap = apin) {
                    apin = ap->argchn.ap;
                    if (!sh_isoption(shp, SH_NOGLOB)) {
                        brace = path_expand(shp, ap->argval, arghead);
                    } else {
                        ap->argchn.ap = *arghead;
                        *arghead = ap;
                        brace = 1;
                    }
                    if (brace) {
                        count += brace;
                        (*arghead)->argflag |= ARG_MAKE;
                    }
                }
                return count;
            }
            default: { break; }
        }
    }

endloop1:
    rescan = cp;
    cp = pat - 1;
    *cp = 0;

    while (1) {
        brace = 0;
        if (range) {
            if (range == 1) {
                pat[0] = first;
                cp = &pat[1];
            } else {
                *(rescan - 1) = 0;
                pat = tmp;
                assert(format);
                sfsprintf(pat, sizeof(tmp), format, first);
                *(rescan - 1) = '}';
                cp = &end_char;
                *cp = 0;
            }
            if (incr * (first + incr) > last * incr) {
                *cp = '}';
            } else {
                first += incr;
            }
        } else {  // generate each pattern and put on the todo list
            while (1) {
                switch (*++cp) {
                    case '\\': {
                        cp++;
                        break;
                    }
                    case '{': {
                        brace++;
                        break;
                    }
                    case ',': {
                        if (brace == 0) goto endloop2;
                        break;
                    }
                    case '}': {
                        if (--brace < 0) goto endloop2;
                    }
                    default: { break; }
                }
            }
        }

    endloop2:
        brace = *cp;
        *cp = 0;
        sh_sigcheck(shp);
        ap = (struct argnod *)stkseek(shp->stk, ARGVAL);
        ap->argflag = ARG_RAW;
        ap->argchn.ap = todo;
        sfputr(shp->stk, apin->argval, -1);
        sfputr(shp->stk, pat, -1);
        sfputr(shp->stk, rescan, -1);
        todo = ap = (struct argnod *)stkfreeze(shp->stk, 1);
        if (brace == '}') break;
        if (!range) pat = cp + 1;
    }
    goto again;
}