Skip to content

Commit

Permalink
alxwded@github, keep track of the :g and :a modifiers per modifier they
Browse files Browse the repository at this point in the history
affect.
  • Loading branch information
zoulasc committed Jan 3, 2020
1 parent d85e2f0 commit 96c1e29
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 47 deletions.
2 changes: 2 additions & 0 deletions Fixes
@@ -1,3 +1,5 @@
7. alxwded@github, keep track of the :g and :a modifiers per modifier they
affect.
6. alzwded@github, fix infinite loop with :gas variable modifier
5. PR/88: Add a Q: modifier that preserves empty arguments leaving :q
alone.
Expand Down
117 changes: 71 additions & 46 deletions sh.dol.c
Expand Up @@ -64,8 +64,10 @@ static Char *dolp; /* Remaining chars from this word */
static Char **dolnxt; /* Further words */
static int dolcnt; /* Count of further words */
static struct Strbuf dolmod; /* = Strbuf_INIT; : modifier characters */
static int dolmcnt; /* :gx -> INT_MAX, else 1 */
static int dol_flag_a; /* :ax -> 1, else 0 */

static int ndolflags; /* keep track of mod counts for each modifier */
static int *dolmcnts; /* :gx -> INT_MAX, else 1 */
static int *dolaflags; /* :ax -> 1, else 0 */

static Char **Dfix2 (Char *const *);
static int Dpack (struct Strbuf *);
Expand Down Expand Up @@ -378,7 +380,7 @@ Dgetdol(void)
static Char *dolbang = NULL;

cleanup_push(name, Strbuf_free);
dolmod.len = dolmcnt = dol_flag_a = 0;
dolmod.len = ndolflags = 0;
c = sc = DgetC(0);
if (c == DEOF) {
stderror(ERR_SYNTAX);
Expand Down Expand Up @@ -718,21 +720,27 @@ fixDolMod(void)

c = DgetC(0);
if (c == ':') {
ndolflags = 0;
do {
c = DgetC(0), dolmcnt = 1, dol_flag_a = 0;
++ndolflags;
dolmcnts = xrealloc(dolmcnts, ndolflags);
dolaflags = xrealloc(dolaflags, ndolflags);
c = DgetC(0), dolmcnts[ndolflags - 1] = 1, dolaflags[ndolflags - 1] = 0;
if (c == 'g' || c == 'a') {
if (c == 'g')
dolmcnt = INT_MAX;
else
dol_flag_a = 1;
if (c == 'g') {
dolmcnts[ndolflags - 1] = INT_MAX;
} else {
dolaflags[ndolflags - 1] = 1;
}
c = DgetC(0);
}
if ((c == 'g' && dolmcnt != INT_MAX) ||
(c == 'a' && dol_flag_a == 0)) {
if (c == 'g')
dolmcnt = INT_MAX;
else
dol_flag_a = 1;
if ((c == 'g' && dolmcnts[ndolflags - 1] != INT_MAX) ||
(c == 'a' && dolaflags[ndolflags - 1] == 0)) {
if (c == 'g') {
dolmcnts[ndolflags - 1] = INT_MAX;
} else {
dolaflags[ndolflags - 1] = 1;
}
c = DgetC(0);
}

Expand Down Expand Up @@ -761,8 +769,9 @@ fixDolMod(void)
if (!any(TCSH_MODIFIERS, c))
stderror(ERR_BADMOD, (int)c);
Strbuf_append1(&dolmod, (Char) c);
if (c == 'q')
dolmcnt = INT_MAX;
if (c == 'q') {
dolmcnts[ndolflags - 1] = INT_MAX;
}
}
while ((c = DgetC(0)) == ':');
unDredc(c);
Expand All @@ -771,13 +780,25 @@ fixDolMod(void)
unDredc(c);
}

static int
all_dolmcnts_are_0()
{
int i = 0;
for(; i < ndolflags; ++i) {
if(dolmcnts[i] != 0)
return 0;
}
return 1;
}

static void
setDolp(Char *cp)
{
Char *dp;
size_t i;
int nthMod = 0;

if (dolmod.len == 0 || dolmcnt == 0) {
if (dolmod.len == 0 || all_dolmcnts_are_0()) {
dolp = cp;
return;
}
Expand Down Expand Up @@ -812,36 +833,38 @@ setDolp(Char *cp)

strip(lhsub);
strip(rhsub);
strip(cp);
dp = cp;
do {
dp = Strstr(dp + last_match, lhsub);
if (dp) {
ptrdiff_t diff = dp - cp;
size_t len = (Strlen(cp) + 1 - lhlen + rhlen);
np = xmalloc(len * sizeof(Char));
(void) Strncpy(np, cp, diff);
(void) Strcpy(np + diff, rhsub);
(void) Strcpy(np + diff + rhlen, dp + lhlen);
last_match = diff + rhlen;

xfree(cp);
dp = cp = np;
cp[--len] = '\0';
didmod = 1;
if (diff >= (ssize_t)len)
break;
} else {
/* should this do a seterror? */
break;
}
}
while (dol_flag_a != 0);
if(dolmcnts[nthMod] != 0) {
strip(cp);
dp = cp;
do {
dp = Strstr(dp + last_match, lhsub);
if (dp) {
ptrdiff_t diff = dp - cp;
size_t len = (Strlen(cp) + 1 - lhlen + rhlen);
np = xmalloc(len * sizeof(Char));
(void) Strncpy(np, cp, diff);
(void) Strcpy(np + diff, rhsub);
(void) Strcpy(np + diff + rhlen, dp + lhlen);
last_match = diff + rhlen;

xfree(cp);
dp = cp = np;
cp[--len] = '\0';
didmod = 1;
if (diff >= (ssize_t)len)
break;
} else {
/* should this do a seterror? */
break;
}
}
while (dolaflags[nthMod] != 0);
}
/*
* restore dolmod for additional words
*/
dolmod.s[i] = rhsub[-1] = (Char) delim;
} else {
} else if(dolmcnts[nthMod] != 0) {

do {
if ((dp = domod(cp, dolmod.s[i])) != NULL) {
Expand All @@ -859,14 +882,16 @@ setDolp(Char *cp)
else
break;
}
while (dol_flag_a != 0);
while (dolaflags[nthMod] != 0);
}
if (didmod && dolmcnt != INT_MAX)
dolmcnt--;
if(didmod && dolmcnts[nthMod] != INT_MAX)
dolmcnts[nthMod]--;
#ifdef notdef
else
break;
#endif

++nthMod;
}

addla(cp);
Expand Down
2 changes: 1 addition & 1 deletion sh.lex.c
Expand Up @@ -596,7 +596,7 @@ getdol(void)
int gmodflag = 0, amodflag = 0;

do {
Strbuf_append1(&name, c), c = getC(DOEXCL);
Strbuf_append1(&name, c), c = getC(DOEXCL), gmodflag = 0, amodflag = 0;
if (c == 'g' || c == 'a') {
if (c == 'g')
gmodflag++;
Expand Down
22 changes: 22 additions & 0 deletions tests/lexical.at
Expand Up @@ -627,6 +627,28 @@ AT_CHECK([tcsh -f escape_echo.csh], 0,

AT_CLEANUP

AT_SETUP([:gas work as described in the man pages])

AT_DATA([gas.csh],
[[set x=(aa bb aa bb)
echo $x:gas/a/c/:gs/b/d/
foreach i ( "$x:gas/a/c/:q" )
echo $i
end
echo $x:gas/a/q/:gs/b/w/:s/b/e/
echo $x:gas/a/q/:gs/b/w/:s/b/e/:gas/q/Q/
exit 0
]])

AT_CHECK([tcsh -f gas.csh], 0,
[cc db cc db
cc bb cc bb
qq we qq wb
QQ we QQ wb
])

AT_CLEANUP

AT_SETUP([avoid infinite loop in :gas])

AT_DATA([replace_all.csh],
Expand Down

0 comments on commit 96c1e29

Please sign in to comment.