1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-03-09 15:50:02 +00:00

posix mode: disable effect of repeating whitespace char in $IFS

ksh has a little-known field splitting feature that conflicts with
POSIX: if a single-byte whitespace character (cf. isspace(3)) is
repated in $IFS, then field splitting is done as if that character
wasn't a whitespace character. An exmaple with the tab character:

  $ (IFS=$'\t'; val=$'\tone\t\ttwo\t'; set -- $val; echo $#)
  2
  $ (IFS=$'\t\t'; val=$'\tone\t\ttwo\t'; set -- $val; echo $#)
  4
The latter being the same as, for example
  $ (IFS=':'; val='1️⃣2️⃣'; set -- $val; echo $#)
  4

However, this is incompatible with the POSIX spec and with every
other shell except zsh, in which repeating a character in IFS does
not have any effect. So the POSIX mode must disable this.

src/cmd/ksh93/include/defs.h,
src/cmd/ksh93/sh/init.c:
- Add sh_invalidate_ifs() function that invalidates the IFS state
  table by setting the ifsnp discipline struct member to NULL,
  which will cause the next get_ifs() call to regenerate it.
- get_ifs(): Treat a repeated char as S_DELIM even if whitespace,
  unless --posix is on.

src/cmd/ksh93/sh/args.c:
- sh_argopts(): Call sh_invalidate_ifs() when enabling or disabling
  the POSIX option. This is needed to make the change in field
  splitting behaviour take immediate effect instead of taking
  effect at the next assignment to IFS.
This commit is contained in:
Martijn Dekker 2022-03-08 20:20:57 +01:00
parent fae1932e62
commit 9e2a8c6925
5 changed files with 33 additions and 5 deletions

View file

@ -549,6 +549,18 @@ static void put_ifs(register Namval_t* np,const char *val,int flags,Namfun_t *fp
}
}
/* Invalidate IFS state table */
void sh_invalidate_ifs(void)
{
Namval_t *np = sh_scoped(IFSNOD);
if(np)
{
struct ifs *ip = (struct ifs*)np->nvfun;
if(ip)
ip->ifsnp = 0;
}
}
/*
* This is the lookup function for IFS
* It keeps the sh.ifstable up to date
@ -574,7 +586,8 @@ static char* get_ifs(register Namval_t* np, Namfun_t *fp)
continue;
}
n = S_DELIM;
if(c== *cp)
/* Treat a repeated char as S_DELIM even if whitespace, unless --posix is on */
if(c==*cp && !sh_isoption(SH_POSIX))
cp++;
else if(c=='\n')
n = S_NL;