mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-02-13 03:32:24 +00:00
Fix compile/regress fails on compiling without SHOPT_* options
Many compile-time options were broken so that they could not be turned off without causing compile errors and/or regression test failures. This commit now allows the following to be disabled: SHOPT_2DMATCH # two dimensional ${.sh.match} for ${var//pat/str} SHOPT_BGX # one SIGCHLD trap per completed job SHOPT_BRACEPAT # C-shell {...,...} expansions (, required) SHOPT_ESH # emacs/gmacs edit mode SHOPT_HISTEXPAND # csh-style history file expansions SHOPT_MULTIBYTE # multibyte character handling SHOPT_NAMESPACE # allow namespaces SHOPT_STATS # add .sh.stats variable SHOPT_VSH # vi edit mode The following still break ksh when disabled: SHOPT_FIXEDARRAY # fixed dimension indexed array SHOPT_RAWONLY # make viraw the only vi mode SHOPT_TYPEDEF # enable typeset type definitions Compiling without SHOPT_RAWONLY just gives four regression test failures in pty.sh, but turning off SHOPT_FIXEDARRAY and SHOPT_TYPEDEF causes compilation to fail. I've managed to tweak the code to make it compile without those two options, but then dozens of regression test failures occur, often in things nothing directly to do with those options. It looks like the separation between the code for these options and the rest was never properly maintained. Making it possible to disable SHOPT_FIXEDARRAY and SHOPT_TYPEDEF may involve major refactoring and testing and may not be worth it. This commit has far too many tweaks to list. Notables fixes are: src/cmd/ksh93/data/builtins.c, src/cmd/ksh93/data/options.c: - Do not compile in the shell options and documentation for disabled features (braceexpand, emacs/gmacs, vi/viraw), so the shell is not left with no-op options and inaccurate self-doc. src/cmd/ksh93/data/lexstates.c: - Comment the state tables to associte them with their IDs. - In the ST_MACRO table (sh_lexstate9[]), do not make the S_BRACE state for position 123 (ASCII for '{') conditional upon SHOPT_BRACEPAT (brace expansion), otherwise disabling this causes glob patterns of the form {3}(x) (matching 3 x'es) to stop working as well -- and that is ksh globbing, not brace expansion. src/cmd/ksh93/edit/edit.c: ed_read(): - Fixed a bug: SIGWINCH was not handled by the gmacs edit mode. src/cmd/ksh93/sh/name.c: nv_putval(): - The -L/-R left/right adjustment options to typeset do not count zero-width characters. This is the behaviour with SHOPT_MULTIBYTE enabled, regardless of locale. Of course, what a zero-width character is depends on the locale, but control characters are always considered zero-width. So, to avoid a regression, add some fallback code for non-SHOPT_MULTIBYTE builds that skips ASCII control characters (as per iscntrl(3)) so they are still considered to have zero width. src/cmd/ksh93/tests/shtests: - Export the SHOPT_* macros from SHOPT.sh to the tests as environment variables, so the tests can check for them and decide whether or how to run tests based on the compile-time options that the tested binary was presumably compiled with. - Do not run the C.UTF-8 tests if SHOPT_MULTIBYTE is not enabled. src/cmd/ksh93/tests/*.sh: - Add a bunch of checks for SHOPT_* env vars. Since most should have a value 0 (off) or 1 (on), the form ((SHOPT_FOO)) is a convenient way to use them as arithmetic booleans. .github/workflows/ci.yml: - Make GitHub do more testing: run two locale tests (Dutch and Japanese UTF-8 locales), then disable all the SHOPTs that we can currently disable, recompile ksh, and run the tests again.
This commit is contained in:
parent
a9d77bba40
commit
2182ecfa08
40 changed files with 413 additions and 157 deletions
7
.github/workflows/ci.yml
vendored
7
.github/workflows/ci.yml
vendored
|
@ -16,4 +16,11 @@ jobs:
|
|||
run: |
|
||||
export TZ=UTC
|
||||
ulimit -n 1024
|
||||
script -q -e -c "bin/shtests" &&
|
||||
LANG=nl_NL.UTF-8 script -q -e -c "bin/shtests --locale --nocompile" &&
|
||||
LANG=ja_JP.UTF-8 script -q -e -c "bin/shtests --locale --nocompile" &&
|
||||
sed --regexp-extended --in-place=.orig \
|
||||
'/^SHOPT (2DMATCH|AUDIT|BGX|BRACEPAT|DYNAMIC|EDPREDICT|ESH|HISTEXPAND|MULTIBYTE|NAMESPACE|OPTIMIZE|SUID_EXEC|STATS|VSH)=/ s/=1/=0/' \
|
||||
src/cmd/ksh93/SHOPT.sh &&
|
||||
bin/package make &&
|
||||
script -q -e -c "bin/shtests"
|
||||
|
|
|
@ -616,10 +616,10 @@
|
|||
10-09-29 A bug in which loading a function from FPATH could leave a file
|
||||
descriptor open has been fixed.
|
||||
10-09-28 +A new compile option SHOPT_FIXEDARRAY has been added and is being
|
||||
evaluation. It allows fixed sized indexed arrays be to defined
|
||||
evaluated. It allows fixed sized indexed arrays be to defined
|
||||
using "typeset array[dim1][dim2]...[dimn]". Fixed sized arrays
|
||||
are used the same way indexed arrays are. Currently, only fixed
|
||||
arrays of fixed objects (float, int, and justifies objects) are
|
||||
arrays of fixed objects (float, int, and justified objects) are
|
||||
supported.
|
||||
10-09-22 A bug which could cause an exception when a function with static
|
||||
variables was redefined has been fixed.
|
||||
|
|
|
@ -649,7 +649,7 @@ static int varname(const char *str, int n)
|
|||
}
|
||||
for(;n > 0; n-=len)
|
||||
{
|
||||
#ifdef SHOPT_MULTIBYTE
|
||||
#if SHOPT_MULTIBYTE
|
||||
len = mbsize(str);
|
||||
c = mbchar(str);
|
||||
#else
|
||||
|
|
|
@ -346,7 +346,7 @@ int b_typeset(int argc,register char *argv[],Shbltin_t *context)
|
|||
case 'r':
|
||||
flag |= NV_RDONLY;
|
||||
break;
|
||||
#ifdef SHOPT_TYPEDEF
|
||||
#if SHOPT_TYPEDEF
|
||||
case 'S':
|
||||
sflag=1;
|
||||
break;
|
||||
|
|
|
@ -207,13 +207,19 @@ const char sh_set[] =
|
|||
"The value of \aoption\a must be one of the following:]{"
|
||||
"[+allexport?Equivalent to \b-a\b.]"
|
||||
"[+bgnice?Runs background jobs at lower priorities.]"
|
||||
#if SHOPT_BRACEPAT
|
||||
"[+braceexpand?Equivalent to \b-B\b.] "
|
||||
#endif
|
||||
#if SHOPT_ESH
|
||||
"[+emacs?Enables/disables \bemacs\b editing mode.]"
|
||||
#endif
|
||||
"[+errexit?Equivalent to \b-e\b.]"
|
||||
"[+globstar?Equivalent to \b-G\b.]"
|
||||
#if SHOPT_ESH
|
||||
"[+gmacs?Enables/disables \bgmacs\b editing mode. \bgmacs\b "
|
||||
"editing mode is the same as \bemacs\b editing mode "
|
||||
"except for the handling of \b^T\b.]"
|
||||
#endif
|
||||
#if SHOPT_HISTEXPAND
|
||||
"[+histexpand?Equivalent to \b-H\b.]"
|
||||
#endif
|
||||
|
@ -245,9 +251,11 @@ const char sh_set[] =
|
|||
"as if \b-x\b were enabled but not executed.]"
|
||||
"[+trackall?Equivalent to \b-h\b.]"
|
||||
"[+verbose?Equivalent to \b-v\b.]"
|
||||
#if SHOPT_VSH
|
||||
"[+vi?Enables/disables \bvi\b editing mode.]"
|
||||
"[+viraw?Does not use canonical input mode when using \bvi\b "
|
||||
"edit mode.]"
|
||||
#endif
|
||||
"[+xtrace?Equivalent to \b-x\b.]"
|
||||
"}"
|
||||
"[p?Privileged mode. Disabling \b-p\b sets the effective user id to the "
|
||||
|
@ -1831,7 +1839,7 @@ const char sh_opttypeset[] =
|
|||
"notation. \an\a specifies the number of significant figures when the "
|
||||
"value is expanded.]"
|
||||
|
||||
#ifdef SHOPT_TYPEDEF
|
||||
#if SHOPT_TYPEDEF
|
||||
"[h]:[string?Used within a type definition to provide a help string "
|
||||
"for variable \aname\a. Otherwise, it is ignored.]"
|
||||
"[S?Used with a type definition to indicate that the variable is shared by "
|
||||
|
|
|
@ -24,8 +24,10 @@
|
|||
#include "FEATURE/options"
|
||||
#include "lexstates.h"
|
||||
|
||||
/* The ST_* state table names are defined in include/lexstates.h */
|
||||
|
||||
/*
|
||||
* ST_BEGIN (0)
|
||||
* This is the initial state for tokens
|
||||
*/
|
||||
static const char sh_lexstate0[256] =
|
||||
|
@ -77,6 +79,7 @@ static const char sh_lexstate0[256] =
|
|||
};
|
||||
|
||||
/*
|
||||
* ST_NAME
|
||||
* This state is for identifiers
|
||||
*/
|
||||
static const char sh_lexstate1[256] =
|
||||
|
@ -123,6 +126,9 @@ static const char sh_lexstate1[256] =
|
|||
S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
|
||||
};
|
||||
|
||||
/*
|
||||
* ST_NORM
|
||||
*/
|
||||
static const char sh_lexstate2[256] =
|
||||
{
|
||||
S_EOF, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
@ -151,6 +157,7 @@ static const char sh_lexstate2[256] =
|
|||
};
|
||||
|
||||
/*
|
||||
* ST_LIT
|
||||
* for skipping over '...'
|
||||
*/
|
||||
static const char sh_lexstate3[256] =
|
||||
|
@ -172,6 +179,7 @@ static const char sh_lexstate3[256] =
|
|||
};
|
||||
|
||||
/*
|
||||
* ST_QUOTE
|
||||
* for skipping over "..." and `...`
|
||||
*/
|
||||
static const char sh_lexstate4[256] =
|
||||
|
@ -195,6 +203,7 @@ static const char sh_lexstate4[256] =
|
|||
};
|
||||
|
||||
/*
|
||||
* ST_NESTED, ST_QNEST
|
||||
* for skipping over ?(...), [...]
|
||||
*/
|
||||
static const char sh_lexstate5[256] =
|
||||
|
@ -218,6 +227,7 @@ static const char sh_lexstate5[256] =
|
|||
};
|
||||
|
||||
/*
|
||||
* ST_DOL
|
||||
* Defines valid expansion characters
|
||||
*/
|
||||
static const char sh_lexstate6[256] =
|
||||
|
@ -265,6 +275,7 @@ static const char sh_lexstate6[256] =
|
|||
};
|
||||
|
||||
/*
|
||||
* ST_BRACE
|
||||
* for skipping over ${...} until modifier
|
||||
*/
|
||||
static const char sh_lexstate7[256] =
|
||||
|
@ -308,6 +319,7 @@ static const char sh_lexstate7[256] =
|
|||
};
|
||||
|
||||
/*
|
||||
* ST_DOLNAME
|
||||
* This state is for $name
|
||||
*/
|
||||
static const char sh_lexstate8[256] =
|
||||
|
@ -351,6 +363,7 @@ static const char sh_lexstate8[256] =
|
|||
};
|
||||
|
||||
/*
|
||||
* ST_MACRO
|
||||
* This is used for macro expansion
|
||||
*/
|
||||
static const char sh_lexstate9[256] =
|
||||
|
@ -370,13 +383,12 @@ static const char sh_lexstate9[256] =
|
|||
S_GRAVE,0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
#if SHOPT_BRACEPAT
|
||||
0, 0, 0, S_BRACE,S_PAT, S_ENDCH,0, 0
|
||||
#else
|
||||
0, 0, 0, 0, S_PAT, S_ENDCH,0, 0
|
||||
#endif /* SHOPT_BRACEPAT */
|
||||
};
|
||||
|
||||
/*
|
||||
* This must be kept synchronous with all the above and the ST_* definitions in lexstates.h
|
||||
*/
|
||||
const char *sh_lexrstates[ST_NONE] =
|
||||
{
|
||||
sh_lexstate0, sh_lexstate1, sh_lexstate2, sh_lexstate3,
|
||||
|
|
|
@ -32,14 +32,20 @@ const Shtable_t shtab_options[] =
|
|||
{
|
||||
"allexport", SH_ALLEXPORT,
|
||||
"bgnice", SH_BGNICE,
|
||||
#if SHOPT_BRACEPAT
|
||||
"braceexpand", SH_BRACEEXPAND,
|
||||
#endif
|
||||
"noclobber", SH_NOCLOBBER,
|
||||
#if SHOPT_ESH
|
||||
"emacs", SH_EMACS,
|
||||
#endif
|
||||
"errexit", SH_ERREXIT,
|
||||
"noexec", SH_NOEXEC,
|
||||
"noglob", SH_NOGLOB,
|
||||
"globstar", SH_GLOBSTARS,
|
||||
#if SHOPT_ESH
|
||||
"gmacs", SH_GMACS,
|
||||
#endif
|
||||
#if SHOPT_HISTEXPAND
|
||||
"histexpand", SH_HISTEXPAND,
|
||||
#endif
|
||||
|
@ -65,8 +71,10 @@ const Shtable_t shtab_options[] =
|
|||
"trackall", SH_TRACKALL,
|
||||
"nounset", SH_NOUNSET,
|
||||
"verbose", SH_VERBOSE,
|
||||
#if SHOPT_VSH
|
||||
"vi", SH_VI,
|
||||
"viraw", SH_VIRAW,
|
||||
#endif
|
||||
"xtrace", SH_XTRACE,
|
||||
"", 0
|
||||
};
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
/*
|
||||
* This is the list of built-in shell variables and default values
|
||||
* and default attributes.
|
||||
*
|
||||
* The order must be kept synchronous with the defines in include/variables.h.
|
||||
*/
|
||||
|
||||
const struct shtable2 shtab_variables[] =
|
||||
|
@ -109,7 +111,7 @@ const struct shtable2 shtab_variables[] =
|
|||
|
||||
const char *nv_discnames[] = { "get", "set", "append", "unset", "getn", 0 };
|
||||
|
||||
#ifdef SHOPT_STATS
|
||||
#if SHOPT_STATS
|
||||
const Shtable_t shtab_stats[] =
|
||||
{
|
||||
"arg_cachehits", STAT_ARGHITS,
|
||||
|
|
|
@ -240,10 +240,18 @@ int ed_expand(Edit_t *ep, char outbuff[],int *cur,int *eol,int mode, int count)
|
|||
*eol = ed_external((genchar*)outbuff,outbuff);
|
||||
}
|
||||
#endif /* SHOPT_MULTIBYTE */
|
||||
#if SHOPT_VSH
|
||||
out = outbuff + *cur + (sh_isoption(SH_VI)!=0);
|
||||
#else
|
||||
out = outbuff + *cur;
|
||||
#endif
|
||||
if(out[-1]=='"' || out[-1]=='\'')
|
||||
{
|
||||
#if SHOPT_VSH
|
||||
rval = -(sh_isoption(SH_VI)!=0);
|
||||
#else
|
||||
rval = 0;
|
||||
#endif
|
||||
goto done;
|
||||
}
|
||||
comptr->comtyp = COMSCAN;
|
||||
|
@ -565,6 +573,10 @@ int ed_fulledit(Edit_t *ep)
|
|||
}
|
||||
cp = strcopy((char*)ep->e_inbuf,e_runvi);
|
||||
cp = strcopy(cp, fmtbase((long)ep->e_hline,10,0));
|
||||
#if SHOPT_VSH
|
||||
ep->e_eol = ((unsigned char*)cp - (unsigned char*)ep->e_inbuf)-(sh_isoption(SH_VI)!=0);
|
||||
#else
|
||||
ep->e_eol = ((unsigned char*)cp - (unsigned char*)ep->e_inbuf);
|
||||
#endif
|
||||
return(0);
|
||||
}
|
||||
|
|
|
@ -59,9 +59,11 @@ static char KILL_LINE[20] = { ESC, '[', 'J', 0 };
|
|||
#if SHOPT_MULTIBYTE
|
||||
# define is_cntrl(c) ((c<=STRIP) && iscntrl(c))
|
||||
# define is_print(c) ((c&~STRIP) || isprint(c))
|
||||
# define genlen(str) ed_genlen(str)
|
||||
#else
|
||||
# define is_cntrl(c) iscntrl(c)
|
||||
# define is_print(c) isprint(c)
|
||||
# define genlen(str) strlen(str)
|
||||
#endif
|
||||
|
||||
#if (CC_NATIVE == CC_ASCII)
|
||||
|
@ -147,11 +149,9 @@ static char KILL_LINE[20] = { ESC, '[', 'J', 0 };
|
|||
#ifdef future
|
||||
static int compare(const char*, const char*, int);
|
||||
#endif /* future */
|
||||
#if SHOPT_VSH || SHOPT_ESH
|
||||
#define ttyparm (ep->e_ttyparm)
|
||||
#define nttyparm (ep->e_nttyparm)
|
||||
static const char bellchr[] = "\a"; /* bell char */
|
||||
#endif /* SHOPT_VSH || SHOPT_ESH */
|
||||
|
||||
|
||||
/*
|
||||
|
@ -227,7 +227,6 @@ int tty_set(int fd, int action, struct termios *tty)
|
|||
return(0);
|
||||
}
|
||||
|
||||
#if SHOPT_ESH || SHOPT_VSH
|
||||
/*{ TTY_COOKED( fd )
|
||||
*
|
||||
* This routine will set the tty in cooked mode.
|
||||
|
@ -561,6 +560,7 @@ void ed_ringbell(void)
|
|||
write(ERRIO,bellchr,1);
|
||||
}
|
||||
|
||||
#if SHOPT_ESH || SHOPT_VSH
|
||||
/*
|
||||
* send a carriage return line feed to the terminal
|
||||
*/
|
||||
|
@ -579,7 +579,9 @@ void ed_crlf(register Edit_t *ep)
|
|||
ed_putchar(ep,'\n');
|
||||
ed_flush(ep);
|
||||
}
|
||||
#endif /* SHOPT_ESH || SHOPT_VSH */
|
||||
|
||||
#if SHOPT_ESH || SHOPT_VSH
|
||||
/* ED_SETUP( max_prompt_size )
|
||||
*
|
||||
* This routine sets up the prompt string
|
||||
|
@ -640,7 +642,15 @@ void ed_setup(register Edit_t *ep, int fd, int reedit)
|
|||
ep->e_hismax = ep->e_hismin = ep->e_hloff = 0;
|
||||
}
|
||||
ep->e_hline = ep->e_hismax;
|
||||
#if SHOPT_ESH && SHOPT_VSH
|
||||
if(!sh_isoption(SH_VI) && !sh_isoption(SH_EMACS) && !sh_isoption(SH_GMACS))
|
||||
#elif SHOPT_ESH
|
||||
if(!sh_isoption(SH_EMACS) && !sh_isoption(SH_GMACS))
|
||||
#elif SHOPT_VSH
|
||||
if(!sh_isoption(SH_VI))
|
||||
#else
|
||||
if(1)
|
||||
#endif /* SHOPT_ESH && SHOPT_VSH */
|
||||
ep->e_wsize = MAXLINE;
|
||||
else
|
||||
ep->e_wsize = ed_window()-2;
|
||||
|
@ -795,6 +805,7 @@ void ed_setup(register Edit_t *ep, int fd, int reedit)
|
|||
ep->e_default = 0;
|
||||
}
|
||||
}
|
||||
#endif /* SHOPT_ESH || SHOPT_VSH */
|
||||
|
||||
static void ed_putstring(register Edit_t *ep, const char *str)
|
||||
{
|
||||
|
@ -840,7 +851,15 @@ int ed_read(void *context, int fd, char *buff, int size, int reedit)
|
|||
{
|
||||
if(shp->trapnote&(SH_SIGSET|SH_SIGTRAP))
|
||||
goto done;
|
||||
if(ep->sh->winch && sh_isstate(SH_INTERACTIVE) && (sh_isoption(SH_VI) || sh_isoption(SH_EMACS)))
|
||||
#if SHOPT_ESH && SHOPT_VSH
|
||||
if(ep->sh->winch && sh_isstate(SH_INTERACTIVE) && (sh_isoption(SH_VI) || sh_isoption(SH_EMACS) || sh_isoption(SH_GMACS)))
|
||||
#elif SHOPT_ESH
|
||||
if(ep->sh->winch && sh_isstate(SH_INTERACTIVE) && (sh_isoption(SH_EMACS) || sh_isoption(SH_GMACS)))
|
||||
#elif SHOPT_VSH
|
||||
if(ep->sh->winch && sh_isstate(SH_INTERACTIVE) && sh_isoption(SH_VI))
|
||||
#else
|
||||
if(0)
|
||||
#endif
|
||||
{
|
||||
Edpos_t lastpos;
|
||||
int n, rows, newsize;
|
||||
|
@ -881,7 +900,6 @@ int ed_read(void *context, int fd, char *buff, int size, int reedit)
|
|||
buff[2] = 'a';
|
||||
return(3);
|
||||
}
|
||||
if(sh_isoption(SH_EMACS) || sh_isoption(SH_VI))
|
||||
buff[0] = cntl('L');
|
||||
return(1);
|
||||
}
|
||||
|
@ -1115,13 +1133,16 @@ int ed_getchar(register Edit_t *ep,int mode)
|
|||
return(c);
|
||||
}
|
||||
|
||||
#if SHOPT_ESH || SHOPT_VSH
|
||||
void ed_ungetchar(Edit_t *ep,register int c)
|
||||
{
|
||||
if (ep->e_lookahead < LOOKAHEAD)
|
||||
ep->e_lbuf[ep->e_lookahead++] = c;
|
||||
return;
|
||||
}
|
||||
#endif /* SHOPT_ESH || SHOPT_VSH */
|
||||
|
||||
#if SHOPT_ESH || SHOPT_VSH
|
||||
/*
|
||||
* put a character into the output buffer
|
||||
*/
|
||||
|
@ -1162,7 +1183,9 @@ void ed_putchar(register Edit_t *ep,register int c)
|
|||
else
|
||||
ep->e_outptr = dp;
|
||||
}
|
||||
#endif /* SHOPT_ESH || SHOPT_VSH */
|
||||
|
||||
#if SHOPT_ESH || SHOPT_VSH
|
||||
/*
|
||||
* returns the line and column corresponding to offset <off> in the physical buffer
|
||||
* if <cur> is non-zero and <= <off>, then correspodning <curpos> will start the search
|
||||
|
@ -1211,7 +1234,9 @@ Edpos_t ed_curpos(Edit_t *ep,genchar *phys, int off, int cur, Edpos_t curpos)
|
|||
pos.col = col;
|
||||
return(pos);
|
||||
}
|
||||
#endif /* SHOPT_ESH || SHOPT_VSH */
|
||||
|
||||
#if SHOPT_ESH || SHOPT_VSH
|
||||
int ed_setcursor(register Edit_t *ep,genchar *physical,register int old,register int new,int first)
|
||||
{
|
||||
static int oldline;
|
||||
|
@ -1261,7 +1286,7 @@ int ed_setcursor(register Edit_t *ep,genchar *physical,register int old,register
|
|||
int m = ep->e_winsz+1-plen;
|
||||
ed_putchar(ep,'\n');
|
||||
n = plen;
|
||||
if(m < ed_genlen(physical))
|
||||
if(m < genlen(physical))
|
||||
{
|
||||
while(physical[m] && n-->0)
|
||||
ed_putchar(ep,physical[m++]);
|
||||
|
@ -1311,7 +1336,9 @@ int ed_setcursor(register Edit_t *ep,genchar *physical,register int old,register
|
|||
ed_putchar(ep,physical[old++]);
|
||||
return(new);
|
||||
}
|
||||
#endif /* SHOPT_ESH || SHOPT_VSH */
|
||||
|
||||
#if SHOPT_ESH || SHOPT_VSH
|
||||
/*
|
||||
* copy virtual to physical and return the index for cursor in physical buffer
|
||||
*/
|
||||
|
@ -1375,8 +1402,9 @@ int ed_virt_to_phys(Edit_t *ep,genchar *virt,genchar *phys,int cur,int voff,int
|
|||
ep->e_peol = dp-phys;
|
||||
return(r);
|
||||
}
|
||||
#endif /* SHOPT_ESH || SHOPT_VSH */
|
||||
|
||||
#if SHOPT_MULTIBYTE
|
||||
#if (SHOPT_ESH || SHOPT_VSH) && SHOPT_MULTIBYTE
|
||||
/*
|
||||
* convert external representation <src> to an array of genchars <dest>
|
||||
* <src> and <dest> can be the same
|
||||
|
@ -1400,7 +1428,9 @@ int ed_internal(const char *src, genchar *dest)
|
|||
*dp = 0;
|
||||
return(dp-(wchar_t*)dest);
|
||||
}
|
||||
#endif /* (SHOPT_ESH || SHOPT_VSH) && SHOPT_MULTIBYTE */
|
||||
|
||||
#if SHOPT_MULTIBYTE
|
||||
/*
|
||||
* convert internal representation <src> into character array <dest>.
|
||||
* The <src> and <dest> may be the same.
|
||||
|
@ -1439,7 +1469,9 @@ int ed_external(const genchar *src, char *dest)
|
|||
*dp = 0;
|
||||
return(dp-dest);
|
||||
}
|
||||
#endif /* SHOPT_MULTIBYTE */
|
||||
|
||||
#if (SHOPT_ESH || SHOPT_VSH) && SHOPT_MULTIBYTE
|
||||
/*
|
||||
* copy <sp> to <dp>
|
||||
*/
|
||||
|
@ -1450,7 +1482,9 @@ void ed_gencpy(genchar *dp,const genchar *sp)
|
|||
sp = (const genchar*)roundof((char*)sp-(char*)0,sizeof(genchar));
|
||||
while(*dp++ = *sp++);
|
||||
}
|
||||
#endif /* (SHOPT_ESH || SHOPT_VSH) && SHOPT_MULTIBYTE */
|
||||
|
||||
#if (SHOPT_ESH || SHOPT_VSH) && SHOPT_MULTIBYTE
|
||||
/*
|
||||
* copy at most <n> items from <sp> to <dp>
|
||||
*/
|
||||
|
@ -1461,8 +1495,9 @@ void ed_genncpy(register genchar *dp,register const genchar *sp, int n)
|
|||
sp = (const genchar*)roundof((char*)sp-(char*)0,sizeof(genchar));
|
||||
while(n-->0 && (*dp++ = *sp++));
|
||||
}
|
||||
#endif /* (SHOPT_ESH || SHOPT_VSH) && SHOPT_MULTIBYTE */
|
||||
|
||||
#endif /* SHOPT_MULTIBYTE */
|
||||
#if (SHOPT_ESH || SHOPT_VSH) && SHOPT_MULTIBYTE
|
||||
/*
|
||||
* find the string length of <str>
|
||||
*/
|
||||
|
@ -1474,7 +1509,7 @@ int ed_genlen(register const genchar *str)
|
|||
while(*sp++);
|
||||
return(sp-str-1);
|
||||
}
|
||||
#endif /* SHOPT_ESH || SHOPT_VSH */
|
||||
#endif /* (SHOPT_ESH || SHOPT_VSH) && SHOPT_MULTIBYTE */
|
||||
|
||||
#ifdef future
|
||||
/*
|
||||
|
@ -1776,6 +1811,7 @@ int ed_histgen(Edit_t *ep,const char *pattern)
|
|||
return(ep->hmax=ac);
|
||||
}
|
||||
|
||||
#if SHOPT_ESH || SHOPT_VSH
|
||||
void ed_histlist(Edit_t *ep,int n)
|
||||
{
|
||||
Histmatch_t *mp,**mpp = ep->hlist+ep->hoff;
|
||||
|
@ -1828,6 +1864,8 @@ void ed_histlist(Edit_t *ep,int n)
|
|||
}
|
||||
ed_flush(ep);
|
||||
}
|
||||
#endif /* SHOPT_ESH || SHOPT_VSH */
|
||||
|
||||
#endif /* SHOPT_EDPREDICT */
|
||||
|
||||
void *ed_open(Shell_t *shp)
|
||||
|
|
|
@ -61,6 +61,8 @@ One line screen editor for any program
|
|||
* but you can use them to separate features.
|
||||
*/
|
||||
|
||||
#if SHOPT_ESH
|
||||
|
||||
#include <ast.h>
|
||||
#include "FEATURE/cmds"
|
||||
#if KSHELL
|
||||
|
@ -1600,3 +1602,5 @@ static int _isword(register int c)
|
|||
return((c&~STRIP) || isalnum(c) || c=='_');
|
||||
}
|
||||
#endif /* SHOPT_MULTIBYTE */
|
||||
|
||||
#endif /* SHOPT_ESH */
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
* cbosgd!pds
|
||||
-*/
|
||||
|
||||
#if SHOPT_VSH
|
||||
|
||||
#if KSHELL
|
||||
# include "defs.h"
|
||||
|
@ -252,7 +253,7 @@ int ed_viread(void *context, int fd, register char *shbuf, int nchar, int reedit
|
|||
/*** Change the eol characters to '\r' and eof ***/
|
||||
/* in addition to '\n' and make eof an ESC */
|
||||
if(tty_alt(ERRIO) < 0)
|
||||
return(reexit?reedit:ed_read(context, fd, shbuf, nchar,0));
|
||||
return(reedit?reedit:ed_read(context, fd, shbuf, nchar,0));
|
||||
|
||||
#ifdef FIORDCHK
|
||||
ioctl(fd,FIORDCHK,&vp->typeahead);
|
||||
|
@ -2783,3 +2784,5 @@ static int getrchar(register Vi_t *vp)
|
|||
c = ed_getchar(vp->ed,2);
|
||||
return(c);
|
||||
}
|
||||
|
||||
#endif /* SHOPT_VSH */
|
||||
|
|
|
@ -316,7 +316,9 @@ struct shared
|
|||
#define SH_INTESTCMD 20 /* set while test/[ command is being run */
|
||||
#define SH_XARG 21 /* set while in xarg (command -x) mode */
|
||||
|
||||
#if SHOPT_BRACEPAT
|
||||
#define SH_BRACEEXPAND 42
|
||||
#endif
|
||||
#define SH_POSIX 46
|
||||
#define SH_MULTILINE 47
|
||||
|
||||
|
@ -451,7 +453,7 @@ extern const char e_dict[];
|
|||
#define PRINT_NO_HEADER 0x04 /* omit listing header */
|
||||
#define PRINT_TABLE 0x10 /* table of all options */
|
||||
|
||||
#ifdef SHOPT_STATS
|
||||
#if SHOPT_STATS
|
||||
/* performance statistics */
|
||||
# define STAT_ARGHITS 0
|
||||
# define STAT_ARGEXPAND 1
|
||||
|
|
|
@ -31,9 +31,6 @@
|
|||
|
||||
#include "FEATURE/options"
|
||||
#include "FEATURE/locale"
|
||||
#if !SHOPT_VSH && !SHOPT_ESH
|
||||
# define ed_winsize() (SEARCHSIZE)
|
||||
#else
|
||||
|
||||
#if !KSHELL
|
||||
# include <setjmp.h>
|
||||
|
@ -231,11 +228,12 @@ extern int ed_setcursor(Edit_t*, genchar*, int, int, int);
|
|||
extern void ed_gencpy(genchar*,const genchar*);
|
||||
extern void ed_genncpy(genchar*,const genchar*,int);
|
||||
extern int ed_genlen(const genchar*);
|
||||
extern int ed_setwidth(const char*);
|
||||
# endif /* SHOPT_MULTIBYTE */
|
||||
#if SHOPT_EDPREDICT
|
||||
extern int ed_histgen(Edit_t*, const char*);
|
||||
# if SHOPT_ESH || SHOPT_VSH
|
||||
extern void ed_histlist(Edit_t*, int);
|
||||
# endif /* SHOPT_ESH || SHOPT_VSH */
|
||||
#endif /* SHOPT_EDPREDICT */
|
||||
|
||||
extern const char e_runvi[];
|
||||
|
@ -269,7 +267,7 @@ extern const char e_runvi[];
|
|||
#define HIST_FLAG_RETURN_MASK (HIST_EVENT|HIST_PRINT|HIST_ERROR)
|
||||
|
||||
extern int hist_expand(const char *, char **);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif /* SHOPT_HISTEXPAND */
|
||||
|
||||
#endif /* !SEARCHSIZE */
|
||||
|
|
|
@ -89,7 +89,7 @@ struct jobs
|
|||
unsigned int in_critical; /* >0 => in critical region */
|
||||
int savesig; /* active signal */
|
||||
int numpost; /* number of posted jobs */
|
||||
#ifdef SHOPT_BGX
|
||||
#if SHOPT_BGX
|
||||
int numbjob; /* number of background jobs */
|
||||
#endif /* SHOPT_BGX */
|
||||
short fd; /* tty descriptor number */
|
||||
|
@ -169,7 +169,7 @@ extern int job_wait(pid_t);
|
|||
extern int job_post(Shell_t*,pid_t,pid_t);
|
||||
extern void *job_subsave(void);
|
||||
extern void job_subrestore(void*);
|
||||
#ifdef SHOPT_BGX
|
||||
#if SHOPT_BGX
|
||||
extern void job_chldtrap(Shell_t*, const char*,int);
|
||||
#endif /* SHOPT_BGX */
|
||||
#ifdef JOBS
|
||||
|
|
|
@ -66,6 +66,7 @@
|
|||
#define S_ESC2 41 /* escape character inside '...' */
|
||||
|
||||
/* These are the lexical state table names */
|
||||
/* See lexstates.c (ST_NONE must be last) */
|
||||
#define ST_BEGIN 0
|
||||
#define ST_NAME 1
|
||||
#define ST_NORM 2
|
||||
|
|
|
@ -34,4 +34,6 @@
|
|||
|
||||
extern int sh_strchr(const char*,const char*);
|
||||
|
||||
#else
|
||||
# define sh_strchr(s,c) strchr(s,*(c))
|
||||
#endif /* SHOPT_MULTIBYTE */
|
||||
|
|
|
@ -77,14 +77,18 @@ typedef union Shnode_u Shnode_t;
|
|||
#define SH_NOCLOBBER 14
|
||||
#define SH_MARKDIRS 15
|
||||
#define SH_BGNICE 16
|
||||
#if SHOPT_VSH
|
||||
#define SH_VI 17
|
||||
#define SH_VIRAW 18
|
||||
#endif
|
||||
#define SH_TFLAG 19
|
||||
#define SH_TRACKALL 20
|
||||
#define SH_SFLAG 21
|
||||
#define SH_NOEXEC 22
|
||||
#if SHOPT_ESH
|
||||
#define SH_GMACS 24
|
||||
#define SH_EMACS 25
|
||||
#endif
|
||||
#define SH_PRIVILEGED 26
|
||||
#define SH_NOLOG 28
|
||||
#define SH_NOTIFY 29
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#include "FEATURE/options"
|
||||
#include "FEATURE/dynamic"
|
||||
|
||||
/* The following defines are coordinated with data in data/variables.c */
|
||||
/* The following defines must be kept synchronous with shtab_variables[] in data/variables.c */
|
||||
|
||||
#define PATHNOD (shgd->bltin_nodes)
|
||||
#define PS1NOD (shgd->bltin_nodes+1)
|
||||
|
|
|
@ -40,16 +40,6 @@
|
|||
#if SHOPT_KIA || SHOPT_DEVFD
|
||||
# include "io.h"
|
||||
#endif
|
||||
#if SHOPT_PFSH
|
||||
# define PFSHOPT "P"
|
||||
#else
|
||||
# define PFSHOPT
|
||||
#endif
|
||||
#if SHOPT_HISTEXPAND
|
||||
# define HFLAG "H"
|
||||
#else
|
||||
# define HFLAG ""
|
||||
#endif
|
||||
|
||||
#define SORT 1
|
||||
#define PRINT 2
|
||||
|
@ -57,7 +47,19 @@
|
|||
static char *null;
|
||||
|
||||
/* The following order is determined by sh_optset */
|
||||
static const char optksh[] = PFSHOPT "DircabefhkmnpstuvxBCGEl" HFLAG;
|
||||
static const char optksh[] =
|
||||
#if SHOPT_PFSH
|
||||
"P"
|
||||
#endif
|
||||
"Dircabefhkmnpstuvx"
|
||||
#if SHOPT_BRACEPAT
|
||||
"B"
|
||||
#endif
|
||||
"CGEl"
|
||||
#if SHOPT_HISTEXPAND
|
||||
"H"
|
||||
#endif
|
||||
;
|
||||
static const int flagval[] =
|
||||
{
|
||||
#if SHOPT_PFSH
|
||||
|
@ -66,8 +68,11 @@ static const int flagval[] =
|
|||
SH_DICTIONARY, SH_INTERACTIVE, SH_RESTRICTED, SH_CFLAG,
|
||||
SH_ALLEXPORT, SH_NOTIFY, SH_ERREXIT, SH_NOGLOB, SH_TRACKALL,
|
||||
SH_KEYWORD, SH_MONITOR, SH_NOEXEC, SH_PRIVILEGED, SH_SFLAG, SH_TFLAG,
|
||||
SH_NOUNSET, SH_VERBOSE, SH_XTRACE, SH_BRACEEXPAND, SH_NOCLOBBER,
|
||||
SH_GLOBSTARS, SH_RC, SH_LOGIN_SHELL,
|
||||
SH_NOUNSET, SH_VERBOSE, SH_XTRACE,
|
||||
#if SHOPT_BRACEPAT
|
||||
SH_BRACEEXPAND,
|
||||
#endif
|
||||
SH_NOCLOBBER, SH_GLOBSTARS, SH_RC, SH_LOGIN_SHELL,
|
||||
#if SHOPT_HISTEXPAND
|
||||
SH_HISTEXPAND,
|
||||
#endif
|
||||
|
@ -231,12 +236,21 @@ int sh_argopts(int argc,register char *argv[], void *context)
|
|||
}
|
||||
if(f)
|
||||
{
|
||||
#if SHOPT_ESH && SHOPT_VSH
|
||||
if(o==SH_VI || o==SH_EMACS || o==SH_GMACS)
|
||||
{
|
||||
off_option(&newflags,SH_VI);
|
||||
off_option(&newflags,SH_EMACS);
|
||||
off_option(&newflags,SH_GMACS);
|
||||
}
|
||||
#elif SHOPT_ESH
|
||||
if(o==SH_EMACS || o==SH_GMACS)
|
||||
{
|
||||
off_option(&newflags,SH_EMACS);
|
||||
off_option(&newflags,SH_GMACS);
|
||||
}
|
||||
|
||||
#endif /* SHOPT_ESH && SHOPT_VSH */
|
||||
on_option(&newflags,o);
|
||||
off_option(&ap->sh->offoptions,o);
|
||||
}
|
||||
|
@ -567,7 +581,7 @@ void sh_printopts(Shopt_t oflags,register int mode, Shopt_t *mask)
|
|||
sfputc(sfstdout,'\n');
|
||||
return;
|
||||
}
|
||||
#if SHOPT_RAWONLY
|
||||
#if SHOPT_VSH && SHOPT_RAWONLY
|
||||
on_option(&oflags,SH_VIRAW);
|
||||
#endif
|
||||
if(!(mode&(PRINT_ALL|PRINT_VERBOSE))) /* only print set options */
|
||||
|
|
|
@ -42,10 +42,6 @@
|
|||
#include "io.h"
|
||||
#include "path.h"
|
||||
|
||||
#if !SHOPT_BRACEPAT
|
||||
# define SHOPT_BRACEPAT 0
|
||||
#endif
|
||||
|
||||
#if KSHELL
|
||||
# define argbegin argnxt.cp
|
||||
static const char *sufstr;
|
||||
|
|
|
@ -413,7 +413,7 @@ void sh_chktrap(Shell_t* shp)
|
|||
}
|
||||
if(shp->sigflag[SIGALRM]&SH_SIGALRM)
|
||||
sh_timetraps(shp);
|
||||
#ifdef SHOPT_BGX
|
||||
#if SHOPT_BGX
|
||||
if((shp->sigflag[SIGCHLD]&SH_SIGTRAP) && shp->st.trapcom[SIGCHLD])
|
||||
job_chldtrap(shp,shp->st.trapcom[SIGCHLD],1);
|
||||
#endif /* SHOPT_BGX */
|
||||
|
@ -421,7 +421,7 @@ void sh_chktrap(Shell_t* shp)
|
|||
{
|
||||
if(sig==cursig)
|
||||
continue;
|
||||
#ifdef SHOPT_BGX
|
||||
#if SHOPT_BGX
|
||||
if(sig==SIGCHLD)
|
||||
continue;
|
||||
#endif /* SHOPT_BGX */
|
||||
|
@ -626,9 +626,17 @@ void sh_done(void *ptr, register int sig)
|
|||
sh_accend();
|
||||
#endif /* SHOPT_ACCT */
|
||||
#if SHOPT_VSH || SHOPT_ESH
|
||||
if(mbwide()||sh_isoption(SH_EMACS)||sh_isoption(SH_VI)||sh_isoption(SH_GMACS))
|
||||
tty_cooked(-1);
|
||||
if(mbwide()
|
||||
#if SHOPT_ESH
|
||||
|| sh_isoption(SH_EMACS)
|
||||
|| sh_isoption(SH_GMACS)
|
||||
#endif
|
||||
#if SHOPT_VSH
|
||||
|| sh_isoption(SH_VI)
|
||||
#endif
|
||||
)
|
||||
tty_cooked(-1);
|
||||
#endif /* SHOPT_VSH || SHOPT_ESH */
|
||||
#ifdef JOBS
|
||||
if((sh_isoption(SH_INTERACTIVE) && shp->login_sh) || (!sh_isoption(SH_INTERACTIVE) && (sig==SIGHUP)))
|
||||
job_walk(sfstderr, job_hup, SIGHUP, NIL(char**));
|
||||
|
|
|
@ -178,8 +178,10 @@ typedef struct _init_
|
|||
Namfun_t CDPATH_init;
|
||||
Namfun_t SHELL_init;
|
||||
Namfun_t ENV_init;
|
||||
#if SHOPT_VSH || SHOPT_ESH
|
||||
Namfun_t VISUAL_init;
|
||||
Namfun_t EDITOR_init;
|
||||
#endif
|
||||
Namfun_t HISTFILE_init;
|
||||
Namfun_t HISTSIZE_init;
|
||||
Namfun_t OPTINDEX_init;
|
||||
|
@ -227,6 +229,7 @@ static char *nospace(int unused)
|
|||
return(NIL(char*));
|
||||
}
|
||||
|
||||
#if SHOPT_VSH || SHOPT_ESH
|
||||
/* Trap for VISUAL and EDITOR variables */
|
||||
static void put_ed(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
|
||||
{
|
||||
|
@ -239,22 +242,34 @@ static void put_ed(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
|
|||
goto done;
|
||||
/* turn on vi or emacs option if editor name is either*/
|
||||
cp = path_basename(cp);
|
||||
#if SHOPT_VSH
|
||||
if(strmatch(cp,"*[Vv][Ii]*"))
|
||||
newopt=SH_VI;
|
||||
else if(strmatch(cp,"*gmacs*"))
|
||||
#endif
|
||||
#if SHOPT_VSH && SHOPT_ESH
|
||||
else
|
||||
#endif
|
||||
#if SHOPT_ESH
|
||||
if(strmatch(cp,"*gmacs*"))
|
||||
newopt=SH_GMACS;
|
||||
else if(strmatch(cp,"*macs*"))
|
||||
newopt=SH_EMACS;
|
||||
#endif
|
||||
if(newopt)
|
||||
{
|
||||
#if SHOPT_VSH
|
||||
sh_offoption(SH_VI);
|
||||
#endif
|
||||
#if SHOPT_ESH
|
||||
sh_offoption(SH_EMACS);
|
||||
sh_offoption(SH_GMACS);
|
||||
#endif
|
||||
sh_onoption(newopt);
|
||||
}
|
||||
done:
|
||||
nv_putv(np, val, flags, fp);
|
||||
}
|
||||
#endif /* SHOPT_VSH || SHOPT_ESH */
|
||||
|
||||
/* Trap for HISTFILE and HISTSIZE variables */
|
||||
static void put_history(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
|
||||
|
@ -727,11 +742,11 @@ void sh_setmatch(Shell_t *shp,const char *v, int vsize, int nmatch, regoff_t mat
|
|||
Namarr_t *ap = nv_arrayptr(SH_MATCHNOD);
|
||||
Namarr_t *ap_save = ap;
|
||||
shp->subshell = 0;
|
||||
#ifndef SHOPT_2DMATCH
|
||||
#if !SHOPT_2DMATCH
|
||||
index = 0;
|
||||
#else
|
||||
if(index==0)
|
||||
#endif /* SHOPT_2DMATCH */
|
||||
#endif /* !SHOPT_2DMATCH */
|
||||
{
|
||||
if(ap->hdr.next != &mp->hdr)
|
||||
{
|
||||
|
@ -759,7 +774,7 @@ void sh_setmatch(Shell_t *shp,const char *v, int vsize, int nmatch, regoff_t mat
|
|||
mp->v = v;
|
||||
mp->first = match[0];
|
||||
}
|
||||
#ifdef SHOPT_2DMATCH
|
||||
#if SHOPT_2DMATCH
|
||||
else
|
||||
{
|
||||
if(index==1)
|
||||
|
@ -882,7 +897,9 @@ static const Namdisc_t SH_VERSION_disc = { 0, 0, get_version, nget_version };
|
|||
static const Namdisc_t IFS_disc = { sizeof(struct ifs), put_ifs, get_ifs };
|
||||
const Namdisc_t RESTRICTED_disc = { sizeof(Namfun_t), put_restricted };
|
||||
static const Namdisc_t CDPATH_disc = { sizeof(Namfun_t), put_cdpath };
|
||||
#if SHOPT_VSH || SHOPT_ESH
|
||||
static const Namdisc_t EDITOR_disc = { sizeof(Namfun_t), put_ed };
|
||||
#endif
|
||||
static const Namdisc_t HISTFILE_disc = { sizeof(Namfun_t), put_history };
|
||||
static const Namdisc_t OPTINDEX_disc = { sizeof(Namfun_t), put_optindex, 0, nget_optindex, 0, 0, clone_optindex };
|
||||
static const Namdisc_t SECONDS_disc = { sizeof(struct seconds), put_seconds, get_seconds, nget_seconds };
|
||||
|
@ -1416,7 +1433,7 @@ Shell_t *sh_init(register int argc,register char *argv[], Shinit_f userinit)
|
|||
/* set[ug]id scripts require the -p flag */
|
||||
if(shp->gd->userid!=shp->gd->euserid || shp->gd->groupid!=shp->gd->egroupid)
|
||||
{
|
||||
#ifdef SHOPT_P_SUID
|
||||
#if SHOPT_P_SUID
|
||||
/* require sh -p to run setuid and/or setgid */
|
||||
if(!sh_isoption(SH_PRIVILEGED) && shp->gd->userid >= SHOPT_P_SUID)
|
||||
{
|
||||
|
@ -1548,14 +1565,18 @@ int sh_reinit(char *argv[])
|
|||
#endif /* SHOPT_NAMESPACE */
|
||||
if(sh_isoption(SH_TRACKALL))
|
||||
on_option(&opt,SH_TRACKALL);
|
||||
#if SHOPT_ESH
|
||||
if(sh_isoption(SH_EMACS))
|
||||
on_option(&opt,SH_EMACS);
|
||||
if(sh_isoption(SH_GMACS))
|
||||
on_option(&opt,SH_GMACS);
|
||||
#endif
|
||||
#if SHOPT_VSH
|
||||
if(sh_isoption(SH_VI))
|
||||
on_option(&opt,SH_VI);
|
||||
if(sh_isoption(SH_VIRAW))
|
||||
on_option(&opt,SH_VIRAW);
|
||||
#endif
|
||||
shp->options = opt;
|
||||
/* set up new args */
|
||||
if(argv)
|
||||
|
@ -1607,7 +1628,7 @@ Namfun_t *nv_cover(register Namval_t *np)
|
|||
|
||||
static const char *shdiscnames[] = { "tilde", 0};
|
||||
|
||||
#ifdef SHOPT_STATS
|
||||
#if SHOPT_STATS
|
||||
struct Stats
|
||||
{
|
||||
Namfun_t hdr;
|
||||
|
@ -1735,10 +1756,12 @@ static Init_t *nv_init(Shell_t *shp)
|
|||
ip->SHELL_init.nofree = 1;
|
||||
ip->ENV_init.disc = &RESTRICTED_disc;
|
||||
ip->ENV_init.nofree = 1;
|
||||
#if SHOPT_VSH || SHOPT_ESH
|
||||
ip->VISUAL_init.disc = &EDITOR_disc;
|
||||
ip->VISUAL_init.nofree = 1;
|
||||
ip->EDITOR_init.disc = &EDITOR_disc;
|
||||
ip->EDITOR_init.nofree = 1;
|
||||
#endif
|
||||
ip->HISTFILE_init.disc = &HISTFILE_disc;
|
||||
ip->HISTFILE_init.nofree = 1;
|
||||
ip->HISTSIZE_init.disc = &HISTFILE_disc;
|
||||
|
@ -1781,8 +1804,10 @@ static Init_t *nv_init(Shell_t *shp)
|
|||
nv_stack(CDPNOD, &ip->CDPATH_init);
|
||||
nv_stack(SHELLNOD, &ip->SHELL_init);
|
||||
nv_stack(ENVNOD, &ip->ENV_init);
|
||||
#if SHOPT_VSH || SHOPT_ESH
|
||||
nv_stack(VISINOD, &ip->VISUAL_init);
|
||||
nv_stack(EDITNOD, &ip->EDITOR_init);
|
||||
#endif
|
||||
nv_stack(HISTFILE, &ip->HISTFILE_init);
|
||||
nv_stack(HISTSIZE, &ip->HISTSIZE_init);
|
||||
nv_stack(OPTINDNOD, &ip->OPTINDEX_init);
|
||||
|
|
|
@ -129,7 +129,7 @@ struct back_save
|
|||
#define P_COREDUMP 0100
|
||||
#define P_DISOWN 0200
|
||||
#define P_FG 0400
|
||||
#ifdef SHOPT_BGX
|
||||
#if SHOPT_BGX
|
||||
#define P_BG 01000
|
||||
#endif /* SHOPT_BGX */
|
||||
|
||||
|
@ -194,7 +194,7 @@ static struct back_save bck;
|
|||
|
||||
typedef int (*Waitevent_f)(int,long,int);
|
||||
|
||||
#ifdef SHOPT_BGX
|
||||
#if SHOPT_BGX
|
||||
void job_chldtrap(Shell_t *shp, const char *trap, int unpost)
|
||||
{
|
||||
register struct process *pw,*pwnext;
|
||||
|
@ -404,7 +404,7 @@ int job_reap(register int sig)
|
|||
if(WEXITSTATUS(wstat) > pw->p_exitmin)
|
||||
pw->p_exit = WEXITSTATUS(wstat);
|
||||
}
|
||||
#ifdef SHOPT_BGX
|
||||
#if SHOPT_BGX
|
||||
if((pw->p_flag&P_DONE) && (pw->p_flag&P_BG))
|
||||
{
|
||||
job.numbjob--;
|
||||
|
@ -443,7 +443,7 @@ int job_reap(register int sig)
|
|||
if(!px && sh_isoption(SH_INTERACTIVE))
|
||||
tcsetpgrp(JOBTTY,job.mypid);
|
||||
}
|
||||
#ifndef SHOPT_BGX
|
||||
#if !SHOPT_BGX
|
||||
if(!shp->intrap && shp->st.trapcom[SIGCHLD] && pid>0 && (pwfg!=job_bypid(pid)))
|
||||
{
|
||||
shp->sigflag[SIGCHLD] |= SH_SIGTRAP;
|
||||
|
@ -454,7 +454,7 @@ int job_reap(register int sig)
|
|||
if(errno==ECHILD)
|
||||
{
|
||||
errno = oerrno;
|
||||
#ifdef SHOPT_BGX
|
||||
#if SHOPT_BGX
|
||||
job.numbjob = 0;
|
||||
#endif /* SHOPT_BGX */
|
||||
nochild = 1;
|
||||
|
@ -1188,7 +1188,7 @@ void job_clear(void)
|
|||
init_savelist();
|
||||
job.pwlist = NIL(struct process*);
|
||||
job.numpost=0;
|
||||
#ifdef SHOPT_BGX
|
||||
#if SHOPT_BGX
|
||||
job.numbjob = 0;
|
||||
#endif /* SHOPT_BGX */
|
||||
job.waitall = 0;
|
||||
|
@ -1210,7 +1210,7 @@ int job_post(Shell_t *shp,pid_t pid, pid_t join)
|
|||
{
|
||||
register struct process *pw;
|
||||
register History_t *hp = shp->gd->hist_ptr;
|
||||
#ifdef SHOPT_BGX
|
||||
#if SHOPT_BGX
|
||||
int val,bg=0;
|
||||
#else
|
||||
int val;
|
||||
|
@ -1222,7 +1222,7 @@ int job_post(Shell_t *shp,pid_t pid, pid_t join)
|
|||
return(0);
|
||||
}
|
||||
job_lock();
|
||||
#ifdef SHOPT_BGX
|
||||
#if SHOPT_BGX
|
||||
if(join==1)
|
||||
{
|
||||
join = 0;
|
||||
|
@ -1314,7 +1314,7 @@ int job_post(Shell_t *shp,pid_t pid, pid_t join)
|
|||
else
|
||||
pw->p_flag |= (P_DONE|P_NOTIFY);
|
||||
}
|
||||
#ifdef SHOPT_BGX
|
||||
#if SHOPT_BGX
|
||||
if(bg)
|
||||
{
|
||||
if(pw->p_flag&P_DONE)
|
||||
|
@ -1610,7 +1610,7 @@ int job_switch(register struct process *pw,int bgflag)
|
|||
{
|
||||
sfprintf(outfile,"[%d]\t",(int)pw->p_job);
|
||||
sh.bckpid = pw->p_pid;
|
||||
#ifdef SHOPT_BGX
|
||||
#if SHOPT_BGX
|
||||
pw->p_flag |= P_BG;
|
||||
#endif
|
||||
msg = "&";
|
||||
|
@ -1634,7 +1634,7 @@ int job_switch(register struct process *pw,int bgflag)
|
|||
}
|
||||
job.waitall = 1;
|
||||
pw->p_flag |= P_FG;
|
||||
#ifdef SHOPT_BGX
|
||||
#if SHOPT_BGX
|
||||
pw->p_flag &= ~P_BG;
|
||||
#endif
|
||||
job_wait(pw->p_pid);
|
||||
|
@ -1703,7 +1703,7 @@ static struct process *job_unpost(register struct process *pwtop,int notify)
|
|||
pwtop = pw = job_byjid((int)pwtop->p_job);
|
||||
if(!pw)
|
||||
return(0);
|
||||
#ifdef SHOPT_BGX
|
||||
#if SHOPT_BGX
|
||||
if(pw->p_flag&P_BG)
|
||||
return(pw);
|
||||
#endif /* SHOPT_BGX */
|
||||
|
|
|
@ -1252,12 +1252,14 @@ int sh_lex(Lex_t* lp)
|
|||
/* check for reserved word { or } */
|
||||
if(lp->lex.reservok && state[n]==S_BREAK && isfirst)
|
||||
break;
|
||||
#if SHOPT_BRACEPAT
|
||||
if(sh_isoption(SH_BRACEEXPAND) && c==LBRACE && !assignment && state[n]!=S_BREAK
|
||||
&& !lp->lex.incase && !lp->lex.intest
|
||||
&& !lp->lex.skipword)
|
||||
{
|
||||
wordflags |= ARG_EXP;
|
||||
}
|
||||
#endif
|
||||
if(c==RBRACE && n==LPAREN)
|
||||
goto epat;
|
||||
break;
|
||||
|
@ -1892,8 +1894,10 @@ static int here_copy(Lex_t *lp,register struct ionod *iop)
|
|||
sfputc(sp,'\\');
|
||||
}
|
||||
}
|
||||
#if SHOPT_MULTIBYTE
|
||||
if(LEN < 1)
|
||||
LEN = 1;
|
||||
#endif
|
||||
bufp = fcseek(-LEN);
|
||||
}
|
||||
else
|
||||
|
|
|
@ -508,8 +508,10 @@ static void copyto(register Mac_t *mp,int endch, int newquote)
|
|||
sfputc(stkp,ESCAPE);
|
||||
break;
|
||||
}
|
||||
#if SHOPT_BRACEPAT
|
||||
else if(sh_isoption(SH_BRACEEXPAND) && mp->pattern==4 && (*cp==',' || *cp==LBRACE || *cp==RBRACE || *cp=='.'))
|
||||
break;
|
||||
#endif
|
||||
else if(mp->split && endch && !mp->quote && !mp->lit)
|
||||
{
|
||||
if(c)
|
||||
|
@ -763,15 +765,21 @@ static void copyto(register Mac_t *mp,int endch, int newquote)
|
|||
case S_BRACE:
|
||||
if(!(mp->quote || mp->lit))
|
||||
{
|
||||
#if SHOPT_BRACEPAT
|
||||
mp->patfound = mp->split && sh_isoption(SH_BRACEEXPAND);
|
||||
#else
|
||||
mp->patfound = 0;
|
||||
#endif
|
||||
brace++;
|
||||
}
|
||||
pattern:
|
||||
if(!mp->pattern || !(mp->quote || mp->lit))
|
||||
{
|
||||
/* mark beginning of {a,b} */
|
||||
#if SHOPT_BRACEPAT
|
||||
if(n==S_BRACE && endch==0 && mp->pattern)
|
||||
mp->pattern=4;
|
||||
#endif
|
||||
if(n==S_SLASH && mp->pattern==2)
|
||||
mp->pattern=3;
|
||||
break;
|
||||
|
@ -1102,7 +1110,7 @@ retry1:
|
|||
{
|
||||
if(c=='#')
|
||||
type = M_SIZE;
|
||||
#ifdef SHOPT_TYPEDEF
|
||||
#if SHOPT_TYPEDEF
|
||||
else if(c=='@')
|
||||
{
|
||||
type = M_TYPE;
|
||||
|
@ -1410,7 +1418,7 @@ retry1:
|
|||
if(ap && !mp->dotdot && !(ap->nelem&ARRAY_UNDEF))
|
||||
addsub = 1;
|
||||
}
|
||||
#ifdef SHOPT_TYPEDEF
|
||||
#if SHOPT_TYPEDEF
|
||||
else if(type==M_TYPE)
|
||||
{
|
||||
Namval_t *nq = nv_type(np);
|
||||
|
|
|
@ -1053,8 +1053,15 @@ Namval_t *nv_create(const char *name, Dt_t *root, int flags, Namfun_t *dp)
|
|||
}
|
||||
else
|
||||
cp = sp;
|
||||
if((c = *cp)=='.' || (c=='[' && nv_isarray(np)) || (n&ARRAY_FILL) || ((ap || (flags&NV_ASSIGN)) && (flags&NV_ARRAY)))
|
||||
|
||||
if((c = *cp)=='.'
|
||||
|| (c=='[' && nv_isarray(np))
|
||||
|| (n&ARRAY_FILL)
|
||||
|| ((
|
||||
#if SHOPT_FIXEDARRAY
|
||||
ap ||
|
||||
#endif
|
||||
(flags&NV_ASSIGN)) && (flags&NV_ARRAY)))
|
||||
{
|
||||
int m = cp-sp;
|
||||
sub = m?nv_getsub(np):0;
|
||||
|
@ -1839,6 +1846,18 @@ void nv_putval(register Namval_t *np, const char *string, int flags)
|
|||
#if SHOPT_MULTIBYTE
|
||||
if(size)
|
||||
size = ja_size((char*)sp,size,nv_isattr(np,NV_RJUST|NV_ZFILL));
|
||||
#else
|
||||
/* fallback: consider control characters to have zero width */
|
||||
if(size)
|
||||
{
|
||||
char *c = (char*)sp;
|
||||
int s = size;
|
||||
for( ; *c && s; c++)
|
||||
if(iscntrl(*c))
|
||||
size++;
|
||||
else
|
||||
s--;
|
||||
}
|
||||
#endif /* SHOPT_MULTIBYTE */
|
||||
}
|
||||
if(!up->cp || *up->cp==0)
|
||||
|
|
|
@ -752,12 +752,14 @@ static void outval(char *name, const char *vname, struct Walk *wp)
|
|||
{
|
||||
Namarr_t *ap;
|
||||
nv_attribute(np,wp->out,"typeset",'=');
|
||||
#if SHOPT_FIXEDARRAY
|
||||
if((ap=nv_arrayptr(np)) && ap->fixed)
|
||||
{
|
||||
sfprintf(wp->out,"%s",name);
|
||||
nv_arrfixed(np,wp->out,0,(char*)0);
|
||||
sfputc(wp->out,';');
|
||||
}
|
||||
#endif
|
||||
}
|
||||
nv_outname(wp->out,name,-1);
|
||||
if((np->nvalue.cp && np->nvalue.cp!=Empty) || nv_isattr(np,~(NV_MINIMAL|NV_NOFREE)) || nv_isvtree(np))
|
||||
|
|
|
@ -1240,7 +1240,12 @@ int sh_exec(register const Shnode_t *t, int flags)
|
|||
int jmpval, save_prompt;
|
||||
int was_nofork = execflg?sh_isstate(SH_NOFORK):0;
|
||||
struct checkpt *buffp = (struct checkpt*)stkalloc(shp->stk,sizeof(struct checkpt));
|
||||
volatile unsigned long was_vi=0, was_emacs=0, was_gmacs=0;
|
||||
#if SHOPT_VSH
|
||||
volatile unsigned long was_vi=0;
|
||||
#endif
|
||||
#if SHOPT_ESH
|
||||
volatile unsigned long was_emacs=0, was_gmacs=0;
|
||||
#endif
|
||||
struct stat statb;
|
||||
bp = &shp->bltindata;
|
||||
save_ptr = bp->ptr;
|
||||
|
@ -1252,12 +1257,16 @@ int sh_exec(register const Shnode_t *t, int flags)
|
|||
* disable editors for built-in
|
||||
* versions of commands on PATH
|
||||
*/
|
||||
#if SHOPT_VSH
|
||||
was_vi = sh_isoption(SH_VI);
|
||||
sh_offoption(SH_VI);
|
||||
#endif
|
||||
#if SHOPT_ESH
|
||||
was_emacs = sh_isoption(SH_EMACS);
|
||||
was_gmacs = sh_isoption(SH_GMACS);
|
||||
sh_offoption(SH_VI);
|
||||
sh_offoption(SH_EMACS);
|
||||
sh_offoption(SH_GMACS);
|
||||
#endif
|
||||
}
|
||||
if(execflg)
|
||||
sh_onstate(SH_NOFORK);
|
||||
|
@ -1392,12 +1401,17 @@ int sh_exec(register const Shnode_t *t, int flags)
|
|||
shp->bltinfun = 0;
|
||||
if(buffp->olist)
|
||||
free_list(buffp->olist);
|
||||
#if SHOPT_VSH
|
||||
if(was_vi)
|
||||
sh_onoption(SH_VI);
|
||||
else if(was_emacs)
|
||||
else
|
||||
#endif
|
||||
#if SHOPT_ESH
|
||||
if(was_emacs)
|
||||
sh_onoption(SH_EMACS);
|
||||
else if(was_gmacs)
|
||||
sh_onoption(SH_GMACS);
|
||||
#endif
|
||||
if(scope)
|
||||
sh_unscope(shp);
|
||||
bp->ptr = (void*)save_ptr;
|
||||
|
@ -1555,7 +1569,7 @@ int sh_exec(register const Shnode_t *t, int flags)
|
|||
job.parent=parent=0;
|
||||
else
|
||||
{
|
||||
#ifdef SHOPT_BGX
|
||||
#if SHOPT_BGX
|
||||
int maxjob;
|
||||
if(((type&(FAMP|FINT)) == (FAMP|FINT)) && (maxjob=nv_getnum(JOBMAXNOD))>0)
|
||||
{
|
||||
|
@ -2856,7 +2870,7 @@ pid_t _sh_fork(Shell_t *shp,register pid_t parent,int flags,int *jobid)
|
|||
shp->cpid = parent;
|
||||
if(!postid && job.curjobid && (flags&FPOU))
|
||||
postid = job.curpgid;
|
||||
#ifdef SHOPT_BGX
|
||||
#if SHOPT_BGX
|
||||
if(!postid && (flags&(FAMP|FINT)) == (FAMP|FINT))
|
||||
postid = 1;
|
||||
myjob = job_post(shp,parent,postid);
|
||||
|
|
|
@ -285,7 +285,7 @@ word=$(print $'foo\nbar' | ( read line; "$bincat") )
|
|||
if [[ $word != bar ]]
|
||||
then err_exit "pipe to ( read line; $bincat) not working"
|
||||
fi
|
||||
if [[ $(print x{a,b}y) != 'xay xby' ]]
|
||||
if ((SHOPT_BRACEPAT)) && [[ $(print x{a,b}y) != 'xay xby' ]]
|
||||
then err_exit 'brace expansion not working'
|
||||
fi
|
||||
if [[ $(for i in foo bar
|
||||
|
|
|
@ -316,7 +316,8 @@ function test_sub
|
|||
}
|
||||
alias test_sub='test_sub $LINENO'
|
||||
|
||||
set --noglob --nobraceexpand
|
||||
set --noglob
|
||||
((SHOPT_BRACEPAT)) && set --nobraceexpand
|
||||
|
||||
subject='A regular expressions test'
|
||||
|
||||
|
|
|
@ -698,10 +698,11 @@ got=$(export tmp; "$SHELL" -ec \
|
|||
|
||||
# ======
|
||||
# Redirections of the form {varname}>file stopped working if brace expansion was turned off
|
||||
set +B
|
||||
{ redirect {v}>$tmp/v.out && echo ok >&$v; } 2>/dev/null
|
||||
set -B
|
||||
((SHOPT_BRACEPAT)) && set +B
|
||||
{ redirect {v}>$tmp/v.out && echo ok >&$v; } 2>/dev/null && redirect {v}>&-
|
||||
((SHOPT_BRACEPAT)) && set -B
|
||||
[[ -r $tmp/v.out && $(<$tmp/v.out) == ok ]] || err_exit '{varname}>file not working with brace expansion turned off'
|
||||
|
||||
# ...and they didn't work in subshells: https://github.com/ksh93/ksh/issues/167
|
||||
(redirect {v}>$tmp/v.out; echo ok2 >&$v) 2>/dev/null
|
||||
[[ -r $tmp/v.out && $(<$tmp/v.out) == ok2 ]] || err_exit 'redirect {varname}>file not working in a subshell'
|
||||
|
|
|
@ -38,11 +38,12 @@ b=$($SHELL -c '(LC_ALL=debug / 2>/dev/null); /' 2>&1 | sed -e "s,.*: *,," -e "s,
|
|||
b=$($SHELL -c '(LC_ALL=debug; / 2>/dev/null); /' 2>&1 | sed -e "s,.*: *,," -e "s, *\[.*,,")
|
||||
[[ "$b" == "$a" ]] || err_exit "locale not restored after subshell -- expected '$a', got '$b'"
|
||||
|
||||
if((SHOPT_MULTIBYTE)); then
|
||||
# test shift-jis \x81\x40 ... \x81\x7E encodings
|
||||
# (shift char followed by 7 bit ascii)
|
||||
|
||||
typeset -i16 chr
|
||||
for locale in $(PATH=/bin:/usr/bin locale -a 2>/dev/null | grep -i jis)
|
||||
for locale in $(command -p locale -a 2>/dev/null | grep -i jis)
|
||||
do export LC_ALL=$locale
|
||||
for ((chr=0x40; chr<=0x7E; chr++))
|
||||
do c=${chr#16#}
|
||||
|
@ -56,11 +57,16 @@ do export LC_ALL=$locale
|
|||
done
|
||||
done
|
||||
done
|
||||
fi # SHOPT_MULTIBYTE
|
||||
|
||||
# this locale is supported by ast on all platforms
|
||||
# EU for { decimal_point="," thousands_sep="." }
|
||||
|
||||
if((SHOPT_MULTIBYTE)); then
|
||||
locale=C_EU.UTF-8
|
||||
else
|
||||
locale=C_EU
|
||||
fi
|
||||
|
||||
export LC_ALL=C
|
||||
|
||||
|
@ -104,7 +110,11 @@ fi
|
|||
|
||||
#$SHELL -c 'export LANG='$locale'; printf "\u[20ac]\u[20ac]" > $tmp/two_euro_chars.txt'
|
||||
printf $'\342\202\254\342\202\254' > $tmp/two_euro_chars.txt
|
||||
if((SHOPT_MULTIBYTE)); then
|
||||
exp="6 2 6"
|
||||
else
|
||||
exp="6 6 6"
|
||||
fi # SHOPT_MULTIBYTE
|
||||
set -- $($SHELL -c "
|
||||
if builtin wc 2>/dev/null || builtin -f cmd wc 2>/dev/null
|
||||
then unset LC_CTYPE
|
||||
|
@ -191,6 +201,7 @@ got="$(<out)"
|
|||
|
||||
# multibyte identifiers
|
||||
|
||||
if((SHOPT_MULTIBYTE)); then
|
||||
exp=OK
|
||||
got=$(set +x; LC_ALL=C.UTF-8 $SHELL -c $'\u[5929]=OK; print ${\u[5929]}' 2>&1)
|
||||
[[ $got == "$exp" ]] || err_exit "multibyte variable definition/expansion failed -- expected '$exp', got '$got'"
|
||||
|
@ -198,6 +209,7 @@ got=$(set +x; LC_ALL=C.UTF-8 $SHELL -c $'function \u[5929]\n{\nprint OK;\n}; \u[
|
|||
[[ $got == "$exp" ]] || err_exit "multibyte ksh function definition/execution failed -- expected '$exp', got '$got'"
|
||||
got=$(set +x; LC_ALL=C.UTF-8 $SHELL -c $'\u[5929]()\n{\nprint OK;\n}; \u[5929]' 2>&1)
|
||||
[[ $got == "$exp" ]] || err_exit "multibyte posix function definition/execution failed -- expected '$exp', got '$got'"
|
||||
fi # SHOPT_MULTIBYTE
|
||||
|
||||
# this locale is supported by ast on all platforms
|
||||
# mainly used to debug multibyte and message translation code
|
||||
|
@ -205,6 +217,7 @@ got=$(set +x; LC_ALL=C.UTF-8 $SHELL -c $'\u[5929]()\n{\nprint OK;\n}; \u[5929]'
|
|||
|
||||
locale=debug
|
||||
|
||||
if((SHOPT_MULTIBYTE)); then
|
||||
if [[ "$(LC_ALL=$locale $SHELL <<- \+EOF+
|
||||
x=a<1z>b<2yx>c
|
||||
print ${#x}
|
||||
|
@ -212,6 +225,7 @@ if [[ "$(LC_ALL=$locale $SHELL <<- \+EOF+
|
|||
]]
|
||||
then err_exit '${#x} not working with multibyte locales'
|
||||
fi
|
||||
fi # SHOPT_MULTIBYTE
|
||||
|
||||
dir=_not_found_
|
||||
exp=2
|
||||
|
@ -243,9 +257,11 @@ do for cmd in "($lc=$locale;cd $dir)" "$lc=$locale;cd $dir;unset $lc" "function
|
|||
done
|
||||
done
|
||||
|
||||
if((SHOPT_MULTIBYTE)); then
|
||||
exp=123
|
||||
got=$(LC_ALL=debug $SHELL -c "a<2A@>z=$exp; print \$a<2A@>z")
|
||||
[[ $got == $exp ]] || err_exit "multibyte debug locale \$a<2A@>z failed -- expected '$exp', got '$got'"
|
||||
fi # SHOPT_MULTIBYTE
|
||||
|
||||
unset LC_ALL LC_MESSAGES
|
||||
export LANG=debug
|
||||
|
@ -297,7 +313,11 @@ x=$( LC_ALL=debug $SHELL ./script$$.1)
|
|||
|
||||
|
||||
x=$(LC_ALL=debug $SHELL -c 'x="a<2b|>c";print -r -- ${#x}')
|
||||
if((SHOPT_MULTIBYTE)); then
|
||||
(( x == 3 )) || err_exit 'character length of multibyte character should be 3'
|
||||
else
|
||||
(( x == 7 )) || err_exit 'character length of multibyte character should be 7 with SHOPT_MULTIBYTE disabled'
|
||||
fi # SHOPT_MULTIBYTE
|
||||
x=$(LC_ALL=debug $SHELL -c 'typeset -R10 x="a<2b|>c";print -r -- "${x}"')
|
||||
[[ $x == ' a<2b|>c' ]] || err_exit 'typeset -R10 should begin with three spaces'
|
||||
x=$(LC_ALL=debug $SHELL -c 'typeset -L10 x="a<2b|>c";print -r -- "${x}"')
|
||||
|
|
|
@ -198,8 +198,27 @@ test_has_iszero
|
|||
# printf formatting options as well as checking for correct float scaling
|
||||
# of the fractional parts.
|
||||
|
||||
if ((SHOPT_BRACEPAT))
|
||||
then set -- {'','-'}{0..1}.{0,9}{0,9}{0,1,9}{0,1,9}
|
||||
else set -- 0.0000 0.0001 0.0009 0.0010 0.0011 0.0019 0.0090 0.0091 0.0099 \
|
||||
0.0900 0.0901 0.0909 0.0910 0.0911 0.0919 0.0990 0.0991 0.0999 \
|
||||
0.9000 0.9001 0.9009 0.9010 0.9011 0.9019 0.9090 0.9091 0.9099 \
|
||||
0.9900 0.9901 0.9909 0.9910 0.9911 0.9919 0.9990 0.9991 0.9999 \
|
||||
1.0000 1.0001 1.0009 1.0010 1.0011 1.0019 1.0090 1.0091 1.0099 \
|
||||
1.0900 1.0901 1.0909 1.0910 1.0911 1.0919 1.0990 1.0991 1.0999 \
|
||||
1.9000 1.9001 1.9009 1.9010 1.9011 1.9019 1.9090 1.9091 1.9099 \
|
||||
1.9900 1.9901 1.9909 1.9910 1.9911 1.9919 1.9990 1.9991 1.9999 \
|
||||
-0.0000 -0.0001 -0.0009 -0.0010 -0.0011 -0.0019 -0.0090 -0.0091 -0.0099 \
|
||||
-0.0900 -0.0901 -0.0909 -0.0910 -0.0911 -0.0919 -0.0990 -0.0991 -0.0999 \
|
||||
-0.9000 -0.9001 -0.9009 -0.9010 -0.9011 -0.9019 -0.9090 -0.9091 -0.9099 \
|
||||
-0.9900 -0.9901 -0.9909 -0.9910 -0.9911 -0.9919 -0.9990 -0.9991 -0.9999 \
|
||||
-1.0000 -1.0001 -1.0009 -1.0010 -1.0011 -1.0019 -1.0090 -1.0091 -1.0099 \
|
||||
-1.0900 -1.0901 -1.0909 -1.0910 -1.0911 -1.0919 -1.0990 -1.0991 -1.0999 \
|
||||
-1.9000 -1.9001 -1.9009 -1.9010 -1.9011 -1.9019 -1.9090 -1.9091 -1.9099 \
|
||||
-1.9900 -1.9901 -1.9909 -1.9910 -1.9911 -1.9919 -1.9990 -1.9991 -1.9999
|
||||
fi
|
||||
unset i tf pf; typeset -F 3 tf
|
||||
for i in {'','-'}{0..1}.{0,9}{0,9}{0,1,9}{0,1,9}
|
||||
for i
|
||||
do tf=$i
|
||||
pf=${ printf '%.3f' tf ;}
|
||||
if [[ $tf != "$pf" ]]
|
||||
|
@ -207,7 +226,7 @@ do tf=$i
|
|||
fi
|
||||
done
|
||||
unset i tf pf; typeset -lF 3 tf
|
||||
for i in {'','-'}{0..1}.{0,9}{0,9}{0,1,9}{0,1,9}
|
||||
for i
|
||||
do tf=$i
|
||||
pf=${ printf '%.3Lf' tf ;}
|
||||
if [[ $tf != "$pf" ]]
|
||||
|
@ -215,7 +234,7 @@ do tf=$i
|
|||
fi
|
||||
done
|
||||
unset i tf pf; typeset -E 3 tf
|
||||
for i in {'','-'}{0..1}.{0,9}{0,9}{0,1,9}{0,1,9}
|
||||
for i
|
||||
do tf=$i
|
||||
pf=${ printf '%.3g' tf ;}
|
||||
if [[ $tf != "$pf" ]]
|
||||
|
@ -223,7 +242,7 @@ do tf=$i
|
|||
fi
|
||||
done
|
||||
unset i tf pf; typeset -lE 3 tf
|
||||
for i in {'','-'}{0..1}.{0,9}{0,9}{0,1,9}{0,1,9}
|
||||
for i
|
||||
do tf=$i
|
||||
pf=${ printf '%.3Lg' tf ;}
|
||||
if [[ $tf != "$pf" ]]
|
||||
|
|
|
@ -30,6 +30,11 @@ integer Errors=0
|
|||
|
||||
[[ -d $tmp && -w $tmp && $tmp == "$PWD" ]] || { err\_exit "$LINENO" '$tmp not set; run this from shtests. Aborting.'; exit 1; }
|
||||
|
||||
if((!SHOPT_NAMESPACE))
|
||||
then err\_exit "$LINENO" 'warning: shell compiled without SHOPT_NAMESPACE; skipping tests'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
foo=abc
|
||||
typeset -C bar=(x=3 y=4 t=7)
|
||||
typeset -A z=([abc]=qqq)
|
||||
|
|
|
@ -202,20 +202,21 @@ rm .profile
|
|||
|
||||
# { exec interactive login_shell restricted xtrace } in the following test
|
||||
|
||||
for opt in \
|
||||
set -- \
|
||||
allexport all-export all_export \
|
||||
bgnice bg-nice bg_nice \
|
||||
clobber emacs \
|
||||
clobber \
|
||||
errexit err-exit err_exit \
|
||||
glob \
|
||||
globstar glob-star glob_star \
|
||||
gmacs \
|
||||
ignoreeof ignore-eof ignore_eof \
|
||||
keyword log markdirs monitor notify \
|
||||
pipefail pipe-fail pipe_fail \
|
||||
trackall track-all track_all \
|
||||
unset verbose vi \
|
||||
viraw vi-raw vi_raw
|
||||
unset verbose
|
||||
((SHOPT_ESH)) && set -- "$@" emacs gmacs
|
||||
((SHOPT_VSH)) && set -- "$@" vi viraw vi-raw vi_raw
|
||||
for opt
|
||||
do old=$opt
|
||||
if [[ ! -o $opt ]]
|
||||
then old=no$opt
|
||||
|
@ -394,15 +395,16 @@ got=$(
|
|||
[[ $got == @((12|21)(12|21)) ]] || err_exit "& job delayed by --pipefail, expected '$exp', got '$got'"
|
||||
$SHELL -c '[[ $- == *c* ]]' || err_exit 'option c not in $-'
|
||||
> $tmp/.profile
|
||||
for i in i l r s D E a b e f h k n t u v x B C G H
|
||||
for i in i l r s D E a b e f h k n t u v x $(let SHOPT_BRACEPAT && echo B) C G $(let SHOPT_HISTEXPAND && echo H)
|
||||
do HOME=$tmp ENV=/./dev/null $SHELL -$i >/dev/null 2>&1 <<- ++EOF++ || err_exit "option $i not in \$-"
|
||||
[[ \$- == *$i* ]] || exit 1
|
||||
++EOF++
|
||||
done
|
||||
letters=ilrabefhknuvxBCGE
|
||||
letters=ilrabefhknuvx$(let SHOPT_BRACEPAT && echo B)CGE
|
||||
integer j=0
|
||||
for i in interactive login restricted allexport notify errexit \
|
||||
noglob trackall keyword noexec nounset verbose xtrace braceexpand \
|
||||
noglob trackall keyword noexec nounset verbose xtrace \
|
||||
$(let SHOPT_BRACEPAT && echo braceexpand) \
|
||||
noclobber globstar rc
|
||||
do HOME=$tmp ENV=/./dev/null $SHELL -o $i >/dev/null 2>&1 <<- ++EOF++ || err_exit "option $i not equivalent to ${letters:j:1}"
|
||||
[[ \$- == *${letters:j:1}* ]] || exit 1
|
||||
|
@ -551,6 +553,7 @@ fi
|
|||
|
||||
# ======
|
||||
# Brace expansion could not be turned off in command substitutions (rhbz#1078698)
|
||||
if((SHOPT_BRACEPAT)); then
|
||||
set -B
|
||||
expect='test{1,2}'
|
||||
actual=$(set +B; echo `echo test{1,2}`)
|
||||
|
@ -562,6 +565,7 @@ actual=$(set +B; echo $(echo test{1,2}))
|
|||
actual=$(set +B; echo ${ echo test{1,2}; })
|
||||
[[ $actual == "$expect" ]] || err_exit 'Brace expansion not turned off in ${ comsub; }' \
|
||||
"(expected $(printf %q "$expect"), got $(printf %q "$actual"))"
|
||||
fi # SHOPT_BRACEPAT
|
||||
|
||||
# ======
|
||||
# ksh 93u+ did not correctly handle the combination of pipefail and (errexit or the ERR trap).
|
||||
|
|
|
@ -23,7 +23,9 @@
|
|||
# called 'pty', which allows for scripting interactive sessions and which is
|
||||
# installed in arch/*/bin while building. To understand these tests, first
|
||||
# read the pty manual by running: arch/*/bin/pty --man
|
||||
|
||||
#
|
||||
# Do not globally set the locale; these tests must pass for all locales.
|
||||
#
|
||||
# The # err_exit # comments are to enable shtests to count the tests.
|
||||
|
||||
# the trickiest part of the tests is avoiding typeahead
|
||||
|
@ -52,19 +54,18 @@ stty erase ^H kill ^X
|
|||
|
||||
bintrue=$(whence -p true)
|
||||
|
||||
x=$( $SHELL <<- \EOF
|
||||
x=$( "$SHELL" 2>&1 <<- \EOF
|
||||
trap 'exit 0' EXIT
|
||||
bintrue=$(whence -p true)
|
||||
set -o monitor
|
||||
{
|
||||
eval $'set -o vi\npty $bintrue'
|
||||
eval $'command set -o vi 2>/dev/null\npty $bintrue'
|
||||
} < /dev/null & pid=$!
|
||||
#sleep 1
|
||||
jobs
|
||||
kill $$
|
||||
EOF
|
||||
)
|
||||
[[ $x == *Stop* ]] && err_exit 'monitor mode enabled incorrectly causes job to stop'
|
||||
[[ $x == *Stop* ]] && err_exit "monitor mode enabled incorrectly causes job to stop (got $(printf %q "$x"))"
|
||||
|
||||
if [[ -o xtrace ]]
|
||||
then debug=--debug=1
|
||||
|
@ -86,7 +87,10 @@ function tst
|
|||
done
|
||||
}
|
||||
|
||||
export PS1=':test-!: ' PS2='> ' PS4=': ' ENV=/./dev/null EXINIT= HISTFILE= TERM=dumb VISUAL=vi LC_ALL=C
|
||||
# VISUAL, or if that is not set, EDITOR, automatically sets vi, gmacs or emacs mode if
|
||||
# its value matches *[Vv][Ii]*, *gmacs* or *macs*, respectively. See put_ed() in init.c.
|
||||
unset EDITOR
|
||||
export VISUAL=vi PS1=':test-!: ' PS2='> ' PS4=': ' ENV=/./dev/null EXINIT= HISTFILE= TERM=dumb
|
||||
|
||||
if ! pty $bintrue < /dev/null
|
||||
then err_exit pty command hangs on $bintrue -- tests skipped
|
||||
|
@ -163,7 +167,7 @@ u (Killed|Done)
|
|||
!
|
||||
|
||||
# err_exit #
|
||||
tst $LINENO <<"!"
|
||||
((SHOPT_VSH)) && tst $LINENO <<"!"
|
||||
L POSIX sh 091(C)
|
||||
|
||||
# If the User Portability Utilities Option is supported and shell
|
||||
|
@ -179,7 +183,7 @@ u ^hello\r?\n$
|
|||
!
|
||||
|
||||
# err_exit #
|
||||
tst $LINENO <<"!"
|
||||
((SHOPT_VSH)) && tst $LINENO <<"!"
|
||||
L POSIX sh 093(C)
|
||||
|
||||
# If the User Portability Utilities Option is supported and shell
|
||||
|
@ -195,7 +199,7 @@ u ^goodbye\r?\n$
|
|||
!
|
||||
|
||||
# err_exit #
|
||||
tst $LINENO <<"!"
|
||||
((SHOPT_VSH)) && tst $LINENO <<"!"
|
||||
L POSIX sh 094(C)
|
||||
|
||||
# If the User Portability Utilities Option is supported and shell
|
||||
|
@ -242,7 +246,7 @@ r history
|
|||
fi
|
||||
|
||||
# err_exit #
|
||||
tst $LINENO <<"!"
|
||||
((SHOPT_VSH)) && tst $LINENO <<"!"
|
||||
L POSIX sh 097(C)
|
||||
|
||||
# If the User Portability Utilities Option is supported and shell
|
||||
|
@ -303,7 +307,7 @@ u ^ok\r?\n$
|
|||
!
|
||||
|
||||
# err_exit #
|
||||
tst $LINENO <<"!"
|
||||
((SHOPT_VSH)) && tst $LINENO <<"!"
|
||||
L POSIX sh 101(C)
|
||||
|
||||
# If the User Portability Utilities Option is supported and shell
|
||||
|
@ -368,7 +372,7 @@ if [[ $(id -u) == 0 ]]
|
|||
then print -u2 "\t${Command}[$LINENO]: warning: running as root: skipping test POSIX sh 111(C)"
|
||||
else
|
||||
# err_exit #
|
||||
tst $LINENO <<"!"
|
||||
((SHOPT_VSH)) && tst $LINENO <<"!"
|
||||
L POSIX sh 111(C)
|
||||
|
||||
# If the User Portability Utilities Option is supported and shell
|
||||
|
@ -395,7 +399,7 @@ fi
|
|||
# It is left here for re-enabling temporarily if related changes in ksh need testing.
|
||||
: <<\end_disabled
|
||||
# err_(don't count me)_exit #
|
||||
TMPDIR=/tmp tst $LINENO <<"!"
|
||||
((SHOPT_VSH)) && TMPDIR=/tmp tst $LINENO <<"!"
|
||||
L POSIX sh 137(C)
|
||||
|
||||
# If the User Portability Utilities Option is supported and shell
|
||||
|
@ -420,7 +424,7 @@ if [[ $(id -u) == 0 ]]
|
|||
then print -u2 "\t${Command}[$LINENO]: warning: running as root: skipping test POSIX sh 251(C)"
|
||||
else
|
||||
# err_exit #
|
||||
tst $LINENO <<"!"
|
||||
((SHOPT_VSH)) && tst $LINENO <<"!"
|
||||
L POSIX sh 251(C)
|
||||
|
||||
# If the User Portability Utilities Option is supported and shell
|
||||
|
@ -480,6 +484,7 @@ disabled
|
|||
|
||||
# err_exit #
|
||||
# Test file name completion in vi mode
|
||||
if((SHOPT_VSH)); then
|
||||
mkdir "/tmp/fakehome_$$" && tst $LINENO <<!
|
||||
L vi mode file name completion
|
||||
|
||||
|
@ -492,49 +497,33 @@ w echo ~/tes\t
|
|||
u ^/tmp/fakehome_$$/testfile_$$\r?\n$
|
||||
!
|
||||
rm -r "/tmp/fakehome_$$"
|
||||
fi # SHOPT_VSH
|
||||
|
||||
# err_exit #
|
||||
LC_ALL=C tst $LINENO <<"!"
|
||||
L raw Bourne mode literal tab characters with wide characters disabled
|
||||
VISUAL='' tst $LINENO <<"!"
|
||||
L raw Bourne mode literal tab characters
|
||||
|
||||
# This gets handled by ed_read() in edit.c; it does not expand tab
|
||||
# characters on the command line.
|
||||
# With wide characters (e.g. UTF-8) disabled, raw mode is handled by ed_read()
|
||||
# in edit.c; it does not expand tab characters on the command line.
|
||||
# With wide characters enabled, and if vi mode is compiled in, raw mode is
|
||||
# handled by ed_viread() in vi.c (even though vi mode is off); it expands tab
|
||||
# characters to spaces on the command line. See slowread() in io.c.
|
||||
|
||||
d 20
|
||||
p :test-1:
|
||||
w set +o vi +o emacs
|
||||
p :test-2:
|
||||
w true /de\tv/nu\tl\tl
|
||||
r ^:test-2: true (/de\tv/nu\tl\tl|/de v/nu l l)\r\n$
|
||||
p :test-3:
|
||||
r ^:test-1: true (/de\tv/nu\tl\tl|/de v/nu l l)\r\n$
|
||||
p :test-2:
|
||||
!
|
||||
|
||||
# err_exit #
|
||||
LC_ALL=C.UTF-8 tst $LINENO <<"!"
|
||||
L raw Bourne mode literal tab characters with wide characters enabled
|
||||
|
||||
# This gets handled by ed_viread() in vi.c (even though vi mode is off);
|
||||
# it expands tab characters to spaces on the command line.
|
||||
|
||||
d 20
|
||||
p :test-1:
|
||||
w set +o vi +o emacs
|
||||
p :test-2:
|
||||
w true /de\tv/nu\tl\tl
|
||||
r ^:test-2: true /de v/nu l l\r\n$
|
||||
p :test-3:
|
||||
!
|
||||
|
||||
# err_exit #
|
||||
LC_ALL=C.UTF-8 tst $LINENO <<"!"
|
||||
VISUAL='' tst $LINENO <<"!"
|
||||
L raw Bourne mode backslash handling
|
||||
|
||||
# The escaping backslash feature should be disabled in the raw Bourne mode.
|
||||
# This is tested with both erase and kill characters.
|
||||
|
||||
d 20
|
||||
p :test-1:
|
||||
w set +o vi +o emacs; stty erase ^H kill ^X
|
||||
w stty erase ^H kill ^X
|
||||
p :test-2:
|
||||
w true string\\\\\cH\cH
|
||||
r ^:test-2: true string\r\n$
|
||||
|
@ -545,16 +534,19 @@ r ^:test-3: true correct\r\n$
|
|||
|
||||
# err_exit #
|
||||
# err_exit #
|
||||
for mode in emacs vi; do
|
||||
tst $LINENO << !
|
||||
set --
|
||||
((SHOPT_VSH)) && set -- "$@" vi
|
||||
((SHOPT_ESH)) && set -- "$@" emacs gmacs
|
||||
for mode do
|
||||
VISUAL=$mode tst $LINENO << !
|
||||
L escaping backslashes in $mode mode
|
||||
|
||||
# Backslashes should only be escaped if the previous input was a backslash.
|
||||
# Other backslashes stored in the input buffer should be erased normally.
|
||||
|
||||
d 20
|
||||
d 10
|
||||
p :test-1:
|
||||
w set -o $mode; stty erase ^H
|
||||
w stty erase ^H
|
||||
p :test-2:
|
||||
w true string\\\\\\\\\\cH\\cH\\cH
|
||||
r ^:test-2: true string\\r\\n$
|
||||
|
|
|
@ -8,7 +8,7 @@ valgrindflags='--xml=yes --log-file=/dev/null --track-origins=yes --read-var-inf
|
|||
|
||||
USAGE=$'
|
||||
[-s8?
|
||||
@(#)$Id: shtests (ksh 93u+m) 2020-09-02 $
|
||||
@(#)$Id: shtests (ksh 93u+m) 2021-02-04 $
|
||||
]
|
||||
[-author?David Korn <dgk@research.att.com>]
|
||||
[-author?Glenn Fowler <gsf@research.att.com>]
|
||||
|
@ -270,8 +270,8 @@ case $SHELL in
|
|||
*) SHELL=$(whence $SHELL);;
|
||||
esac
|
||||
PATH=$(
|
||||
PATH=/run/current-system/sw/bin:/usr/xpg7/bin:/usr/xpg6/bin:/usr/xpg4/bin:/bin:/usr/bin:$PATH
|
||||
getconf PATH 2>/dev/null || { builtin getconf 2>/dev/null && getconf PATH; }
|
||||
builtin getconf 2>/dev/null || PATH=/run/current-system/sw/bin:/usr/xpg7/bin:/usr/xpg6/bin:/usr/xpg4/bin:/bin:/usr/bin:$PATH
|
||||
getconf PATH 2>/dev/null
|
||||
) || PATH=/bin:/usr/bin
|
||||
if [[ -d /usr/ucb ]]
|
||||
then PATH=$PATH:/usr/ucb
|
||||
|
@ -310,6 +310,18 @@ fi
|
|||
# (some tests must unset or modify $HISTFILE, so set $HOME instead)
|
||||
export HOME=$tmp
|
||||
|
||||
# make the SHOPT_* macros available to the tests as environment variables
|
||||
SHOPT()
|
||||
{
|
||||
[[ $1 == *=* ]] && eval "export SHOPT_${ printf %q "${1%%=*}"; }=${ printf %q "${1#*=}"; }"
|
||||
}
|
||||
. "${SHOPTFILE:-../SHOPT.sh}"
|
||||
unset -f SHOPT
|
||||
if (( !SHOPT_MULTIBYTE && utf8 && !posix && !compile ))
|
||||
then echo "The -u/--utf8 option is unavailable as SHOPT_MULTIBYTE is turned off in ${SHOPTFILE:-SHOPT.sh}." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if (( compile ))
|
||||
then if whence $SHCOMP > /dev/null
|
||||
then :
|
||||
|
@ -352,7 +364,7 @@ do [[ $i == *.sh ]] || i+='.sh'
|
|||
if (( posix || utf8 ))
|
||||
then locales=
|
||||
(( posix )) && locales+=" ${LANG:-C}"
|
||||
[[ $utf8 == 0 || $i == $setslocale ]] || locales+=" C.UTF-8"
|
||||
[[ $utf8 == 0 || $i == $setslocale ]] || ((!SHOPT_MULTIBYTE)) || locales+=" C.UTF-8"
|
||||
for lang in $locales
|
||||
do o=$u
|
||||
tmp_s=$tmp/$u.$lang
|
||||
|
|
|
@ -260,8 +260,12 @@ fi
|
|||
if [[ ${var//+(\S)/Q} != 'Q Q' ]]
|
||||
then err_exit '${var//+(\S)/Q} not workding'
|
||||
fi
|
||||
|
||||
var=$($SHELL -c 'v=/vin:/usr/vin r=vin; : ${v//vin/${r//v/b}};typeset -p .sh.match') 2> /dev/null
|
||||
[[ $var == 'typeset -a .sh.match=((vin vin) )' ]] || err_exit '.sh.match not correct when replacement pattern contains a substring match'
|
||||
((SHOPT_2DMATCH)) && exp='typeset -a .sh.match=((vin vin) )' || exp='typeset -a .sh.match=(vin)'
|
||||
[[ $var == "$exp" ]] || err_exit '.sh.match not correct when replacement pattern contains a substring match' \
|
||||
"(expected $(printf %q "$exp"), got $(printf %q "$var"))"
|
||||
|
||||
foo='foo+bar+'
|
||||
[[ $(print -r -- ${foo//+/'|'}) != 'foo|bar|' ]] && err_exit "\${foobar//+/'|'}"
|
||||
[[ $(print -r -- ${foo//+/"|"}) != 'foo|bar|' ]] && err_exit '${foobar//+/"|"}'
|
||||
|
@ -523,7 +527,8 @@ fi
|
|||
string='foo(d:\nt\box\something)bar'
|
||||
expected='d:\nt\box\something'
|
||||
[[ ${string/*\(+([!\)])\)*/\1} == "$expected" ]] || err_exit "substring expansion failed '${string/*\(+([!\)])\)*/\1}' returned -- '$expected' expected"
|
||||
if [[ $($SHELL -c $'export LC_ALL=C.UTF-8; print -r "\342\202\254\342\202\254\342\202\254\342\202\254w\342\202\254\342\202\254\342\202\254\342\202\254" | wc -m' 2>/dev/null) == 10 ]]
|
||||
if ((SHOPT_MULTIBYTE)) &&
|
||||
[[ $($SHELL -c $'export LC_ALL=C.UTF-8; print -r "\342\202\254\342\202\254\342\202\254\342\202\254w\342\202\254\342\202\254\342\202\254\342\202\254" | wc -m' 2>/dev/null) == 10 ]]
|
||||
then LC_ALL=C.UTF-8 $SHELL -c b1=$'"\342\202\254\342\202\254\342\202\254\342\202\254w\342\202\254\342\202\254\342\202\254\342\202\254"; [[ ${b1:4:1} == w ]]' || err_exit 'multibyte ${var:offset:len} not working correctly'
|
||||
fi
|
||||
{ $SHELL -c 'unset x;[[ ${SHELL:$x} == $SHELL ]]';} 2> /dev/null || err_exit '${var:$x} fails when x is not set'
|
||||
|
@ -581,6 +586,7 @@ do i=$1
|
|||
done
|
||||
|
||||
#multibyte locale tests
|
||||
if((SHOPT_MULTIBYTE)); then
|
||||
x='a<2b|>c<3d|\>e' LC_ALL=debug $SHELL -c 'test "${x:0:1}" == a || err_exit ${x:0:1} should be a'
|
||||
x='a<2b|>c<3d|\>e' LC_ALL=debug $SHELL -c 'test "${x:1:1}" == "<2b|>" || err_exit ${x:1:1} should be <2b|>'
|
||||
x='a<2b|>c<3d|\>e' LC_ALL=debug $SHELL -c 'test "${x:3:1}" == "<3d|\\>" || err_exit ${x:3:1} should be <3d|\>'
|
||||
|
@ -591,6 +597,7 @@ x='a<2b|>c<3d|\>e' LC_ALL=debug $SHELL -c 'test "${x: -2:1}" == "<3d|\\>" || err
|
|||
x='a<2b|>c<3d|\>e' LC_ALL=debug $SHELL -c 'test "${x:1:3}" == "<2b|>c<3d|\\>" || err_exit ${x:1:3} should be <2b|>c<3d|\>'
|
||||
x='a<2b|>c<3d|\>e' LC_ALL=debug $SHELL -c 'test "${x:1:20}" == "<2b|>c<3d|\\>e" || err_exit ${x:1:20} should be <2b|>c<3d|\>e'
|
||||
x='a<2b|>c<3d|\>e' LC_ALL=debug $SHELL -c 'test "${x#??}" == "c<3d|\\>e" || err_exit "${x#??} should be c<3d|\>e'
|
||||
fi # SHOPT_MULTIBYTE
|
||||
|
||||
x='a one and a two'
|
||||
[[ "${x//~(E)\<.\>/}" == ' one and two' ]] || err_exit "\< and \> not working in with ere's"
|
||||
|
|
|
@ -717,7 +717,11 @@ actual=$(
|
|||
expect=$'4\n3\n3\n2\n1'
|
||||
[[ $actual == "$expect" ]] || err_exit "\${.sh.subshell} failure (expected $(printf %q "$expect"), got $(printf %q "$actual"))"
|
||||
|
||||
set -- {1..32768}
|
||||
unset IFS
|
||||
if ((SHOPT_BRACEPAT)) && command set -o braceexpand
|
||||
then set -- {1..32768}
|
||||
else set -- $(awk 'BEGIN { for(i=1;i<=32768;i++) print i; }')
|
||||
fi
|
||||
(( $# == 32768 )) || err_exit "\$# failed -- expected 32768, got $#"
|
||||
set --
|
||||
|
||||
|
|
Loading…
Reference in a new issue