1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-03-09 15:50:02 +00:00
cde/src/cmd/ksh93/include/shell.h
Martijn Dekker 24c3d77e3c cleanup: remove redundant sh.st.execbrk flag
The 'break' and 'continue' flow control commands use three int
variables in the scoped sh.st struct:

	sh.st.execbrk:	nonzero if 'break' or 'continue' are used
	sh.st.breakcnt:	number of levels to 'break'/'continue'
			(negative if 'continue')
	sh.st.loopcnt:	loop level counter for 'break'/'continue'

Reading the code that sets and uses these (in bltins/cflow.c and
sh/xec.c) makes it fairly obvious that the sh.st.execbrk flag is
redundant; it is zero if no 'break' or 'continue' should happen,
but the same is true for sh.st.breakcnt.

This commit simplifies the code by removing sh.st.execbrk.
It also adds some comments clarifying the use of the other two.

Trivia: the ancient "Version 06/03/86a" ksh source code was
recently discovered. It uses global execbrk, breakcnt and loopcnt
variables with the same redundancy. More evidence that the AT&T
team always lacked a question-everything department...
https://minnie.tuhs.org/pipermail/tuhs/2020-December/022640.html
https://github.com/weiss/original-bsd/blob/master/local/toolchest/ksh/sh/builtin.c
https://github.com/weiss/original-bsd/blob/master/local/toolchest/ksh/sh/xec.c
2022-07-03 12:53:15 +02:00

498 lines
15 KiB
C

/***********************************************************************
* *
* This software is part of the ast package *
* Copyright (c) 1982-2012 AT&T Intellectual Property *
* Copyright (c) 2020-2022 Contributors to ksh 93u+m *
* and is licensed under the *
* Eclipse Public License, Version 1.0 *
* by AT&T Intellectual Property *
* *
* A copy of the License is available at *
* http://www.eclipse.org/org/documents/epl-v10.html *
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
* *
* Information and Software Systems Research *
* AT&T Research *
* Florham Park NJ *
* *
* David Korn <dgk@research.att.com> *
* *
***********************************************************************/
#ifndef shell_h_defined
#define shell_h_defined
/*
* David Korn
* AT&T Labs
*
* Interface definitions for shell command language
*
*/
#define SH_VERSION 20220106
#include <ast.h>
#include <cdt.h>
#include <history.h>
#include <stk.h>
#ifdef defs_h_defined
# include "name.h"
#else
# include <nval.h>
#endif /* defs_h_defined */
#include "fault.h"
/* options */
typedef struct
{
unsigned long v[4];
}
Shopt_t;
typedef struct Shell_s Shell_t;
#include <shcmd.h>
typedef void (*Shinit_f)(Shell_t*, int);
#ifndef SH_wait_f_defined
typedef int (*Shwait_f)(int, long, int);
# define SH_wait_f_defined
#endif
union Shnode_u;
typedef union Shnode_u Shnode_t;
/*
* Shell state flags. Used with sh_isstate(), sh_onstate(), sh_offstate().
* See also shell options below. States 0-5 are also used as shell options.
*/
#define SH_NOFORK 0 /* set when fork not necessary */
#define SH_FORKED 7 /* set when process has been forked */
#define SH_PROFILE 8 /* set when processing profiles */
#define SH_NOALIAS 9 /* do not expand non-exported aliases */
#define SH_NOTRACK 10 /* set to disable sftrack() function */
#define SH_STOPOK 11 /* set for stopable builtins */
#define SH_GRACE 12 /* set for timeout grace period */
#define SH_TIMING 13 /* set while timing pipelines */
#define SH_DEFPATH 14 /* set when using default path */
#define SH_INIT 15 /* set when initializing the shell */
#define SH_TTYWAIT 16 /* waiting for keyboard input */
#define SH_FCOMPLETE 17 /* set for filename completion */
#define SH_PREINIT 18 /* set with SH_INIT before parsing options */
#define SH_COMPLETE 19 /* set for command completion */
#define SH_XARG 21 /* set while in xarg (command -x) mode */
/*
* Shell options (set -o). Used with sh_isoption(), sh_onoption(), sh_offoption().
* There can be a maximum of 256 (0..0xFF) shell options.
* The short option letters are defined in optksh[] and flagval[] in sh/args.c.
* The long option names are defined in shtab_options[] in data/options.c.
*/
#define SH_CFLAG 0
#define SH_HISTORY 1 /* used also as a state */
#define SH_ERREXIT 2 /* used also as a state */
#define SH_VERBOSE 3 /* used also as a state */
#define SH_MONITOR 4 /* used also as a state */
#define SH_INTERACTIVE 5 /* used also as a state */
#define SH_RESTRICTED 6
#define SH_XTRACE 7
#define SH_KEYWORD 8
#define SH_NOUNSET 9
#define SH_NOGLOB 10
#define SH_ALLEXPORT 11
#define SH_FUNCTRACE 12
#define SH_IGNOREEOF 13
#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
#define SH_DICTIONARY 30
#define SH_PIPEFAIL 32
#define SH_GLOBSTARS 33
#if SHOPT_GLOBCASEDET
#define SH_GLOBCASEDET 34
#endif
#define SH_RC 35
#define SH_SHOWME 36
#define SH_LETOCTAL 37
#if SHOPT_BRACEPAT
#define SH_BRACEEXPAND 42
#endif
#if SHOPT_HISTEXPAND
#define SH_HISTEXPAND 43
#if SHOPT_ESH || SHOPT_VSH
#define SH_HISTREEDIT 44
#define SH_HISTVERIFY 45
#endif
#endif
#define SH_POSIX 46
#if SHOPT_ESH || SHOPT_VSH
#define SH_MULTILINE 47
#endif
#define SH_NOBACKSLCTRL 48
#define SH_LOGIN_SHELL 67
#define SH_NOUSRPROFILE 79 /* internal use only */
#define SH_COMMANDLINE 0x100 /* bit flag for invocation-only options ('set -o' cannot change them) */
/*
* passed as flags to builtins in Nambltin_t struct when BLT_OPTIM is on
*/
#define SH_BEGIN_OPTIM 0x1
#define SH_END_OPTIM 0x2
/* The following type is used for error messages */
/* error messages */
extern const char e_found[];
#ifdef ENAMETOOLONG
extern const char e_toolong[];
#endif
extern const char e_format[];
extern const char e_number[];
extern const char e_restricted[];
extern const char e_recursive[];
extern char e_version[];
typedef struct sh_scope
{
struct sh_scope *par_scope;
int argc;
char **argv;
char *cmdname;
char *filename;
char *funname;
int lineno;
Dt_t *var_tree;
struct sh_scope *self;
} Shscope_t;
struct sh_scoped
{
struct sh_scoped *prevst; /* pointer to previous state */
int dolc;
char **dolv;
char *cmdname;
char *filename;
char *funname;
int lineno;
Dt_t *save_tree; /* var_tree for calling function */
struct sh_scoped *self; /* pointer to copy of this scope */
Dt_t *var_local; /* local level variables for name() */
struct slnod *staklist; /* link list of function stacks */
int states; /* shell state bits used by sh_isstate(), etc. */
int breakcnt; /* number of levels to 'break'/'continue' (negative if 'continue') */
int loopcnt; /* loop level counter for 'break'/'continue' */
int firstline;
int32_t optindex;
int32_t optnum;
int32_t tmout; /* value for TMOUT */
short optchar;
short opterror;
int ioset;
unsigned short trapmax;
char trapdontexec; /* stop exec optimization if any non-DEBUG/SIGKILL/SIGSTOP trap is set and non-empty */
char *trap[SH_DEBUGTRAP+1];
char **otrap;
char **trapcom;
char **otrapcom;
struct Ufunction *real_fun; /* current 'function name' function */
int repl_index;
char *repl_arg;
};
struct limits
{
int open_max; /* maximum number of file descriptors */
int clk_tck; /* number of ticks per second */
int child_max; /* maximum number of children */
};
/*
* Saves the state of the shell
*/
struct Shell_s
{
Shopt_t options; /* set -o options */
Dt_t *var_tree; /* for shell variables */
Dt_t *fun_tree; /* for shell functions */
Dt_t *alias_tree; /* for alias names */
Dt_t *bltin_tree; /* for builtin commands */
Dt_t *track_tree; /* for tracked aliases */
Shscope_t *topscope; /* pointer to top-level scope */
int inlineno; /* line number of current input file */
int exitval; /* exit status of the command currently being run */
int savexit; /* $? == exit status of the last command executed */
/* These are the former 'struct shared' (shgd) members. */
struct limits lim;
uid_t userid;
uid_t euserid;
gid_t groupid;
gid_t egroupid;
pid_t pid; /* $$, the main shell's PID (invariable) */
pid_t ppid; /* $PPID, the main shell's parent's PID */
pid_t current_pid; /* ${.sh.pid}, PID of current ksh process (updates when subshell forks) */
unsigned char sigruntime[2];
Namval_t *bltin_nodes;
Namval_t *bltin_cmds;
History_t *hist_ptr;
char *shpath;
char *user;
char **sigmsg;
char **login_files;
void *ed_context;
int sigmax;
Shwait_f waitevent;
#if SHOPT_STATS
int *stats;
#endif
/* The following members are not considered to be part of the documented API.
* Programs using libshell should not rely on them as they may change. */
int subshell; /* set for virtual subshell */
int realsubshell; /* ${.sh.subshell}, actual subshell level (including virtual and forked) */
char shcomp; /* set when running shcomp */
unsigned char trapnote; /* set when trap/signal is pending */
struct sh_scoped st; /* scoped information */
Stk_t *stk; /* stack pointer */
Sfio_t *heredocs; /* current here-doc temp file */
Sfio_t *funlog; /* for logging function definitions */
int **fdptrs; /* pointer to file numbers */
char *lastarg;
char *lastpath; /* last absolute path found */
int path_err; /* last error on path search */
Dt_t *var_base; /* global level variables */
Dt_t *fun_base; /* global level functions */
Dt_t *openmatch;
Namval_t *namespace; /* current active namespace */
Namval_t *last_table; /* last table used in last nv_open */
Namval_t *prev_table; /* previous table used in nv_open */
Sfio_t *outpool; /* output stream pool */
long timeout; /* read timeout */
unsigned int curenv; /* current subshell number */
unsigned int jobenv; /* subshell number for jobs */
int infd; /* input file descriptor */
short nextprompt; /* next prompt is PS<nextprompt> */
Namval_t *posix_fun; /* points to last name() function */
char *outbuff; /* pointer to output buffer */
char *errbuff; /* pointer to stderr buffer */
char *prompt; /* pointer to prompt string */
char *shname; /* shell name */
char *comdiv; /* points to sh -c argument */
char *prefix; /* prefix for compound assignment */
sigjmp_buf *jmplist; /* longjmp return stack */
pid_t bckpid; /* background process id */
pid_t cpid;
pid_t spid; /* subshell process id */
pid_t pipepid;
pid_t outpipepid;
int topfd;
int savesig;
unsigned char *sigflag; /* pointer to signal states */
char intrap;
char login_sh;
char lastbase;
char forked;
char binscript;
char funload;
char used_pos; /* used positional parameter */
char universe;
#ifdef SIGWINCH
char winch;
#endif
short arithrecursion; /* current arithmetic recursion level */
char indebug; /* set when in debug trap */
unsigned char ignsig; /* ignored signal in subshell */
unsigned char lastsig; /* last signal received */
char chldexitsig; /* set if the last command was a child process that exited due to a signal */
char pathinit; /* pathinit called from subshell */
char comsub; /* set to 1 when in `...`, 2 when in ${ ...; }, 3 when in $(...) */
char subshare; /* set when comsub==2 (shared-state ${ ...; } command substitution) */
char toomany; /* set when out of fd's */
char instance; /* in set_instance */
char radixpoint; /* current radix point ('.' or ',') */
char redir0; /* redirect of 0 */
char intrace; /* set when trace expands PS4 */
char *readscript; /* set before reading a script */
int subdup; /* bitmask for dups of 1 */
int *inpipe; /* input pipe pointer */
int *outpipe; /* output pipe pointer */
int cpipe[3];
int coutpipe;
int inuse_bits;
struct argnod *envlist;
struct dolnod *arglist;
int fn_depth; /* scoped ksh-style function call depth */
int dot_depth; /* dot-script and POSIX function call depth */
int hist_depth;
int xargmin;
int xargmax;
int xargexit;
int nenv;
mode_t mask;
void *init_context;
void *mac_context;
void *lex_context;
void *arg_context;
void *pathlist;
void *cdpathlist;
char **argaddr;
char cond_expan; /* set while processing ${var=val}, ${var:=val}, ${var?err}, ${var:?err} */
void *optlist;
struct sh_scoped global;
struct checkpt checkbase;
Shinit_f userinit;
Shbltin_f bltinfun;
Shbltin_t bltindata;
int offsets[10];
Sfio_t **sftable;
unsigned char *fdstatus;
const char *pwd;
void *jmpbuffer;
void *mktype;
Sfio_t *strbuf;
Sfio_t *strbuf2;
Dt_t *first_root;
Dt_t *prefix_root;
Dt_t *last_root;
Dt_t *prev_root;
Dt_t *fpathdict;
Dt_t *typedict;
Dt_t *inpool;
char ifstable[256];
Shopt_t offoptions; /* options that were explicitly disabled by the user on the command line */
Shopt_t glob_options;
Namval_t *typeinit;
Namfun_t nvfun;
char *mathnodes;
char *bltin_dir;
#if SHOPT_FILESCAN
char *cur_line;
#endif /* SHOPT_FILESCAN */
#if !SHOPT_DEVFD
char *fifo; /* FIFO name for current process substitution */
Dt_t *fifo_tree; /* for cleaning up process substitution FIFOs */
#endif /* !SHOPT_DEVFD */
#if SHOPT_REGRESS
struct Regress_s *regress;
#endif /* SHOPT_REGRESS */
};
/* used for builtins */
typedef struct Libcomp_s
{
void* dll;
char* lib;
dev_t dev;
ino_t ino;
unsigned int attr;
} Libcomp_t;
extern Libcomp_t *liblist;
/* flags for sh_parse */
#define SH_NL 1 /* Treat new-lines as ; */
#define SH_EOF 2 /* EOF causes syntax error */
/* symbolic values for sh_iogetiop */
#define SH_IOCOPROCESS (-2)
#define SH_IOHISTFILE (-3)
#include <cmd.h>
/* symbolic value for sh_fdnotify */
#define SH_FDCLOSE (-1)
#undef getenv /* -lshell provides its own */
#if defined(__EXPORT__) && defined(_DLL)
# define extern __EXPORT__
#endif /* _DLL */
extern void sh_subfork(void);
extern Shell_t *sh_init(int,char*[],Shinit_f);
extern int sh_reinit(char*[]);
extern int sh_eval(Sfio_t*,int);
extern void sh_delay(double,int);
extern void *sh_parse(Sfio_t*,int);
extern int sh_trap(const char*,int);
extern int sh_fun(Namval_t*,Namval_t*, char*[]);
extern int sh_funscope(int,char*[],int(*)(void*),void*,int);
extern Sfio_t *sh_iogetiop(int,int);
extern int sh_main(int, char*[], Shinit_f);
extern int sh_run(int, char*[]);
extern void sh_menu(Sfio_t*, int, char*[]);
extern Namval_t *sh_addbuiltin(const char*, int(*)(int, char*[],Shbltin_t*), void*);
extern char *sh_fmtq(const char*);
extern char *sh_fmtqf(const char*, int, int);
extern Sfdouble_t sh_strnum(const char*, char**, int);
extern int sh_access(const char*,int);
extern int sh_close(int);
extern int sh_chdir(const char*);
extern int sh_dup(int);
extern void sh_exit(int);
extern int sh_fchdir(int);
extern int sh_fcntl(int, int, ...);
extern Sfio_t *sh_fd2sfio(int);
extern int (*sh_fdnotify(int(*)(int,int)))(int,int);
extern int sh_open(const char*, int, ...);
extern Sfio_t *sh_pathopen(const char*);
extern ssize_t sh_read(int, void*, size_t);
extern ssize_t sh_write(int, const void*, size_t);
extern off_t sh_seek(int, off_t, int);
extern int sh_pipe(int[]);
extern mode_t sh_umask(mode_t);
extern void *sh_waitnotify(Shwait_f);
extern Shscope_t *sh_getscope(int,int);
extern Shscope_t *sh_setscope(Shscope_t*);
extern void sh_sigcheck(void);
extern unsigned long sh_isoption(int);
extern unsigned long sh_onoption(int);
extern unsigned long sh_offoption(int);
extern int sh_exec(const Shnode_t*,int);
/*
* As of 93u+m, direct access to sh is no longer obsolete;
* sh_getinterp() is here for compatibility with the documented interface.
*/
extern Shell_t sh;
#define sh_getinterp() (&sh)
#ifdef _DLL
# undef extern
#endif /* _DLL */
#define chdir(a) sh_chdir(a)
#define fchdir(a) sh_fchdir(a)
#ifndef defs_h_defined
# define access(a,b) sh_access(a,b)
# define close(a) sh_close(a)
# define exit(a) sh_exit(a)
# define fcntl(a,b,c) sh_fcntl(a,b,c)
# define pipe(a) sh_pipe(a)
# define read(a,b,c) sh_read(a,b,c)
# define write(a,b,c) sh_write(a,b,c)
# define umask(a) sh_umask(a)
# define dup sh_dup
# define open sh_open
# define lseek sh_seek
#endif /* !defs_h_defined */
#define SH_SIGSET 4
#define SH_EXITSIG 0400 /* signal exit bit */
#define SH_EXITMASK (SH_EXITSIG-1) /* normal exit status bits */
#endif /* !shell_h_defined */