1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2024-12-28 16:15:02 +01:00

zsh-3.1.6-pws-1

This commit is contained in:
Tanaka Akira 1999-08-06 18:01:35 +00:00
parent 61e68d70da
commit 784c413690
39 changed files with 3261 additions and 1738 deletions

View file

@ -1,3 +1,54 @@
1999-08-06 Peter Stephenson <pws@ibmth.df.unipi.it>
* pws: Config/version.mk: 3.1.6-pws-1 made available.
* Sven: 7386: Src/subst.c: Order of q and Q parameter flags matters.
1999-08-05 Peter Stephenson <pws@ibmth.df.unipi.it>
* Sven: 7380: Src/hist.c, Src/subst.c, Doc/Zsh/expn.yo: flag X for
reporting errors de-quoting.
* Sven: 7374: Src/subst.c, Doc/Zsh/expn.yo: modifier to remove one
level of quotation, corresponding flags.
* Sven: 7373: Src/Zle/comp.h, Src/Zle/zle_tricky.c,
Completion/Base/_brace_parameter: support nested parameter
expansion type of deal.
1999-08-04 Peter Stephenson <pws@ibmth.df.unipi.it>
* Sven: 7355: Src/Zle/compctl.c, Src/Zle/zle_tricky.c: make
compadd quoting consistent with compgen.
1999-08-02 Peter Stephenson <pws@ibmth.df.unipi.it>
* Sven: 7349: Src/loop.c, Src/signals.c: restore errflags in
select after a zleread; fix problem restoring function-style trap
after a function set it to something else.
* Sven: 7348: Completion/Core/_path_files, Doc/Zsh/compsys.yo:
remove path_keepdir configuration key but don't do keepdir
trick unless _files had no type arguments.
* Sven: 7345, 7346, 7347: Src/Zle/zle_tricky.c: match control
problems.
* Sven: 7344, 7353: Src/cond.c, Src/Modules/example.c,
Src/Zle/compctl.c, Util/zsh-development-guide: conditions can
get the tokenized string; better quoting behaviour in
IPREFIX/ISUFFIX.
* Sven: 7343: Src/Zle/zle_tricky.c: quote path prefix and suffix
earlier.
* pws: 7342: Doc/Makfile.in: use makeinfo ... || exit 0 to
ignore result of makeinfo.
* Irving Wolfe: 7336: utils.c: same fcntl() change.
* Geoff: 7335: init.c: third argument for fcntl().
1999-08-01 Peter Stephenson <pws@ibmth.df.unipi.it>
* pws: Config/version.mk: zsh 3.1.6 released.

View file

@ -7,6 +7,8 @@ local lp ls n q suf=''
if [[ "$SUFFIX" = *\}* ]]; then
ISUFFIX="${SUFFIX#*\}}$ISUFFIX"
SUFFIX="${SUFFIX%%\}*}"
elif [[ "$LBUFFER" = *\$\{[^}]#\$\{[^}]#$PREFIX ]]; then
suf='}'
else
suf='} '
fi
@ -18,4 +20,4 @@ q=${(M)lp%%\"#}
[[ n -gt 0 ]] && suf=''
_parameters -Qs "${q[1,-n-1]}" -S "$suf" -r '-:?#%+=[/'
_parameters -Qs "${q[1,-n-1]}" -S "$suf" -r '-:?#%+=[/}'

View file

@ -25,7 +25,7 @@
local linepath realpath donepath prepath testpath exppath
local tmp1 tmp2 tmp3 tmp4 i orig pre suf tpre tsuf
local pats ignore group expl addpfx addsfx remsfx
local pats haspats=no ignore group expl addpfx addsfx remsfx
local nm=$compstate[nmatches] menu
typeset -U prepaths exppaths
@ -82,9 +82,11 @@ while getopts "P:S:qr:R:W:F:J:V:X:f/g:" opt; do
;;
/) sopt="${sopt}/"
pats=("$pats[@]" '*(-/)')
haspats=yes
;;
g) gopt='-g'
pats=("$pats[@]" ${=OPTARG})
haspats=yes
;;
esac
done
@ -259,14 +261,11 @@ for prepath in "$prepaths[@]"; do
# an attempt to correct a valid directory name. So we just add the
# original string in such a case so that the command line doesn't
# change but other completers still think there are matches.
# We do this only if we weren't given a `-g' or `-/' option because
# otherwise this would keep `_files' from completing all filenames
# if none of the patterns match.
# Problem: this seems to stop _files from finding directory
# completions if there were no file completions, for
# example `_files *(*)' no longer completes subdirectories after
# a /. For now, make this a configuration option, but
# probably it needs to be done better.
if [[ -n "$compconfig[path_keepdir]" && -z "$tpre$tsuf" &&
if [[ "$haspats" = no && -z "$tpre$tsuf" &&
"$pre" = */ && -z "$suf" ]]; then
compadd -nQS '' - "$linepath$donepath$orig"
tmp4=-

View file

@ -27,5 +27,5 @@
# This must also serve as a shell script, so do not add spaces around the
# `=' signs.
VERSION=3.1.6
VERSION_DATE='July 30, 1999'
VERSION=3.1.6-pws-1
VERSION_DATE='August 6, 1999'

View file

@ -74,7 +74,7 @@ zsh.dvi: zsh.texi
$(TEXI2DVI) $(sdir)/zsh.texi
zsh.info: zsh.texi
$(MAKEINFO) $(sdir)/zsh.texi; exit 0
$(MAKEINFO) $(sdir)/zsh.texi || exit 0
zsh.texi: zsh.yo
$(YODL) -o $(sdir)/zsh.texi -I$(sdir) -w ztexi.yo version.yo zsh.yo

View file

@ -738,7 +738,7 @@ These functions also accept the `tt(-J)', `tt(-V)', `tt(-X)', `tt(-P)',
`tt(-S)', `tt(-q)', `tt(-r)', and `tt(-R)' options from the
tt(compadd) builtin.
Finally, the tt(_path_files) function supports three configuration keys.
Finally, the tt(_path_files) function supports two configuration keys.
startitem()
item(tt(path_expand))(
If this is set to any non-empty string, the partially
@ -750,14 +750,6 @@ If this is set to a non-empty string, the cursor will be left
after the first ambiguous pathname component even when menucompletion
is used.
)
item(tt(path_keepdir))(
If this is set to a non-empty string, then if completion immediately after
a slash fails, treat the original string as a successful completion. This
prevents a valid directory being treated as a candidate for correction.
However, it has the side effect that a pattern completion, such as
`tt(files -g *(*))', will no longer try to complete directories in this
position if there are no file matches.
)
enditem()
)
item(tt(_parameters))(

View file

@ -166,6 +166,9 @@ with history expansion and parameter expansion, though in the second
case it is only useful if the resulting text is to be re-evaluated
such as by tt(eval).
)
item(tt(Q))(
Remove one level of quotes from the substituted words.
)
item(tt(x))(
Like tt(q), but break into words at each blank.
)
@ -578,6 +581,17 @@ Capitalize the resulting words. `Words' in this case refers to sequences
of alphanumeric characters separated by non-alphanumerics, em(not) to words
that result from field splitting.
)
item(tt(q))(
Quote the resulting words with backslashes.
)
item(tt(Q))(
Remove one level of quotes from the resulting words.
)
item(tt(X))(
With this flag parsing errors occuring with the tt(Q) flag or the
pattern matching forms such as `tt(${)var(name)tt(#)var(pattern)tt(})'
are reported. Without the flag they are silently ignored.
)
item(tt(c))(
With tt(${#)var(name)tt(}), count the total number of characters in an array,
as if the elements were concatenated with spaces between them.

View file

@ -71,7 +71,8 @@ item(Poland)(
nofill(tt(ftp://sunsite.icm.edu.pl/pub/unix/shells/zsh/))
)
item(Romania)(
nofill(tt(ftp://ftp.roedu.net/pub/mirrors/ftp.zsh.org/pub/zsh/))
nofill(tt(ftp://ftp.roedu.net/pub/mirrors/ftp.zsh.org/pub/zsh/)
tt(ftp://ftp.kappa.ro/pub/mirrors/ftp.zsh.org/pub/zsh/))
)
item(Slovenia)(
nofill(tt(ftp://ftp.siol.net/mirrors/zsh/))

View file

@ -48,14 +48,3 @@ Numeric ranges are still too greedy with using characters; for example,
<1-1000>33 will not match 633 because the 633 matches the range. Some
backtracking will be necessary.
------------------------------------------------------------------------
Matching control can leave the wrong thing in the line. For example,
touch Abc-Def-Ghij.txt
touch Abc-def.ghi.jkl_mno.pqr.txt
touch Abc_def_ghi_jkl_mno_pqr.txt
compctl -M 'm:{a-z}={A-Z} r:|[.,_-]=*'
ls a<TAB>
produces
ls Abcdefghi
which won't complete further. It seems to get confused over the choice of
possible punctuation characters, and the string won't complete further.
------------------------------------------------------------------------

View file

@ -18,7 +18,7 @@ at <coordinator@zsh.org>.
Version 3.1.6
-------------
* Sven Wishnowsky <wischnow@informatik.hu-berlin.de>: completion code,
* Sven Wischnowsky <wischnow@informatik.hu-berlin.de>: completion code,
major rewrite and enhancements, including matching control, completion
widgets and function system, complist module; zle code additions; job
control code changes; parameters code changes; parameter module;

View file

@ -14,6 +14,11 @@ while read res str pat; do
(( failed++ ))
fi
done <<EOT
# a few simple things certain nameless idiots have been known to mess up
t foo~ foo~
t foo.c *.c~boo*
f foo.c *.c~boo*~foo*
# closures
t fofo (fo#)#
t ffo (fo#)#
t foooofo (fo#)#
@ -95,6 +100,8 @@ t zoox (^z*|*x)
t foo (^foo)#
f foob (^foo)b*
t foobb (^foo)b*
f foob (*~foo)b*
t foobb (*~foo)b*
f zsh ^z*
t a%1X [[:alpha:][:punct:]]#[[:digit:]][^[:lower:]]
f a%1 [[:alpha:][:punct:]]#[[:digit:]][^[:lower:]]
@ -115,6 +122,16 @@ f fooxx ((#i)FOOX)X
f BAR (bar|(#i)foo)
t FOO (bar|(#i)foo)
t Modules (#i)*m*
t fooGRUD (#i)(bar|(#I)foo|(#i)rod)grud
f FOOGRUD (#i)(bar|(#I)foo|(#i)rod)grud
t readme (#i)readme~README|readme
# the readme doesn't get excluded the second time...
t readme (#i)readme~README|readme~README
# Ranges with backtracking
t 633 <1-1000>33
t 633 <-1000>33
t 633 <1->33
t 633 <->33
# Approximate matching
t READ.ME (#ia1)readme
f READ..ME (#ia1)readme
@ -143,6 +160,8 @@ t dcba (#a3)abcd
t aabaXaaabY (#a1)(a#b)#Y
t aabaXaaabY (#a1)(a#b)(a#b)Y
t aaXaaaaabY (#a1)(a#b)(a#b)Y
t aaaXaaabY (#a1)(a##b)##Y
t aaaXbaabY (#a1)(a##b)##Y
f read.me (#ia1)README~READ.ME
t read.me (#ia1)README~READ_ME
f read.me (#ia1)README~(#a1)READ_ME

View file

@ -6,7 +6,7 @@ DISTFILES_SRC='
builtin.c compat.c cond.c exec.c glob.c hashtable.c hashtable.h
hist.c init.c input.c jobs.c lex.c linklist.c loop.c main.c makepro.awk
math.c mem.c mkbltnmlst.sh mkmakemod.sh mkmodindex.sh
module.c options.c params.c parse.c prompt.c prototypes.h
module.c options.c params.c parse.c pattern.c prompt.c prototypes.h
signals.c signals.h subst.c system.h text.c utils.c
watch.c xmods.conf zsh.h zsh.mdd ztype.h zsh.export
'

View file

@ -35,6 +35,7 @@ VPATH = @srcdir@
sdir = @srcdir@
sdir_top = @top_srcdir@
INSTALL = @INSTALL@
LN = @LN@
@DEFS_MK@
@ -163,10 +164,10 @@ install.bin-here: zsh install.bin-@L@
$(INSTALL_PROGRAM) $(STRIPFLAGS) zsh $(bindir)/zsh-$(VERSION)
if test -f $(bindir)/zsh; then \
rm -f $(bindir)/zsh.old; \
ln $(bindir)/zsh $(bindir)/zsh.old; \
$(LN) $(bindir)/zsh $(bindir)/zsh.old; \
else :; fi
rm -f $(bindir)/zsh.new
ln $(bindir)/zsh-$(VERSION) $(bindir)/zsh.new
$(LN) $(bindir)/zsh-$(VERSION) $(bindir)/zsh.new
mv $(bindir)/zsh.new $(bindir)/zsh
install.bin-N:

View file

@ -80,7 +80,7 @@ bin_example(char *nam, char **args, char *ops, int func)
static int
cond_p_len(char **a, int id)
{
char *s1 = cond_str(a, 0);
char *s1 = cond_str(a, 0, 0);
if (a[1]) {
zlong v = cond_val(a, 1);
@ -95,7 +95,7 @@ cond_p_len(char **a, int id)
static int
cond_i_ex(char **a, int id)
{
char *s1 = cond_str(a, 0), *s2 = cond_str(a, 1);
char *s1 = cond_str(a, 0, 0), *s2 = cond_str(a, 1, 0);
return !strcmp("example", dyncat(s1, s2));
}

View file

@ -227,7 +227,8 @@ struct cmatch {
#define CMF_FILE 1 /* this is a file */
#define CMF_REMOVE 2 /* remove the suffix */
#define CMF_PARBR 4 /* paramter expansion with a brace */
#define CMF_NOLIST 8 /* should not be listed */
#define CMF_PARNEST 8 /* nested paramter expansion */
#define CMF_NOLIST 16 /* should not be listed */
/* Stuff for completion matcher control. */

View file

@ -1947,25 +1947,25 @@ do_comp_vars(int test, int na, char *sa, int nb, char *sb, int mod)
if (compcurrent - 1 < na || compcurrent - 1 > nb)
return 0;
restrict_range(na, nb);
if (mod)
restrict_range(na, nb);
return 1;
}
case CVT_RANGEPAT:
{
char **p;
int i, l = arrlen(compwords), t = 0, b = 0, e = l - 1;
Comp c;
Patprog pp;
i = compcurrent - 1;
if (i < 0 || i >= l)
return 0;
singsub(&sa);
c = parsereg(sa);
pp = patcompile(sa, PAT_STATIC, NULL);
for (i--, p = compwords + i; i >= 0; p--, i--) {
if (domatch(*p, c, 0)) {
if (pattry(pp, *p)) {
b = i + 1;
t = 1;
break;
@ -1975,10 +1975,10 @@ do_comp_vars(int test, int na, char *sa, int nb, char *sb, int mod)
int tt = 0;
singsub(&sb);
c = parsereg(sb);
pp = patcompile(sb, PAT_STATIC, NULL);
for (i++, p = compwords + i; i < l; p++, i++) {
if (domatch(*p, c, 0)) {
if (pattry(pp, *p)) {
e = i - 1;
tt = 1;
break;
@ -1989,7 +1989,7 @@ do_comp_vars(int test, int na, char *sa, int nb, char *sb, int mod)
}
if (e < b)
t = 0;
if (t)
if (t && mod)
restrict_range(b, e);
return t;
}
@ -2011,12 +2011,12 @@ do_comp_vars(int test, int na, char *sa, int nb, char *sb, int mod)
case CVT_PREPAT:
case CVT_SUFPAT:
{
Comp c;
Patprog pp;
if (!na)
return 0;
if (!(c = parsereg(sa)))
if (!(pp = patcompile(sa, PAT_STATIC, 0)))
return 0;
if (test == CVT_PREPAT) {
@ -2036,15 +2036,15 @@ do_comp_vars(int test, int na, char *sa, int nb, char *sb, int mod)
for (; l; l--, p += add) {
sav = *p;
*p = '\0';
test = domatch(compprefix, c, 0);
test = pattry(pp, compprefix);
*p = sav;
if (test && !--na)
break;
}
if (!l)
return 0;
ignore_prefix(p - compprefix);
if (mod)
ignore_prefix(p - compprefix);
} else {
int l, ol, add;
char *p;
@ -2060,13 +2060,13 @@ do_comp_vars(int test, int na, char *sa, int nb, char *sb, int mod)
add = -1;
}
for (; l; l--, p += add)
if (domatch(p, c, 0) && !--na)
if (pattry(pp, p) && !--na)
break;
if (!l)
return 0;
ignore_suffix(ol - (p - compsuffix));
if (mod)
ignore_suffix(ol - (p - compsuffix));
}
return 1;
}
@ -2126,9 +2126,11 @@ bin_compset(char *name, char **argv, char *ops, int func)
case CVT_RANGEPAT:
tokenize(sa);
sa = rembslash(sa);
remnulargs(sa);
if (sb) {
tokenize(sb);
sb = rembslash(sb);
remnulargs(sb);
}
break;
case CVT_PRENUM:
@ -2144,6 +2146,7 @@ bin_compset(char *name, char **argv, char *ops, int func)
na = -1;
tokenize(sa);
sa = rembslash(sa);
remnulargs(sa);
break;
}
return !do_comp_vars(test, na, sa, nb, sb, 1);
@ -2469,10 +2472,10 @@ cond_psfix(char **a, int id)
{
if (comp_check()) {
if (a[1])
return do_comp_vars(id, cond_val(a, 0), cond_str(a, 1),
return do_comp_vars(id, cond_val(a, 0), cond_str(a, 1, 1),
0, NULL, 0);
else
return do_comp_vars(id, -1, cond_str(a, 0), 0, NULL, 0);
return do_comp_vars(id, -1, cond_str(a, 0, 1), 0, NULL, 0);
}
return 0;
}
@ -2481,8 +2484,8 @@ cond_psfix(char **a, int id)
static int
cond_range(char **a, int id)
{
return do_comp_vars(CVT_RANGEPAT, 0, cond_str(a, 0), 0,
(id ? cond_str(a, 1) : NULL), 0);
return do_comp_vars(CVT_RANGEPAT, 0, cond_str(a, 0, 1), 0,
(id ? cond_str(a, 1, 1) : NULL), 0);
}
static struct builtin bintab[] = {

View file

@ -163,7 +163,7 @@ static int ispattern, haspattern;
* from the whole word we are completing and the second one from that *
* part of the word that was identified as a possible filename. */
static Comp patcomp, filecomp;
static Patprog patcomp, filecomp;
/* We store the following prefixes/suffixes: *
* lpre/lsuf -- what's on the line *
@ -728,7 +728,7 @@ check_param(char *s, int set, int test)
if ((*p == String || *p == Qstring) && p[1] != Inpar && p[1] != Inbrack) {
/* This is really a parameter expression (not $(...) or $[...]). */
char *b = p + 1, *e = b;
int n = 0, br = 1;
int n = 0, br = 1, nest = 0;
if (*b == Inbrace) {
char *tb = b;
@ -740,6 +740,10 @@ check_param(char *s, int set, int test)
/* Ignore the possible (...) flags. */
b++, br++;
n = skipparens(Inpar, Outpar, &b);
for (tb = p - 1; tb > s && *tb != Outbrace && *tb != Inbrace; tb--);
if (tb > s && *tb == Inbrace && (tb[-1] == String || *tb == Qstring))
nest = 1;
}
/* Ignore the stuff before the parameter name. */
@ -788,9 +792,11 @@ check_param(char *s, int set, int test)
* global variables. */
if (set) {
if (br >= 2)
if (br >= 2) {
mflags |= CMF_PARBR;
if (nest)
mflags |= CMF_PARNEST;
}
/* Get the prefix (anything up to the character before the name). */
isuf = dupstring(e);
untokenize(isuf);
@ -2542,9 +2548,12 @@ match_str(char *l, char *w, int *bp, int *rwlp, int sfx, int test)
lm = NULL;
} else {
/* No matcher and different characters: l does not match w. */
if (test)
return 0;
abort_match();
return (test ? 0 : -1);
return -1;
}
}
/* If this is a recursive call, we just return if l matched w or not. */
@ -2600,7 +2609,7 @@ match_str(char *l, char *w, int *bp, int *rwlp, int sfx, int test)
* and the suffix don't match the word w. */
static char *
comp_match(char *pfx, char *sfx, char *w, Comp cp,
comp_match(char *pfx, char *sfx, char *w, Patprog cp,
Cline *clp, int qu, int *bpl, int *bsl, int *exact)
{
char *r = NULL;
@ -2610,7 +2619,7 @@ comp_match(char *pfx, char *sfx, char *w, Comp cp,
int wl;
r = w;
if (!domatch(r, cp, 0))
if (!pattry(cp, r))
return NULL;
r = (qu ? quotename(r, NULL) : dupstring(r));
@ -2868,7 +2877,8 @@ join_strs(int la, char *sa, int lb, char *sb)
*ap += mp->wlen; *alp -= mp->wlen;
*bp += bl; *blp -= bl;
t = 1;
}
} else
t = 0;
}
}
}
@ -2907,7 +2917,7 @@ cmp_anchors(Cline o, Cline n, int join)
/* First try the exact strings. */
if ((!(o->flags & CLF_LINE) && o->wlen == n->wlen &&
(!o->word || !strncmp(o->word, n->word, o->wlen))) ||
(line = ((!o->line && !n->line) ||
(line = ((!o->line && !n->line && !o->wlen && !n->wlen) ||
(o->llen == n->llen && o->line && n->line &&
!strncmp(o->line, n->line, o->llen))))) {
if (line) {
@ -3419,6 +3429,11 @@ join_clines(Cline o, Cline n)
}
/* Now see if they have matching anchors. If not, cut the list. */
if (!(o->flags & CLF_MID) && !cmp_anchors(o, n, 1)) {
#if 0
/* This used to search forward for matching anchors.
* Unfortunately this does the wrong thing if the prefixes
* before the differing anchors match nicely. */
Cline t, tn;
for (t = n; (tn = t->next) && !cmp_anchors(o, tn, 1); t = tn);
@ -3427,6 +3442,7 @@ join_clines(Cline o, Cline n)
n = tn;
continue;
} else {
#endif
if (o->flags & CLF_SUF)
break;
@ -3434,7 +3450,10 @@ join_clines(Cline o, Cline n)
o->wlen = 0;
free_cline(o->next);
o->next = NULL;
o->flags |= CLF_MISS;
#if 0
}
#endif
}
/* Ok, they are equal, now join the sub-lists. */
if (o->flags & CLF_MID)
@ -3726,7 +3745,7 @@ int
addmatches(Cadata dat, char **argv)
{
char *s, *ms, *lipre = NULL, *lisuf = NULL, *lpre = NULL, *lsuf = NULL;
char **aign = NULL, **dparr = NULL, oaq = autoq;
char **aign = NULL, **dparr = NULL, oaq = autoq, *oppre = dat->ppre;
char *oqp = qipre, *oqs = qisuf, qc;
int lpl, lsl, pl, sl, bpl, bsl, llpl = 0, llsl = 0, nm = mnum;
int oisalt = 0, isalt, isexact, doadd, ois = instring, oib = inbackt;
@ -3734,7 +3753,7 @@ addmatches(Cadata dat, char **argv)
Cmatch cm;
struct cmlist mst;
Cmlist oms = mstack;
Comp cp = NULL;
Patprog cp = NULL;
LinkList aparl = NULL, oparl = NULL, dparl = NULL;
if (compquote && (qc = *compquote)) {
@ -3798,13 +3817,8 @@ addmatches(Cadata dat, char **argv)
/* Get the contents of the completion variables if we have
* to perform matching. */
if (dat->aflags & CAF_MATCH) {
if (dat->aflags & CAF_QUOTE) {
lipre = dupstring(compiprefix);
lisuf = dupstring(compisuffix);
} else {
lipre = quotename(compiprefix, NULL);
lisuf = quotename(compisuffix, NULL);
}
lipre = dupstring(compiprefix);
lisuf = dupstring(compisuffix);
lpre = dupstring(compprefix);
lsuf = dupstring(compsuffix);
llpl = strlen(lpre);
@ -3830,7 +3844,7 @@ addmatches(Cadata dat, char **argv)
if (haswilds(tmp)) {
if (is)
tmp[llpl] = Star;
if ((cp = parsereg(tmp)))
if ((cp = patcompile(tmp, 0, NULL)))
haspattern = 1;
}
}
@ -3847,12 +3861,21 @@ addmatches(Cadata dat, char **argv)
else if (lisuf)
dat->isuf = lisuf;
if (dat->ppre) {
dat->ppre = dupstring(dat->ppre);
if (!(dat->aflags & CAF_QUOTE)) {
dat->ppre = quotename(dat->ppre, NULL);
if ((dat->flags & CMF_FILE) &&
dat->ppre[0] == '\\' && dat->ppre[1] == '~')
chuck(dat->ppre);
} else
dat->ppre = dupstring(dat->ppre);
lpl = strlen(dat->ppre);
} else
lpl = 0;
if (dat->psuf) {
dat->psuf = dupstring(dat->psuf);
if (!(dat->aflags & CAF_QUOTE))
dat->psuf = quotename(dat->psuf, NULL);
else
dat->psuf = dupstring(dat->psuf);
lsl = strlen(dat->psuf);
} else
lsl = 0;
@ -3877,7 +3900,7 @@ addmatches(Cadata dat, char **argv)
dat->pre = dupstring(dat->pre);
if (dat->suf)
dat->suf = dupstring(dat->suf);
if (!dat->prpre && (dat->prpre = dat->ppre)) {
if (!dat->prpre && (dat->prpre = oppre)) {
singsub(&(dat->prpre));
untokenize(dat->prpre);
} else
@ -3901,22 +3924,6 @@ addmatches(Cadata dat, char **argv)
dat->rems = NULL;
} else if (dat->rems)
dat->rems = dupstring(dat->rems);
/* Probably quote the prefix and suffix for testing. */
if (!(dat->aflags & CAF_QUOTE)) {
if (!cp && (dat->aflags & CAF_MATCH)) {
lpre = quotename(lpre, NULL);
lsuf = quotename(lsuf, NULL);
}
if (dat->ppre) {
dat->ppre = quotename(dat->ppre, NULL);
if ((dat->flags & CMF_FILE) &&
dat->ppre[0] == '\\' && dat->ppre[1] == '~')
chuck(dat->ppre);
}
if (dat->psuf)
dat->psuf = quotename(dat->psuf, NULL);
}
}
/* Walk through the matches given. */
for (; (s = *argv); argv++) {
@ -4340,7 +4347,7 @@ gen_matches_files(int dirs, int execs, int all)
addwhat = execs ? -8 : -5;
if (filecomp)
/* If we have a pattern for the filename check, use it. */
test = domatch(n, filecomp, 0);
test = pattry(filecomp, n);
else {
/* Otherwise use the prefix and suffix strings directly. */
e = n + strlen(n) - fsl;
@ -5024,8 +5031,6 @@ comp_str(int *ipl, int *pl, int untok)
remnulargs(p);
ctokenize(s);
remnulargs(s);
ctokenize(ip);
remnulargs(ip);
}
lp = strlen(p);
ls = strlen(s);
@ -5563,14 +5568,14 @@ static int
makecomplistpc(char *os, int incmd)
{
Patcomp pc;
Comp pat;
Patprog pat;
char *s = findcmd(cmdstr, 1);
int ret = 0;
for (pc = patcomps; pc; pc = pc->next) {
if ((pat = parsereg(pc->pat)) &&
(domatch(cmdstr, pat, 0) ||
(s && domatch(s, pat, 0)))) {
if ((pat = patcompile(pc->pat, PAT_STATIC, NULL)) &&
(pattry(pat, cmdstr) ||
(s && pattry(pat, s)))) {
makecomplistcc(pc->cc, os, incmd);
ret |= 2;
if (!(ccont & CC_CCCONT))
@ -5666,7 +5671,7 @@ makecomplistext(Compctl occ, char *os, int incmd)
{
Compctl compc;
Compcond or, cc;
Comp comp;
Patprog pprog;
int compadd, m = 0, d = 0, t, tt, i, j, a, b, ins;
char *sc = NULL, *s, *ss;
@ -5752,8 +5757,8 @@ makecomplistext(Compctl occ, char *os, int incmd)
if (cc->type == CCT_CURPAT ||
cc->type == CCT_WORDPAT) {
tokenize(ss = dupstring(cc->u.s.s[i]));
t = ((comp = parsereg(ss)) &&
domatch(s, comp, 0));
t = ((pprog = patcompile(ss, PAT_STATIC, NULL)) &&
pattry(pprog, s));
} else
t = (!strcmp(s, rembslash(cc->u.s.s[i])));
break;
@ -5767,8 +5772,8 @@ makecomplistext(Compctl occ, char *os, int incmd)
sc = rembslash(cc->u.l.a[i]);
if (cc->type == CCT_RANGESTR ?
!strncmp(s, sc, strlen(sc)) :
((comp = parsereg(sc)) &&
domatch(s, comp, 0))) {
((pprog = patcompile(sc, PAT_STATIC, 0)) &&
pattry(pprog, s))) {
zsfree(s);
brange = j + 1;
t = 1;
@ -5785,8 +5790,8 @@ makecomplistext(Compctl occ, char *os, int incmd)
sc = rembslash(cc->u.l.b[i]);
if (cc->type == CCT_RANGESTR ?
!strncmp(s, sc, strlen(sc)) :
((comp = parsereg(sc)) &&
domatch(s, comp, 0))) {
((pprog = patcompile(sc, PAT_STATIC, 0)) &&
pattry(pprog, s))) {
zsfree(s);
erange = j - 1;
t = clwpos <= erange;
@ -6050,7 +6055,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
strcpy(p + rpl + 1, rsuf);
} else
strcpy(p + rpl, rsuf);
patcomp = parsereg(p);
patcomp = patcompile(p, 0, NULL);
haspattern = 1;
}
if (!patcomp) {
@ -6148,7 +6153,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
(!comppatmatch || *comppatmatch == '*'))
p[t2++] = Star;
strcpy(p + t2, fsuf);
filecomp = parsereg(p);
filecomp = patcompile(p, 0, NULL);
}
if (!filecomp) {
untokenize(fpre);
@ -6567,7 +6572,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
}
if (cc->hpat) {
/* We have a pattern to take things from the history. */
Comp compc = NULL;
Patprog pprogc = NULL;
char *e, *h, hpatsav;
Histent he;
int i = addhistnum(curhist,-1,HIST_FOREIGN), n = cc->hnum;
@ -6577,7 +6582,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
char *thpat = dupstring(cc->hpat);
tokenize(thpat);
compc = parsereg(thpat);
pprogc = patcompile(thpat, 0, NULL);
}
/* n holds the number of history line we have to search. */
if (!n)
@ -6594,7 +6599,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
/* We now have a word from the history, ignore it *
* if it begins with a quote or `$'. */
if (*h != '\'' && *h != '"' && *h != '`' && *h != '$' &&
(!compc || domatch(h, compc, 0)))
(!pprogc || pattry(pprogc, h)))
/* Otherwise add it if it was matched. */
addmatch(dupstring(h), NULL);
if (hpatsav)
@ -7729,6 +7734,8 @@ do_single(Cmatch m)
minfo.insc++;
if (minfo.we)
minfo.end += minfo.insc;
if (m->flags & CMF_PARNEST)
havesuff = 1;
}
if ((m->flags & CMF_FILE) || (m->ripre && isset(AUTOPARAMSLASH))) {
/* If we have a filename or we completed a parameter name *
@ -7742,11 +7749,12 @@ do_single(Cmatch m)
t = 1;
else {
/* Build the path name. */
if (m->ripre && !*psuf) {
if (m->ripre && !*psuf && !(m->flags & CMF_PARNEST)) {
int ne = noerrs;
p = (char *) zhalloc(strlen(m->ripre) + strlen(str) + 1);
sprintf(p, "%s%s", m->ripre, str);
p = (char *) zhalloc(strlen(m->ripre) + strlen(str) + 2);
sprintf(p, "%s%s%c", m->ripre, str,
((m->flags & CMF_PARBR) ? Outbrace : '\0'));
noerrs = 1;
parsestr(p);
singsub(&p);

View file

@ -86,6 +86,10 @@ static struct builtin builtins[] =
BUILTIN("mem", 0, bin_mem, 0, 0, 0, "v", NULL),
#endif
#if defined(ZSH_PAT_DEBUG)
BUILTIN("patdebug", 0, bin_patdebug, 1, -1, 0, "p", NULL),
#endif
BUILTIN("popd", 0, bin_cd, 0, 2, BIN_POPD, NULL, NULL),
BUILTIN("print", BINF_PRINTOPTS, bin_print, 0, -1, BIN_PRINT, "RDPbnrslzNu0123456789pioOcm-", NULL),
BUILTIN("pushd", 0, bin_cd, 0, 2, BIN_PUSHD, NULL, NULL),
@ -377,7 +381,7 @@ bin_enable(char *name, char **argv, char *ops, int func)
HashTable ht;
HashNode hn;
ScanFunc scanfunc;
Comp com;
Patprog pprog;
int flags1 = 0, flags2 = 0;
int match = 0, returnval = 0;
@ -414,8 +418,8 @@ bin_enable(char *name, char **argv, char *ops, int func)
for (; *argv; argv++) {
/* parse pattern */
tokenize(*argv);
if ((com = parsereg(*argv)))
match += scanmatchtable(ht, com, 0, 0, scanfunc, 0);
if ((pprog = patcompile(*argv, PAT_STATIC, 0)))
match += scanmatchtable(ht, pprog, 0, 0, scanfunc, 0);
else {
untokenize(*argv);
zwarnnam(name, "bad pattern : %s", *argv, 0);
@ -1174,7 +1178,7 @@ bin_fc(char *nam, char **argv, char *ops, int func)
int first = -1, last = -1, retval, minflag = 0;
char *s;
struct asgment *asgf = NULL, *asgl = NULL;
Comp com = NULL;
Patprog pprog = NULL;
/* fc is only permitted in interactive shells */
if (!interact) {
@ -1185,7 +1189,7 @@ bin_fc(char *nam, char **argv, char *ops, int func)
* as a pattern that history lines have to match */
if (*argv && ops['m']) {
tokenize(*argv);
if (!(com = parsereg(*argv++))) {
if (!(pprog = patcompile(*argv++, 0, NULL))) {
zwarnnam(nam, "invalid match pattern", NULL, 0);
return 1;
}
@ -1257,7 +1261,7 @@ bin_fc(char *nam, char **argv, char *ops, int func)
/* list the required part of the history */
retval = fclist(stdout, !ops['n'], ops['r'], ops['D'],
ops['d'] + ops['f'] * 2 + ops['E'] * 4 + ops['i'] * 8,
first, last, asgf, com);
first, last, asgf, pprog);
else {
/* edit history file, and (if successful) use the result as a new command */
int tempfd;
@ -1271,7 +1275,7 @@ bin_fc(char *nam, char **argv, char *ops, int func)
((out = fdopen(tempfd, "w")) == NULL)) {
zwarnnam("fc", "can't open temp file: %e", NULL, errno);
} else {
if (!fclist(out, 0, ops['r'], 0, 0, first, last, asgf, com)) {
if (!fclist(out, 0, ops['r'], 0, 0, first, last, asgf, pprog)) {
char *editor;
editor = auxdata ? auxdata : getsparam("FCEDIT");
@ -1372,7 +1376,7 @@ fcsubs(char **sp, struct asgment *sub)
/**/
static int
fclist(FILE *f, int n, int r, int D, int d, int first, int last, struct asgment *subs, Comp com)
fclist(FILE *f, int n, int r, int D, int d, int first, int last, struct asgment *subs, Patprog pprog)
{
int fclistdone = 0;
char *s;
@ -1400,7 +1404,7 @@ fclist(FILE *f, int n, int r, int D, int d, int first, int last, struct asgment
for (;;) {
s = dupstring(ent->text);
/* this if does the pattern matching, if required */
if (!com || domatch(s, com, 0)) {
if (!pprog || pattry(pprog, s)) {
/* perform substitution */
fclistdone |= fcsubs(&s, subs);
@ -1775,7 +1779,7 @@ bin_typeset(char *name, char **argv, char *ops, int func)
{
Param pm;
Asgment asg;
Comp com;
Patprog pprog;
char *optstr = "aiALRZlurtxUT";
int on = 0, off = 0, roff, bit = PM_ARRAY;
int i;
@ -1914,7 +1918,7 @@ bin_typeset(char *name, char **argv, char *ops, int func)
LinkNode pmnode;
tokenize(asg->name); /* expand argument */
if (!(com = parsereg(asg->name))) {
if (!(pprog = patcompile(asg->name, 0, NULL))) {
untokenize(asg->name);
zwarnnam(name, "bad pattern : %s", argv[-1], 0);
returnval = 1;
@ -1934,7 +1938,7 @@ bin_typeset(char *name, char **argv, char *ops, int func)
if (((pm->flags & PM_RESTRICTED) && isset(RESTRICTED)) ||
(pm->flags & PM_UNSET))
continue;
if (domatch(pm->nam, com, 0))
if (pattry(pprog, pm->nam))
addlinknode(pmlist, pm);
}
}
@ -1974,7 +1978,7 @@ bin_typeset(char *name, char **argv, char *ops, int func)
int
bin_functions(char *name, char **argv, char *ops, int func)
{
Comp com;
Patprog pprog;
Shfunc shf;
int i, returnval = 0;
int on = 0, off = 0, pflags = 0;
@ -2018,16 +2022,18 @@ bin_functions(char *name, char **argv, char *ops, int func)
for (; *argv; argv++) {
/* expand argument */
tokenize(*argv);
if ((com = parsereg(*argv))) {
if ((pprog = patcompile(*argv, PAT_STATIC, 0))) {
/* with no options, just print all functions matching the glob pattern */
if (!(on|off)) {
scanmatchtable(shfunctab, com, 0, DISABLED,
scanmatchtable(shfunctab, pprog, 0, DISABLED,
shfunctab->printnode, pflags);
} else {
/* apply the options to all functions matching the glob pattern */
for (i = 0; i < shfunctab->hsize; i++) {
for (shf = (Shfunc) shfunctab->nodes[i]; shf; shf = (Shfunc) shf->next)
if (domatch(shf->nam, com, 0) && !(shf->flags & DISABLED))
for (shf = (Shfunc) shfunctab->nodes[i]; shf;
shf = (Shfunc) shf->next)
if (pattry(pprog, shf->nam) &&
!(shf->flags & DISABLED))
shf->flags = (shf->flags | on) & (~off);
}
}
@ -2097,7 +2103,7 @@ int
bin_unset(char *name, char **argv, char *ops, int func)
{
Param pm, next;
Comp com;
Patprog pprog;
char *s;
int match = 0, returnval = 0;
int i;
@ -2111,14 +2117,15 @@ bin_unset(char *name, char **argv, char *ops, int func)
while ((s = *argv++)) {
/* expand */
tokenize(s);
if ((com = parsereg(s))) {
if ((pprog = patcompile(s, PAT_STATIC, NULL))) {
/* Go through the parameter table, and unset any matches */
for (i = 0; i < paramtab->hsize; i++) {
for (pm = (Param) paramtab->nodes[i]; pm; pm = next) {
/* record pointer to next, since we may free this one */
next = (Param) pm->next;
if ((!(pm->flags & PM_RESTRICTED) ||
unset(RESTRICTED)) && domatch(pm->nam, com, 0)) {
unset(RESTRICTED)) &&
pattry(pprog, pm->nam)) {
unsetparam_pm(pm, 0, 1);
match++;
}
@ -2184,7 +2191,7 @@ int
bin_whence(char *nam, char **argv, char *ops, int func)
{
HashNode hn;
Comp com;
Patprog pprog;
int returnval = 0;
int printflags = 0;
int csh, all, v, wd;
@ -2213,7 +2220,7 @@ bin_whence(char *nam, char **argv, char *ops, int func)
for (; *argv; argv++) {
/* parse the pattern */
tokenize(*argv);
if (!(com = parsereg(*argv))) {
if (!(pprog = patcompile(*argv, PAT_STATIC, NULL))) {
untokenize(*argv);
zwarnnam(nam, "bad pattern : %s", *argv, 0);
returnval = 1;
@ -2224,21 +2231,26 @@ bin_whence(char *nam, char **argv, char *ops, int func)
* We're not using it, so search for ... */
/* aliases ... */
scanmatchtable(aliastab, com, 0, DISABLED, aliastab->printnode, printflags);
scanmatchtable(aliastab, pprog, 0, DISABLED,
aliastab->printnode, printflags);
/* and reserved words ... */
scanmatchtable(reswdtab, com, 0, DISABLED, reswdtab->printnode, printflags);
scanmatchtable(reswdtab, pprog, 0, DISABLED,
reswdtab->printnode, printflags);
/* and shell functions... */
scanmatchtable(shfunctab, com, 0, DISABLED, shfunctab->printnode, printflags);
scanmatchtable(shfunctab, pprog, 0, DISABLED,
shfunctab->printnode, printflags);
/* and builtins. */
scanmatchtable(builtintab, com, 0, DISABLED, builtintab->printnode, printflags);
scanmatchtable(builtintab, pprog, 0, DISABLED,
builtintab->printnode, printflags);
}
/* Done search for `internal' commands, if the -p option *
* was not used. Now search the path. */
cmdnamtab->filltable(cmdnamtab);
scanmatchtable(cmdnamtab, com, 0, 0, cmdnamtab->printnode, printflags);
scanmatchtable(cmdnamtab, pprog, 0, 0,
cmdnamtab->printnode, printflags);
}
return returnval;
@ -2367,7 +2379,7 @@ int
bin_hash(char *name, char **argv, char *ops, int func)
{
HashTable ht;
Comp com;
Patprog pprog;
Asgment asg;
int returnval = 0;
@ -2405,9 +2417,9 @@ bin_hash(char *name, char **argv, char *ops, int func)
if (ops['m']) {
/* with the -m option, treat the argument as a glob pattern */
tokenize(*argv); /* expand */
if ((com = parsereg(*argv))) {
if ((pprog = patcompile(*argv, PAT_STATIC, NULL))) {
/* display matching hash table elements */
scanmatchtable(ht, com, 0, 0, ht->printnode, 0);
scanmatchtable(ht, pprog, 0, 0, ht->printnode, 0);
} else {
untokenize(*argv);
zwarnnam(name, "bad pattern : %s", *argv, 0);
@ -2464,7 +2476,7 @@ bin_unhash(char *name, char **argv, char *ops, int func)
{
HashTable ht;
HashNode hn, nhn;
Comp com;
Patprog pprog;
int match = 0, returnval = 0;
int i;
@ -2484,13 +2496,13 @@ bin_unhash(char *name, char **argv, char *ops, int func)
for (; *argv; argv++) {
/* expand argument */
tokenize(*argv);
if ((com = parsereg(*argv))) {
if ((pprog = patcompile(*argv, PAT_STATIC, NULL))) {
/* remove all nodes matching glob pattern */
for (i = 0; i < ht->hsize; i++) {
for (hn = ht->nodes[i]; hn; hn = nhn) {
/* record pointer to next, since we may free this one */
nhn = hn->next;
if (domatch(hn->nam, com, 0)) {
if (pattry(pprog, hn->nam)) {
ht->freenode(ht->removenode(ht, hn->nam));
match++;
}
@ -2529,7 +2541,7 @@ int
bin_alias(char *name, char **argv, char *ops, int func)
{
Alias a;
Comp com;
Patprog pprog;
Asgment asg;
int haveflags = 0, returnval = 0;
int flags1 = 0, flags2 = DISABLED;
@ -2565,9 +2577,10 @@ bin_alias(char *name, char **argv, char *ops, int func)
if (ops['m']) {
for (; *argv; argv++) {
tokenize(*argv); /* expand argument */
if ((com = parsereg(*argv))) {
if ((pprog = patcompile(*argv, PAT_STATIC, NULL))) {
/* display the matching aliases */
scanmatchtable(aliastab, com, flags1, flags2, aliastab->printnode, printflags);
scanmatchtable(aliastab, pprog, flags1, flags2,
aliastab->printnode, printflags);
} else {
untokenize(*argv);
zwarnnam(name, "bad pattern : %s", *argv, 0);
@ -2636,17 +2649,17 @@ bin_print(char *name, char **args, char *ops, int func)
/* -m option -- treat the first argument as a pattern and remove
* arguments not matching */
if (ops['m']) {
Comp com;
Patprog pprog;
char **t, **p;
tokenize(*args);
if (!(com = parsereg(*args))) {
if (!(pprog = patcompile(*args, PAT_STATIC, NULL))) {
untokenize(*args);
zwarnnam(name, "bad pattern : %s", *args, 0);
return 1;
}
for (p = ++args; *p; p++)
if (!domatch(*p, com, 0))
if (!pattry(pprog, *p))
for (t = p--; (*t = t[1]); t++);
}
/* compute lengths, and interpret according to -P, -D, -e, etc. */

View file

@ -303,12 +303,13 @@ optison(char *s)
/**/
char *
cond_str(char **args, int num)
cond_str(char **args, int num, int raw)
{
char *s = args[num];
singsub(&s);
untokenize(s);
if (!raw)
untokenize(s);
return s;
}

1807
Src/glob.c

File diff suppressed because it is too large Load diff

View file

@ -418,7 +418,7 @@ scanhashtable(HashTable ht, int sorted, int flags1, int flags2, ScanFunc scanfun
/**/
int
scanmatchtable(HashTable ht, Comp com, int flags1, int flags2, ScanFunc scanfunc, int scanflags)
scanmatchtable(HashTable ht, Patprog pprog, int flags1, int flags2, ScanFunc scanfunc, int scanflags)
{
int i, hsize = ht->hsize;
HashNode *nodes = ht->nodes;
@ -433,7 +433,7 @@ scanmatchtable(HashTable ht, Comp com, int flags1, int flags2, ScanFunc scanfunc
HashNode hn = st.u.u;
st.u.u = st.u.u->next;
if ((hn->flags & flags1) + !flags1 && !(hn->flags & flags2) &&
domatch(hn->nam, com, 0)) {
pattry(pprog, hn->nam)) {
scanfunc(hn, scanflags);
match++;
}

View file

@ -577,6 +577,18 @@ histsubchar(int c)
case 'q':
quote(&sline);
break;
case 'Q':
{
int one = noerrs, oef = errflag;
noerrs = 1;
parse_subst_string(sline);
noerrs = one;
errflag = oef;
remnulargs(sline);
untokenize(sline);
}
break;
case 'x':
quotebreak(&sline);
break;
@ -1947,6 +1959,7 @@ lockhistfile(char *fn, int keep_trying)
int fd, len = strlen(fn);
char *tmpfile, *lockfile;
#ifdef HAVE_LINK
tmpfile = zalloc(len + 10 + 1);
sprintf(tmpfile, "%s.%ld", fn, (long)mypid);
if ((fd = open(tmpfile, O_RDWR|O_CREAT|O_EXCL, 0644)) >= 0) {
@ -1973,6 +1986,21 @@ lockhistfile(char *fn, int keep_trying)
}
unlink(tmpfile);
free(tmpfile);
#else /* not HAVE_LINK */
lockfile = zalloc(len + 5 + 1);
sprintf(lockfile, "%s.LOCK", fn);
while ((fd = open(lockfile, O_CREAT|O_EXCL, 0644)) < 0) {
if (errno == EEXIST) continue;
else if (keep_trying) {
if (time(NULL) - sb.st_mtime < 10)
sleep(1);
continue;
}
lockhistct--;
break;
}
free(lockfile);
#endif /* HAVE_LINK */
}
return ct != lockhistct;
}

View file

@ -353,7 +353,7 @@ init_io(void)
* Try both stdin and stdout before trying /dev/tty. -- Bart
*/
#if defined(HAVE_FCNTL_H) && defined(F_GETFL)
#define rdwrtty(fd) ((fcntl(fd, F_GETFL) & O_RDWR) == O_RDWR)
#define rdwrtty(fd) ((fcntl(fd, F_GETFL, 0) & O_RDWR) == O_RDWR)
#else
#define rdwrtty(fd) 1
#endif

View file

@ -835,7 +835,11 @@ waitforpid(pid_t pid)
/* child_block() around this loop in case #ifndef WNOHANG */
child_block(); /* unblocked in child_suspend() */
#ifdef BROKEN_KILL_ESRCH
while (!errflag && (kill(pid, 0) >= 0 || (errno != ESRCH && errno != EINVAL))) {
#else /* not BROKEN_KILL_ESRCH */
while (!errflag && (kill(pid, 0) >= 0 || errno != ESRCH)) {
#endif /* BROKEN_KILL_ESRCH */
if (first)
first = 0;
else

View file

@ -178,8 +178,13 @@ execselect(Cmd cmd, LinkList args, int flags)
for (;;) {
if (empty(bufstack)) {
if (interact && SHTTY != -1 && isset(USEZLE)) {
int oef = errflag;
isfirstln = 1;
str = (char *)zleread(prompt3, NULL, 0);
if (errflag)
str = NULL;
errflag = oef;
} else {
str = promptexpand(prompt3, 0, NULL, NULL);
zputs(str, stderr);

View file

@ -526,7 +526,7 @@ bin_setopt(char *nam, char **args, char *ops, int isun)
} else {
/* Globbing option (-m) set. */
while (*args) {
Comp com;
Patprog pprog;
char *s, *t;
t = s = dupstring(*args);
@ -540,12 +540,12 @@ bin_setopt(char *nam, char **args, char *ops, int isun)
/* Expand the current arg. */
tokenize(s);
if (!(com = parsereg(s))) {
if (!(pprog = patcompile(s, PAT_STATIC, NULL))) {
zwarnnam(nam, "bad pattern: %s", *args, 0);
continue;
}
/* Loop over expansions. */
scanmatchtable(optiontab, com, 0, OPT_ALIAS, setoption, !isun);
scanmatchtable(optiontab, pprog, 0, OPT_ALIAS, setoption, !isun);
args++;
}
}
@ -653,6 +653,14 @@ dosetopt(int optno, int value, int force)
setuid(getuid());
setgid(getgid());
#endif /* HAVE_SETUID */
#ifndef JOB_CONTROL
} else if(optno == MONITOR && value) {
return -1;
#endif /* not JOB_CONTROL */
#ifdef GETPWNAM_FAKED
} else if(optno == CDABLEVARS && value) {
return -1;
#endif /* GETPWNAM_FAKED */
}
opts[optno] = value;
if (optno == BANGHIST || optno == SHINSTDIN)

View file

@ -354,7 +354,7 @@ scancountparams(HashNode hn, int flags)
++numparamvals;
}
static Comp scancomp;
static Patprog scanprog;
static char **paramvals;
/**/
@ -366,7 +366,8 @@ scanparamvals(HashNode hn, int flags)
!(flags & SCANPM_MATCHMANY))
return;
v.pm = (Param)hn;
if ((flags & SCANPM_MATCHKEY) && !domatch(v.pm->nam, scancomp, 0)) {
if ((flags & SCANPM_MATCHKEY) &&
!pattry(scanprog, v.pm->nam)) {
return;
}
if (flags & SCANPM_WANTKEYS) {
@ -380,7 +381,7 @@ scanparamvals(HashNode hn, int flags)
v.b = -1;
paramvals[numparamvals] = getstrvalue(&v);
if (flags & SCANPM_MATCHVAL) {
if (domatch(paramvals[numparamvals], scancomp, 0)) {
if (pattry(scanprog, paramvals[numparamvals])) {
numparamvals += ((flags & SCANPM_WANTVALS) ? 1 :
!(flags & SCANPM_WANTKEYS));
} else if (flags & SCANPM_WANTKEYS)
@ -724,7 +725,7 @@ getarg(char **str, int *inv, Value v, int a2, zlong *w)
int hasbeg = 0, word = 0, rev = 0, ind = 0, down = 0, l, i, ishash;
char *s = *str, *sep = NULL, *t, sav, *d, **ta, **p, *tt;
zlong num = 1, beg = 0, r = 0;
Comp c;
Patprog pprog;
ishash = (v->pm && PM_TYPE(v->pm->flags) == PM_HASHED);
@ -923,12 +924,12 @@ getarg(char **str, int *inv, Value v, int a2, zlong *w)
}
tokenize(s);
if ((c = parsereg(s))) {
if ((pprog = patcompile(s, 0, NULL))) {
int len;
if (v->isarr) {
if (ishash) {
scancomp = c;
scanprog = pprog;
if (ind)
v->isarr |= SCANPM_MATCHKEY;
else
@ -952,12 +953,12 @@ getarg(char **str, int *inv, Value v, int a2, zlong *w)
if (!hasbeg)
beg = len - 1;
for (r = 1 + beg, p = ta + beg; p >= ta; r--, p--) {
if (domatch(*p, c, 0) && !--num)
if (pattry(pprog, *p) && !--num)
return r;
}
} else
for (r = 1 + beg, p = ta + beg; *p; r++, p++)
if (domatch(*p, c, 0) && !--num)
if (pattry(pprog, *p) && !--num)
return r;
}
} else if (word) {
@ -970,13 +971,13 @@ getarg(char **str, int *inv, Value v, int a2, zlong *w)
if (!hasbeg)
beg = len - 1;
for (r = 1 + beg, p = ta + beg; p >= ta; p--, r--)
if (domatch(*p, c, 0) && !--num)
if (pattry(pprog, *p) && !--num)
break;
if (p < ta)
return 0;
} else {
for (r = 1 + beg, p = ta + beg; *p; r++, p++)
if (domatch(*p, c, 0) && !--num)
if (pattry(pprog, *p) && !--num)
break;
if (!*p)
return 0;
@ -1007,7 +1008,8 @@ getarg(char **str, int *inv, Value v, int a2, zlong *w)
for (r = beg, t = d + beg; t >= d; r--, t--) {
sav = *t;
*t = '\0';
if (domatch(d, c, 0) && !--num) {
if (pattry(pprog, d)
&& !--num) {
*t = sav;
return r;
}
@ -1017,7 +1019,8 @@ getarg(char **str, int *inv, Value v, int a2, zlong *w)
for (r = beg, t = d + beg; *t; r++, t++) {
sav = *t;
*t = '\0';
if (domatch(d, c, 0) && !--num) {
if (pattry(pprog, d) &&
!--num) {
*t = sav;
return r;
}
@ -1028,12 +1031,14 @@ getarg(char **str, int *inv, Value v, int a2, zlong *w)
if (!hasbeg)
beg = len - 1;
for (r = beg + 1, t = d + beg; t >= d; r--, t--) {
if (domatch(t, c, 0) && !--num)
if (pattry(pprog, t) &&
!--num)
return r;
}
} else
for (r = beg + 1, t = d + beg; *t; r++, t++)
if (domatch(t, c, 0) && !--num)
if (pattry(pprog, t) &&
!--num)
return r;
}
}

2284
Src/pattern.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -326,14 +326,23 @@ signal_suspend(int sig, int sig2)
#ifdef POSIX_SIGNALS
sigset_t set;
#ifdef BROKEN_POSIX_SIGSUSPEND
sigset_t oset;
#endif /* BROKEN_POSIX_SIGSUSPEND */
sigfillset(&set);
sigdelset(&set, sig);
sigdelset(&set, SIGHUP); /* still don't know why we add this? */
if (sig2)
sigdelset(&set, sig2);
#ifdef BROKEN_POSIX_SIGSUSPEND
sigprocmask(SIG_SETMASK, &set, &oset);
pause();
sigprocmask(SIG_SETMASK, &oset, NULL);
#else /* not BROKEN_POSIX_SIGSUSPEND */
ret = sigsuspend(&set);
#else
#endif /* BROKEN_POSIX_SIGSUSPEND */
#else /* not POSIX_SIGNALS */
# ifdef BSD_SIGNALS
sigset_t set;
@ -601,6 +610,9 @@ killjb(Job jn, int sig)
}
for (pn = jn->procs; pn; pn = pn->next)
if ((err = kill(pn->pid, sig)) == -1 && errno != ESRCH)
#ifdef BROKEN_KILL_ESRCH
if(errno != EINVAL || sig != 0)
#endif /* BROKEN_KILL_ESRCH */
return -1;
return err;
}
@ -640,7 +652,11 @@ dosavetrap(int sig, int level)
*/
char func[20];
sprintf(func, "TRAP%s", sigs[sig]);
st->list = shfunctab->removenode(shfunctab, func);
/* We call removehashnode() directly because otherwise
* removeshfuncnode() would be called which in turn would
* call us again so that we would end up with a NULL pointer
* instead of the list for the trap. */
st->list = removehashnode(shfunctab, func);
} else {
st->list = sigfuncs[sig];
unsettrap(sig);

View file

@ -721,6 +721,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
int flnum = 0;
int sortit = 0, casind = 0;
int casmod = 0;
int quotemod = 0, quoteerr = 0;
char *sep = NULL, *spsep = NULL;
char *premul = NULL, *postmul = NULL, *preone = NULL, *postone = NULL;
char *replstr = NULL; /* replacement string for /orig/repl */
@ -822,6 +823,17 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
case 'i':
casind = 1;
break;
case 'q':
quotemod++;
break;
case 'Q':
quotemod--;
break;
case 'X':
quoteerr = 1;
break;
case 'e':
eval = 1;
break;
@ -1379,12 +1391,23 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
case '#':
case Pound:
case '/':
if (qt)
if (parse_subst_string(s)) {
if (qt) {
int one = noerrs, oef = errflag, haserr;
if (!quoteerr)
noerrs = 1;
haserr = parse_subst_string(s);
noerrs = one;
if (!quoteerr) {
errflag = oef;
if (haserr)
tokenize(s);
} else if (haserr || errflag) {
zerr("parse error in ${...%c...} substitution",
NULL, s[-1]);
return NULL;
}
}
{
char t = s[-1];
@ -1546,6 +1569,58 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
makecapitals(&val);
}
}
if (quotemod) {
if (isarr) {
char **ap;
if (!copied)
aval = arrdup(aval), copied = 1;
ap = aval;
if (quotemod > 0)
for (; *ap; ap++)
*ap = bslashquote(*ap, NULL, 0);
else {
int one = noerrs, oef = errflag, haserr = 0;
if (!quoteerr)
noerrs = 1;
for (; *ap; ap++) {
haserr |= parse_subst_string(*ap);
remnulargs(*ap);
untokenize(*ap);
}
noerrs = one;
if (!quoteerr)
errflag = oef;
else if (haserr || errflag) {
zerr("parse error in parameter value", NULL, 0);
return NULL;
}
}
} else {
if (!copied)
val = dupstring(val), copied = 1;
if (quotemod > 0)
val = bslashquote(val, NULL, 0);
else {
int one = noerrs, oef = errflag, haserr;
if (!quoteerr)
noerrs = 1;
haserr = parse_subst_string(val);
noerrs = one;
if (!quoteerr)
errflag = oef;
else if (haserr || errflag) {
zerr("parse error in parameter value", NULL, 0);
return NULL;
}
remnulargs(val);
untokenize(val);
}
}
}
if (isarr) {
char *x;
char *y;
@ -1747,6 +1822,7 @@ modify(char **str, char **ptr)
case 'l':
case 'u':
case 'q':
case 'Q':
c = **ptr;
break;
@ -1868,6 +1944,18 @@ modify(char **str, char **ptr)
case 'q':
copy = bslashquote(copy, NULL, 0);
break;
case 'Q':
{
int one = noerrs, oef = errflag;
noerrs = 1;
parse_subst_string(copy);
noerrs = one;
errflag = oef;
remnulargs(copy);
untokenize(copy);
}
break;
}
tc = *tt;
*tt = '\0';
@ -1922,6 +2010,18 @@ modify(char **str, char **ptr)
case 'q':
*str = bslashquote(*str, NULL, 0);
break;
case 'Q':
{
int one = noerrs, oef = errflag;
noerrs = 1;
parse_subst_string(*str);
noerrs = one;
errflag = oef;
remnulargs(*str);
untokenize(*str);
}
break;
}
}
if (rec < 0) {

View file

@ -267,6 +267,8 @@ struct timezone {
# ifndef TIME_H_SELECT_H_CONFLICTS
# include <sys/select.h>
# endif
#elif defined(SELECT_IN_SYS_SOCKET_H)
# include <sys/socket.h>
#endif
#ifdef HAVE_SYS_FILIO_H
@ -613,3 +615,8 @@ extern short ospeed;
#define ftell ftello
#endif
#endif
/* Can't support job control without working tcsetgrp() */
#ifdef BROKEN_TCSETPGRP
#undef JOB_CONTROL
#endif /* BROKEN_TCSETPGRP */

View file

@ -1249,7 +1249,7 @@ setblock_stdin(void)
long mode;
if (!fstat(0, &st) && !S_ISREG(st.st_mode)) {
mode = fcntl(0, F_GETFL);
mode = fcntl(0, F_GETFL, 0);
if (mode != -1 && (mode & NONBLOCK) &&
!fcntl(0, F_SETFL, mode & ~NONBLOCK))
return 1;

View file

@ -50,7 +50,6 @@ deletehookfunc
deleteparamdefs
deleteparamtable
deletewrapper
domatch
dosetopt
doshfunc
down_histent
@ -177,10 +176,11 @@ paramtab
parbegin
parend
parse_string
parsereg
parsestr
patcompile
path
pathchecked
pattry
popheap
postedit
ppid

View file

@ -260,6 +260,7 @@ typedef struct builtin *Builtin;
typedef struct nameddir *Nameddir;
typedef struct module *Module;
typedef struct patprog *Patprog;
typedef struct process *Process;
typedef struct job *Job;
typedef struct value *Value;
@ -270,7 +271,6 @@ typedef struct cmd *Cmd;
typedef struct pline *Pline;
typedef struct sublist *Sublist;
typedef struct list *List;
typedef struct comp *Comp;
typedef struct redir *Redir;
typedef struct complist *Complist;
typedef struct heap *Heap;
@ -906,6 +906,57 @@ struct hookdef {
#define HOOKDEF(name, func, flags) { NULL, name, (Hookfn) func, flags, NULL }
/*
* Types used in pattern matching. Most of these longs could probably
* happily be ints.
*/
#define NSUBEXP 10
struct patprog {
long startoff; /* length before start of programme */
long size; /* total size from start of struct */
long mustoff; /* offset to string that must be present */
int globflags; /* globbing flags to set at start */
int globend; /* globbing flags set after finish */
int flags; /* PAT_* flags */
int patmlen;
char patstartch;
#ifdef BACKREFERENCES
unsigned char * ppStartp[NSUBEXP];
unsigned char * ppEndp[NSUBEXP];
};
/* Same as patprog, but without the backreference storage.
* Note the calling code must test PAT_BACKR to know which is
* which, since they are both passed back as a Patprog.
*/
struct patprog_short {
long startoff;
long size;
long mustoff;
int globflags;
int globend;
int flags;
int patmlen;
char patstartch;
#endif
};
/* Flags used in pattern matchers (Patprog) and passed down to patcompile */
#define PAT_FILE 0x0001 /* Pattern is a file name */
#define PAT_FILET 0x0002 /* Pattern is top level file, affects ~ */
#define PAT_ANY 0x0004 /* Match anything (cheap "*") */
#define PAT_NOANCH 0x0008 /* Not anchored at end */
#define PAT_NOGLD 0x0010 /* Don't glob dots */
#define PAT_PURES 0x0020 /* Pattern is a pure string: set internally */
#define PAT_STATIC 0x0040 /* Don't copy pattern to heap as per default */
#define PAT_SCAN 0x0080 /* Scanning, so don't try must-match test */
#ifdef BACKREFERENCES
#define PAT_BACKR 0x0100 /* Parentheses make backreferences */
#endif
/* node used in parameter hash table (paramtab) */
struct param {

View file

@ -5,7 +5,7 @@ alwayslink=1
objects="builtin.o compat.o cond.o exec.o glob.o hashtable.o \
hist.o init.o input.o jobs.o lex.o linklist.o loop.o math.o \
mem.o module.o options.o params.o parse.o prompt.o signals.o \
mem.o module.o options.o params.o parse.o pattern.o prompt.o signals.o \
signames.o subst.o text.o utils.o watch.o"
headers="../config.h system.h zsh.h sigcount.h signals.h \

View file

@ -285,11 +285,12 @@ Note that no preprocessing is done on the strings. This means that
no substitutions are performed on them and that they will be
tokenized. There are three helper functions available:
- char *cond_str(args, num)
- char *cond_str(args, num, raw)
The first argument is the array of strings the handler function
got as an argument and the second one is an index into this array.
The return value is the num'th string from the array with
substitutions performed and untokenized.
substitutions performed. If the last argument is zero, the string
will also be untokenized.
- long cond_val(args, num)
The arguments are the same as for cond_str(). The return value is
the result of the mathematical evaluation of the num'th string

View file

@ -198,6 +198,9 @@
/* Define to 1 if there is a prototype defined for ioctl() on your system */
#undef HAVE_IOCTL_PROTO
/* Define to 1 if select() is defined in <sys/socket.h>, ie BeOS R4.51*/
#undef SELECT_IN_SYS_SOCKET_H
/* Define to 1 if system has working FIFO's */
#undef HAVE_FIFOS
@ -216,6 +219,21 @@
/* Define to 1 if /bin/sh does not interpret \ escape sequences */
#undef SH_USE_BSD_ECHO
/* Define to 1 if system has working link() */
#undef HAVE_LINK
/* Define to 1 if kill(pid, 0) doesn't return ESRCH, ie BeOS R4.51 */
#undef BROKEN_KILL_ESRCH
/* Define to 1 if sigsuspend() is broken, ie BeOS R4.51 */
#undef BROKEN_POSIX_SIGSUSPEND
/* Define to 1 if getpwnam() is faked, ie BeOS R4.51 */
#undef GETPWNAM_FAKED
/* Define to 1 if tcsetpgrp() doesn't work, ie BeOS R4.51 */
#undef BROKEN_TCSETPGRP
/* Define to 1 if an underscore has to be prepended to dlsym() argument */
#undef DLSYM_NEEDS_UNDERSCORE

22
aclocal.m4 vendored
View file

@ -52,4 +52,26 @@ case "x$fp_cv_prog_cc_stdc" in
esac
])
AC_DEFUN(AC_PROG_LN,
[AC_MSG_CHECKING(whether ln works)
AC_CACHE_VAL(ac_cv_prog_LN,
[rm -f conftestdata conftestlink
echo > conftestdata
if ln conftestdata conftestlink 2>/dev/null
then
rm -f conftestdata conftestlink
ac_cv_prog_LN="ln"
else
rm -f conftestdata
ac_cv_prog_LN="cp"
fi])dnl
LN="$ac_cv_prog_LN"
if test "$ac_cv_prog_LN" = "ln"; then
AC_MSG_RESULT(yes)
else
AC_MSG_RESULT(no)
fi
AC_SUBST(LN)dnl
])
builtin(include, aczsh.m4)

View file

@ -380,6 +380,7 @@ dnl ------------------
AC_PROG_MAKE_SET dnl Does make define $MAKE
AC_PROG_INSTALL dnl Check for BSD compatible `install'
AC_PROG_AWK dnl Check for mawk,gawk,nawk, then awk.
AC_PROG_LN dnl Check for working ln, for "make install"
AC_CHECK_PROGS([YODL], [yodl], [:])
dnl ------------------
@ -1046,6 +1047,20 @@ if test "$ac_cv_prog_cc_stdc" != no; then
fi
fi
dnl -------------------
dnl select() defined in <sys/socket.h>, ie BeOS R4.51
dnl -------------------
if test $ac_cv_header_sys_select_h != yes; then
AC_CACHE_CHECK(for select() in <sys/socket.h>,
zsh_cv_header_socket_h_select_proto,
[AC_TRY_COMPILE([#include <sys/socket.h>], [fd_set fd;],
zsh_cv_header_socket_h_select_proto=yes,
zsh_cv_header_socket_h_select_proto=no)])
if test $zsh_cv_header_socket_h_select_proto = yes; then
AC_DEFINE(SELECT_IN_SYS_SOCKET_H)
fi
fi
dnl -----------
dnl named FIFOs
dnl -----------
@ -1099,6 +1114,156 @@ if test $zsh_cv_prog_sh_echo_escape = no; then
AC_DEFINE(SH_USE_BSD_ECHO)
fi
dnl -----------
dnl test for whether link() works
dnl for instance, BeOS R4.51 doesn't support hard links yet
dnl -----------
AC_CACHE_CHECK(if link() works,
zsh_cv_sys_link,
[AC_TRY_RUN([
#include <unistd.h>
#include <fcntl.h>
main()
{
int ret;
char *tmpfile, *newfile;
tmpfile="/tmp/zsh.linktest$$";
newfile="/tmp/zsh.linktest2$$";
unlink(tmpfile);
unlink(newfile);
if(creat(tmpfile, 0644) < 0)
exit(1);
ret = link(tmpfile, newfile);
unlink(tmpfile);
unlink(newfile);
exit(ret<0);
}
],
zsh_cv_sys_link=yes,
zsh_cv_sys_link=no,
zsh_cv_sys_link=yes)])
if test $zsh_cv_sys_link = yes; then
AC_DEFINE(HAVE_LINK)
fi
dnl -----------
dnl test for whether kill(pid, 0) where pid doesn't exit
dnl should set errno to ESRCH, but some like BeOS R4.51 set to EINVAL
dnl -----------
AC_CACHE_CHECK(if kill(pid, 0) returns ESRCH correctly,
zsh_cv_sys_killesrch,
[AC_TRY_RUN([
#include <unistd.h>
#include <signal.h>
#include <errno.h>
main()
{
int pid, ret;
pid=getpid() + 10000;
ret=kill(pid, 0);
exit(ret<0 && errno!=ESRCH);
}
],
zsh_cv_sys_killesrch=yes,
zsh_cv_sys_killesrch=no,
zsh_cv_sys_killesrch=yes)])
if test $zsh_cv_sys_killesrch = no; then
AC_DEFINE(BROKEN_KILL_ESRCH)
fi
dnl -----------
dnl if POSIX, test for working sigsuspend().
dnl for instance, BeOS R4.51 is broken.
dnl -----------
if test $signals_style=POSIX_SIGNALS; then
AC_CACHE_CHECK(if POSIX sigsuspend() works,
zsh_cv_sys_sigsuspend,
[AC_TRY_RUN([
#include <signal.h>
#include <unistd.h>
int child=0;
void handler(sig)
int sig;
{if(sig==SIGCHLD) child=1;}
main() {
struct sigaction act;
sigset_t set;
int pid, ret;
act.sa_handler = &handler;
sigfillset(&act.sa_mask);
act.sa_flags = 0;
sigaction(SIGCHLD, &act, 0);
sigfillset(&set);
sigprocmask(SIG_SETMASK, &set, 0);
pid=fork();
if(pid==0) return 0;
if(pid>0) {
sigemptyset(&set);
ret=sigsuspend(&set);
exit(child==0);
}
}
],
zsh_cv_sys_sigsuspend=yes,
zsh_cv_sys_sigsuspend=no,
zsh_cv_sys_sigsuspend=yes)])
if test $zsh_cv_sys_sigsuspend = no; then
AC_DEFINE(BROKEN_POSIX_SIGSUSPEND)
fi
fi
dnl -----------
dnl if found tcsetpgrp, test to see if it actually works
dnl for instance, BeOS R4.51 does not support it yet
dnl -----------
if test $ac_cv_func_tcsetpgrp=yes; then
AC_CACHE_CHECK(if tcsetpgrp() actually works,
zsh_cv_sys_tcsetpgrp,
[AC_TRY_RUN([
#include <sys/types.h>
#include <unistd.h>
main() {
int ret;
ret=tcsetpgrp(0, tcgetpgrp(0));
exit(ret<0);
}
],
zsh_cv_sys_tcsetpgrp=yes,
zsh_cv_sys_tcsetpgrp=no,
zsh_cv_sys_tcsetpgrp=yes)])
if test $zsh_cv_sys_tcsetpgrp = no; then
AC_DEFINE(BROKEN_TCSETPGRP)
fi
fi
dnl -----------
dnl test for faked getpwnam() entry, ie a single entry returned for any username
dnl for instance, BeOS R4.51 is not multiuser yet, and fakes getpwnam()
dnl test by looking up two usernames that shouldn't succeed, and compare entry
dnl -----------
if test $ac_cv_func_getpwnam=yes; then
AC_CACHE_CHECK(if getpwnam() is faked,
zsh_cv_sys_getpwnam_faked,
[AC_TRY_RUN([
#include <pwd.h>
main() {
struct passwd *pw1, *pw2;
char buf[1024];
sprintf(buf, "%d:%d", getpid(), rand());
pw1=getpwnam(buf);
sprintf(buf, "%d:%d", rand(), getpid());
pw2=getpwnam(buf);
exit(pw1!=0 && pw2!=0 && !strcmp(pw1->pw_name, pw2->pw_name));
}
],
zsh_cv_sys_getpwnam_faked=no,
zsh_cv_sys_getpwnam_faked=yes,
zsh_cv_sys_getpwnam_faked=no)])
if test $zsh_cv_sys_getpwnam_faked = yes; then
AC_DEFINE(GETPWNAM_FAKED)
fi
fi
dnl ---------------
dnl dynamic loading
dnl ---------------