diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8da245115..97f68f3e9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -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" diff --git a/src/cmd/ksh93/RELEASE b/src/cmd/ksh93/RELEASE index 8b06db054..2faf28a49 100644 --- a/src/cmd/ksh93/RELEASE +++ b/src/cmd/ksh93/RELEASE @@ -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. diff --git a/src/cmd/ksh93/bltins/print.c b/src/cmd/ksh93/bltins/print.c index 443e6c83a..981ab642d 100644 --- a/src/cmd/ksh93/bltins/print.c +++ b/src/cmd/ksh93/bltins/print.c @@ -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 diff --git a/src/cmd/ksh93/bltins/typeset.c b/src/cmd/ksh93/bltins/typeset.c index fdc685f57..79f271bdf 100644 --- a/src/cmd/ksh93/bltins/typeset.c +++ b/src/cmd/ksh93/bltins/typeset.c @@ -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; diff --git a/src/cmd/ksh93/data/builtins.c b/src/cmd/ksh93/data/builtins.c index 676c1286b..193633342 100644 --- a/src/cmd/ksh93/data/builtins.c +++ b/src/cmd/ksh93/data/builtins.c @@ -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 " diff --git a/src/cmd/ksh93/data/lexstates.c b/src/cmd/ksh93/data/lexstates.c index 4f257a38c..7fa143758 100644 --- a/src/cmd/ksh93/data/lexstates.c +++ b/src/cmd/ksh93/data/lexstates.c @@ -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, diff --git a/src/cmd/ksh93/data/options.c b/src/cmd/ksh93/data/options.c index 785a8e81f..c4e35aa32 100644 --- a/src/cmd/ksh93/data/options.c +++ b/src/cmd/ksh93/data/options.c @@ -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 }; diff --git a/src/cmd/ksh93/data/variables.c b/src/cmd/ksh93/data/variables.c index cadada6fd..76999d0a1 100644 --- a/src/cmd/ksh93/data/variables.c +++ b/src/cmd/ksh93/data/variables.c @@ -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, diff --git a/src/cmd/ksh93/edit/completion.c b/src/cmd/ksh93/edit/completion.c index dd9dd3980..1efc09b69 100644 --- a/src/cmd/ksh93/edit/completion.c +++ b/src/cmd/ksh93/edit/completion.c @@ -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); } diff --git a/src/cmd/ksh93/edit/edit.c b/src/cmd/ksh93/edit/edit.c index f198e8955..35d0f182d 100644 --- a/src/cmd/ksh93/edit/edit.c +++ b/src/cmd/ksh93/edit/edit.c @@ -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 */ +#define ttyparm (ep->e_ttyparm) +#define nttyparm (ep->e_nttyparm) +static const char bellchr[] = "\a"; /* bell char */ /* @@ -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,8 +900,7 @@ 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'); + buff[0] = cntl('L'); return(1); } else @@ -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 in the physical buffer * if is non-zero and <= , then correspodning 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 to an array of genchars * and 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 into character array . * The and 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 to */ @@ -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 items from to */ @@ -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 */ @@ -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) diff --git a/src/cmd/ksh93/edit/emacs.c b/src/cmd/ksh93/edit/emacs.c index 46c753264..007f7fec1 100644 --- a/src/cmd/ksh93/edit/emacs.c +++ b/src/cmd/ksh93/edit/emacs.c @@ -61,6 +61,8 @@ One line screen editor for any program * but you can use them to separate features. */ +#if SHOPT_ESH + #include #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 */ diff --git a/src/cmd/ksh93/edit/vi.c b/src/cmd/ksh93/edit/vi.c index 8ab7583e3..0f31b57a6 100644 --- a/src/cmd/ksh93/edit/vi.c +++ b/src/cmd/ksh93/edit/vi.c @@ -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 */ diff --git a/src/cmd/ksh93/include/defs.h b/src/cmd/ksh93/include/defs.h index b3f854986..c94160de0 100644 --- a/src/cmd/ksh93/include/defs.h +++ b/src/cmd/ksh93/include/defs.h @@ -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 diff --git a/src/cmd/ksh93/include/edit.h b/src/cmd/ksh93/include/edit.h index b167e3aaf..4fbb194b5 100644 --- a/src/cmd/ksh93/include/edit.h +++ b/src/cmd/ksh93/include/edit.h @@ -31,9 +31,6 @@ #include "FEATURE/options" #include "FEATURE/locale" -#if !SHOPT_VSH && !SHOPT_ESH -# define ed_winsize() (SEARCHSIZE) -#else #if !KSHELL # include @@ -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*); - extern void ed_histlist(Edit_t*, int); + 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 */ diff --git a/src/cmd/ksh93/include/jobs.h b/src/cmd/ksh93/include/jobs.h index ddd169b63..7dd01085c 100644 --- a/src/cmd/ksh93/include/jobs.h +++ b/src/cmd/ksh93/include/jobs.h @@ -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 diff --git a/src/cmd/ksh93/include/lexstates.h b/src/cmd/ksh93/include/lexstates.h index c83a5e0c2..6370ae79e 100644 --- a/src/cmd/ksh93/include/lexstates.h +++ b/src/cmd/ksh93/include/lexstates.h @@ -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 diff --git a/src/cmd/ksh93/include/national.h b/src/cmd/ksh93/include/national.h index 4c1888b7b..d5956c132 100644 --- a/src/cmd/ksh93/include/national.h +++ b/src/cmd/ksh93/include/national.h @@ -34,4 +34,6 @@ extern int sh_strchr(const char*,const char*); +#else +# define sh_strchr(s,c) strchr(s,*(c)) #endif /* SHOPT_MULTIBYTE */ diff --git a/src/cmd/ksh93/include/shell.h b/src/cmd/ksh93/include/shell.h index 15f32059d..becb19330 100644 --- a/src/cmd/ksh93/include/shell.h +++ b/src/cmd/ksh93/include/shell.h @@ -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 diff --git a/src/cmd/ksh93/include/variables.h b/src/cmd/ksh93/include/variables.h index 6fff7921c..76c409159 100644 --- a/src/cmd/ksh93/include/variables.h +++ b/src/cmd/ksh93/include/variables.h @@ -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) diff --git a/src/cmd/ksh93/sh/args.c b/src/cmd/ksh93/sh/args.c index 527639d4d..fc830ab81 100644 --- a/src/cmd/ksh93/sh/args.c +++ b/src/cmd/ksh93/sh/args.c @@ -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 */ diff --git a/src/cmd/ksh93/sh/expand.c b/src/cmd/ksh93/sh/expand.c index a9726101c..145306b29 100644 --- a/src/cmd/ksh93/sh/expand.c +++ b/src/cmd/ksh93/sh/expand.c @@ -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; diff --git a/src/cmd/ksh93/sh/fault.c b/src/cmd/ksh93/sh/fault.c index 91378ed7e..e50758c44 100644 --- a/src/cmd/ksh93/sh/fault.c +++ b/src/cmd/ksh93/sh/fault.c @@ -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**)); diff --git a/src/cmd/ksh93/sh/init.c b/src/cmd/ksh93/sh/init.c index f7aa10966..c77df551b 100644 --- a/src/cmd/ksh93/sh/init.c +++ b/src/cmd/ksh93/sh/init.c @@ -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); diff --git a/src/cmd/ksh93/sh/jobs.c b/src/cmd/ksh93/sh/jobs.c index 6952b9d71..8a4097fca 100644 --- a/src/cmd/ksh93/sh/jobs.c +++ b/src/cmd/ksh93/sh/jobs.c @@ -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 */ diff --git a/src/cmd/ksh93/sh/lex.c b/src/cmd/ksh93/sh/lex.c index 6baa0cc10..31614b42c 100644 --- a/src/cmd/ksh93/sh/lex.c +++ b/src/cmd/ksh93/sh/lex.c @@ -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 diff --git a/src/cmd/ksh93/sh/macro.c b/src/cmd/ksh93/sh/macro.c index 5a740b4f0..3512acd0a 100644 --- a/src/cmd/ksh93/sh/macro.c +++ b/src/cmd/ksh93/sh/macro.c @@ -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); diff --git a/src/cmd/ksh93/sh/name.c b/src/cmd/ksh93/sh/name.c index 7e4487a9a..2ea2d009e 100644 --- a/src/cmd/ksh93/sh/name.c +++ b/src/cmd/ksh93/sh/name.c @@ -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) diff --git a/src/cmd/ksh93/sh/nvtree.c b/src/cmd/ksh93/sh/nvtree.c index 4e5c375b6..7b5be9824 100644 --- a/src/cmd/ksh93/sh/nvtree.c +++ b/src/cmd/ksh93/sh/nvtree.c @@ -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)) diff --git a/src/cmd/ksh93/sh/xec.c b/src/cmd/ksh93/sh/xec.c index a3fba2907..d388069f5 100644 --- a/src/cmd/ksh93/sh/xec.c +++ b/src/cmd/ksh93/sh/xec.c @@ -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); diff --git a/src/cmd/ksh93/tests/basic.sh b/src/cmd/ksh93/tests/basic.sh index 405a02215..552e8f015 100755 --- a/src/cmd/ksh93/tests/basic.sh +++ b/src/cmd/ksh93/tests/basic.sh @@ -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 diff --git a/src/cmd/ksh93/tests/glob.sh b/src/cmd/ksh93/tests/glob.sh index 9502dcb32..c96003d24 100755 --- a/src/cmd/ksh93/tests/glob.sh +++ b/src/cmd/ksh93/tests/glob.sh @@ -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' diff --git a/src/cmd/ksh93/tests/io.sh b/src/cmd/ksh93/tests/io.sh index 468817bdc..d74404b8b 100755 --- a/src/cmd/ksh93/tests/io.sh +++ b/src/cmd/ksh93/tests/io.sh @@ -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' diff --git a/src/cmd/ksh93/tests/locale.sh b/src/cmd/ksh93/tests/locale.sh index 7d8d2e8b0..85b4cc374 100755 --- a/src/cmd/ksh93/tests/locale.sh +++ b/src/cmd/ksh93/tests/locale.sh @@ -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="$(&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}"') diff --git a/src/cmd/ksh93/tests/math.sh b/src/cmd/ksh93/tests/math.sh index f2b304cc2..2e4c948b9 100755 --- a/src/cmd/ksh93/tests/math.sh +++ b/src/cmd/ksh93/tests/math.sh @@ -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" ]] diff --git a/src/cmd/ksh93/tests/namespace.sh b/src/cmd/ksh93/tests/namespace.sh index 7848b2b5f..3d6027965 100755 --- a/src/cmd/ksh93/tests/namespace.sh +++ b/src/cmd/ksh93/tests/namespace.sh @@ -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) diff --git a/src/cmd/ksh93/tests/options.sh b/src/cmd/ksh93/tests/options.sh index 53a1b349b..d3e26445a 100755 --- a/src/cmd/ksh93/tests/options.sh +++ b/src/cmd/ksh93/tests/options.sh @@ -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). diff --git a/src/cmd/ksh93/tests/pty.sh b/src/cmd/ksh93/tests/pty.sh index cb63ab608..a13223119 100755 --- a/src/cmd/ksh93/tests/pty.sh +++ b/src/cmd/ksh93/tests/pty.sh @@ -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 <] [-author?Glenn Fowler ] @@ -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 diff --git a/src/cmd/ksh93/tests/substring.sh b/src/cmd/ksh93/tests/substring.sh index 19a0099d2..7b6594453 100755 --- a/src/cmd/ksh93/tests/substring.sh +++ b/src/cmd/ksh93/tests/substring.sh @@ -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" diff --git a/src/cmd/ksh93/tests/variables.sh b/src/cmd/ksh93/tests/variables.sh index 144f22c22..5309b04a9 100755 --- a/src/cmd/ksh93/tests/variables.sh +++ b/src/cmd/ksh93/tests/variables.sh @@ -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 --