Example #1
0
static void*
stkpush(Stk_t* sp, size_t size)
{
	Stk_frame_t*	f;
	Stk_pos_t	p;

	stknew(sp, &p);
	size = sizeof(Stk_frame_t) + sizeof(size_t) + size - 1;
	if (!(f = (Stk_frame_t*)stkalloc(sp, sizeof(Stk_frame_t) + sizeof(Stk_frame_t*) + size - 1)))
		return 0;
	f->pos = p;
	stkframe(sp) = f;
	return f->data;
}
Example #2
0
static struct dolnod *r_comlist(Shell_t *shp)
{
	register struct dolnod *dol=0;
	register long l;
	register char **argv;
	if((l=sfgetl(infile))>0)
	{
		dol = (struct dolnod*)stkalloc(shp->stk,sizeof(struct dolnod) + sizeof(char*)*(l+ARG_SPARE));
		dol->dolnum = l;
		dol->dolbot = ARG_SPARE;
		argv = dol->dolval+ARG_SPARE;
		while(*argv++ = r_string(shp->stk));
	}
	return(dol);
}
Example #3
0
static char *r_string(Stk_t *stkp)
{
	register Sfio_t *in = infile;
	register unsigned long l = sfgetu(in);
	register char *ptr;
	if(l == 0)
		return(NIL(char*));
	ptr = stkalloc(stkp,(unsigned)l);
	if(--l > 0)
	{
		if(sfread(in,ptr,(size_t)l)!=(size_t)l)
			return(NIL(char*));
		ccmaps(ptr, l, CC_ASCII, CC_NATIVE);
	}
	ptr[l] = 0;
	return(ptr);
}
Example #4
0
/*
 * read in a shell tree
 */
static Shnode_t *r_tree(Shell_t *shp)
{
	long l = sfgetl(infile); 
	register int type;
	register Shnode_t *t=0;
	if(l<0)
		return(t);
	type = l;
	switch(type&COMMSK)
	{
		case TTIME:
		case TPAR:
			t = getnode(shp->stk,parnod);
			t->par.partre = r_tree(shp);
			break;
		case TCOM:
			t = getnode(shp->stk,comnod);
			t->tre.tretyp = type;
			r_comarg(shp,(struct comnod*)t);
			break;
		case TSETIO:
		case TFORK:
			t = getnode(shp->stk,forknod);
			t->fork.forkline = sfgetu(infile);
			t->fork.forktre = r_tree(shp);
			t->fork.forkio = r_redirect(shp);
			break;
		case TIF:
			t = getnode(shp->stk,ifnod);
			t->if_.iftre = r_tree(shp);
			t->if_.thtre = r_tree(shp);
			t->if_.eltre = r_tree(shp);
			break;
		case TWH:
			t = getnode(shp->stk,whnod);
			t->wh.whinc = (struct arithnod*)r_tree(shp);
			t->wh.whtre = r_tree(shp);
			t->wh.dotre = r_tree(shp);
			break;
		case TLST:
		case TAND:
		case TORF:
		case TFIL:
			t = getnode(shp->stk,lstnod);
			t->lst.lstlef = r_tree(shp);
			t->lst.lstrit = r_tree(shp);
			break;
		case TARITH:
			t = getnode(shp->stk,arithnod);
			t->ar.arline = sfgetu(infile);
			t->ar.arexpr = r_arg(shp);
			t->ar.arcomp = 0;
			if((t->ar.arexpr)->argflag&ARG_RAW)
				 t->ar.arcomp = sh_arithcomp((t->ar.arexpr)->argval);
			break;
		case TFOR:
			t = getnode(shp->stk,fornod);
			t->for_.forline = 0;
			if(type&FLINENO)
				t->for_.forline = sfgetu(infile);
			t->for_.fortre = r_tree(shp);
			t->for_.fornam = r_string(shp->stk);
			t->for_.forlst = (struct comnod*)r_tree(shp);
			break;
		case TSW:
			t = getnode(shp->stk,swnod);
			t->sw.swline = 0;
			if(type&FLINENO)
				t->sw.swline = sfgetu(infile);
			t->sw.swarg = r_arg(shp);
			if(type&COMSCAN)
				t->sw.swio = r_redirect(shp);
			else
				t->sw.swio = 0;
			t->sw.swlst = r_switch(shp);
			break;
		case TFUN:
		{
			Stak_t *savstak;
			struct slnod *slp;
			struct functnod *fp;
			t = getnode(shp->stk,functnod);
			t->funct.functloc = -1;
			t->funct.functline = sfgetu(infile);
			t->funct.functnam = r_string(shp->stk);
			savstak = stakcreate(STAK_SMALL);
			savstak = stakinstall(savstak, 0);
			slp = (struct slnod*)stkalloc(shp->stk,sizeof(struct slnod)+sizeof(struct functnod));
			slp->slchild = 0;
			slp->slnext = shp->st.staklist;
			shp->st.staklist = 0;
			fp = (struct functnod*)(slp+1);
			memset(fp, 0, sizeof(*fp));
			fp->functtyp = TFUN|FAMP;
			if(shp->st.filename)
				fp->functnam = stkcopy(shp->stk,shp->st.filename);
			t->funct.functtre = r_tree(shp); 
			t->funct.functstak = slp;
			slp->slptr =  stakinstall(savstak,0);
			slp->slchild = shp->st.staklist;
			t->funct.functargs = (struct comnod*)r_tree(shp);
			break;
		}
		case TTST:
			t = getnode(shp->stk,tstnod);
			t->tst.tstline = sfgetu(infile);
			if((type&TPAREN)==TPAREN)
				t->lst.lstlef = r_tree(shp); 
			else
			{
				t->lst.lstlef = (Shnode_t*)r_arg(shp);
				if((type&TBINARY))
					t->lst.lstrit = (Shnode_t*)r_arg(shp);
			}
	}
	if(t)
		t->tre.tretyp = type;
	return(t);
}
Example #5
0
File: completion.c Project: att/ast
//
// File name generation for edit modes.
// Non-zero exit for error, <0 ring bell.
// Don't search back past beginning of the buffer.
// Mode is '*' for inline expansion.
// Mode is '\' for filename completion.
// Mode is '=' cause files to be listed in select format.
//
int ed_expand(Edit_t *ep, char outbuff[], int *cur, int *eol, int mode, int count) {
    struct comnod *comptr;
    struct argnod *ap;
    char *out;
    char *av[2], *begin;
    char *dir = NULL;
    int addstar = 0, rval = 0, var = 0, strip = 1, narg = 0;
    int nomarkdirs = !sh_isoption(ep->sh, SH_MARKDIRS);
    Shell_t *shp = ep->sh;
    char **com = NULL;

    sh_onstate(shp, SH_FCOMPLETE);
    if (ep->e_nlist) {
        if (mode == '=' && count > 0) {
            if (count > ep->e_nlist) return -1;
            mode = '?';
            av[0] = ep->e_clist[count - 1];
            av[1] = 0;
        } else {
            stkset(shp->stk, ep->e_stkptr, ep->e_stkoff);
            ep->e_nlist = 0;
        }
    }
    comptr = stkalloc(shp->stk, sizeof(struct comnod));
    ap = (struct argnod *)stkseek(shp->stk, ARGVAL);

    {
        // Adjust cur.
        int c;
        genchar *cp;
        cp = (genchar *)outbuff + *cur;
        c = *cp;
        *cp = 0;
        *cur = ed_external((genchar *)outbuff, (char *)stkptr(shp->stk, 0));
        *cp = c;
        *eol = ed_external((genchar *)outbuff, outbuff);
    }

    out = outbuff + *cur + (sh_isoption(shp, SH_VI) != 0);
#if 0
        if(out[-1]=='"' || out[-1]=='\'')
        {
                rval = -(sh_isoption(shp,SH_VI)!=0);
                goto done;
        }
#endif
    comptr->comtyp = COMSCAN;
    comptr->comarg = ap;
    ap->argflag = (ARG_MAC | ARG_EXP);
    ap->argnxt.ap = NULL;
    ap->argchn.cp = NULL;

    {
        char *last = out;
        Namval_t *np = nv_search("COMP_KEY", shp->var_tree, 0);
        if (np) STORE_VT(np->nvalue, i16, '\t');
        np = nv_search("COMP_TYPE", shp->var_tree, 0);
        if (np) STORE_VT(np->nvalue, i16, mode == '\\' ? '\t' : '?');
        var = mode;
        begin = out = find_begin(outbuff, last, 0, &var);
        if (ep->compdict && mode != '?' &&
            (com = prog_complete(ep->compdict, outbuff, out, *cur))) {
            char **av;
            for (av = com; *av; av++) {
                ;  // empty loop
            }
            narg = av - com;
        }
        // Addstar set to zero if * should not be added.
        if (var == '$') {
            sfwrite(shp->stk, "${!", 3);
            sfwrite(shp->stk, out, last - out);
            sfwrite(shp->stk, "$@}", 2);
            out = last;
        } else {
            addstar = '*';
            while (out < last) {
                char c = *out;
                if (c == 0) break;
                if (isexp(c)) addstar = 0;
                if (c == '/') {
                    if (addstar == 0) strip = 0;
                    dir = out + 1;
                }
                sfputc(shp->stk, c);
                out++;
            }
        }
        if (mode == '?') mode = '*';
        if (var != '$' && mode == '\\' && out[-1] != '*') addstar = '*';
        if (*begin == '~' && !strchr(begin, '/')) addstar = 0;
        sfputc(shp->stk, addstar);
        ap = (struct argnod *)stkfreeze(shp->stk, 1);
    }

    if (mode != '*') sh_onoption(shp, SH_MARKDIRS);

    {
        char *cp = begin, *left = NULL;
        int cmd_completion = 0;
        int size = 'x';
        while (cp > outbuff && ((size = cp[-1]) == ' ' || size == '\t')) cp--;
        if (!var && !strchr(ap->argval, '/') &&
            ((cp == outbuff && shp->nextprompt == 1) ||
             (strchr(";&|(", size) && (cp == outbuff + 1 || size == '(' || cp[-2] != '>') &&
              *begin != '~'))) {
            cmd_completion = 1;
            sh_onstate(shp, SH_COMPLETE);
        }
        if (ep->e_nlist) {
            narg = 1;
            com = av;
            if (dir) begin += (dir - begin);
        } else {
            if (!com) com = sh_argbuild(shp, &narg, comptr, 0);
            // Special handling for leading quotes.
            if (begin > outbuff && (begin[-1] == '"' || begin[-1] == '\'')) begin--;
        }
        sh_offstate(shp, SH_COMPLETE);
        // Allow a search to be aborted.
        if (shp->trapnote & SH_SIGSET) {
            rval = -1;
            goto done;
        }
        // Match?
        if (*com == 0 || ((narg <= 1 && (strcmp(ap->argval, *com) == 0)) ||
                          (addstar && com[0][strlen(*com) - 1] == '*'))) {
            rval = -1;
            goto done;
        }
        if (mode == '\\' && out[-1] == '/' && narg > 1) mode = '=';
        if (mode == '=') {
            if (strip && !cmd_completion) {
                char **ptrcom;
                for (ptrcom = com; *ptrcom; ptrcom++) {  // trim directory prefix
                    *ptrcom = path_basename(*ptrcom);
                }
            }
            sfputc(sfstderr, '\n');
            sh_menu(shp, sfstderr, narg, com);
            sfsync(sfstderr);
            ep->e_nlist = narg;
            ep->e_clist = com;
            goto done;
        }
        // See if there is enough room.
        size = *eol - (out - begin);
        if (mode == '\\') {
            int c;
            if (dir) {
                c = *dir;
                *dir = 0;
            }
            if (dir) *dir = c;
            // Just expand until name is unique.
            size += strlen(*com);
        } else {
            char **tmpcom = com;
            size += narg;
            while (*tmpcom) {
                cp = fmtx(shp, *tmpcom++);
                size += strlen(cp);
            }
        }
        // See if room for expansion.
        if (outbuff + size >= &outbuff[MAXLINE]) {
            com[0] = ap->argval;
            com[1] = 0;
        }
        // Save remainder of the buffer.
        if (*out) left = stkcopy(shp->stk, out);
        if (cmd_completion && mode == '\\') {
            cp = *com++;
            out = stpcpy(begin, path_basename(cp));
        } else if (mode == '*') {
            if (ep->e_nlist && dir && var) {
                if (*cp == var) {
                    cp++;
                } else {
                    *begin++ = var;
                }
                out = stpcpy(begin, cp);
                var = 0;
            } else {
                out = stpcpy(begin, fmtx(shp, *com));
            }
            com++;
        } else {
            out = stpcpy(begin, *com++);
        }
        if (mode == '\\') {
            char *saveout = ++out;
            while (*com && *begin) {
                if (cmd_completion) {
                    out = overlaid(begin, path_basename(*com++), false);
                } else {
                    out = overlaid(begin, *com++, false);
                }
            }
            mode = (out == saveout);
            if (out[-1] == 0) out--;
            if (mode && out[-1] != '/') {
                if (cmd_completion) {
                    Namval_t *np;
                    // Add as tracked alias.
                    Pathcomp_t *pp;
                    if (*cp == '/' && (pp = path_dirfind(shp->pathlist, cp, '/')) &&
                        (np = nv_search(begin, shp->track_tree, NV_ADD))) {
                        path_alias(np, pp);
                    }
                    out = stpcpy(begin, cp);
                }
                // Add quotes if necessary.
                if ((cp = fmtx(shp, begin)) != begin) out = stpcpy(begin, cp);
                if (var == '$' && begin[-1] == '{') {
                    *out = '}';
                } else {
                    *out = ' ';
                }
                *++out = 0;
            } else if ((cp = fmtx(shp, begin)) != begin) {
                out = stpcpy(begin, cp);
                if (out[-1] == '"' || out[-1] == '\'') *--out = 0;
            }
            if (*begin == 0 && begin[-1] != ' ') ed_ringbell();
        } else {
            while (*com) {
                *out++ = ' ';
                out = stpcpy(out, fmtx(shp, *com++));
            }
        }
        if (ep->e_nlist) {
            cp = com[-1];
            if (cp[strlen(cp) - 1] != '/') {
                if (var == '$' && begin[-1] == '{') {
                    *out = '}';
                } else {
                    *out = ' ';
                }
                out++;
            } else if (out[-1] == '"' || out[-1] == '\'') {
                out--;
            }
            *out = 0;
        }
        *cur = (out - outbuff);
        // Restore rest of buffer.
        if (left) out = stpcpy(out, left);
        *eol = (out - outbuff);
    }

done:
    sh_offstate(shp, SH_FCOMPLETE);
    if (!ep->e_nlist) stkset(shp->stk, ep->e_stkptr, ep->e_stkoff);
    if (nomarkdirs) sh_offoption(shp, SH_MARKDIRS);

    {
        // First re-adjust cur.
        int c, n = 0;
        c = outbuff[*cur];
        outbuff[*cur] = 0;
        for (out = outbuff; *out; n++) mb1char(&out);
        outbuff[*cur] = c;
        *cur = n;
        outbuff[*eol + 1] = 0;
        *eol = ed_internal(outbuff, (genchar *)outbuff);
    }

    return rval;
}