add a “\builtin” builtin, make it forward assignments, fix some bugs

related to that:
• while AT&T ksh may do it, POSIX says nothing about allowing
  declaration commands only without vars and redirections, and
  “without vars” especially seems against which commands they are
• fix relationship between forwarders and real declaration commands
• clean up c_builtin vs shcomexec mess

Also, re-run “make repool” with a fixed src/scripts/stringpool.sh,v 1.3
This commit is contained in:
tg
2017-03-12 02:04:15 +00:00
parent 86773fcf21
commit b531baa7fd
5 changed files with 88 additions and 86 deletions

19
exec.c
View File

@ -23,7 +23,7 @@
#include "sh.h" #include "sh.h"
__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.189 2017/03/11 23:22:34 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/exec.c,v 1.190 2017/03/12 02:04:12 tg Exp $");
#ifndef MKSH_DEFAULT_EXECSHELL #ifndef MKSH_DEFAULT_EXECSHELL
#define MKSH_DEFAULT_EXECSHELL MKSH_UNIXROOT "/bin/sh" #define MKSH_DEFAULT_EXECSHELL MKSH_UNIXROOT "/bin/sh"
@ -982,8 +982,13 @@ scriptexec(struct op *tp, const char **ap)
int int
c_builtin(const char **wp) c_builtin(const char **wp)
{ {
return (call_builtin(ktsearch(&builtins, *wp, hash(*wp)), wp, return (call_builtin(get_builtin(*wp), wp, Tbuiltin, false));
Tbuiltin, false)); }
struct tbl *
get_builtin(const char *s)
{
return (s && *s ? ktsearch(&builtins, s, hash(s)) : NULL);
} }
/* /*
@ -1089,6 +1094,14 @@ builtin(const char *name, int (*func) (const char **))
/* external utility overrides built-in utility, with flags */ /* external utility overrides built-in utility, with flags */
flag |= LOW_BI; flag |= LOW_BI;
break; break;
case '-':
/* is declaration utility if argv[1] is one (POSIX: command) */
flag |= DECL_FWDR;
break;
case '^':
/* is declaration utility (POSIX: export, readonly) */
flag |= DECL_UTIL;
break;
default: default:
goto flags_seen; goto flags_seen;
} }

13
funcs.c
View File

@ -38,7 +38,7 @@
#endif #endif
#endif #endif
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.325 2017/03/11 23:22:35 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.326 2017/03/12 02:04:13 tg Exp $");
#if HAVE_KILLPG #if HAVE_KILLPG
/* /*
@ -92,6 +92,7 @@ c_false(const char **wp MKSH_A_UNUSED)
/* /*
* A leading = means assignments before command are kept. * A leading = means assignments before command are kept.
* A leading * means a POSIX special builtin. * A leading * means a POSIX special builtin.
* A leading ^ means declaration utility, - forwarder.
*/ */
const struct builtin mkshbuiltins[] = { const struct builtin mkshbuiltins[] = {
{Tsgdot, c_dot}, {Tsgdot, c_dot},
@ -100,19 +101,19 @@ const struct builtin mkshbuiltins[] = {
/* no =: AT&T manual wrong */ /* no =: AT&T manual wrong */
{Talias, c_alias}, {Talias, c_alias},
{"*=break", c_brkcont}, {"*=break", c_brkcont},
{T_builtin, c_builtin}, {T__builtin, c_builtin},
{Tbuiltin, c_builtin}, {Tbuiltin, c_builtin},
{Tbcat, c_cat}, {Tbcat, c_cat},
{Tcd, c_cd}, {Tcd, c_cd},
/* dash compatibility hack */ /* dash compatibility hack */
{"chdir", c_cd}, {"chdir", c_cd},
{Tcommand, c_command}, {T_command, c_command},
{"*=continue", c_brkcont}, {"*=continue", c_brkcont},
{"echo", c_print}, {"echo", c_print},
{"*=eval", c_eval}, {"*=eval", c_eval},
{"*=exec", c_exec}, {"*=exec", c_exec},
{"*=exit", c_exitreturn}, {"*=exit", c_exitreturn},
{Tsgexport, c_typeset}, {Tdsgexport, c_typeset},
{Tfalse, c_false}, {Tfalse, c_false},
{"fc", c_fc}, {"fc", c_fc},
{Tgetopts, c_getopts}, {Tgetopts, c_getopts},
@ -124,7 +125,7 @@ const struct builtin mkshbuiltins[] = {
{"print", c_print}, {"print", c_print},
{"pwd", c_pwd}, {"pwd", c_pwd},
{Tread, c_read}, {Tread, c_read},
{Tsgreadonly, c_typeset}, {Tdsgreadonly, c_typeset},
{"!realpath", c_realpath}, {"!realpath", c_realpath},
{"~rename", c_rename}, {"~rename", c_rename},
{"*=return", c_exitreturn}, {"*=return", c_exitreturn},
@ -138,7 +139,7 @@ const struct builtin mkshbuiltins[] = {
{"*=times", c_times}, {"*=times", c_times},
{"*=trap", c_trap}, {"*=trap", c_trap},
{Ttrue, c_true}, {Ttrue, c_true},
{Tgtypeset, c_typeset}, {Tdgtypeset, c_typeset},
{"ulimit", c_ulimit}, {"ulimit", c_ulimit},
{"umask", c_umask}, {"umask", c_umask},
{Tunalias, c_unalias}, {Tunalias, c_unalias},

16
lex.c
View File

@ -23,7 +23,7 @@
#include "sh.h" #include "sh.h"
__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.229 2017/02/18 02:33:12 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/lex.c,v 1.230 2017/03/12 02:04:14 tg Exp $");
/* /*
* states while lexing word * states while lexing word
@ -1014,15 +1014,12 @@ yylex(int cf)
while ((dp - ident) < IDENT && (c = *sp++) == CHAR) while ((dp - ident) < IDENT && (c = *sp++) == CHAR)
*dp++ = *sp++; *dp++ = *sp++;
if (c != EOS) if (c != EOS)
/* word is not unquoted */ /* word is not unquoted, or space ran out */
dp = ident; dp = ident;
/* make sure the ident array stays NUL padded */ /* make sure the ident array stays NUL padded */
memset(dp, 0, (ident + IDENT) - dp + 1); memset(dp, 0, (ident + IDENT) - dp + 1);
if (!(cf & (KEYWORD | ALIAS))) if (*ident != '\0' && (cf & (KEYWORD | ALIAS))) {
return (LWORD);
if (*ident != '\0') {
struct tbl *p; struct tbl *p;
uint32_t h = hash(ident); uint32_t h = hash(ident);
@ -1077,9 +1074,12 @@ yylex(int cf)
goto Again; goto Again;
} }
} }
} else if (cf & ALIAS) { } else if (*ident == '\0') {
/* retain typeset et al. even when quoted */ /* retain typeset et al. even when quoted */
if (assign_command((dp = wdstrip(yylval.cp, 0)), true)) struct tbl *tt = get_builtin((dp = wdstrip(yylval.cp, 0)));
uint32_t flag = tt ? tt->flag : 0;
if (flag & (DECL_UTIL | DECL_FWDR))
strlcpy(ident, dp, sizeof(ident)); strlcpy(ident, dp, sizeof(ident));
afree(dp, ATEMP); afree(dp, ATEMP);
} }

90
sh.h
View File

@ -175,9 +175,9 @@
#endif #endif
#ifdef EXTERN #ifdef EXTERN
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.793 2017/02/18 02:33:14 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/sh.h,v 1.794 2017/03/12 02:04:14 tg Exp $");
#endif #endif
#define MKSH_VERSION "R54 2017/02/18" #define MKSH_VERSION "R54 2017/03/11"
/* arithmetic types: C implementation */ /* arithmetic types: C implementation */
#if !HAVE_CAN_INTTYPES #if !HAVE_CAN_INTTYPES
@ -847,8 +847,8 @@ EXTERN char null[] E_INIT("");
#ifndef HAVE_STRING_POOLING /* helpers for pooled strings */ #ifndef HAVE_STRING_POOLING /* helpers for pooled strings */
EXTERN const char T4spaces[] E_INIT(" "); EXTERN const char T4spaces[] E_INIT(" ");
#define T1space (T4spaces + 3) #define T1space (Treal_sp2 + 5)
EXTERN const char Tcolsp[] E_INIT(": "); #define Tcolsp (Tf_sD_ + 2)
EXTERN const char TC_LEX1[] E_INIT("|&;<>() \t\n"); EXTERN const char TC_LEX1[] E_INIT("|&;<>() \t\n");
#define TC_IFSWS (TC_LEX1 + 7) #define TC_IFSWS (TC_LEX1 + 7)
EXTERN const char TFCEDIT_dollaru[] E_INIT("${FCEDIT:-/bin/ed} $_"); EXTERN const char TFCEDIT_dollaru[] E_INIT("${FCEDIT:-/bin/ed} $_");
@ -857,15 +857,15 @@ EXTERN const char Tsgdot[] E_INIT("*=.");
EXTERN const char Taugo[] E_INIT("augo"); EXTERN const char Taugo[] E_INIT("augo");
EXTERN const char Tbracket[] E_INIT("["); EXTERN const char Tbracket[] E_INIT("[");
#define Tdot (Tsgdot + 2) #define Tdot (Tsgdot + 2)
EXTERN const char Talias[] E_INIT("alias"); #define Talias (Tunalias + 2)
EXTERN const char Tbadsubst[] E_INIT("bad substitution"); #define Tbadsubst (Tfg_badsubst + 10)
EXTERN const char Tbg[] E_INIT("bg"); EXTERN const char Tbg[] E_INIT("bg");
EXTERN const char Tbad_bsize[] E_INIT("bad shf/buf/bsize"); EXTERN const char Tbad_bsize[] E_INIT("bad shf/buf/bsize");
#define Tbsize (Tbad_bsize + 12) #define Tbsize (Tbad_bsize + 12)
EXTERN const char Tbad_sig_ss[] E_INIT("%s: bad signal '%s'"); EXTERN const char Tbad_sig_ss[] E_INIT("%s: bad signal '%s'");
#define Tbad_sig_s (Tbad_sig_ss + 4) #define Tbad_sig_s (Tbad_sig_ss + 4)
EXTERN const char Tgbuiltin[] E_INIT("=builtin"); EXTERN const char T__builtin[] E_INIT("-\\builtin");
#define Tbuiltin (Tgbuiltin + 1) #define Tbuiltin (T__builtin + 2)
EXTERN const char Toomem[] E_INIT("can't allocate %zu data bytes"); EXTERN const char Toomem[] E_INIT("can't allocate %zu data bytes");
EXTERN const char Tcant_cd[] E_INIT("restricted shell - can't cd"); EXTERN const char Tcant_cd[] E_INIT("restricted shell - can't cd");
EXTERN const char Tcant_find[] E_INIT("can't find"); EXTERN const char Tcant_find[] E_INIT("can't find");
@ -874,26 +874,27 @@ EXTERN const char Tcant_open[] E_INIT("can't open");
EXTERN const char Tbcat[] E_INIT("!cat"); EXTERN const char Tbcat[] E_INIT("!cat");
#define Tcat (Tbcat + 1) #define Tcat (Tbcat + 1)
#define Tcd (Tcant_cd + 25) #define Tcd (Tcant_cd + 25)
EXTERN const char Tcommand[] E_INIT("command"); #define T_command (T_funny_command + 9)
#define Tcommand (T_funny_command + 10)
EXTERN const char Tcreate[] E_INIT("create"); EXTERN const char Tcreate[] E_INIT("create");
EXTERN const char TELIF_unexpected[] E_INIT("TELIF unexpected"); EXTERN const char TELIF_unexpected[] E_INIT("TELIF unexpected");
EXTERN const char TEXECSHELL[] E_INIT("EXECSHELL"); EXTERN const char TEXECSHELL[] E_INIT("EXECSHELL");
EXTERN const char Tsgexport[] E_INIT("*=export"); EXTERN const char Tdsgexport[] E_INIT("^*=export");
#define Texport (Tsgexport + 2) #define Texport (Tdsgexport + 3)
#ifdef __OS2__ #ifdef __OS2__
EXTERN const char Textproc[] E_INIT("extproc"); EXTERN const char Textproc[] E_INIT("extproc");
#endif #endif
EXTERN const char Tfalse[] E_INIT("false"); EXTERN const char Tfalse[] E_INIT("false");
EXTERN const char Tfg[] E_INIT("fg"); EXTERN const char Tfg[] E_INIT("fg");
EXTERN const char Tfg_badsubst[] E_INIT("fileglob: bad substitution"); EXTERN const char Tfg_badsubst[] E_INIT("fileglob: bad substitution");
EXTERN const char Tfile[] E_INIT("file"); #define Tfile (Tfile_fd + 20)
EXTERN const char Tfile_fd[] E_INIT("function definition file"); EXTERN const char Tfile_fd[] E_INIT("function definition file");
EXTERN const char TFPATH[] E_INIT("FPATH"); EXTERN const char TFPATH[] E_INIT("FPATH");
EXTERN const char T_function[] E_INIT(" function"); EXTERN const char T_function[] E_INIT(" function");
#define Tfunction (T_function + 1) #define Tfunction (T_function + 1)
EXTERN const char T_funny_command[] E_INIT("funny $() command"); EXTERN const char T_funny_command[] E_INIT("funny $()-command");
EXTERN const char Tgetopts[] E_INIT("getopts"); EXTERN const char Tgetopts[] E_INIT("getopts");
EXTERN const char Thistory[] E_INIT("history"); #define Thistory (Tnot_in_history + 7)
EXTERN const char Tintovfl[] E_INIT("integer overflow %zu %c %zu prevented"); EXTERN const char Tintovfl[] E_INIT("integer overflow %zu %c %zu prevented");
EXTERN const char Tjobs[] E_INIT("jobs"); EXTERN const char Tjobs[] E_INIT("jobs");
EXTERN const char Tjob_not_started[] E_INIT("job not started"); EXTERN const char Tjob_not_started[] E_INIT("job not started");
@ -909,20 +910,20 @@ EXTERN const char Tnot_found_s[] E_INIT("%s not found");
#define TOLDPWD (Tno_OLDPWD + 3) #define TOLDPWD (Tno_OLDPWD + 3)
#define Topen (Tcant_open + 6) #define Topen (Tcant_open + 6)
#define TPATH (TFPATH + 1) #define TPATH (TFPATH + 1)
EXTERN const char Tpv[] E_INIT("pv"); #define Tpv (TpVv + 1)
EXTERN const char TpVv[] E_INIT("Vpv"); EXTERN const char TpVv[] E_INIT("Vpv");
#define TPWD (Tno_OLDPWD + 6) #define TPWD (Tno_OLDPWD + 6)
EXTERN const char Tread[] E_INIT("read"); #define Tread (Tshf_read + 4)
EXTERN const char Tsgreadonly[] E_INIT("*=readonly"); EXTERN const char Tdsgreadonly[] E_INIT("^*=readonly");
#define Treadonly (Tsgreadonly + 2) #define Treadonly (Tdsgreadonly + 3)
EXTERN const char Tredirection_dup[] E_INIT("can't finish (dup) redirection"); EXTERN const char Tredirection_dup[] E_INIT("can't finish (dup) redirection");
#define Tredirection (Tredirection_dup + 19) #define Tredirection (Tredirection_dup + 19)
EXTERN const char Treal_sp1[] E_INIT("real "); #define Treal_sp1 (Treal_sp2 + 1)
EXTERN const char Treal_sp2[] E_INIT(" real "); EXTERN const char Treal_sp2[] E_INIT(" real ");
EXTERN const char Treq_arg[] E_INIT("requires an argument"); EXTERN const char Treq_arg[] E_INIT("requires an argument");
EXTERN const char Tselect[] E_INIT("select"); EXTERN const char Tselect[] E_INIT("select");
EXTERN const char Tsgset[] E_INIT("*=set"); EXTERN const char Tsgset[] E_INIT("*=set");
#define Tset (Tsgset + 2) #define Tset (Tf_parm + 18)
#define Tsh (Tmksh + 2) #define Tsh (Tmksh + 2)
#define TSHELL (TEXECSHELL + 4) #define TSHELL (TEXECSHELL + 4)
EXTERN const char Tshf_read[] E_INIT("shf_read"); EXTERN const char Tshf_read[] E_INIT("shf_read");
@ -935,27 +936,27 @@ EXTERN const char Ttoo_many_args[] E_INIT("too many arguments");
EXTERN const char Ttrue[] E_INIT("true"); EXTERN const char Ttrue[] E_INIT("true");
EXTERN const char Ttty_fd_dupof[] E_INIT("dup of tty fd"); EXTERN const char Ttty_fd_dupof[] E_INIT("dup of tty fd");
#define Ttty_fd (Ttty_fd_dupof + 7) #define Ttty_fd (Ttty_fd_dupof + 7)
EXTERN const char Tgtypeset[] E_INIT("=typeset"); EXTERN const char Tdgtypeset[] E_INIT("^=typeset");
#define Ttypeset (Tgtypeset + 1) #define Ttypeset (Tdgtypeset + 2)
#define Tugo (Taugo + 1) #define Tugo (Taugo + 1)
EXTERN const char Tunalias[] E_INIT("unalias"); EXTERN const char Tunalias[] E_INIT("unalias");
#define Tunexpected (TELIF_unexpected + 6) #define Tunexpected (TELIF_unexpected + 6)
EXTERN const char Tunknown_option[] E_INIT("unknown option"); EXTERN const char Tunknown_option[] E_INIT("unknown option");
EXTERN const char Tuser_sp1[] E_INIT("user "); #define Tuser_sp1 (Tuser_sp2 + 1)
EXTERN const char Tuser_sp2[] E_INIT(" user "); EXTERN const char Tuser_sp2[] E_INIT(" user ");
#define Twrite (Tshf_write + 4) #define Twrite (Tshf_write + 4)
EXTERN const char Tf__S[] E_INIT(" %S"); EXTERN const char Tf__S[] E_INIT(" %S");
EXTERN const char Tf__d[] E_INIT(" %d"); #define Tf__d (Tf_sd + 2)
EXTERN const char Tf__ss[] E_INIT(" %s%s"); EXTERN const char Tf__ss[] E_INIT(" %s%s");
EXTERN const char Tf__sN[] E_INIT(" %s\n"); #define Tf__sN (Tf_s_s_sN + 5)
EXTERN const char Tf_sSs[] E_INIT("%s/%s"); EXTERN const char Tf_sSs[] E_INIT("%s/%s");
EXTERN const char Tf_T[] E_INIT("%T"); #define Tf_T (Tf_s_T + 3)
EXTERN const char Tf_dN[] E_INIT("%d\n"); EXTERN const char Tf_dN[] E_INIT("%d\n");
EXTERN const char Tf_s_[] E_INIT("%s "); EXTERN const char Tf_s_[] E_INIT("%s ");
EXTERN const char Tf_s_T[] E_INIT("%s %T"); EXTERN const char Tf_s_T[] E_INIT("%s %T");
EXTERN const char Tf_s_s_sN[] E_INIT("%s %s %s\n"); EXTERN const char Tf_s_s_sN[] E_INIT("%s %s %s\n");
EXTERN const char Tf_s_s[] E_INIT("%s %s"); #define Tf_s_s (Tf_sD_s_s + 4)
EXTERN const char Tf_s_sD_s[] E_INIT("%s %s: %s"); #define Tf_s_sD_s (Tf_cant + 6)
EXTERN const char Tf_optfoo[] E_INIT("%s%s-%c: %s"); EXTERN const char Tf_optfoo[] E_INIT("%s%s-%c: %s");
EXTERN const char Tf_sD_[] E_INIT("%s: "); EXTERN const char Tf_sD_[] E_INIT("%s: ");
EXTERN const char Tf_szs[] E_INIT("%s: %zd %s"); EXTERN const char Tf_szs[] E_INIT("%s: %zd %s");
@ -968,18 +969,18 @@ EXTERN const char Tf_nonnum[] E_INIT("non-numeric %s %s '%s'");
#endif #endif
EXTERN const char Tf_S_[] E_INIT("%S "); EXTERN const char Tf_S_[] E_INIT("%S ");
#define Tf_S (Tf__S + 1) #define Tf_S (Tf__S + 1)
EXTERN const char Tf_lu[] E_INIT("%lu"); #define Tf_lu (Tf_toolarge + 17)
EXTERN const char Tf_toolarge[] E_INIT("%s %s too large: %lu"); EXTERN const char Tf_toolarge[] E_INIT("%s %s too large: %lu");
EXTERN const char Tf_ldfailed[] E_INIT("%s %s(%d, %ld) failed: %s"); EXTERN const char Tf_ldfailed[] E_INIT("%s %s(%d, %ld) failed: %s");
#define Tf_ss (Tf__ss + 1) #define Tf_ss (Tf_sss + 2)
EXTERN const char Tf_sss[] E_INIT("%s%s%s"); EXTERN const char Tf_sss[] E_INIT("%s%s%s");
EXTERN const char Tf_sD_s_sD_s[] E_INIT("%s: %s %s: %s"); EXTERN const char Tf_sD_s_sD_s[] E_INIT("%s: %s %s: %s");
EXTERN const char Tf_toomany[] E_INIT("too many %ss\n"); EXTERN const char Tf_toomany[] E_INIT("too many %ss\n");
EXTERN const char Tf_sd[] E_INIT("%s %d"); EXTERN const char Tf_sd[] E_INIT("%s %d");
#define Tf_s (Tf__ss + 3) #define Tf_s (Tf_temp + 28)
EXTERN const char Tft_end[] E_INIT("%;"); EXTERN const char Tft_end[] E_INIT("%;");
EXTERN const char Tft_R[] E_INIT("%R"); EXTERN const char Tft_R[] E_INIT("%R");
#define Tf_d (Tf__d + 1) #define Tf_d (Tf_sd + 3)
EXTERN const char Tf_sD_s_qs[] E_INIT("%s: %s '%s'"); EXTERN const char Tf_sD_s_qs[] E_INIT("%s: %s '%s'");
EXTERN const char Tf_ro[] E_INIT("read-only: %s"); EXTERN const char Tf_ro[] E_INIT("read-only: %s");
EXTERN const char Tf_flags[] E_INIT("%s: flags 0x%X"); EXTERN const char Tf_flags[] E_INIT("%s: flags 0x%X");
@ -988,8 +989,8 @@ EXTERN const char Tf_ssfaileds[] E_INIT("%s: %s failed: %s");
EXTERN const char Tf_sD_sD_s[] E_INIT("%s: %s: %s"); EXTERN const char Tf_sD_sD_s[] E_INIT("%s: %s: %s");
EXTERN const char Tf__c_[] E_INIT("-%c "); EXTERN const char Tf__c_[] E_INIT("-%c ");
EXTERN const char Tf_sD_s_s[] E_INIT("%s: %s %s"); EXTERN const char Tf_sD_s_s[] E_INIT("%s: %s %s");
#define Tf_sN (Tf__sN + 1) #define Tf_sN (Tf_s_s_sN + 6)
#define Tf_sD_s (Tf_s_sD_s + 3) #define Tf_sD_s (Tf_temp + 24)
EXTERN const char T_devtty[] E_INIT("/dev/tty"); EXTERN const char T_devtty[] E_INIT("/dev/tty");
#else /* helpers for string pooling */ #else /* helpers for string pooling */
#define T4spaces " " #define T4spaces " "
@ -1010,7 +1011,7 @@ EXTERN const char T_devtty[] E_INIT("/dev/tty");
#define Tbsize "bsize" #define Tbsize "bsize"
#define Tbad_sig_ss "%s: bad signal '%s'" #define Tbad_sig_ss "%s: bad signal '%s'"
#define Tbad_sig_s "bad signal '%s'" #define Tbad_sig_s "bad signal '%s'"
#define Tgbuiltin "=builtin" #define T__builtin "-\\builtin"
#define Tbuiltin "builtin" #define Tbuiltin "builtin"
#define Toomem "can't allocate %zu data bytes" #define Toomem "can't allocate %zu data bytes"
#define Tcant_cd "restricted shell - can't cd" #define Tcant_cd "restricted shell - can't cd"
@ -1020,11 +1021,12 @@ EXTERN const char T_devtty[] E_INIT("/dev/tty");
#define Tbcat "!cat" #define Tbcat "!cat"
#define Tcat "cat" #define Tcat "cat"
#define Tcd "cd" #define Tcd "cd"
#define T_command "-command"
#define Tcommand "command" #define Tcommand "command"
#define Tcreate "create" #define Tcreate "create"
#define TELIF_unexpected "TELIF unexpected" #define TELIF_unexpected "TELIF unexpected"
#define TEXECSHELL "EXECSHELL" #define TEXECSHELL "EXECSHELL"
#define Tsgexport "*=export" #define Tdsgexport "^*=export"
#define Texport "export" #define Texport "export"
#ifdef __OS2__ #ifdef __OS2__
#define Textproc "extproc" #define Textproc "extproc"
@ -1037,7 +1039,7 @@ EXTERN const char T_devtty[] E_INIT("/dev/tty");
#define TFPATH "FPATH" #define TFPATH "FPATH"
#define T_function " function" #define T_function " function"
#define Tfunction "function" #define Tfunction "function"
#define T_funny_command "funny $() command" #define T_funny_command "funny $()-command"
#define Tgetopts "getopts" #define Tgetopts "getopts"
#define Thistory "history" #define Thistory "history"
#define Tintovfl "integer overflow %zu %c %zu prevented" #define Tintovfl "integer overflow %zu %c %zu prevented"
@ -1059,7 +1061,7 @@ EXTERN const char T_devtty[] E_INIT("/dev/tty");
#define TpVv "Vpv" #define TpVv "Vpv"
#define TPWD "PWD" #define TPWD "PWD"
#define Tread "read" #define Tread "read"
#define Tsgreadonly "*=readonly" #define Tdsgreadonly "^*=readonly"
#define Treadonly "readonly" #define Treadonly "readonly"
#define Tredirection_dup "can't finish (dup) redirection" #define Tredirection_dup "can't finish (dup) redirection"
#define Tredirection "redirection" #define Tredirection "redirection"
@ -1081,7 +1083,7 @@ EXTERN const char T_devtty[] E_INIT("/dev/tty");
#define Ttrue "true" #define Ttrue "true"
#define Ttty_fd_dupof "dup of tty fd" #define Ttty_fd_dupof "dup of tty fd"
#define Ttty_fd "tty fd" #define Ttty_fd "tty fd"
#define Tgtypeset "=typeset" #define Tdgtypeset "^=typeset"
#define Ttypeset "typeset" #define Ttypeset "typeset"
#define Tugo "ugo" #define Tugo "ugo"
#define Tunalias "unalias" #define Tunalias "unalias"
@ -1322,7 +1324,7 @@ EXTERN sigset_t sm_default, sm_sigchld;
/* name of called builtin function (used by error functions) */ /* name of called builtin function (used by error functions) */
EXTERN const char *builtin_argv0; EXTERN const char *builtin_argv0;
/* is called builtin SPEC_BI? (also KEEPASN, odd use though) */ /* is called builtin a POSIX special builtin? (error functions only) */
EXTERN bool builtin_spec; EXTERN bool builtin_spec;
/* current working directory */ /* current working directory */
@ -1492,6 +1494,8 @@ EXTERN bool last_lookup_was_array;
#define SPEC_BI BIT(12) /* a POSIX special builtin */ #define SPEC_BI BIT(12) /* a POSIX special builtin */
#define LOWER_BI BIT(13) /* (with LOW_BI) override even w/o flags */ #define LOWER_BI BIT(13) /* (with LOW_BI) override even w/o flags */
#define LOW_BI BIT(14) /* external utility overrides built-in one */ #define LOW_BI BIT(14) /* external utility overrides built-in one */
#define DECL_UTIL BIT(15) /* is declaration utility */
#define DECL_FWDR BIT(16) /* is declaration utility forwarder */
/* /*
* Attributes that can be set by the user (used to decide if an unset * Attributes that can be set by the user (used to decide if an unset
@ -2011,7 +2015,8 @@ int glob_str(char *, XPtrV *, bool);
char *do_tilde(char *); char *do_tilde(char *);
/* exec.c */ /* exec.c */
int execute(struct op * volatile, volatile int, volatile int * volatile); int execute(struct op * volatile, volatile int, volatile int * volatile);
int shcomexec(const char **); int c_builtin(const char **);
struct tbl *get_builtin(const char *);
struct tbl *findfunc(const char *, uint32_t, bool); struct tbl *findfunc(const char *, uint32_t, bool);
int define(const char *, struct op *); int define(const char *, struct op *);
const char *builtin(const char *, int (*)(const char **)); const char *builtin(const char *, int (*)(const char **));
@ -2078,8 +2083,6 @@ int c_times(const char **);
int timex(struct op *, int, volatile int *); int timex(struct op *, int, volatile int *);
void timex_hook(struct op *, char ** volatile *); void timex_hook(struct op *, char ** volatile *);
int c_exec(const char **); int c_exec(const char **);
/* dummy function (just need pointer value), special case in comexec() */
#define c_builtin shcomexec
int c_test(const char **); int c_test(const char **);
#if HAVE_MKNOD #if HAVE_MKNOD
int c_mknod(const char **); int c_mknod(const char **);
@ -2287,7 +2290,6 @@ char *shf_smprintf(const char *, ...)
ssize_t shf_vfprintf(struct shf *, const char *, va_list) ssize_t shf_vfprintf(struct shf *, const char *, va_list)
MKSH_A_FORMAT(__printf__, 2, 0); MKSH_A_FORMAT(__printf__, 2, 0);
/* syn.c */ /* syn.c */
int assign_command(const char *, bool) MKSH_A_PURE;
void initkeywords(void); void initkeywords(void);
struct op *compile(Source *, bool); struct op *compile(Source *, bool);
bool parse_usec(const char *, struct timeval *); bool parse_usec(const char *, struct timeval *);

36
syn.c
View File

@ -23,7 +23,7 @@
#include "sh.h" #include "sh.h"
__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.116 2017/03/11 22:49:56 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/syn.c,v 1.117 2017/03/12 02:04:15 tg Exp $");
struct nesting_state { struct nesting_state {
int start_token; /* token than began nesting (eg, FOR) */ int start_token; /* token than began nesting (eg, FOR) */
@ -289,11 +289,11 @@ get_command(int cf)
t->lineno = source->line; t->lineno = source->line;
goto get_command_start; goto get_command_start;
while (/* CONSTCOND */ 1) { while (/* CONSTCOND */ 1) {
bool check_assign_cmd; bool check_decl_utility;
if (XPsize(args) == 0) { if (XPsize(args) == 0) {
get_command_start: get_command_start:
check_assign_cmd = true; check_decl_utility = true;
cf = sALIAS | CMDASN; cf = sALIAS | CMDASN;
} else if (t->u.evalflags) } else if (t->u.evalflags)
cf = CMDWORD | CMDASN; cf = CMDWORD | CMDASN;
@ -311,16 +311,15 @@ get_command(int cf)
case LWORD: case LWORD:
ACCEPT; ACCEPT;
/* if (check_decl_utility) {
* the iopn == 0 and XPsize(vars) == 0 are struct tbl *tt = get_builtin(ident);
* dubious but AT&T ksh acts this way uint32_t flag;
*/
if (iopn == 0 && XPsize(vars) == 0 && flag = tt ? tt->flag : 0;
check_assign_cmd) { if (flag & DECL_UTIL)
if (assign_command(ident, false))
t->u.evalflags = DOVACHECK; t->u.evalflags = DOVACHECK;
else if (strcmp(ident, Tcommand) != 0) if (!(flag & DECL_FWDR))
check_assign_cmd = false; check_decl_utility = false;
} }
if ((XPsize(args) == 0 || Flag(FKEYWORD)) && if ((XPsize(args) == 0 || Flag(FKEYWORD)) &&
is_wdvarassign(yylval.cp)) is_wdvarassign(yylval.cp))
@ -937,19 +936,6 @@ compile(Source *s, bool skiputf8bom)
return (outtree); return (outtree);
} }
/* lexical analysis for declaration utilities */
int
assign_command(const char *s, bool docommand)
{
if (!*s)
return (0);
return ((strcmp(s, Talias) == 0) ||
(strcmp(s, Texport) == 0) ||
(strcmp(s, Treadonly) == 0) ||
(docommand && (strcmp(s, Tcommand) == 0)) ||
(strcmp(s, Ttypeset) == 0));
}
/* Check if we are in the middle of reading an alias */ /* Check if we are in the middle of reading an alias */
static int static int
inalias(struct source *s) inalias(struct source *s)