da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/***********************************************************************
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* This software is part of the ast package *
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner* Copyright (c) 1982-2010 AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* and is licensed under the *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Common Public License, Version 1.0 *
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin* by AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* A copy of the License is available at *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* http://www.opensource.org/licenses/cpl1.0.txt *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Information and Software Systems Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* AT&T Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Florham Park NJ *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* David Korn <dgk@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin***********************************************************************/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#pragma prototyped
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * File name expansion
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * David Korn
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * AT&T Labs
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if KSHELL
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# include "defs.h"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# include "variables.h"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# include "test.h"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# include <ast.h>
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# include <ctype.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# include <setjmp.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* KSHELL */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <glob.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <ls.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <stak.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <ast_dir.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include "io.h"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include "path.h"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if !SHOPT_BRACEPAT
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# define SHOPT_BRACEPAT 0
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if KSHELL
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# define argbegin argnxt.cp
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin static const char *sufstr;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin static int suflen;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin static int scantree(Dt_t*,const char*, struct argnod**);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# define sh_sigcheck() (0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# define sh_access access
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# define suflen 0
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* KSHELL */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * This routine builds a list of files that match a given pathname
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Uses external routine strgrpmatch() to match each component
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * A leading . must match explicitly
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifndef GLOB_AUGMENTED
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# define GLOB_AUGMENTED 0
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define GLOB_RESCAN 1
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define globptr() ((struct glob*)membase)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic struct glob *membase;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if GLOB_VERSION >= 20010916L
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic char *nextdir(glob_t *gp, char *dir)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Pathcomp_t *pp = (Pathcomp_t*)gp->gl_handle;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!dir)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pp = path_get("");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pp = pp->next;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin gp->gl_handle = (void*)pp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(pp)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(pp->name);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint path_expand(const char *pattern, struct argnod **arghead)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin Shell_t *shp = &sh;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin glob_t gdata;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct argnod *ap;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register glob_t *gp= &gdata;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int flags,extra=0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if SHOPT_BASH
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int off;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register char *sp, *cp, *cp2;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sh_stats(STAT_GLOBS);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin memset(gp,0,sizeof(gdata));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin flags = GLOB_AUGMENTED|GLOB_NOCHECK|GLOB_NOSORT|GLOB_STACK|GLOB_LIST|GLOB_DISC;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sh_isoption(SH_MARKDIRS))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin flags |= GLOB_MARK;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sh_isoption(SH_GLOBSTARS))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin flags |= GLOB_STARSTAR;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if SHOPT_BASH
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if 0
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sh_isoption(SH_BASH) && !sh_isoption(SH_EXTGLOB))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin flags &= ~GLOB_AUGMENTED;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sh_isoption(SH_NULLGLOB))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin flags &= ~GLOB_NOCHECK;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sh_isoption(SH_NOCASEGLOB))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin flags |= GLOB_ICASE;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sh_isstate(SH_COMPLETE))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if KSHELL
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin extra += scantree(shp->alias_tree,pattern,arghead);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin extra += scantree(shp->fun_tree,pattern,arghead);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# if GLOB_VERSION >= 20010916L
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin gp->gl_nextdir = nextdir;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* KSHELL */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin flags |= GLOB_COMPLETE;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin flags &= ~GLOB_NOCHECK;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if SHOPT_BASH
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(off = staktell())
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sp = stakfreeze(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sh_isoption(SH_BASH))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * For bash, FIGNORE is a colon separated list of suffixes to
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * ignore when doing filename/command completion.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * GLOBIGNORE is similar to ksh FIGNORE, but colon separated
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * instead of being an augmented shell pattern.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Generate shell patterns out of those here.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sh_isstate(SH_FCOMPLETE))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin cp=nv_getval(sh_scoped(shp,FIGNORENOD));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin static Namval_t *GLOBIGNORENOD;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!GLOBIGNORENOD)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin GLOBIGNORENOD = nv_open("GLOBIGNORE",shp->var_tree,0);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin cp=nv_getval(sh_scoped(shp,GLOBIGNORENOD));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(cp)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin flags |= GLOB_AUGMENTED;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin stakputs("@(");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!sh_isstate(SH_FCOMPLETE))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin stakputs(cp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(cp=stakptr(off); *cp; cp++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(*cp == ':')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *cp='|';
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cp2 = strtok(cp, ":");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!cp2)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cp2=cp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin do
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin stakputc('*');
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin stakputs(cp2);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(cp2 = strtok(NULL, ":"))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *(cp2-1)=':';
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin stakputc('|');
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin } while(cp2);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin stakputc(')');
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin gp->gl_fignore = stakfreeze(1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(!sh_isstate(SH_FCOMPLETE) && sh_isoption(SH_DOTGLOB))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin gp->gl_fignore = "";
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin gp->gl_fignore = nv_getval(sh_scoped(shp,FIGNORENOD));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(suflen)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin gp->gl_suffix = sufstr;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin gp->gl_intr = &shp->trapnote;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin suflen = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(memcmp(pattern,"~(N",3)==0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin flags &= ~GLOB_NOCHECK;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin glob(pattern, flags, 0, gp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if SHOPT_BASH
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(off)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin stakset(sp,off);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin stakseek(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sh_sigcheck();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(ap= (struct argnod*)gp->gl_list; ap; ap = ap->argnxt.ap)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ap->argchn.ap = ap->argnxt.ap;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!ap->argnxt.ap)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ap->argchn.ap = *arghead;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(gp->gl_list)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *arghead = (struct argnod*)gp->gl_list;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(gp->gl_pathc+extra);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if KSHELL
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * scan tree and add each name that matches the given pattern
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int scantree(Dt_t *tree, const char *pattern, struct argnod **arghead)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register Namval_t *np;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct argnod *ap;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int nmatch=0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register char *cp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin np = (Namval_t*)dtfirst(tree);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(;np && !nv_isnull(np);(np = (Namval_t*)dtnext(tree,np)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(strmatch(cp=nv_name(np),pattern))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ap = (struct argnod*)stakseek(ARGVAL);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin stakputs(cp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ap = (struct argnod*)stakfreeze(1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ap->argbegin = NIL(char*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ap->argchn.ap = *arghead;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ap->argflag = ARG_RAW|ARG_MAKE;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *arghead = ap;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin nmatch++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(nmatch);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * file name completion
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * generate the list of files found by adding an suffix to end of name
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * The number of matches is returned
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint path_complete(const char *name,register const char *suffix, struct argnod **arghead)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sufstr = suffix;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin suflen = strlen(suffix);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(path_expand(name,arghead));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if SHOPT_BRACEPAT
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int checkfmt(Sfio_t* sp, void* vp, Sffmt_t* fp)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint path_generate(struct argnod *todo, struct argnod **arghead)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*@
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin assume todo!=0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return count satisfying count>=1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin@*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register char *cp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int brace;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct argnod *ap;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct argnod *top = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct argnod *apin;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char *pat, *rescan;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char *format;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char comma, range=0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int first, last, incr, count = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char tmp[32], end[1];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin todo->argchn.ap = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinagain:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin apin = ap = todo;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin todo = ap->argchn.ap;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cp = ap->argval;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin range = comma = brace = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* first search for {...,...} */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(1) switch(*cp++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '{':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(brace++==0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pat = cp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '}':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(--brace>0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(brace==0 && comma && *cp!='(')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto endloop1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin comma = brace = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '.':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(brace==1 && *cp=='.')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char *endc;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin incr = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(isdigit(*pat) || *pat=='+' || *pat=='-')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin first = strtol(pat,&endc,0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(endc==(cp-1))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin last = strtol(cp+1,&endc,0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(*endc=='.' && endc[1]=='.')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin incr = strtol(endc+2,&endc,0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(last<first)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin incr = -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(incr)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(*endc=='%')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Sffmt_t fmt;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin memset(&fmt, 0, sizeof(fmt));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fmt.version = SFIO_VERSION;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fmt.form = endc;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fmt.extf = checkfmt;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfprintf(sfstdout, "%!", &fmt);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!(fmt.flags&(SFFMT_LLONG|SFFMT_LDOUBLE)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (fmt.fmt)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'c':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'd':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'i':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'o':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'u':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'x':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'X':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin format = endc;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin endc = fmt.form;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin format = "%d";
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(*endc=='}')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cp = endc+1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin range = 2;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto endloop1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin 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')))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin first = *pat;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin last = cp[1];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cp += 2;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(*cp=='.')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin incr = strtol(cp+2,&endc,0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cp = endc;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(first>last)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin incr = -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(incr && *cp=='}')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cp++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin range = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto endloop1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cp++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case ',':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(brace==1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin comma = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '\\':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cp++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 0:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* insert on stack */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ap->argchn.ap = top;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin top = ap;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(todo)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto again;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(; ap; ap=apin)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin apin = ap->argchn.ap;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!sh_isoption(SH_NOGLOB))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin brace=path_expand(ap->argval,arghead);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ap->argchn.ap = *arghead;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *arghead = ap;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin brace=1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(brace)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin count += brace;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (*arghead)->argflag |= ARG_MAKE;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(count);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinendloop1:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rescan = cp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cp = pat-1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *cp = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin brace = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(range)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(range==1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pat[0] = first;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cp = &pat[1];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *(rescan - 1) = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfsprintf(pat=tmp,sizeof(tmp),format,first);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *(rescan - 1) = '}';
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *(cp = end) = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(incr*(first+incr) > last*incr)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *cp = '}';
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin first += incr;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* generate each pattern and put on the todo list */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else while(1) switch(*++cp)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '\\':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cp++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '{':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin brace++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case ',':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(brace==0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto endloop2;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '}':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(--brace<0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto endloop2;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin endloop2:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin brace = *cp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *cp = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sh_sigcheck();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ap = (struct argnod*)stakseek(ARGVAL);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ap->argflag = ARG_RAW;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ap->argchn.ap = todo;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin stakputs(apin->argval);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin stakputs(pat);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin stakputs(rescan);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin todo = ap = (struct argnod*)stakfreeze(1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(brace == '}')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!range)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pat = cp+1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto again;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_BRACEPAT */