diff options
Diffstat (limited to 'Src/zsh.h')
-rw-r--r-- | Src/zsh.h | 964 |
1 files changed, 677 insertions, 287 deletions
diff --git a/Src/zsh.h b/Src/zsh.h index e96fc6e86..35b9c6737 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -31,15 +31,75 @@ #define zleread(X,Y,H) zlereadptr(X,Y,H) #define spaceinline(X) spaceinlineptr(X) #define gotword() gotwordptr() -#define refresh() refreshptr() +#define zrefresh() refreshptr() #define compctlread(N,A,O,R) compctlreadptr(N,A,O,R) /* A few typical macros */ #define minimum(a,b) ((a) < (b) ? (a) : (b)) +/* + * Our longest integer type: will be a 64 bit either if long already is, + * or if we found some alternative such as long long. + * Currently we only define this to be longer than a long if --enable-lfs + * was given. That enables internal use of 64-bit types even if + * no actual large file support is present. + */ +#ifdef ZSH_64_BIT_TYPE +typedef ZSH_64_BIT_TYPE zlong; +#ifdef ZSH_64_BIT_UTYPE +typedef ZSH_64_BIT_UTYPE zulong; +#else +typedef unsigned zlong zulong; +#endif +#else +typedef long zlong; +typedef unsigned long zulong; +#endif + +/* + * Double float support requires 64-bit alignment, so if longs and + * pointers are less we need to pad out. + */ +#ifndef LONG_IS_64_BIT +# define PAD_64_BIT 1 +#endif + /* math.c */ -typedef int LV; +typedef struct { + union { + zlong l; + double d; + } u; + int type; +} mnumber; + +#define MN_INTEGER 1 /* mnumber is integer */ +#define MN_FLOAT 2 /* mnumber is floating point */ + +typedef struct mathfunc *MathFunc; +typedef mnumber (*NumMathFunc)(char *, int, mnumber *, int); +typedef mnumber (*StrMathFunc)(char *, char *, int); + +struct mathfunc { + MathFunc next; + char *name; + int flags; + NumMathFunc nfunc; + StrMathFunc sfunc; + char *module; + int minargs; + int maxargs; + int funcid; +}; + +#define MFF_STR 1 +#define MFF_ADDED 2 + +#define NUMMATHFUNC(name, func, min, max, id) \ + { NULL, name, 0, func, NULL, NULL, min, max, id } +#define STRMATHFUNC(name, func, id) \ + { NULL, name, MFF_STR, NULL, func, NULL, 0, 0, id } /* Character tokens are sometimes casted to (unsigned char)'s. * * Unfortunately, some compilers don't correctly cast signed to * @@ -207,6 +267,7 @@ enum { #define INP_HIST (1<<2) /* expanding history */ #define INP_CONT (1<<3) /* continue onto previously stacked input */ #define INP_ALCONT (1<<4) /* stack is continued from alias expn. */ +#define INP_LINENO (1<<5) /* update line number */ /* Flags for metafy */ #define META_REALLOC 0 @@ -228,34 +289,33 @@ typedef struct linklist *LinkList; typedef struct hashnode *HashNode; typedef struct hashtable *HashTable; +typedef struct optname *Optname; typedef struct reswd *Reswd; typedef struct alias *Alias; typedef struct param *Param; +typedef struct paramdef *Paramdef; typedef struct cmdnam *Cmdnam; typedef struct shfunc *Shfunc; +typedef struct funcstack *Funcstack; +typedef struct funcwrap *FuncWrap; typedef struct builtin *Builtin; typedef struct nameddir *Nameddir; typedef struct module *Module; +typedef struct linkedmod *Linkedmod; +typedef struct patprog *Patprog; typedef struct process *Process; typedef struct job *Job; typedef struct value *Value; -typedef struct varasg *Varasg; -typedef struct cond *Cond; -typedef struct cmd *Cmd; -typedef struct pline *Pline; -typedef struct sublist *Sublist; -typedef struct list *List; -typedef struct comp *Comp; +typedef struct conddef *Conddef; typedef struct redir *Redir; typedef struct complist *Complist; typedef struct heap *Heap; typedef struct heapstack *Heapstack; typedef struct histent *Histent; -typedef struct forcmd *Forcmd; -typedef struct autofn *AutoFn; +typedef struct hookdef *Hookdef; -typedef struct asgment *Asgment; +typedef struct asgment *Asgment; /********************************/ @@ -277,167 +337,57 @@ struct linklist { /* Macros for manipulating link lists */ -#define addlinknode(X,Y) insertlinknode(X,(X)->last,Y) -#define uaddlinknode(X,Y) uinsertlinknode(X,(X)->last,Y) -#define empty(X) ((X)->first == NULL) -#define nonempty(X) ((X)->first != NULL) -#define firstnode(X) ((X)->first) -#define getaddrdata(X) (&((X)->dat)) -#define getdata(X) ((X)->dat) -#define setdata(X,Y) ((X)->dat = (Y)) -#define lastnode(X) ((X)->last) -#define nextnode(X) ((X)->next) -#define prevnode(X) ((X)->last) -#define peekfirst(X) ((X)->first->dat) -#define pushnode(X,Y) insertlinknode(X,(LinkNode) X,Y) -#define incnode(X) (X = nextnode(X)) -#define gethistent(X) (histentarr+((X)%histentct)) - +#define addlinknode(X,Y) insertlinknode(X,(X)->last,Y) +#define zaddlinknode(X,Y) zinsertlinknode(X,(X)->last,Y) +#define uaddlinknode(X,Y) uinsertlinknode(X,(X)->last,Y) +#define empty(X) ((X)->first == NULL) +#define nonempty(X) ((X)->first != NULL) +#define firstnode(X) ((X)->first) +#define getaddrdata(X) (&((X)->dat)) +#define getdata(X) ((X)->dat) +#define setdata(X,Y) ((X)->dat = (Y)) +#define lastnode(X) ((X)->last) +#define nextnode(X) ((X)->next) +#define prevnode(X) ((X)->last) +#define peekfirst(X) ((X)->first->dat) +#define pushnode(X,Y) insertlinknode(X,(LinkNode) X,Y) +#define zpushnode(X,Y) zinsertlinknode(X,(LinkNode) X,Y) +#define incnode(X) (X = nextnode(X)) +#define firsthist() (hist_ring? hist_ring->down->histnum : curhist) +#define setsizednode(X,Y,Z) ((X)->first[(Y)].dat = (void *) (Z)) + +/* stack allocated linked lists */ + +#define local_list0(N) struct linklist N +#define init_list0(N) \ + do { \ + (N).first = NULL; \ + (N).last = (LinkNode) &(N); \ + } while (0) +#define local_list1(N) struct linklist N; struct linknode __n0 +#define init_list1(N,V0) \ + do { \ + (N).first = &__n0; \ + (N).last = &__n0; \ + __n0.next = NULL; \ + __n0.last = (LinkNode) &(N); \ + __n0.dat = (void *) (V0); \ + } while (0) /********************************/ /* Definitions for syntax trees */ /********************************/ -/* struct list, struct sublist, struct pline, etc. all fit the form * - * of this structure and are used interchangably. The ptrs may hold * - * integers or pointers, depending on the type of the node. */ - -/* Generic node structure for syntax trees */ -struct node { - int ntype; /* node type */ -}; - -#define N_LIST 0 -#define N_SUBLIST 1 -#define N_PLINE 2 -#define N_CMD 3 -#define N_REDIR 4 -#define N_COND 5 -#define N_FOR 6 -#define N_CASE 7 -#define N_IF 8 -#define N_WHILE 9 -#define N_VARASG 10 -#define N_AUTOFN 11 -#define N_COUNT 12 - -/* values for types[4] */ - -#define NT_EMPTY 0 -#define NT_NODE 1 -#define NT_STR 2 -#define NT_LIST 4 -#define NT_ARR 8 - -#define NT_TYPE(T) ((T) & 0xff) -#define NT_N(T, N) (((T) >> (8 + (N) * 4)) & 0xf) -#define NT_SET(T0, T1, T2, T3, T4) \ - ((T0) | ((T1) << 8) | ((T2) << 12) | ((T3) << 16) | ((T4) << 20)) -#define NT_HEAP (1 << 30) - -/* tree element for lists */ - -struct list { - int ntype; /* node type */ - int type; - Sublist left; - List right; -}; - /* These are control flags that are passed * * down the execution pipeline. */ -#define Z_TIMED (1<<0) /* pipeline is being timed */ -#define Z_SYNC (1<<1) /* run this sublist synchronously (;) */ -#define Z_ASYNC (1<<2) /* run this sublist asynchronously (&) */ +#define Z_TIMED (1<<0) /* pipeline is being timed */ +#define Z_SYNC (1<<1) /* run this sublist synchronously (;) */ +#define Z_ASYNC (1<<2) /* run this sublist asynchronously (&) */ #define Z_DISOWN (1<<3) /* run this sublist without job control (&|) */ +/* (1<<4) is used for Z_END, see the wordcode definitions */ +/* (1<<5) is used for Z_SIMPLE, see the wordcode definitions */ -/* tree element for sublists */ - -struct sublist { - int ntype; /* node type */ - int type; - int flags; /* see PFLAGs below */ - Pline left; - Sublist right; -}; - -#define ORNEXT 10 /* || */ -#define ANDNEXT 11 /* && */ - -#define PFLAG_NOT 1 /* ! ... */ -#define PFLAG_COPROC 32 /* coproc ... */ - -/* tree element for pipes */ - -struct pline { - int ntype; /* node type */ - int type; - Cmd left; - Pline right; -}; - -#define END 0 /* pnode *right is null */ -#define PIPE 1 /* pnode *right is the rest of the pipeline */ - -/* tree element for commands */ - -struct cmd { - int ntype; /* node type */ - int type; - int flags; /* see CFLAGs below */ - int lineno; /* lineno of script for command */ - union { - List list; /* for SUBSH/CURSH/SHFUNC */ - Forcmd forcmd; - struct casecmd *casecmd; - struct ifcmd *ifcmd; - struct whilecmd *whilecmd; - Sublist pline; - Cond cond; - AutoFn autofn; - void *generic; - } u; - LinkList args; /* command & argmument List (char *'s) */ - LinkList redir; /* i/o redirections (struct redir *'s) */ - LinkList vars; /* param assignments (struct varasg *'s) */ -}; - -/* cmd types */ -#define SIMPLE 0 -#define SUBSH 1 -#define CURSH 2 -#define ZCTIME 3 -#define FUNCDEF 4 -#define CFOR 5 -#define CWHILE 6 -#define CREPEAT 7 -#define CIF 8 -#define CCASE 9 -#define CSELECT 10 -#define COND 11 -#define CARITH 12 -#define AUTOFN 13 - -/* flags for command modifiers */ -#define CFLAG_EXEC (1<<0) /* exec ... */ - -/* tree element for redirection lists */ - -struct redir { - int ntype; /* node type */ - int type; - int fd1, fd2; - char *name; -}; - -/* tree element for conditionals */ - -struct cond { - int ntype; /* node type */ - int type; /* can be cond_type, or a single */ - /* letter (-a, -b, ...) */ - void *left, *right; -}; +/* Condition types. */ #define COND_NOT 0 #define COND_AND 1 @@ -455,50 +405,34 @@ struct cond { #define COND_GT 13 #define COND_LE 14 #define COND_GE 15 - -struct forcmd { /* for/select */ -/* Cmd->args contains list of words to loop thru */ - int ntype; /* node type */ - int inflag; /* if there is an in ... clause */ - char *name; /* initializer or parameter name */ - char *condition; /* arithmetic terminating condition */ - char *advance; /* evaluated after each loop */ - List list; /* list to look through for each name */ -}; - -struct casecmd { -/* Cmd->args contains word to test */ - int ntype; /* node type */ - char **pats; - List *lists; /* list to execute */ +#define COND_MOD 16 +#define COND_MODI 17 + +typedef int (*CondHandler) _((char **, int)); + +struct conddef { + Conddef next; /* next in list */ + char *name; /* the condition name */ + int flags; /* see CONDF_* below */ + CondHandler handler; /* handler function */ + int min; /* minimum number of strings */ + int max; /* maximum number of strings */ + int condid; /* for overloading handler functions */ + char *module; /* module to autoload */ }; +#define CONDF_INFIX 1 +#define CONDF_ADDED 2 -/* A command like "if foo then bar elif baz then fubar else fooble" */ -/* generates a tree like: */ -/* */ -/* struct ifcmd a = { next = &b, ifl = "foo", thenl = "bar" } */ -/* struct ifcmd b = { next = &c, ifl = "baz", thenl = "fubar" } */ -/* struct ifcmd c = { next = NULL, ifl = NULL, thenl = "fooble" } */ - -struct ifcmd { - int ntype; /* node type */ - List *ifls; - List *thenls; -}; +#define CONDDEF(name, flags, handler, min, max, condid) \ + { NULL, name, flags, handler, min, max, condid, NULL } -struct whilecmd { - int ntype; /* node type */ - int cond; /* 0 for while, 1 for until */ - List cont; /* condition */ - List loop; /* list to execute until condition met */ -}; - -/* node for autoloading functions */ +/* tree element for redirection lists */ -struct autofn { - int ntype; /* node type */ - Shfunc shf; /* the shell function to define */ +struct redir { + int type; + int fd1, fd2; + char *name; }; /* The number of fds space is allocated for * @@ -520,14 +454,12 @@ struct multio { int fds[MULTIOUNIT]; /* list of src/dests redirected to/from this fd */ }; -/* variable assignment tree element */ +/* structure for foo=bar assignments */ -struct varasg { - int ntype; /* node type */ - int type; /* nonzero means array */ +struct asgment { + struct asgment *next; char *name; - char *str; /* should've been a union here. oh well */ - LinkList arr; + char *value; }; /* lvalue for variable assignment/expansion */ @@ -538,18 +470,191 @@ struct value { int inv; /* should we return the index ? */ int a; /* first element of array slice, or -1 */ int b; /* last element of array slice, or -1 */ + char **arr; /* cache for hash turned into array */ }; -/* structure for foo=bar assignments */ +#define MAX_ARRLEN 262144 -struct asgment { - struct asgment *next; - char *name; - char *value; +/********************************************/ +/* Defintions for word code */ +/********************************************/ + +typedef unsigned int wordcode; +typedef wordcode *Wordcode; + +typedef struct funcdump *FuncDump; +typedef struct eprog *Eprog; + +struct funcdump { + FuncDump next; /* next in list */ + char *name; /* path name */ + int fd; /* file descriptor */ + Wordcode map; /* pointer to header */ + Wordcode addr; /* mapped region */ + int len; /* length */ + int count; /* reference count */ }; -#define MAX_ARRLEN 262144 +struct eprog { + int flags; /* EF_* below */ + int len; /* total block length */ + int npats; /* Patprog cache size */ + Patprog *pats; /* the memory block, the patterns */ + Wordcode prog; /* memory block ctd, the code */ + char *strs; /* memory block ctd, the strings */ + Shfunc shf; /* shell function for autoload */ + FuncDump dump; /* dump file this is in */ +}; + +#define EF_REAL 1 +#define EF_HEAP 2 +#define EF_MAP 4 +#define EF_RUN 8 + +typedef struct estate *Estate; + +struct estate { + Eprog prog; /* the eprog executed */ + Wordcode pc; /* program counter, current pos */ + char *strs; /* strings from prog */ +}; + +typedef struct eccstr *Eccstr; + +struct eccstr { + Eccstr next; + char *str; + wordcode offs; + int nfunc; +}; +#define EC_NODUP 0 +#define EC_DUP 1 +#define EC_DUPTOK 2 + +#define WC_CODEBITS 5 + +#define wc_code(C) ((C) & ((wordcode) ((1 << WC_CODEBITS) - 1))) +#define wc_data(C) ((C) >> WC_CODEBITS) +#define wc_bdata(D) ((D) << WC_CODEBITS) +#define wc_bld(C,D) (((wordcode) (C)) | (((wordcode) (D)) << WC_CODEBITS)) + +#define WC_END 0 +#define WC_LIST 1 +#define WC_SUBLIST 2 +#define WC_PIPE 3 +#define WC_REDIR 4 +#define WC_ASSIGN 5 +#define WC_SIMPLE 6 +#define WC_SUBSH 7 +#define WC_CURSH 8 +#define WC_TIMED 9 +#define WC_FUNCDEF 10 +#define WC_FOR 11 +#define WC_SELECT 12 +#define WC_WHILE 13 +#define WC_REPEAT 14 +#define WC_CASE 15 +#define WC_IF 16 +#define WC_COND 17 +#define WC_ARITH 18 +#define WC_AUTOFN 19 + +#define WCB_END() wc_bld(WC_END, 0) + +#define WC_LIST_TYPE(C) wc_data(C) +#define Z_END (1<<4) +#define Z_SIMPLE (1<<5) +#define WC_LIST_SKIP(C) (wc_data(C) >> 6) +#define WCB_LIST(T,O) wc_bld(WC_LIST, ((T) | ((O) << 6))) + +#define WC_SUBLIST_TYPE(C) (wc_data(C) & ((wordcode) 3)) +#define WC_SUBLIST_END 0 +#define WC_SUBLIST_AND 1 +#define WC_SUBLIST_OR 2 +#define WC_SUBLIST_FLAGS(C) (wc_data(C) & ((wordcode) 0x1c)) +#define WC_SUBLIST_COPROC 4 +#define WC_SUBLIST_NOT 8 +#define WC_SUBLIST_SIMPLE 16 +#define WC_SUBLIST_SKIP(C) (wc_data(C) >> 5) +#define WCB_SUBLIST(T,F,O) wc_bld(WC_SUBLIST, ((T) | (F) | ((O) << 5))) + +#define WC_PIPE_TYPE(C) (wc_data(C) & ((wordcode) 1)) +#define WC_PIPE_END 0 +#define WC_PIPE_MID 1 +#define WC_PIPE_LINENO(C) (wc_data(C) >> 1) +#define WCB_PIPE(T,L) wc_bld(WC_PIPE, ((T) | ((L) << 1))) + +#define WC_REDIR_TYPE(C) wc_data(C) +#define WCB_REDIR(T) wc_bld(WC_REDIR, (T)) + +#define WC_ASSIGN_TYPE(C) (wc_data(C) & ((wordcode) 1)) +#define WC_ASSIGN_SCALAR 0 +#define WC_ASSIGN_ARRAY 1 +#define WC_ASSIGN_NUM(C) (wc_data(C) >> 1) +#define WCB_ASSIGN(T,N) wc_bld(WC_ASSIGN, ((T) | ((N) << 1))) + +#define WC_SIMPLE_ARGC(C) wc_data(C) +#define WCB_SIMPLE(N) wc_bld(WC_SIMPLE, (N)) + +#define WC_SUBSH_SKIP(C) wc_data(C) +#define WCB_SUBSH(O) wc_bld(WC_SUBSH, (O)) + +#define WC_CURSH_SKIP(C) wc_data(C) +#define WCB_CURSH(O) wc_bld(WC_CURSH, (O)) + +#define WC_TIMED_TYPE(C) wc_data(C) +#define WC_TIMED_EMPTY 0 +#define WC_TIMED_PIPE 1 +#define WCB_TIMED(T) wc_bld(WC_TIMED, (T)) + +#define WC_FUNCDEF_SKIP(C) wc_data(C) +#define WCB_FUNCDEF(O) wc_bld(WC_FUNCDEF, (O)) + +#define WC_FOR_TYPE(C) (wc_data(C) & 3) +#define WC_FOR_PPARAM 0 +#define WC_FOR_LIST 1 +#define WC_FOR_COND 2 +#define WC_FOR_SKIP(C) (wc_data(C) >> 2) +#define WCB_FOR(T,O) wc_bld(WC_FOR, ((T) | ((O) << 2))) + +#define WC_SELECT_TYPE(C) (wc_data(C) & 1) +#define WC_SELECT_PPARAM 0 +#define WC_SELECT_LIST 1 +#define WC_SELECT_SKIP(C) (wc_data(C) >> 1) +#define WCB_SELECT(T,O) wc_bld(WC_SELECT, ((T) | ((O) << 1))) + +#define WC_WHILE_TYPE(C) (wc_data(C) & 1) +#define WC_WHILE_WHILE 0 +#define WC_WHILE_UNTIL 1 +#define WC_WHILE_SKIP(C) (wc_data(C) >> 1) +#define WCB_WHILE(T,O) wc_bld(WC_WHILE, ((T) | ((O) << 1))) + +#define WC_REPEAT_SKIP(C) wc_data(C) +#define WCB_REPEAT(O) wc_bld(WC_REPEAT, (O)) + +#define WC_CASE_TYPE(C) (wc_data(C) & 3) +#define WC_CASE_HEAD 0 +#define WC_CASE_OR 1 +#define WC_CASE_AND 2 +#define WC_CASE_SKIP(C) (wc_data(C) >> 2) +#define WCB_CASE(T,O) wc_bld(WC_CASE, ((T) | ((O) << 2))) + +#define WC_IF_TYPE(C) (wc_data(C) & 3) +#define WC_IF_HEAD 0 +#define WC_IF_IF 1 +#define WC_IF_ELIF 2 +#define WC_IF_ELSE 3 +#define WC_IF_SKIP(C) (wc_data(C) >> 2) +#define WCB_IF(T,O) wc_bld(WC_IF, ((T) | ((O) << 2))) + +#define WC_COND_TYPE(C) (wc_data(C) & 127) +#define WC_COND_SKIP(C) (wc_data(C) >> 7) +#define WCB_COND(T,O) wc_bld(WC_COND, ((T) | ((O) << 7))) + +#define WCB_ARITH() wc_bld(WC_ARITH, 0) + +#define WCB_AUTOFN() wc_bld(WC_AUTOFN, 0) /********************************************/ /* Defintions for job table and job control */ @@ -583,9 +688,13 @@ struct job { #define STAT_INUSE (1<<6) /* this job entry is in use */ #define STAT_SUPERJOB (1<<7) /* job has a subjob */ #define STAT_SUBJOB (1<<8) /* job is a subjob */ -#define STAT_CURSH (1<<9) /* last command is in current shell */ -#define STAT_NOSTTY (1<<10) /* the tty settings are not inherited */ +#define STAT_WASSUPER (1<<9) /* was a super-job, sub-job needs to be */ + /* deleted */ +#define STAT_CURSH (1<<10) /* last command is in current shell */ +#define STAT_NOSTTY (1<<11) /* the tty settings are not inherited */ /* from this job when it exits. */ +#define STAT_ATTACH (1<<12) /* delay reattaching shell to tty */ +#define STAT_SUBLEADER (1<<13) /* is super-job, but leader is sub-shell */ #define SP_RUNNING -1 /* fake status for jobs currently running */ @@ -631,7 +740,9 @@ struct execstack { struct heredocs { struct heredocs *next; - Redir rd; + int type; + int pc; + char *str; }; struct dirsav { @@ -641,6 +752,8 @@ struct dirsav { ino_t ino; }; +#define MAX_PIPESTATS 256 + /*******************************/ /* Definitions for Hash Tables */ /*******************************/ @@ -654,10 +767,12 @@ typedef void (*AddNodeFunc) _((HashTable, char *, void *)); typedef HashNode (*GetNodeFunc) _((HashTable, char *)); typedef HashNode (*RemoveNodeFunc) _((HashTable, char *)); typedef void (*FreeNodeFunc) _((HashNode)); +typedef int (*CompareFunc) _((const char *, const char *)); /* type of function that is passed to * * scanhashtable or scanmatchtable */ typedef void (*ScanFunc) _((HashNode, int)); +typedef void (*ScanTabFunc) _((HashTable, ScanFunc, int)); typedef void (*PrintTableStats) _((HashTable)); @@ -673,6 +788,7 @@ struct hashtable { HashFunc hash; /* pointer to hash function for this table */ TableFunc emptytable; /* pointer to function to empty table */ TableFunc filltable; /* pointer to function to fill table */ + CompareFunc cmpnodes; /* pointer to function to compare two nodes */ AddNodeFunc addnode; /* pointer to function to add new node */ GetNodeFunc getnode; /* pointer to function to get an enabled node */ GetNodeFunc getnode2; /* pointer to function to get node */ @@ -682,6 +798,7 @@ struct hashtable { ScanFunc enablenode; /* pointer to function to enable a node */ FreeNodeFunc freenode; /* pointer to function to free a node */ ScanFunc printnode; /* pointer to function to print a node */ + ScanTabFunc scantab; /* pointer to function to scan table */ #ifdef HASHTABLE_INTERNAL_MEMBERS HASHTABLE_INTERNAL_MEMBERS /* internal use in hashtable.c */ @@ -701,6 +818,15 @@ struct hashnode { * reserved words. */ #define DISABLED (1<<0) +/* node in shell option table */ + +struct optname { + HashNode next; /* next in hash chain */ + char *nam; /* hash data */ + int flags; + int optno; /* option number */ +}; + /* node in shell reserved word hash table (reswdtab) */ struct reswd { @@ -746,9 +872,42 @@ struct shfunc { HashNode next; /* next in hash chain */ char *nam; /* name of shell function */ int flags; /* various flags */ - List funcdef; /* function definition */ + Eprog funcdef; /* function definition */ }; +/* Shell function context types. */ + +#define SFC_NONE 0 /* no function running */ +#define SFC_DIRECT 1 /* called directly from the user */ +#define SFC_SIGNAL 2 /* signal handler */ +#define SFC_HOOK 3 /* one of the special functions */ +#define SFC_WIDGET 4 /* user defined widget */ +#define SFC_COMPLETE 5 /* called from completion code */ +#define SFC_CWIDGET 6 /* new style completion widget */ + +/* node in function stack */ + +struct funcstack { + Funcstack prev; /* previous in stack */ + char *name; /* name of function called */ +}; + +/* node in list of function call wrappers */ + +typedef int (*WrapFunc) _((Eprog, FuncWrap, char *)); + +struct funcwrap { + FuncWrap next; + int flags; + WrapFunc handler; + Module module; +}; + +#define WRAPF_ADDED 1 + +#define WRAPDEF(func) \ + { NULL, 0, func, NULL } + /* node in builtin command hash table (builtintab) */ typedef int (*HandlerFunc) _((char *, char **, char *, int)); @@ -794,11 +953,87 @@ struct builtin { struct module { char *nam; int flags; - void *handle; + union { + void *handle; + Linkedmod linked; + } u; LinkList deps; + int wrapper; }; #define MOD_BUSY (1<<0) +#define MOD_UNLOAD (1<<1) +#define MOD_SETUP (1<<2) +#define MOD_LINKED (1<<3) +#define MOD_INIT_S (1<<4) +#define MOD_INIT_B (1<<5) + +typedef int (*Module_func) _((Module)); + +struct linkedmod { + char *name; + Module_func setup; + Module_func boot; + Module_func cleanup; + Module_func finish; +}; + +/* C-function hooks */ + +typedef int (*Hookfn) _((Hookdef, void *)); + +struct hookdef { + Hookdef next; + char *name; + Hookfn def; + int flags; + LinkList funcs; +}; + +#define HOOKF_ALL 1 + +#define HOOKDEF(name, func, flags) { NULL, name, (Hookfn) func, flags, NULL } + +/* + * Types used in pattern matching. Most of these longs could probably + * happily be ints. + */ + +struct patprog { + long startoff; /* length before start of programme */ + long size; /* total size from start of struct */ + long mustoff; /* offset to string that must be present */ + int globflags; /* globbing flags to set at start */ + int globend; /* globbing flags set after finish */ + int flags; /* PAT_* flags */ + int patmlen; /* length of pure string or longest match */ + int patnpar; /* number of active parentheses */ + char patstartch; +}; + +/* Flags used in pattern matchers (Patprog) and passed down to patcompile */ + +#define PAT_FILE 0x0001 /* Pattern is a file name */ +#define PAT_FILET 0x0002 /* Pattern is top level file, affects ~ */ +#define PAT_ANY 0x0004 /* Match anything (cheap "*") */ +#define PAT_NOANCH 0x0008 /* Not anchored at end */ +#define PAT_NOGLD 0x0010 /* Don't glob dots */ +#define PAT_PURES 0x0020 /* Pattern is a pure string: set internally */ +#define PAT_STATIC 0x0040 /* Don't copy pattern to heap as per default */ +#define PAT_SCAN 0x0080 /* Scanning, so don't try must-match test */ +#define PAT_ZDUP 0x0100 /* Copy pattern in real memory */ + +/* Globbing flags: lower 8 bits gives approx count */ +#define GF_LCMATCHUC 0x0100 +#define GF_IGNCASE 0x0200 +#define GF_BACKREF 0x0400 +#define GF_MATCHREF 0x0800 + +/* Dummy Patprog pointers. Used mainly in executable code, but the + * pattern code needs to know about it, too. */ + +#define dummy_patprog1 ((Patprog) 1) +#define dummy_patprog2 ((Patprog) 2) /* node used in parameter hash table (paramtab) */ @@ -812,21 +1047,28 @@ struct param { void *data; /* used by special parameter functions */ char **arr; /* value if declared array (PM_ARRAY) */ char *str; /* value if declared string (PM_SCALAR) */ - long val; /* value if declared integer (PM_INTEGER) */ + zlong val; /* value if declared integer (PM_INTEGER) */ + double dval; /* value if declared float + (PM_EFLOAT|PM_FFLOAT) */ + HashTable hash; /* value if declared assoc (PM_HASHED) */ } u; /* pointer to function to set value of this parameter */ union { void (*cfn) _((Param, char *)); - void (*ifn) _((Param, long)); + void (*ifn) _((Param, zlong)); + void (*ffn) _((Param, double)); void (*afn) _((Param, char **)); + void (*hfn) _((Param, HashTable)); } sets; /* pointer to function to get value of this parameter */ union { char *(*cfn) _((Param)); - long (*ifn) _((Param)); + zlong (*ifn) _((Param)); + double (*ffn) _((Param)); char **(*afn) _((Param)); + HashTable (*hfn) _((Param)); } gets; /* pointer to function to unset this parameter */ @@ -842,30 +1084,108 @@ struct param { /* flags for parameters */ /* parameter types */ -#define PM_SCALAR 0 /* scalar */ -#define PM_ARRAY (1<<0) /* array */ -#define PM_INTEGER (1<<1) /* integer */ +#define PM_SCALAR 0 /* scalar */ +#define PM_ARRAY (1<<0) /* array */ +#define PM_INTEGER (1<<1) /* integer */ +#define PM_EFLOAT (1<<2) /* double with %e output */ +#define PM_FFLOAT (1<<3) /* double with %f output */ +#define PM_HASHED (1<<4) /* association */ -#define PM_TYPE(X) (X & (PM_SCALAR|PM_INTEGER|PM_ARRAY)) +#define PM_TYPE(X) \ + (X & (PM_SCALAR|PM_INTEGER|PM_EFLOAT|PM_FFLOAT|PM_ARRAY|PM_HASHED)) -#define PM_LEFT (1<<2) /* left justify and remove leading blanks */ -#define PM_RIGHT_B (1<<3) /* right justify and fill with leading blanks */ -#define PM_RIGHT_Z (1<<4) /* right justify and fill with leading zeros */ -#define PM_LOWER (1<<5) /* all lower case */ +#define PM_LEFT (1<<5) /* left justify, remove leading blanks */ +#define PM_RIGHT_B (1<<6) /* right justify, fill with leading blanks */ +#define PM_RIGHT_Z (1<<7) /* right justify, fill with leading zeros */ +#define PM_LOWER (1<<8) /* all lower case */ /* The following are the same since they * * both represent -u option to typeset */ -#define PM_UPPER (1<<6) /* all upper case */ -#define PM_UNDEFINED (1<<6) /* undefined (autoloaded) shell function */ - -#define PM_READONLY (1<<7) /* readonly */ -#define PM_TAGGED (1<<8) /* tagged */ -#define PM_EXPORTED (1<<9) /* exported */ -#define PM_UNIQUE (1<<10) /* remove duplicates */ -#define PM_SPECIAL (1<<11) /* special builtin parameter */ -#define PM_DONTIMPORT (1<<12) /* do not import this variable */ -#define PM_RESTRICTED (1<<13) /* cannot be changed in restricted mode */ -#define PM_UNSET (1<<14) /* has null value */ +#define PM_UPPER (1<<9) /* all upper case */ +#define PM_UNDEFINED (1<<9) /* undefined (autoloaded) shell function */ + +#define PM_READONLY (1<<10) /* readonly */ +#define PM_TAGGED (1<<11) /* tagged */ +#define PM_EXPORTED (1<<12) /* exported */ + +/* The following are the same since they * + * both represent -U option to typeset */ +#define PM_UNIQUE (1<<13) /* remove duplicates */ +#define PM_UNALIASED (1<<13) /* do not expand aliases when autoloading */ + +#define PM_HIDE (1<<14) /* Special behaviour hidden by local */ +#define PM_TIED (1<<15) /* array tied to colon-path or v.v. */ + +/* Remaining flags do not correspond directly to command line arguments */ +#define PM_LOCAL (1<<16) /* this parameter will be made local */ +#define PM_SPECIAL (1<<17) /* special builtin parameter */ +#define PM_DONTIMPORT (1<<18) /* do not import this variable */ +#define PM_RESTRICTED (1<<19) /* cannot be changed in restricted mode */ +#define PM_UNSET (1<<20) /* has null value */ +#define PM_REMOVABLE (1<<21) /* special can be removed from paramtab */ +#define PM_AUTOLOAD (1<<22) /* autoloaded from module */ +#define PM_NORESTORE (1<<23) /* do not restore value of local special */ + +/* The option string corresponds to the first of the variables above */ +#define TYPESET_OPTSTR "aiEFALRZlurtxUhT" + +/* These typeset options take an optional numeric argument */ +#define TYPESET_OPTNUM "LRZiEF" + +/* Flags for extracting elements of arrays and associative arrays */ +#define SCANPM_WANTVALS (1<<0) +#define SCANPM_WANTKEYS (1<<1) +#define SCANPM_WANTINDEX (1<<2) +#define SCANPM_MATCHKEY (1<<3) +#define SCANPM_MATCHVAL (1<<4) +#define SCANPM_MATCHMANY (1<<5) +#define SCANPM_ASSIGNING (1<<6) +#define SCANPM_KEYMATCH (1<<7) +#define SCANPM_ISVAR_AT ((-1)<<15) /* Only sign bit is significant */ + +/* + * Flags for doing matches inside parameter substitutions, i.e. + * ${...#...} and friends. This could be an enum, but so + * could a lot of other things. + */ + +#define SUB_END 0x0001 /* match end instead of begining, % or %% */ +#define SUB_LONG 0x0002 /* % or # doubled, get longest match */ +#define SUB_SUBSTR 0x0004 /* match a substring */ +#define SUB_MATCH 0x0008 /* include the matched portion */ +#define SUB_REST 0x0010 /* include the unmatched portion */ +#define SUB_BIND 0x0020 /* index of beginning of string */ +#define SUB_EIND 0x0040 /* index of end of string */ +#define SUB_LEN 0x0080 /* length of match */ +#define SUB_ALL 0x0100 /* match complete string */ +#define SUB_GLOBAL 0x0200 /* global substitution ${..//all/these} */ +#define SUB_DOSUBST 0x0400 /* replacement string needs substituting */ + +/* Flags as the second argument to prefork */ +#define PF_TYPESET 0x01 /* argument handled like typeset foo=bar */ +#define PF_ASSIGN 0x02 /* argument handled like the RHS of foo=bar */ +#define PF_SINGLE 0x04 /* single word substitution */ + +struct paramdef { + char *name; + int flags; + void *var; + void *set; + void *get; + void *unset; +}; + +#define PARAMDEF(name, flags, var, set, get, unset) \ + { name, flags, (void *) var, (void *) set, (void *) get, (void *) unset } +#define INTPARAMDEF(name, var) \ + { name, PM_INTEGER, (void *) var, (void *) intvarsetfn, \ + (void *) intvargetfn, (void *) stdunsetfn } +#define STRPARAMDEF(name, var) \ + { name, PM_SCALAR, (void *) var, (void *) strvarsetfn, \ + (void *) strvargetfn, (void *) stdunsetfn } +#define ARRPARAMDEF(name, var) \ + { name, PM_ARRAY, (void *) var, (void *) arrvarsetfn, \ + (void *) arrvargetfn, (void *) stdunsetfn } /* node for named directory hash table (nameddirtab) */ @@ -880,19 +1200,21 @@ struct nameddir { /* flags for named directories */ /* DISABLED is defined (1<<0) */ #define ND_USERNAME (1<<1) /* nam is actually a username */ +#define ND_NOABBREV (1<<2) /* never print as abbrev (PWD or OLDPWD) */ /* flags for controlling printing of hash table nodes */ #define PRINT_NAMEONLY (1<<0) #define PRINT_TYPE (1<<1) #define PRINT_LIST (1<<2) +#define PRINT_KV_PAIR (1<<3) /* flags for printing for the whence builtin */ -#define PRINT_WHENCE_CSH (1<<3) -#define PRINT_WHENCE_VERBOSE (1<<4) -#define PRINT_WHENCE_SIMPLE (1<<5) -#define PRINT_WHENCE_FUNCDEF (1<<6) -#define PRINT_WHENCE_WORD (1<<7) +#define PRINT_WHENCE_CSH (1<<4) +#define PRINT_WHENCE_VERBOSE (1<<5) +#define PRINT_WHENCE_SIMPLE (1<<6) +#define PRINT_WHENCE_FUNCDEF (1<<7) +#define PRINT_WHENCE_WORD (1<<8) /***********************************/ /* Definitions for history control */ @@ -901,18 +1223,30 @@ struct nameddir { /* history entry */ struct histent { + HashNode hash_next; /* next in hash chain */ char *text; /* the history line itself */ + int flags; /* Misc flags */ + + Histent up; /* previous line (moving upward) */ + Histent down; /* next line (moving downward) */ char *zle_text; /* the edited history line */ time_t stim; /* command started time (datestamp) */ time_t ftim; /* command finished time */ short *words; /* Position of words in history */ /* line: as pairs of start, end */ int nwords; /* Number of words in history line */ - int flags; /* Misc flags */ + int histnum; /* A sequential history number */ }; -#define HIST_OLD 0x00000001 /* Command is already written to disk*/ -#define HIST_READ 0x00000002 /* Command was read back from disk*/ +#define HIST_MAKEUNIQUE 0x00000001 /* Kill this new entry if not unique */ +#define HIST_OLD 0x00000002 /* Command is already written to disk*/ +#define HIST_READ 0x00000004 /* Command was read back from disk*/ +#define HIST_DUP 0x00000008 /* Command duplicates a later line */ +#define HIST_FOREIGN 0x00000010 /* Command came from another shell */ + +#define GETHIST_UPWARD (-1) +#define GETHIST_DOWNWARD 1 +#define GETHIST_EXACT 0 /* Parts of the code where history expansion is disabled * * should be within a pair of STOPHIST ... ALLOWHIST */ @@ -923,7 +1257,14 @@ struct histent { #define HISTFLAG_DONE 1 #define HISTFLAG_NOEXEC 2 #define HISTFLAG_RECALL 4 +#define HISTFLAG_SETTY 8 +#define HFILE_APPEND 0x0001 +#define HFILE_SKIPOLD 0x0002 +#define HFILE_SKIPDUPS 0x0004 +#define HFILE_SKIPFOREIGN 0x0008 +#define HFILE_FAST 0x0010 +#define HFILE_USE_OPTIONS 0x8000 /******************************************/ /* Definitions for programable completion */ @@ -972,12 +1313,15 @@ enum { BADPATTERN, BANGHIST, BAREGLOBQUAL, + BASHAUTOLIST, BEEP, BGNICE, BRACECCL, BSDECHO, CDABLEVARS, + CHASEDOTS, CHASELINKS, + CHECKJOBS, CLOBBER, COMPLETEALIASES, COMPLETEINWORD, @@ -986,6 +1330,7 @@ enum { CSHJUNKIEHISTORY, CSHJUNKIELOOPS, CSHJUNKIEQUOTES, + CSHNULLCMD, CSHNULLGLOB, EQUALS, ERREXIT, @@ -994,6 +1339,7 @@ enum { EXTENDEDHISTORY, FLOWCONTROL, FUNCTIONARGZERO, + GLOBALRCS, GLOBOPT, GLOBASSIGN, GLOBCOMPLETE, @@ -1004,15 +1350,20 @@ enum { HASHLISTALL, HISTALLOWCLOBBER, HISTBEEP, + HISTEXPIREDUPSFIRST, + HISTFINDNODUPS, + HISTIGNOREALLDUPS, HISTIGNOREDUPS, HISTIGNORESPACE, HISTNOFUNCTIONS, HISTNOSTORE, HISTREDUCEBLANKS, + HISTSAVENODUPS, HISTVERIFY, HUP, IGNOREBRACES, IGNOREEOF, + INCAPPENDHISTORY, INTERACTIVE, INTERACTIVECOMMENTS, KSHARRAYS, @@ -1021,8 +1372,11 @@ enum { KSHOPTIONPRINT, LISTAMBIGUOUS, LISTBEEP, + LISTPACKED, + LISTROWSFIRST, LISTTYPES, LOCALOPTIONS, + LOCALTRAPS, LOGINSHELL, LONGLISTJOBS, MAGICEQUALSUBST, @@ -1056,9 +1410,11 @@ enum { RESTRICTED, RMSTARSILENT, RMSTARWAIT, + SHAREHISTORY, SHFILEEXPANSION, SHGLOB, SHINSTDIN, + SHNULLCMD, SHOPTIONLETTERS, SHORTLOOPS, SHWORDSPLIT, @@ -1154,7 +1510,8 @@ struct ttyinfo { #define TCALLATTRSOFF 21 #define TCSTANDOUTEND 22 #define TCUNDERLINEEND 23 -#define TC_COUNT 24 +#define TCHORIZPOS 24 +#define TC_COUNT 25 #define tccan(X) (tclen[X]) @@ -1178,14 +1535,20 @@ struct ttyinfo { /* Definitions for the %_ prompt escape */ /****************************************/ -#define cmdpush(X) if (!(cmdsp >= 0 && cmdsp < 256)) {;} else cmdstack[cmdsp++]=(X) +#define CMDSTACKSZ 256 +#define cmdpush(X) do { \ + if (cmdsp >= 0 && cmdsp < CMDSTACKSZ) \ + cmdstack[cmdsp++]=(X); \ + } while (0) #ifdef DEBUG -# define cmdpop() if (cmdsp <= 0) { \ - fputs("BUG: cmdstack empty\n", stderr); \ - fflush(stderr); \ - } else cmdsp-- +# define cmdpop() do { \ + if (cmdsp <= 0) { \ + fputs("BUG: cmdstack empty\n", stderr); \ + fflush(stderr); \ + } else cmdsp--; \ + } while (0) #else -# define cmdpop() if (cmdsp <= 0) {;} else cmdsp-- +# define cmdpop() do { if (cmdsp > 0) cmdsp--; } while (0) #endif #define CS_FOR 0 @@ -1224,35 +1587,41 @@ struct ttyinfo { * Memory management * *********************/ -#ifndef DEBUG -# define HEAPALLOC do { int nonlocal_useheap = global_heapalloc(); do +/* heappush saves the current heap state using this structure */ -# define PERMALLOC do { int nonlocal_useheap = global_permalloc(); do +struct heapstack { + struct heapstack *next; /* next one in list for this heap */ + size_t used; +}; -# define LASTALLOC while (0); \ - if (nonlocal_useheap) global_heapalloc(); \ - else global_permalloc(); \ - } while(0) +/* A zsh heap. */ -# define LASTALLOC_RETURN \ - if ((nonlocal_useheap ? global_heapalloc() : \ - global_permalloc()), 0) {;} else return -#else -# define HEAPALLOC do { int nonlocal_useheap = global_heapalloc(); \ - alloc_stackp++; do +struct heap { + struct heap *next; /* next one */ + size_t size; /* size of heap */ + size_t used; /* bytes used from the heap */ + struct heapstack *sp; /* used by pushheap() to save the value used */ -# define PERMALLOC do { int nonlocal_useheap = global_permalloc(); \ - alloc_stackp++; do +/* Uncomment the following if the struct needs padding to 64-bit size. */ +/* Make sure sizeof(heap) is a multiple of 8 +#if defined(PAD_64_BIT) && !defined(__GNUC__) + size_t dummy; +#endif +*/ +#define arena(X) ((char *) (X) + sizeof(struct heap)) +} +#if defined(PAD_64_BIT) && defined(__GNUC__) + __attribute__ ((aligned (8))) +#endif +; -# define LASTALLOC while (0); alloc_stackp--; \ - if (nonlocal_useheap) global_heapalloc(); \ - else global_permalloc(); \ - } while(0) +# define LASTALLOC_RETURN return -# define LASTALLOC_RETURN \ - if ((nonlocal_useheap ? global_heapalloc() : \ - global_permalloc()),alloc_stackp--,0){;}else return -#endif +# define NEWHEAPS(h) do { Heap _switch_oldheaps = h = new_heaps(); do +# define OLDHEAPS while (0); old_heaps(_switch_oldheaps); } while (0); + +# define SWITCHHEAPS(h) do { Heap _switch_oldheaps = switch_heaps(h); do +# define SWITCHBACKHEAPS while (0); switch_heaps(_switch_oldheaps); } while (0); /****************/ /* Debug macros */ @@ -1260,12 +1629,8 @@ struct ttyinfo { #ifdef DEBUG # define DPUTS(X,Y) if (!(X)) {;} else dputs(Y) -# define MUSTUSEHEAP(X) if (useheap) {;} else \ - fprintf(stderr, "BUG: permanent allocation in %s\n", X), \ - fflush(stderr) #else # define DPUTS(X,Y) -# define MUSTUSEHEAP(X) #endif /**************************/ @@ -1274,9 +1639,20 @@ struct ttyinfo { /* These used in the sigtrapped[] array */ -#define ZSIG_TRAPPED (1<<0) -#define ZSIG_IGNORED (1<<1) -#define ZSIG_FUNC (1<<2) +#define ZSIG_TRAPPED (1<<0) /* Signal is trapped */ +#define ZSIG_IGNORED (1<<1) /* Signal is ignored */ +#define ZSIG_FUNC (1<<2) /* Trap is a function, not an eval list */ +/* Mask to get the above flags */ +#define ZSIG_MASK (ZSIG_TRAPPED|ZSIG_IGNORED|ZSIG_FUNC) +/* No. of bits to shift local level when storing in sigtrapped */ +#define ZSIG_SHIFT 3 + +/**********************************/ +/* Flags to third argument of zle */ +/**********************************/ + +#define ZLRF_HISTORY 0x01 /* OK to access the history list */ +#define ZLRF_NOSETTY 0x02 /* Don't set tty before return */ /****************/ /* Entry points */ @@ -1291,3 +1667,17 @@ typedef int (*CompctlReadFn) _((char *, char **, char *, char *)); typedef void (*ZleVoidFn) _((void)); typedef void (*ZleVoidIntFn) _((int)); typedef unsigned char * (*ZleReadFn) _((char *, char *, int)); + +/***************************************/ +/* Pseudo-keyword to mark exportedness */ +/***************************************/ + +#define mod_export + +/***************************************/ +/* Hooks in core. */ +/***************************************/ + +#define EXITHOOK (zshhooks + 0) +#define BEFORETRAPHOOK (zshhooks + 1) +#define AFTERTRAPHOOK (zshhooks + 2) |