/* * zsh.h - standard header file * * This file is part of zsh, the Z shell. * * Copyright (c) 1992-1997 Paul Falstad * All rights reserved. * * Permission is hereby granted, without written agreement and without * license or royalty fees, to use, copy, modify, and distribute this * software and to distribute modified versions of this software for any * purpose, provided that the above copyright notice and the following * two paragraphs appear in all copies of this software. * * In no event shall Paul Falstad or the Zsh Development Group be liable * to any party for direct, indirect, special, incidental, or consequential * damages arising out of the use of this software and its documentation, * even if Paul Falstad and the Zsh Development Group have been advised of * the possibility of such damage. * * Paul Falstad and the Zsh Development Group specifically disclaim any * warranties, including, but not limited to, the implied warranties of * merchantability and fitness for a particular purpose. The software * provided hereunder is on an "as is" basis, and Paul Falstad and the * Zsh Development Group have no obligation to provide maintenance, * support, updates, enhancements, or modifications. * */ /* 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. */ #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 /* * Work out how to define large integer constants that will fit * in a zlong. */ #if defined(ZSH_64_BIT_TYPE) || defined(LONG_IS_64_BIT) /* We have some 64-bit type */ #ifdef LONG_IS_64_BIT /* It's long */ #define ZLONG_CONST(x) x ## l #else /* It's long long */ #ifdef ZLONG_IS_LONG_LONG #define ZLONG_CONST(x) x ## ll #else /* * There's some 64-bit type, but we don't know what it is. * We'll just cast it and hope the compiler does the right thing. */ #define ZLONG_CONST(x) ((zlong)x) #endif #endif #else /* We're stuck with long */ #define ZLONG_CONST(x) (x ## l) #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 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 */ #define MN_UNSET 4 /* mnumber not yet retrieved */ 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; /* MFF_* flags defined below */ NumMathFunc nfunc; StrMathFunc sfunc; char *module; int minargs; int maxargs; int funcid; }; /* Math function takes a string argument */ #define MFF_STR 1 /* Math function has been loaded from library */ #define MFF_ADDED 2 /* Math function is implemented by a shell function */ #define MFF_USERFUNC 4 /* When autoloading, enable all features in module */ #define MFF_AUTOALL 8 #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 * * unsigned promotions; i.e. (int)(unsigned char)((char) -1) evaluates * * to -1, instead of 255 like it should. We circumvent the troubles * * of such shameful delinquency by casting to a larger unsigned type * * then back down to unsigned char. */ #ifdef BROKEN_SIGNED_TO_UNSIGNED_CASTING # define STOUC(X) ((unsigned char)(unsigned short)(X)) #else # define STOUC(X) ((unsigned char)(X)) #endif /* Meta together with the character following Meta denotes the character * * which is the exclusive or of 32 and the character following Meta. * * This is used to represent characters which otherwise has special * * meaning for zsh. These are the characters for which the imeta() test * * is true: the null character, and the characters from Meta to Marker. */ #define Meta ((char) 0x83) /* Note that the fourth character in DEFAULT_IFS is Meta * * followed by a space which denotes the null character. */ #define DEFAULT_IFS " \t\n\203 " /* As specified in the standard (POSIX 2008) */ #define DEFAULT_IFS_SH " \t\n" /* * Character tokens. * These should match the characters in ztokens, defined in lex.c */ #define Pound ((char) 0x84) #define String ((char) 0x85) #define Hat ((char) 0x86) #define Star ((char) 0x87) #define Inpar ((char) 0x88) #define Inparmath ((char) 0x89) #define Outpar ((char) 0x8a) #define Outparmath ((char) 0x8b) #define Qstring ((char) 0x8c) #define Equals ((char) 0x8d) #define Bar ((char) 0x8e) #define Inbrace ((char) 0x8f) #define Outbrace ((char) 0x90) #define Inbrack ((char) 0x91) #define Outbrack ((char) 0x92) #define Tick ((char) 0x93) #define Inang ((char) 0x94) #define Outang ((char) 0x95) #define OutangProc ((char) 0x96) #define Quest ((char) 0x97) #define Tilde ((char) 0x98) #define Qtick ((char) 0x99) #define Comma ((char) 0x9a) /* * Null arguments: placeholders for single and double quotes * and backslashes. */ #define Snull ((char) 0x9b) #define Dnull ((char) 0x9c) #define Bnull ((char) 0x9d) /* * Backslash which will be returned to "\" instead of being stripped * when we turn the string into a printable format. */ #define Bnullkeep ((char) 0x9e) /* * Null argument that does not correspond to any character. * This should be last as it does not appear in ztokens and * is used to initialise the IMETA type in inittyptab(). */ #define Nularg ((char) 0x9f) /* * Take care to update the use of IMETA appropriately when adding * tokens here. */ /* * Marker used in paramsubst for rc_expand_param. * Also used in pattern character arrays as guaranteed not to * mark a character in a string. */ #define Marker ((char) 0xa0) /* chars that need to be quoted if meant literally */ #define SPECCHARS "#$^*()=|{}[]`<>?~;&\n\t \\\'\"" /* * Types of quote. This is used in various places, so care needs * to be taken when changing them. (Oooh, don't you look surprised.) * - Passed to quotestring() to indicate style. This is the ultimate * destiny of most of the other uses of members of the enum. * - In paramsubst(), to count q's in parameter substitution. * - In the completion code, where we maintain a stack of quotation types. */ enum { /* * No quote. Not a valid quote, but useful in the substitution * and completion code to indicate we're not doing any quoting. */ QT_NONE, /* Backslash: \ */ QT_BACKSLASH, /* Single quote: ' */ QT_SINGLE, /* Double quote: " */ QT_DOUBLE, /* Print-style quote: $' */ QT_DOLLARS, /* * Backtick: ` * Not understood by many parts of the code; here for a convenience * in those cases where we need to represent a complete set. */ QT_BACKTICK, /* * Single quotes, but the default is not to quote unless necessary. * This is only useful as an argument to quotestring(). */ QT_SINGLE_OPTIONAL, /* * As QT_BACKSLASH, but a NULL string is shown as ''. */ QT_BACKSLASH_SHOWNULL }; #define QT_IS_SINGLE(x) ((x) == QT_SINGLE || (x) == QT_SINGLE_OPTIONAL) /* * Lexical tokens: unlike the character tokens above, these never * appear in strings and don't necessarily represent a single character. */ enum lextok { NULLTOK, /* 0 */ SEPER, NEWLIN, SEMI, DSEMI, AMPER, /* 5 */ INPAR, OUTPAR, DBAR, DAMPER, OUTANG, /* 10 */ OUTANGBANG, DOUTANG, DOUTANGBANG, INANG, INOUTANG, /* 15 */ DINANG, DINANGDASH, INANGAMP, OUTANGAMP, AMPOUTANG, /* 20 */ OUTANGAMPBANG, DOUTANGAMP, DOUTANGAMPBANG, TRINANG, BAR, /* 25 */ BARAMP, INOUTPAR, DINPAR, DOUTPAR, AMPERBANG, /* 30 */ SEMIAMP, SEMIBAR, DOUTBRACK, STRING, ENVSTRING, /* 35 */ ENVARRAY, ENDINPUT, LEXERR, /* Tokens for reserved words */ BANG, /* ! */ DINBRACK, /* [[ */ /* 40 */ INBRACE, /* { */ OUTBRACE, /* } */ CASE, /* case */ COPROC, /* coproc */ DOLOOP, /* do */ /* 45 */ DONE, /* done */ ELIF, /* elif */ ELSE, /* else */ ZEND, /* end */ ESAC, /* esac */ /* 50 */ FI, /* fi */ FOR, /* for */ FOREACH, /* foreach */ FUNC, /* function */ IF, /* if */ /* 55 */ NOCORRECT, /* nocorrect */ REPEAT, /* repeat */ SELECT, /* select */ THEN, /* then */ TIME, /* time */ /* 60 */ UNTIL, /* until */ WHILE /* while */ }; /* Redirection types. If you modify this, you may also have to modify * * redirtab in parse.c and getredirs() in text.c and the IS_* macros * * below. */ enum { REDIR_WRITE, /* > */ REDIR_WRITENOW, /* >| */ REDIR_APP, /* >> */ REDIR_APPNOW, /* >>| */ REDIR_ERRWRITE, /* &>, >& */ REDIR_ERRWRITENOW, /* >&| */ REDIR_ERRAPP, /* >>& */ REDIR_ERRAPPNOW, /* >>&| */ REDIR_READWRITE, /* <> */ REDIR_READ, /* < */ REDIR_HEREDOC, /* << */ REDIR_HEREDOCDASH, /* <<- */ REDIR_HERESTR, /* <<< */ REDIR_MERGEIN, /* <&n */ REDIR_MERGEOUT, /* >&n */ REDIR_CLOSE, /* >&-, <&- */ REDIR_INPIPE, /* < <(...) */ REDIR_OUTPIPE /* > >(...) */ }; #define REDIR_TYPE_MASK (0x1f) /* Redir using {var} syntax */ #define REDIR_VARID_MASK (0x20) /* Mark here-string that came from a here-document */ #define REDIR_FROM_HEREDOC_MASK (0x40) #define IS_WRITE_FILE(X) ((X)>=REDIR_WRITE && (X)<=REDIR_READWRITE) #define IS_APPEND_REDIR(X) (IS_WRITE_FILE(X) && ((X) & 2)) #define IS_CLOBBER_REDIR(X) (IS_WRITE_FILE(X) && ((X) & 1)) #define IS_ERROR_REDIR(X) ((X)>=REDIR_ERRWRITE && (X)<=REDIR_ERRAPPNOW) #define IS_READFD(X) (((X)>=REDIR_READWRITE && (X)<=REDIR_MERGEIN) || (X)==REDIR_INPIPE) #define IS_REDIROP(X) ((X)>=OUTANG && (X)<=TRINANG) /* * Values for the fdtable array. They say under what circumstances * the fd will be close. The fdtable is an unsigned char, so these are * #define's rather than an enum. */ /* Entry not used. */ #define FDT_UNUSED 0 /* * Entry used internally by the shell, should not be visible to other * processes. */ #define FDT_INTERNAL 1 /* * Entry visible to other processes, for example created using * the {varid}> file syntax. */ #define FDT_EXTERNAL 2 /* * Entry used by output from the XTRACE option. */ #define FDT_XTRACE 3 /* * Entry used for file locking. */ #define FDT_FLOCK 4 /* * As above, but the fd is not marked for closing on exec, * so the shell can still exec the last process. */ #define FDT_FLOCK_EXEC 5 #ifdef PATH_DEV_FD /* * Entry used by a process substition. * This marker is not tested internally as we associated the file * descriptor with a job for closing. */ #define FDT_PROC_SUBST 6 #endif /* Flags for input stack */ #define INP_FREE (1<<0) /* current buffer can be free'd */ #define INP_ALIAS (1<<1) /* expanding alias or history */ #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_HISTCONT (1<<5) /* stack is continued from history expn. */ #define INP_LINENO (1<<6) /* update line number */ #define INP_APPEND (1<<7) /* Append new lines to allow backup */ /* Flags for metafy */ #define META_REALLOC 0 #define META_USEHEAP 1 #define META_STATIC 2 #define META_DUP 3 #define META_ALLOC 4 #define META_NOALLOC 5 #define META_HEAPDUP 6 #define META_HREALLOC 7 /* Context to save and restore (bit fields) */ enum { /* History mechanism */ ZCONTEXT_HIST = (1<<0), /* Lexical analyser */ ZCONTEXT_LEX = (1<<1), /* Parser */ ZCONTEXT_PARSE = (1<<2) }; /**************************/ /* Abstract types for zsh */ /**************************/ typedef struct alias *Alias; typedef struct asgment *Asgment; typedef struct builtin *Builtin; typedef struct cmdnam *Cmdnam; typedef struct complist *Complist; typedef struct conddef *Conddef; typedef struct dirsav *Dirsav; typedef struct emulation_options *Emulation_options; typedef struct features *Features; typedef struct feature_enables *Feature_enables; typedef struct funcstack *Funcstack; typedef struct funcwrap *FuncWrap; typedef struct hashnode *HashNode; typedef struct hashtable *HashTable; typedef struct heap *Heap; typedef struct heapstack *Heapstack; typedef struct histent *Histent; typedef struct hookdef *Hookdef; typedef struct jobfile *Jobfile; typedef struct job *Job; typedef struct linkedmod *Linkedmod; typedef struct linknode *LinkNode; typedef union linkroot *LinkList; typedef struct module *Module; typedef struct nameddir *Nameddir; typedef struct options *Options; typedef struct optname *Optname; typedef struct param *Param; typedef struct paramdef *Paramdef; typedef struct patprog *Patprog; typedef struct prepromptfn *Prepromptfn; typedef struct process *Process; typedef struct redir *Redir; typedef struct reswd *Reswd; typedef struct shfunc *Shfunc; typedef struct timedfn *Timedfn; typedef struct value *Value; /********************************/ /* Definitions for linked lists */ /********************************/ /* linked list abstract data type */ struct linknode { LinkNode next; LinkNode prev; void *dat; }; struct linklist { LinkNode first; LinkNode last; int flags; }; union linkroot { struct linklist list; struct linknode node; }; /* Macros for manipulating link lists */ #define firstnode(X) ((X)->list.first) #define lastnode(X) ((X)->list.last) #define peekfirst(X) (firstnode(X)->dat) #define peeklast(X) (lastnode(X)->dat) #define addlinknode(X,Y) insertlinknode(X,lastnode(X),Y) #define zaddlinknode(X,Y) zinsertlinknode(X,lastnode(X),Y) #define uaddlinknode(X,Y) uinsertlinknode(X,lastnode(X),Y) #define empty(X) (firstnode(X) == NULL) #define nonempty(X) (firstnode(X) != NULL) #define getaddrdata(X) (&((X)->dat)) #define getdata(X) ((X)->dat) #define setdata(X,Y) ((X)->dat = (Y)) #define nextnode(X) ((X)->next) #define prevnode(X) ((X)->prev) #define pushnode(X,Y) insertlinknode(X,&(X)->node,Y) #define zpushnode(X,Y) zinsertlinknode(X,&(X)->node,Y) #define incnode(X) (X = nextnode(X)) #define decnode(X) (X = prevnode(X)) #define firsthist() (hist_ring? hist_ring->down->histnum : curhist) #define setsizednode(X,Y,Z) (firstnode(X)[(Y)].dat = (void *) (Z)) /* stack allocated linked lists */ #define local_list0(N) union linkroot N #define init_list0(N) \ do { \ (N).list.first = NULL; \ (N).list.last = &(N).node; \ (N).list.flags = 0; \ } while (0) #define local_list1(N) union linkroot N; struct linknode __n0 #define init_list1(N,V0) \ do { \ (N).list.first = &__n0; \ (N).list.last = &__n0; \ (N).list.flags = 0; \ __n0.next = NULL; \ __n0.prev = &(N).node; \ __n0.dat = (void *) (V0); \ } while (0) /*************************************/ /* Specific elements of linked lists */ /*************************************/ typedef void (*voidvoidfnptr_t) _((void)); /* * Element of the prepromptfns list. */ struct prepromptfn { voidvoidfnptr_t func; }; /* * Element of the timedfns list. */ struct timedfn { voidvoidfnptr_t func; time_t when; }; /********************************/ /* Definitions for syntax trees */ /********************************/ /* 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_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 */ /* Condition types. */ #define COND_NOT 0 #define COND_AND 1 #define COND_OR 2 #define COND_STREQ 3 #define COND_STRNEQ 4 #define COND_STRLT 5 #define COND_STRGTR 6 #define COND_NT 7 #define COND_OT 8 #define COND_EF 9 #define COND_EQ 10 #define COND_NE 11 #define COND_LT 12 #define COND_GT 13 #define COND_LE 14 #define COND_GE 15 #define COND_REGEX 16 #define COND_MOD 17 #define COND_MODI 18 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 */ }; /* Condition is an infix */ #define CONDF_INFIX 1 /* Condition has been loaded from library */ #define CONDF_ADDED 2 /* When autoloading, enable all features in library */ #define CONDF_AUTOALL 4 #define CONDDEF(name, flags, handler, min, max, condid) \ { NULL, name, flags, handler, min, max, condid, NULL } /* Flags for redirections */ enum { /* Mark a here-string that came from a here-document */ REDIRF_FROM_HEREDOC = 1 }; /* tree element for redirection lists */ struct redir { int type; int flags; int fd1, fd2; char *name; char *varid; char *here_terminator; char *munged_here_terminator; }; /* The number of fds space is allocated for * * each time a multio must increase in size. */ #define MULTIOUNIT 8 /* A multio is a list of fds associated with a certain fd. * * Thus if you do "foo >bar >ble", the multio for fd 1 will have * * two fds, the result of open("bar",...), and the result of * * open("ble",....). */ /* structure used for multiple i/o redirection */ /* one for each fd open */ struct multio { int ct; /* # of redirections on this fd */ int rflag; /* 0 if open for reading, 1 if open for writing */ int pipe; /* fd of pipe if ct > 1 */ int fds[MULTIOUNIT]; /* list of src/dests redirected to/from this fd */ }; /* structure for foo=bar assignments */ struct asgment { struct asgment *next; char *name; char *value; }; /* lvalue for variable assignment/expansion */ struct value { int isarr; Param pm; /* parameter node */ int flags; /* flags defined below */ int start; /* first element of array slice, or -1 */ int end; /* 1-rel last element of array slice, or -1 */ char **arr; /* cache for hash turned into array */ }; enum { VALFLAG_INV = 0x0001, /* We are performing inverse subscripting */ VALFLAG_EMPTY = 0x0002, /* Subscripted range is empty */ VALFLAG_SUBST = 0x0004 /* Substitution, so apply padding, case flags */ }; #define MAX_ARRLEN 262144 /********************************************/ /* Definitions 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 */ dev_t dev; /* device */ ino_t ino; /* indoe number */ int fd; /* file descriptor */ Wordcode map; /* pointer to header */ Wordcode addr; /* mapped region */ int len; /* length */ int count; /* reference count */ char *filename; }; /* * A note on the use of reference counts in Eprogs. * * When an Eprog is created, nref is set to -1 if the Eprog is on the * heap; then no attempt is ever made to free it. (This information is * already present in EF_HEAP; we use the redundancy for debugging * checks.) * * Otherwise, nref is initialised to 1. Calling freeprog() decrements * nref and frees the Eprog if the count is now zero. When the Eprog * is in use, we call useeprog() at the start and freeprog() at the * end to increment and decrement the reference counts. If an attempt * is made to free the Eprog from within, this will then take place * when execution is finished, typically in the call to freeeprog() * in execode(). If the Eprog was on the heap, neither useeprog() * nor freeeprog() has any effect. */ struct eprog { int flags; /* EF_* below */ int len; /* total block length */ int npats; /* Patprog cache size */ int nref; /* number of references: delete when zero */ 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 left, right; char *str; wordcode offs, aoffs; 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 WC_TRY 20 /* increment as necessary */ #define WC_COUNT 21 #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_FREE (6) /* Next bit available in integer */ #define WC_LIST_SKIP(C) (wc_data(C) >> WC_LIST_FREE) #define WCB_LIST(T,O) wc_bld(WC_LIST, ((T) | ((O) << WC_LIST_FREE))) #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_FREE (5) /* Next bit available in integer */ #define WC_SUBLIST_SKIP(C) (wc_data(C) >> WC_SUBLIST_FREE) #define WCB_SUBLIST(T,F,O) wc_bld(WC_SUBLIST, \ ((T) | (F) | ((O) << WC_SUBLIST_FREE))) #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) ((int)(wc_data(C) & REDIR_TYPE_MASK)) #define WC_REDIR_VARID(C) ((int)(wc_data(C) & REDIR_VARID_MASK)) #define WC_REDIR_FROM_HEREDOC(C) ((int)(wc_data(C) & REDIR_FROM_HEREDOC_MASK)) #define WCB_REDIR(T) wc_bld(WC_REDIR, (T)) /* Size of redir is 4 words if REDIR_VARID_MASK is set, else 3 */ #define WC_REDIR_WORDS(C) \ ((WC_REDIR_VARID(C) ? 4 : 3) + \ (WC_REDIR_FROM_HEREDOC(C) ? 2 : 0)) #define WC_ASSIGN_TYPE(C) (wc_data(C) & ((wordcode) 1)) #define WC_ASSIGN_TYPE2(C) ((wc_data(C) & ((wordcode) 2)) >> 1) #define WC_ASSIGN_SCALAR 0 #define WC_ASSIGN_ARRAY 1 #define WC_ASSIGN_NEW 0 #define WC_ASSIGN_INC 1 #define WC_ASSIGN_NUM(C) (wc_data(C) >> 2) #define WCB_ASSIGN(T,A,N) wc_bld(WC_ASSIGN, ((T) | ((A) << 1) | ((N) << 2))) #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_TRY_SKIP(C) wc_data(C) #define WCB_TRY(O) wc_bld(WC_TRY, (O)) #define WC_CASE_TYPE(C) (wc_data(C) & 7) #define WC_CASE_HEAD 0 #define WC_CASE_OR 1 #define WC_CASE_AND 2 #define WC_CASE_TESTAND 3 #define WC_CASE_FREE (3) /* Next bit available in integer */ #define WC_CASE_SKIP(C) (wc_data(C) >> WC_CASE_FREE) #define WCB_CASE(T,O) wc_bld(WC_CASE, ((T) | ((O) << WC_CASE_FREE))) #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) /********************************************/ /* Definitions for job table and job control */ /********************************************/ /* Entry in filelist linked list in job table */ struct jobfile { /* Record to be deleted or closed */ union { char *name; /* Name of file to delete */ int fd; /* File descriptor to close */ } u; /* Discriminant */ int is_fd; }; /* entry in the job table */ struct job { pid_t gleader; /* process group leader of this job */ pid_t other; /* subjob id or subshell pid */ int stat; /* see STATs below */ char *pwd; /* current working dir of shell when * * this job was spawned */ struct process *procs; /* list of processes */ struct process *auxprocs; /* auxiliary processes e.g multios */ LinkList filelist; /* list of files to delete when done */ /* elements are struct jobfile */ int stty_in_env; /* if STTY=... is present */ struct ttyinfo *ty; /* the modes specified by STTY */ }; #define STAT_CHANGED (0x0001) /* status changed and not reported */ #define STAT_STOPPED (0x0002) /* all procs stopped or exited */ #define STAT_TIMED (0x0004) /* job is being timed */ #define STAT_DONE (0x0008) /* job is done */ #define STAT_LOCKED (0x0010) /* shell is finished creating this job, */ /* may be deleted from job table */ #define STAT_NOPRINT (0x0020) /* job was killed internally, */ /* we don't want to show that */ #define STAT_INUSE (0x0040) /* this job entry is in use */ #define STAT_SUPERJOB (0x0080) /* job has a subjob */ #define STAT_SUBJOB (0x0100) /* job is a subjob */ #define STAT_WASSUPER (0x0200) /* was a super-job, sub-job needs to be */ /* deleted */ #define STAT_CURSH (0x0400) /* last command is in current shell */ #define STAT_NOSTTY (0x0800) /* the tty settings are not inherited */ /* from this job when it exits. */ #define STAT_ATTACH (0x1000) /* delay reattaching shell to tty */ #define STAT_SUBLEADER (0x2000) /* is super-job, but leader is sub-shell */ #define STAT_BUILTIN (0x4000) /* job at tail of pipeline is a builtin */ #define SP_RUNNING -1 /* fake status for jobs currently running */ struct timeinfo { long ut; /* user space time */ long st; /* system space time */ }; #define JOBTEXTSIZE 80 /* Size to initialise the job table to, and to increment it by when needed. */ #define MAXJOBS_ALLOC (50) /* node in job process lists */ #ifdef HAVE_GETRUSAGE typedef struct rusage child_times_t; #else typedef struct timeinfo child_times_t; #endif struct process { struct process *next; pid_t pid; /* process id */ char text[JOBTEXTSIZE]; /* text to print when 'jobs' is run */ int status; /* return code from waitpid/wait3() */ child_times_t ti; struct timeval bgtime; /* time job was spawned */ struct timeval endtime; /* time job exited */ }; struct execstack { struct execstack *next; pid_t list_pipe_pid; int nowait; int pline_level; int list_pipe_child; int list_pipe_job; char list_pipe_text[JOBTEXTSIZE]; int lastval; int noeval; int badcshglob; pid_t cmdoutpid; int cmdoutval; int use_cmdoutval; int trap_return; int trap_state; int trapisfunc; int traplocallevel; int noerrs; char *underscore; }; struct heredocs { struct heredocs *next; int type; int pc; char *str; }; struct dirsav { int dirfd, level; char *dirname; dev_t dev; ino_t ino; }; #define MAX_PIPESTATS 256 /*******************************/ /* Definitions for Hash Tables */ /*******************************/ typedef void *(*VFunc) _((void *)); typedef void (*FreeFunc) _((void *)); typedef unsigned (*HashFunc) _((const char *)); typedef void (*TableFunc) _((HashTable)); /* * Note that this is deliberately "char *", not "const char *", * since the AddNodeFunc is passed a pointer to a string that * will be stored and later freed. */ typedef void (*AddNodeFunc) _((HashTable, char *, void *)); typedef HashNode (*GetNodeFunc) _((HashTable, const char *)); typedef HashNode (*RemoveNodeFunc) _((HashTable, const 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)); /* hash table for standard open hashing */ struct hashtable { /* HASHTABLE DATA */ int hsize; /* size of nodes[] (number of hash values) */ int ct; /* number of elements */ HashNode *nodes; /* array of size hsize */ void *tmpdata; /* HASHTABLE METHODS */ 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 */ /* (getnode2 will ignore DISABLED flag) */ RemoveNodeFunc removenode; /* pointer to function to delete a node */ ScanFunc disablenode; /* pointer to function to disable a node */ 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 */ #endif }; /* generic hash table node */ struct hashnode { HashNode next; /* next in hash chain */ char *nam; /* hash key */ int flags; /* various flags */ }; /* The flag to disable nodes in a hash table. Currently * * you can disable builtins, shell functions, aliases and * * reserved words. */ #define DISABLED (1<<0) /* node in shell option table */ struct optname { struct hashnode node; int optno; /* option number */ }; /* node in shell reserved word hash table (reswdtab) */ struct reswd { struct hashnode node; int token; /* corresponding lexer token */ }; /* node in alias hash table (aliastab) */ struct alias { struct hashnode node; char *text; /* expansion of alias */ int inuse; /* alias is being expanded */ }; /* bit 0 of flags is the DISABLED flag */ /* is this alias global? */ #define ALIAS_GLOBAL (1<<1) /* is this an alias for suffix handling? */ #define ALIAS_SUFFIX (1<<2) /* node in command path hash table (cmdnamtab) */ struct cmdnam { struct hashnode node; union { char **name; /* full pathname for external commands */ char *cmd; /* file name for hashed commands */ } u; }; /* flag for nodes explicitly added to * * cmdnamtab with hash builtin */ #define HASHED (1<<1) /* node in shell function hash table (shfunctab) */ struct shfunc { struct hashnode node; char *filename; /* Name of file located in */ zlong lineno; /* line number in above file */ Eprog funcdef; /* function definition */ Eprog redir; /* redirections to apply */ Emulation_options sticky; /* sticky emulation definitions, if any */ }; /* 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 */ #define SFC_SUBST 7 /* used to perform substitution task */ /* tp in funcstack */ enum { FS_SOURCE, FS_FUNC, FS_EVAL }; /* node in function stack */ struct funcstack { Funcstack prev; /* previous in stack */ char *name; /* name of function/sourced file called */ char *filename; /* file function resides in */ char *caller; /* name of caller */ zlong flineno; /* line number in file */ zlong lineno; /* line offset from beginning of function */ int tp; /* type of entry: sourced file, func, eval */ }; /* 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 } /* * User-defined hook arrays */ /* Name appended to function name to get hook array */ #define HOOK_SUFFIX "_functions" /* Length of that including NUL byte */ #define HOOK_SUFFIX_LEN 11 /* node in builtin command hash table (builtintab) */ /* * Handling of options. * * Option strings are standard in that a trailing `:' indicates * a mandatory argument. In addition, `::' indicates an optional * argument which must immediately follow the option letter if it is present. * `:%' indicates an optional numeric argument which may follow * the option letter or be in the next word; the only test is * that the next character is a digit, and no actual conversion is done. */ #define MAX_OPS 128 /* Macros taking struct option * and char argument */ /* Option was set as -X */ #define OPT_MINUS(ops,c) ((ops)->ind[c] & 1) /* Option was set as +X */ #define OPT_PLUS(ops,c) ((ops)->ind[c] & 2) /* * Option was set any old how, maybe including an argument * (cheap test when we don't care). Some bits of code * expect this to be 1 or 0. */ #define OPT_ISSET(ops,c) ((ops)->ind[c] != 0) /* Option has an argument */ #define OPT_HASARG(ops,c) ((ops)->ind[c] > 3) /* The argument for the option; not safe if it doesn't have one */ #define OPT_ARG(ops,c) ((ops)->args[((ops)->ind[c] >> 2) - 1]) /* Ditto, but safely returns NULL if there is no argument. */ #define OPT_ARG_SAFE(ops,c) (OPT_HASARG(ops,c) ? OPT_ARG(ops,c) : NULL) struct options { unsigned char ind[MAX_OPS]; char **args; int argscount, argsalloc; }; /* * Handler arguments are: builtin name, null-terminated argument * list excluding command name, option structure, the funcid element from the * builtin structure. */ typedef int (*HandlerFunc) _((char *, char **, Options, int)); #define NULLBINCMD ((HandlerFunc) 0) struct builtin { struct hashnode node; HandlerFunc handlerfunc; /* pointer to function that executes this builtin */ int minargs; /* minimum number of arguments */ int maxargs; /* maximum number of arguments, or -1 for no limit */ int funcid; /* xbins (see above) for overloaded handlerfuncs */ char *optstr; /* string of legal options */ char *defopts; /* options set by default for overloaded handlerfuncs */ }; #define BUILTIN(name, flags, handler, min, max, funcid, optstr, defopts) \ { { NULL, name, flags }, handler, min, max, funcid, optstr, defopts } #define BIN_PREFIX(name, flags) \ BUILTIN(name, flags | BINF_PREFIX, NULLBINCMD, 0, 0, 0, NULL, NULL) /* builtin flags */ /* DISABLE IS DEFINED AS (1<<0) */ #define BINF_PLUSOPTS (1<<1) /* +xyz legal */ #define BINF_PRINTOPTS (1<<2) #define BINF_ADDED (1<<3) /* is in the builtins hash table */ #define BINF_MAGICEQUALS (1<<4) /* needs automatic MAGIC_EQUAL_SUBST substitution */ #define BINF_PREFIX (1<<5) #define BINF_DASH (1<<6) #define BINF_BUILTIN (1<<7) #define BINF_COMMAND (1<<8) #define BINF_EXEC (1<<9) #define BINF_NOGLOB (1<<10) #define BINF_PSPECIAL (1<<11) /* Builtin option handling */ #define BINF_SKIPINVALID (1<<12) /* Treat invalid option as argument */ #define BINF_KEEPNUM (1<<13) /* `[-+]NUM' can be an option */ #define BINF_SKIPDASH (1<<14) /* Treat `-' as argument (maybe `+') */ #define BINF_DASHDASHVALID (1<<15) /* Handle `--' even if SKIPINVALD */ #define BINF_CLEARENV (1<<16) /* new process started with cleared env */ #define BINF_AUTOALL (1<<17) /* autoload all features at once */ /* * Handles options itself. This is only useful if the option string for a * builtin with an empty option string. It is used to indicate that "--" * does not terminate options. */ #define BINF_HANDLES_OPTS (1<<18) struct module { struct hashnode node; union { void *handle; Linkedmod linked; char *alias; } u; LinkList autoloads; LinkList deps; int wrapper; }; /* We are in the process of loading the module */ #define MOD_BUSY (1<<0) /* * We are in the process of unloading the module. * Note this is not needed to indicate a module is actually * unloaded: for that, the handle (or linked pointer) is set to NULL. */ #define MOD_UNLOAD (1<<1) /* We are in the process of setting up the module */ #define MOD_SETUP (1<<2) /* Module is statically linked into the main binary */ #define MOD_LINKED (1<<3) /* Module setup has been carried out (and module has not been finished) */ #define MOD_INIT_S (1<<4) /* Module boot has been carried out (and module has not been finished) */ #define MOD_INIT_B (1<<5) /* Module record is an alias */ #define MOD_ALIAS (1<<6) typedef int (*Module_generic_func) _((void)); typedef int (*Module_void_func) _((Module)); typedef int (*Module_features_func) _((Module, char ***)); typedef int (*Module_enables_func) _((Module, int **)); struct linkedmod { char *name; Module_void_func setup; Module_features_func features; Module_enables_func enables; Module_void_func boot; Module_void_func cleanup; Module_void_func finish; }; /* * Structure combining all the concrete features available in * a module and with space for information about abstract features. */ struct features { /* List of builtins provided by the module and the size thereof */ Builtin bn_list; int bn_size; /* List of conditions provided by the module and the size thereof */ Conddef cd_list; int cd_size; /* List of math functions provided by the module and the size thereof */ MathFunc mf_list; int mf_size; /* List of parameters provided by the module and the size thereof */ Paramdef pd_list; int pd_size; /* Number of abstract features */ int n_abstract; }; /* * Structure describing enables for one feature. */ struct feature_enables { /* String feature to enable (N.B. no leading +/- allowed) */ char *str; /* Optional compiled pattern for str sans +/-, NULL for string match */ Patprog pat; }; /* 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 */ long patmlen; /* length of pure string or longest match */ int globflags; /* globbing flags to set at start */ int globend; /* globbing flags set after finish */ int flags; /* PAT_* flags */ 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 */ #define PAT_NOTSTART 0x0200 /* Start of string is not real start */ #define PAT_NOTEND 0x0400 /* End of string is not real end */ #define PAT_HAS_EXCLUDP 0x0800 /* (internal): top-level path1~path2. */ #define PAT_LCMATCHUC 0x1000 /* equivalent to setting (#l) */ /** * Indexes into the array of active pattern characters. * This must match the array zpc_chars in pattern.c. */ enum zpc_chars { /* * These characters both terminate a pattern segment and * a pure string segment. */ ZPC_SLASH, /* / active as file separator */ ZPC_NULL, /* \0 as string terminator */ ZPC_BAR, /* | for "or" */ ZPC_OUTPAR, /* ) for grouping */ ZPC_TILDE, /* ~ for exclusion (extended glob) */ ZPC_SEG_COUNT, /* No. of the above characters */ /* * These characters terminate a pure string segment. */ ZPC_INPAR = ZPC_SEG_COUNT, /* ( for grouping */ ZPC_QUEST, /* ? as wildcard */ ZPC_STAR, /* * as wildcard */ ZPC_INBRACK, /* [ for character class */ ZPC_INANG, /* < for numeric glob */ ZPC_HAT, /* ^ for exclusion (extended glob) */ ZPC_HASH, /* # for repetition (extended glob) */ ZPC_BNULLKEEP, /* Special backslashed null not removed */ /* * These characters are only valid before a parenthesis */ ZPC_NO_KSH_GLOB, ZPC_KSH_QUEST = ZPC_NO_KSH_GLOB, /* ? for ?(...) in KSH_GLOB */ ZPC_KSH_STAR, /* * for *(...) in KSH_GLOB */ ZPC_KSH_PLUS, /* + for +(...) in KSH_GLOB */ ZPC_KSH_BANG, /* ! for !(...) in KSH_GLOB */ ZPC_KSH_AT, /* @ for @(...) in KSH_GLOB */ ZPC_COUNT /* Number of special chararacters */ }; /* * Structure to save disables special characters for function scope. */ struct zpc_disables_save { struct zpc_disables_save *next; /* * Bit vector of ZPC_COUNT disabled characters. * We'll live dangerously and assumed ZPC_COUNT is no greater * than the number of bits an an unsigned int. */ unsigned int disables; }; typedef struct zpc_disables_save *Zpc_disables_save; /* * Special match types used in character classes. These * are represented as tokens, with Meta added. The character * class is represented as a metafied string, with only these * tokens special. Note that an active leading "!" or "^" for * negation is not part of the string but is flagged in the * surrounding context. * * These types are also used in character and equivalence classes * in completion matching. * * This must be kept ordered by the array colon_stuffs in pattern.c. */ /* Special value for first definition */ #define PP_FIRST 1 /* POSIX-defined types: [:alpha:] etc. */ #define PP_ALPHA 1 #define PP_ALNUM 2 #define PP_ASCII 3 #define PP_BLANK 4 #define PP_CNTRL 5 #define PP_DIGIT 6 #define PP_GRAPH 7 #define PP_LOWER 8 #define PP_PRINT 9 #define PP_PUNCT 10 #define PP_SPACE 11 #define PP_UPPER 12 #define PP_XDIGIT 13 /* Zsh additions: [:IDENT:] etc. */ #define PP_IDENT 14 #define PP_IFS 15 #define PP_IFSSPACE 16 #define PP_WORD 17 /* Special value for last definition */ #define PP_LAST 17 /* Unknown type. Not used in a valid token. */ #define PP_UNKWN 18 /* Range: token followed by the (possibly multibyte) start and end */ #define PP_RANGE 19 /* Globbing flags: lower 8 bits gives approx count */ #define GF_LCMATCHUC 0x0100 #define GF_IGNCASE 0x0200 #define GF_BACKREF 0x0400 #define GF_MATCHREF 0x0800 #define GF_MULTIBYTE 0x1000 /* Use multibyte if supported by build */ /* 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) /* standard node types for get/set/unset union in parameter */ /* * note non-standard const in pointer declaration: structures are * assumed to be read-only. */ typedef const struct gsu_scalar *GsuScalar; typedef const struct gsu_integer *GsuInteger; typedef const struct gsu_float *GsuFloat; typedef const struct gsu_array *GsuArray; typedef const struct gsu_hash *GsuHash; struct gsu_scalar { char *(*getfn) _((Param)); void (*setfn) _((Param, char *)); void (*unsetfn) _((Param, int)); }; struct gsu_integer { zlong (*getfn) _((Param)); void (*setfn) _((Param, zlong)); void (*unsetfn) _((Param, int)); }; struct gsu_float { double (*getfn) _((Param)); void (*setfn) _((Param, double)); void (*unsetfn) _((Param, int)); }; struct gsu_array { char **(*getfn) _((Param)); void (*setfn) _((Param, char **)); void (*unsetfn) _((Param, int)); }; struct gsu_hash { HashTable (*getfn) _((Param)); void (*setfn) _((Param, HashTable)); void (*unsetfn) _((Param, int)); }; /* node used in parameter hash table (paramtab) */ struct param { struct hashnode node; /* the value of this parameter */ union { void *data; /* used by special parameter functions */ char **arr; /* value if declared array (PM_ARRAY) */ char *str; /* value if declared string (PM_SCALAR) */ zlong val; /* value if declared integer (PM_INTEGER) */ zlong *valptr; /* value if special pointer to integer */ double dval; /* value if declared float (PM_EFLOAT|PM_FFLOAT) */ HashTable hash; /* value if declared assoc (PM_HASHED) */ } u; /* * get/set/unset methods. * * Unlike the data union, this points to a single instance * for every type (although there are special types, e.g. * tied arrays have a different gsu_scalar struct from the * normal one). It's really a poor man's vtable. */ union { GsuScalar s; GsuInteger i; GsuFloat f; GsuArray a; GsuHash h; } gsu; int base; /* output base or floating point prec */ int width; /* field width */ char *env; /* location in environment, if exported */ char *ename; /* name of corresponding environment var */ Param old; /* old struct for use with local */ int level; /* if (old != NULL), level of localness */ }; /* structure stored in struct param's u.data by tied arrays */ struct tieddata { char ***arrptr; /* pointer to corresponding array */ int joinchar; /* character used to join arrays */ }; /* flags for parameters */ /* parameter types */ #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_EFLOAT|PM_FFLOAT|PM_ARRAY|PM_HASHED)) #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<<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_HIDEVAL (1<<15) /* Value not shown in `typeset' commands */ #define PM_TIED (1<<16) /* array tied to colon-path or v.v. */ #define PM_TAGGED_LOCAL (1<<16) /* (function): non-recursive PM_TAGGED */ #define PM_KSHSTORED (1<<17) /* function stored in ksh form */ #define PM_ZSHSTORED (1<<18) /* function stored in zsh form */ /* Remaining flags do not correspond directly to command line arguments */ #define PM_LOCAL (1<<21) /* this parameter will be made local */ #define PM_SPECIAL (1<<22) /* special builtin parameter */ #define PM_DONTIMPORT (1<<23) /* do not import this variable */ #define PM_RESTRICTED (1<<24) /* cannot be changed in restricted mode */ #define PM_UNSET (1<<25) /* has null value */ #define PM_REMOVABLE (1<<26) /* special can be removed from paramtab */ #define PM_AUTOLOAD (1<<27) /* autoloaded from module */ #define PM_NORESTORE (1<<28) /* do not restore value of local special */ #define PM_AUTOALL (1<<28) /* autoload all features in module * when loading: valid only if PM_AUTOLOAD * is also present. */ #define PM_HASHELEM (1<<29) /* is a hash-element */ #define PM_NAMEDDIR (1<<30) /* has a corresponding nameddirtab entry */ /* The option string corresponds to the first of the variables above */ #define TYPESET_OPTSTR "aiEFALRZlurtxUhHTkz" /* 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) /* Return value includes hash values */ #define SCANPM_WANTKEYS (1<<1) /* Return value includes hash keys */ #define SCANPM_WANTINDEX (1<<2) /* Return value includes array index */ #define SCANPM_MATCHKEY (1<<3) /* Subscript matched against key */ #define SCANPM_MATCHVAL (1<<4) /* Subscript matched against value */ #define SCANPM_MATCHMANY (1<<5) /* Subscript matched repeatedly, return all */ #define SCANPM_ASSIGNING (1<<6) /* Assigning whole array/hash */ #define SCANPM_KEYMATCH (1<<7) /* keys of hash treated as patterns */ #define SCANPM_DQUOTED (1<<8) /* substitution was double-quoted * (only used for testing early end of * subscript) */ #define SCANPM_ARRONLY (1<<9) /* value is array but we don't * necessarily want to match multiple * elements */ #define SCANPM_ISVAR_AT ((-1)<<15) /* "$foo[@]"-style substitution * 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 beginning, % 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 */ #define SUB_RETFAIL 0x0800 /* return status 0 if no match */ #define SUB_START 0x1000 /* force match at start with SUB_END * and no SUB_SUBSTR */ #define SUB_LIST 0x2000 /* no substitution, return list of matches */ /* * Structure recording multiple matches inside a test string. * b and e are the beginning and end of the match. * replstr is the replacement string, if any. */ struct repldata { int b, e; /* beginning and end of chunk to replace */ char *replstr; /* replacement string to use */ }; typedef struct repldata *Repldata; /* * Flags to zshtokenize. */ enum { /* Do glob substitution */ ZSHTOK_SUBST = 0x0001, /* Use sh-style globbing */ ZSHTOK_SHGLOB = 0x0002 }; /* Flags as the second argument to prefork */ /* argument handled like typeset foo=bar */ #define PREFORK_TYPESET 0x01 /* argument handled like the RHS of foo=bar */ #define PREFORK_ASSIGN 0x02 /* single word substitution */ #define PREFORK_SINGLE 0x04 /* explicitly split nested substitution */ #define PREFORK_SPLIT 0x08 /* SHWORDSPLIT in parameter expn */ #define PREFORK_SHWORDSPLIT 0x10 /* SHWORDSPLIT forced off in nested subst */ #define PREFORK_NOSHWORDSPLIT 0x20 /* * Structure for adding parameters in a module. * The flags should declare the type; note PM_SCALAR is zero. * * Special hashes are recognized by getnfn so the PM_HASHED * is optional. These get slightly non-standard attention: * the function createspecialhash is used to create them. * * The get/set/unset attribute may be NULL; in that case the * parameter is assigned methods suitable for handling the * tie variable var, if that is not NULL, else standard methods. * * pm is set when the parameter is added to the parameter table * and serves as a flag that the parameter has been added. */ struct paramdef { char *name; int flags; void *var; /* tied internal variable, if any */ const void *gsu; /* get/set/unset structure, if special */ GetNodeFunc getnfn; /* function to get node, if special hash */ ScanTabFunc scantfn; /* function to scan table, if special hash */ Param pm; /* structure inserted into param table */ }; /* * Shorthand for common uses of adding parameters, with no special * hash properties. */ #define PARAMDEF(name, flags, var, gsu) \ { name, flags, (void *) var, (void *) gsu, \ NULL, NULL, NULL \ } /* * Note that the following definitions are appropriate for defining * parameters that reference a variable (var). Hence the get/set/unset * methods used will assume var needs dereferencing to get the value. */ #define INTPARAMDEF(name, var) \ { name, PM_INTEGER, (void *) var, NULL, NULL, NULL, NULL } #define STRPARAMDEF(name, var) \ { name, PM_SCALAR, (void *) var, NULL, NULL, NULL, NULL } #define ARRPARAMDEF(name, var) \ { name, PM_ARRAY, (void *) var, NULL, NULL, NULL, NULL } /* * The following is appropriate for a module function that behaves * in a special fashion. Parameters used in a module that don't * have special behaviour shouldn't be declared in a table but * should just be added with the standard parameter functions. * * These parameters are not marked as removable, since they * shouldn't be loaded as local parameters, unlike the special * Zle parameters that are added and removed on each call to Zle. * We add the PM_REMOVABLE flag when removing the feature corresponding * to the parameter. */ #define SPECIALPMDEF(name, flags, gsufn, getfn, scanfn) \ { name, flags | PM_SPECIAL | PM_HIDE | PM_HIDEVAL, \ NULL, gsufn, getfn, scanfn, NULL } #define setsparam(S,V) assignsparam(S,V,0) #define setaparam(S,V) assignaparam(S,V,0) /* * Flags for assignsparam and assignaparam. */ enum { ASSPM_AUGMENT = 1 << 0, ASSPM_WARN_CREATE = 1 << 1, ASSPM_ENV_IMPORT = 1 << 2 }; /* node for named directory hash table (nameddirtab) */ struct nameddir { struct hashnode node; char *dir; /* the directory in full */ int diff; /* strlen(.dir) - strlen(.nam) */ }; /* 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) */ /* Storage for single group/name mapping */ typedef struct { /* Name of group */ char *name; /* Group identifier */ gid_t gid; } groupmap; typedef groupmap *Groupmap; /* Storage for a set of group/name mappings */ typedef struct { /* The set of name to gid mappings */ Groupmap array; /* A count of the valid entries in groupmap. */ int num; } groupset; typedef groupset *Groupset; /* 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) #define PRINT_INCLUDEVALUE (1<<4) #define PRINT_TYPESET (1<<5) /* flags for printing for the whence builtin */ #define PRINT_WHENCE_CSH (1<<6) #define PRINT_WHENCE_VERBOSE (1<<7) #define PRINT_WHENCE_SIMPLE (1<<8) #define PRINT_WHENCE_FUNCDEF (1<<9) #define PRINT_WHENCE_WORD (1<<10) /* Return values from loop() */ enum loop_return { /* Loop executed OK */ LOOP_OK, /* Loop executed no code */ LOOP_EMPTY, /* Loop encountered an error */ LOOP_ERROR }; /* Return values from source() */ enum source_return { /* Source ran OK */ SOURCE_OK = 0, /* File not found */ SOURCE_NOT_FOUND = 1, /* Internal error sourcing file */ SOURCE_ERROR = 2 }; /***********************************/ /* Definitions for history control */ /***********************************/ /* history entry */ struct histent { struct hashnode node; Histent up; /* previous line (moving upward) */ Histent down; /* next line (moving downward) */ char *zle_text; /* the edited history line, * a metafied, NULL-terminated string, * i.e the same format as the original * entry */ 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 */ zlong histnum; /* A sequential history number */ }; #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 HIST_TMPSTORE 0x00000020 /* Kill when user enters another cmd */ #define HIST_NOWRITE 0x00000040 /* Keep internally but don't write */ #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 */ #define STOPHIST (stophist += 4); #define ALLOWHIST (stophist -= 4); #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_NO_REWRITE 0x0020 #define HFILE_USE_OPTIONS 0x8000 /* * Flags argument to bufferwords() used * also by lexflags variable. */ /* * Kick the lexer into special string-analysis * mode without parsing. Any bit set in * the flags has this effect, but this * has otherwise all the default effects. */ #define LEXFLAGS_ACTIVE 0x0001 /* * Being used from zle. This is slightly more intrusive * (=> grotesquely non-modular) than use from within * the main shell, so it's a separate flag. */ #define LEXFLAGS_ZLE 0x0002 /* * Parse comments and treat each comment as a single string */ #define LEXFLAGS_COMMENTS_KEEP 0x0004 /* * Parse comments and strip them. */ #define LEXFLAGS_COMMENTS_STRIP 0x0008 /* * Either of the above */ #define LEXFLAGS_COMMENTS (LEXFLAGS_COMMENTS_KEEP|LEXFLAGS_COMMENTS_STRIP) /* * Treat newlines as whitespace */ #define LEXFLAGS_NEWLINE 0x0010 /******************************************/ /* Definitions for programable completion */ /******************************************/ /* Nothing special. */ #define IN_NOTHING 0 /* In command position. */ #define IN_CMD 1 /* In a mathematical environment. */ #define IN_MATH 2 /* In a condition. */ #define IN_COND 3 /* In a parameter assignment (e.g. `foo=bar'). */ #define IN_ENV 4 /* In a parameter name in an assignment. */ #define IN_PAR 5 /******************************/ /* Definition for zsh options */ /******************************/ /* Possible values of emulation */ #define EMULATE_CSH (1<<1) /* C shell */ #define EMULATE_KSH (1<<2) /* Korn shell */ #define EMULATE_SH (1<<3) /* Bourne shell */ #define EMULATE_ZSH (1<<4) /* `native' mode */ /* Test for a shell emulation. Use this rather than emulation directly. */ #define EMULATION(X) (emulation & (X)) /* Return only base shell emulation field. */ #define SHELL_EMULATION() (emulation & ((1<<5)-1)) /* Additional flags */ #define EMULATE_FULLY (1<<5) /* "emulate -R" in effect */ /* * Higher bits are used in options.c, record lowest unused bit... */ #define EMULATE_UNUSED (1<<6) /* option indices */ enum { OPT_INVALID, ALIASESOPT, ALLEXPORT, ALWAYSLASTPROMPT, ALWAYSTOEND, APPENDHISTORY, AUTOCD, AUTOCONTINUE, AUTOLIST, AUTOMENU, AUTONAMEDIRS, AUTOPARAMKEYS, AUTOPARAMSLASH, AUTOPUSHD, AUTOREMOVESLASH, AUTORESUME, BADPATTERN, BANGHIST, BAREGLOBQUAL, BASHAUTOLIST, BASHREMATCH, BEEP, BGNICE, BRACECCL, BSDECHO, CASEGLOB, CASEMATCH, CBASES, CDABLEVARS, CHASEDOTS, CHASELINKS, CHECKJOBS, CLOBBER, COMBININGCHARS, COMPLETEALIASES, COMPLETEINWORD, CORRECT, CORRECTALL, CONTINUEONERROR, CPRECEDENCES, CSHJUNKIEHISTORY, CSHJUNKIELOOPS, CSHJUNKIEQUOTES, CSHNULLCMD, CSHNULLGLOB, DEBUGBEFORECMD, EMACSMODE, EQUALS, ERREXIT, ERRRETURN, EXECOPT, EXTENDEDGLOB, EXTENDEDHISTORY, EVALLINENO, FLOWCONTROL, FORCEFLOAT, FUNCTIONARGZERO, GLOBOPT, GLOBALEXPORT, GLOBALRCS, GLOBASSIGN, GLOBCOMPLETE, GLOBDOTS, GLOBSUBST, HASHCMDS, HASHDIRS, HASHEXECUTABLESONLY, HASHLISTALL, HISTALLOWCLOBBER, HISTBEEP, HISTEXPIREDUPSFIRST, HISTFCNTLLOCK, HISTFINDNODUPS, HISTIGNOREALLDUPS, HISTIGNOREDUPS, HISTIGNORESPACE, HISTLEXWORDS, HISTNOFUNCTIONS, HISTNOSTORE, HISTREDUCEBLANKS, HISTSAVEBYCOPY, HISTSAVENODUPS, HISTSUBSTPATTERN, HISTVERIFY, HUP, IGNOREBRACES, IGNORECLOSEBRACES, IGNOREEOF, INCAPPENDHISTORY, INCAPPENDHISTORYTIME, INTERACTIVE, INTERACTIVECOMMENTS, KSHARRAYS, KSHAUTOLOAD, KSHGLOB, KSHOPTIONPRINT, KSHTYPESET, KSHZEROSUBSCRIPT, LISTAMBIGUOUS, LISTBEEP, LISTPACKED, LISTROWSFIRST, LISTTYPES, LOCALLOOPS, LOCALOPTIONS, LOCALPATTERNS, LOCALTRAPS, LOGINSHELL, LONGLISTJOBS, MAGICEQUALSUBST, MAILWARNING, MARKDIRS, MENUCOMPLETE, MONITOR, MULTIBYTE, MULTIFUNCDEF, MULTIOS, NOMATCH, NOTIFY, NULLGLOB, NUMERICGLOBSORT, OCTALZEROES, OVERSTRIKE, PATHDIRS, PATHSCRIPT, PIPEFAIL, POSIXALIASES, POSIXARGZERO, POSIXBUILTINS, POSIXCD, POSIXIDENTIFIERS, POSIXJOBS, POSIXSTRINGS, POSIXTRAPS, PRINTEIGHTBIT, PRINTEXITVALUE, PRIVILEGED, PROMPTBANG, PROMPTCR, PROMPTPERCENT, PROMPTSP, PROMPTSUBST, PUSHDIGNOREDUPS, PUSHDMINUS, PUSHDSILENT, PUSHDTOHOME, RCEXPANDPARAM, RCQUOTES, RCS, RECEXACT, REMATCHPCRE, RESTRICTED, RMSTARSILENT, RMSTARWAIT, SHAREHISTORY, SHFILEEXPANSION, SHGLOB, SHINSTDIN, SHNULLCMD, SHOPTIONLETTERS, SHORTLOOPS, SHWORDSPLIT, SINGLECOMMAND, SINGLELINEZLE, SOURCETRACE, SUNKEYBOARDHACK, TRANSIENTRPROMPT, TRAPSASYNC, TYPESETSILENT, UNSET, VERBOSE, VIMODE, WARNCREATEGLOBAL, XTRACE, USEZLE, DVORAK, OPT_SIZE }; /* * Size required to fit an option number. * If OPT_SIZE goes above 256 this will need to expand. */ typedef unsigned char OptIndex; #undef isset #define isset(X) (opts[X]) #define unset(X) (!opts[X]) #define interact (isset(INTERACTIVE)) #define jobbing (isset(MONITOR)) #define islogin (isset(LOGINSHELL)) /* * Record of emulation and options that need to be set * for a full "emulate". */ struct emulation_options { /* The emulation itself */ int emulation; /* The number of options in on_opts. */ int n_on_opts; /* The number of options in off_opts. */ int n_off_opts; /* * Array of options to be turned on. * Only options specified explicitly in the emulate command * are recorded. Null if n_on_opts is zero. */ OptIndex *on_opts; /* Array of options to be turned off, similar. */ OptIndex *off_opts; }; /***********************************************/ /* Definitions for terminal and display control */ /***********************************************/ /* tty state structure */ struct ttyinfo { #ifdef HAVE_TERMIOS_H struct termios tio; #else # ifdef HAVE_TERMIO_H struct termio tio; # else struct sgttyb sgttyb; int lmodes; struct tchars tchars; struct ltchars ltchars; # endif #endif #ifdef TIOCGWINSZ struct winsize winsize; #endif }; #ifndef __INTERIX /* defines for whether tabs expand to spaces */ #if defined(HAVE_TERMIOS_H) || defined(HAVE_TERMIO_H) #define SGTTYFLAG shttyinfo.tio.c_oflag #else /* we're using sgtty */ #define SGTTYFLAG shttyinfo.sgttyb.sg_flags #endif # ifdef TAB3 #define SGTABTYPE TAB3 # else # ifdef OXTABS #define SGTABTYPE OXTABS # else # ifdef XTABS #define SGTABTYPE XTABS # endif # endif # endif #endif /* flags for termflags */ #define TERM_BAD 0x01 /* terminal has extremely basic capabilities */ #define TERM_UNKNOWN 0x02 /* unknown terminal type */ #define TERM_NOUP 0x04 /* terminal has no up capability */ #define TERM_SHORT 0x08 /* terminal is < 3 lines high */ #define TERM_NARROW 0x10 /* terminal is < 3 columns wide */ /* interesting termcap strings */ #define TCCLEARSCREEN 0 #define TCLEFT 1 #define TCMULTLEFT 2 #define TCRIGHT 3 #define TCMULTRIGHT 4 #define TCUP 5 #define TCMULTUP 6 #define TCDOWN 7 #define TCMULTDOWN 8 #define TCDEL 9 #define TCMULTDEL 10 #define TCINS 11 #define TCMULTINS 12 #define TCCLEAREOD 13 #define TCCLEAREOL 14 #define TCINSLINE 15 #define TCDELLINE 16 #define TCNEXTTAB 17 #define TCBOLDFACEBEG 18 #define TCSTANDOUTBEG 19 #define TCUNDERLINEBEG 20 #define TCALLATTRSOFF 21 #define TCSTANDOUTEND 22 #define TCUNDERLINEEND 23 #define TCHORIZPOS 24 #define TCUPCURSOR 25 #define TCDOWNCURSOR 26 #define TCLEFTCURSOR 27 #define TCRIGHTCURSOR 28 #define TCSAVECURSOR 29 #define TCRESTRCURSOR 30 #define TCBACKSPACE 31 #define TCFGCOLOUR 32 #define TCBGCOLOUR 33 #define TC_COUNT 34 #define tccan(X) (tclen[X]) /* * Text attributes for displaying in ZLE */ #define TXTBOLDFACE 0x0001 #define TXTSTANDOUT 0x0002 #define TXTUNDERLINE 0x0004 #define TXTFGCOLOUR 0x0008 #define TXTBGCOLOUR 0x0010 #define TXT_ATTR_ON_MASK 0x001F #define txtisset(X) (txtattrmask & (X)) #define txtset(X) (txtattrmask |= (X)) #define txtunset(X) (txtattrmask &= ~(X)) #define TXTNOBOLDFACE 0x0020 #define TXTNOSTANDOUT 0x0040 #define TXTNOUNDERLINE 0x0080 #define TXTNOFGCOLOUR 0x0100 #define TXTNOBGCOLOUR 0x0200 #define TXT_ATTR_OFF_MASK 0x03E0 /* Bits to shift off right to get on */ #define TXT_ATTR_OFF_ON_SHIFT 5 #define TXT_ATTR_OFF_FROM_ON(attr) \ (((attr) & TXT_ATTR_ON_MASK) << TXT_ATTR_OFF_ON_SHIFT) #define TXT_ATTR_ON_FROM_OFF(attr) \ (((attr) & TXT_ATTR_OFF_MASK) >> TXT_ATTR_OFF_ON_SHIFT) /* * Indicates to zle_refresh.c that the character entry is an * index into the list of multiword symbols. */ #define TXT_MULTIWORD_MASK 0x0400 /* Mask for colour to use in foreground */ #define TXT_ATTR_FG_COL_MASK 0x000FF000 /* Bits to shift the foreground colour */ #define TXT_ATTR_FG_COL_SHIFT (12) /* Mask for colour to use in background */ #define TXT_ATTR_BG_COL_MASK 0x0FF00000 /* Bits to shift the background colour */ #define TXT_ATTR_BG_COL_SHIFT (20) /* Flag to use termcap AF sequence to set colour, if available */ #define TXT_ATTR_FG_TERMCAP 0x10000000 /* Flag to use termcap AB sequence to set colour, if available */ #define TXT_ATTR_BG_TERMCAP 0x20000000 /* Things to turn on, including values for the colour elements */ #define TXT_ATTR_ON_VALUES_MASK \ (TXT_ATTR_ON_MASK|TXT_ATTR_FG_COL_MASK|TXT_ATTR_BG_COL_MASK|\ TXT_ATTR_FG_TERMCAP|TXT_ATTR_BG_TERMCAP) /* Mask out everything to do with setting a foreground colour */ #define TXT_ATTR_FG_ON_MASK \ (TXTFGCOLOUR|TXT_ATTR_FG_COL_MASK|TXT_ATTR_FG_TERMCAP) /* Mask out everything to do with setting a background colour */ #define TXT_ATTR_BG_ON_MASK \ (TXTBGCOLOUR|TXT_ATTR_BG_COL_MASK|TXT_ATTR_BG_TERMCAP) /* Mask out everything to do with activating colours */ #define TXT_ATTR_COLOUR_ON_MASK \ (TXT_ATTR_FG_ON_MASK|TXT_ATTR_BG_ON_MASK) #define txtchangeisset(T,X) ((T) & (X)) #define txtchangeget(T,A) (((T) & A ## _MASK) >> A ## _SHIFT) #define txtchangeset(T, X, Y) ((void)(T && (*T |= (X), *T &= ~(Y)))) /* * For outputting sequences to change colour: specify foreground * or background. */ #define COL_SEQ_FG (0) #define COL_SEQ_BG (1) #define COL_SEQ_COUNT (2) /* * Flags to testcap() and set_colour_attribute (which currently only * handles TSC_PROMPT). */ enum { /* Raw output: use stdout rather than shout */ TSC_RAW = 0x0001, /* Output to current prompt buffer: only used when assembling prompt */ TSC_PROMPT = 0x0002, /* Mask to get the output mode */ TSC_OUTPUT_MASK = 0x0003, /* Change needs reset of other attributes */ TSC_DIRTY = 0x0004 }; /****************************************/ /* Definitions for the %_ prompt escape */ /****************************************/ #define CMDSTACKSZ 256 #define CS_FOR 0 #define CS_WHILE 1 #define CS_REPEAT 2 #define CS_SELECT 3 #define CS_UNTIL 4 #define CS_IF 5 #define CS_IFTHEN 6 #define CS_ELSE 7 #define CS_ELIF 8 #define CS_MATH 9 #define CS_COND 10 #define CS_CMDOR 11 #define CS_CMDAND 12 #define CS_PIPE 13 #define CS_ERRPIPE 14 #define CS_FOREACH 15 #define CS_CASE 16 #define CS_FUNCDEF 17 #define CS_SUBSH 18 #define CS_CURSH 19 #define CS_ARRAY 20 #define CS_QUOTE 21 #define CS_DQUOTE 22 #define CS_BQUOTE 23 #define CS_CMDSUBST 24 #define CS_MATHSUBST 25 #define CS_ELIFTHEN 26 #define CS_HEREDOC 27 #define CS_HEREDOCD 28 #define CS_BRACE 29 #define CS_BRACEPAR 30 #define CS_ALWAYS 31 /* Increment as necessary */ #define CS_COUNT 32 /********************* * Memory management * *********************/ /* * A Heapid is a type for identifying, uniquely up to the point where * the count of new identifiers wraps. all heaps that are or * (importantly) have been valid. Each valid heap is given an * identifier, and every time we push a heap we save the old identifier * and give the heap a new identifier so that when the heap is popped * or freed we can spot anything using invalid memory from the popped * heap. * * We could make this unsigned long long if we wanted a big range. */ typedef unsigned int Heapid; #ifdef ZSH_HEAP_DEBUG /* printf format specifier corresponding to Heapid */ #define HEAPID_FMT "%x" /* Marker that memory is permanently allocated */ #define HEAPID_PERMANENT (UINT_MAX) /* * Heap debug verbosity. * Bits to be 'or'ed into the variable also called heap_debug_verbosity. */ enum heap_debug_verbosity { /* Report when we push a heap */ HDV_PUSH = 0x01, /* Report when we pop a heap */ HDV_POP = 0x02, /* Report when we create a new heap from which to allocate */ HDV_CREATE = 0x04, /* Report every time we free a complete heap */ HDV_FREE = 0x08, /* Report when we temporarily install a new set of heaps */ HDV_NEW = 0x10, /* Report when we restore an old set of heaps */ HDV_OLD = 0x20, /* Report when we temporarily switch heaps */ HDV_SWITCH = 0x40, /* * Report every time we allocate memory from the heap. * This is very verbose, and arguably not very useful: we * would expect to allocate memory from a heap we create. * For much debugging heap_debug_verbosity = 0x7f should be sufficient. */ HDV_ALLOC = 0x80 }; #define HEAP_ERROR(heap_id) \ fprintf(stderr, "%s:%d: HEAP DEBUG: invalid heap: " HEAPID_FMT ".\n", \ __FILE__, __LINE__, heap_id) #endif /* heappush saves the current heap state using this structure */ struct heapstack { struct heapstack *next; /* next one in list for this heap */ size_t used; #ifdef ZSH_HEAP_DEBUG Heapid heap_id; #endif }; /* A zsh heap. */ 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 */ #ifdef ZSH_HEAP_DEBUG unsigned int heap_id; #endif /* 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 NEWHEAPS(h) do { Heap _switch_oldheaps = h = new_heaps(); do # define OLDHEAPS while (0); old_heaps(_switch_oldheaps); } while (0); # define SWITCHHEAPS(o, h) do { o = switch_heaps(h); do # define SWITCHBACKHEAPS(o) while (0); switch_heaps(o); } while (0); /****************/ /* Debug macros */ /****************/ #ifdef DEBUG #define STRINGIFY_LITERAL(x) # x #define STRINGIFY(x) STRINGIFY_LITERAL(x) #define ERRMSG(x) (__FILE__ ":" STRINGIFY(__LINE__) ": " x) # define DPUTS(X,Y) if (!(X)) {;} else dputs(ERRMSG(Y)) # define DPUTS1(X,Y,Z1) if (!(X)) {;} else dputs(ERRMSG(Y), Z1) # define DPUTS2(X,Y,Z1,Z2) if (!(X)) {;} else dputs(ERRMSG(Y), Z1, Z2) # define DPUTS3(X,Y,Z1,Z2,Z3) if (!(X)) {;} else dputs(ERRMSG(Y), Z1, Z2, Z3) #else # define DPUTS(X,Y) # define DPUTS1(X,Y,Z1) # define DPUTS2(X,Y,Z1,Z2) # define DPUTS3(X,Y,Z1,Z2,Z3) #endif /**************************/ /* Signal handling macros */ /**************************/ /* These used in the sigtrapped[] array */ #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_ALIAS (1<<3) /* Trap is stored under an alias */ #define ZSIG_SHIFT 4 /* * State of traps, stored in trap_state. */ enum trap_state { /* Traps are not active; trap_return is not useful. */ TRAP_STATE_INACTIVE, /* * Traps are set but haven't triggered; trap_return gives * minus function depth. */ TRAP_STATE_PRIMED, /* * Trap has triggered to force a return; trap_return givens * return value. */ TRAP_STATE_FORCE_RETURN }; #define IN_EVAL_TRAP() \ (intrap && !trapisfunc && traplocallevel == locallevel) /* * Bits in the errflag variable. */ enum errflag_bits { /* * Standard internal error bit. */ ERRFLAG_ERROR = 1, /* * User interrupt. */ ERRFLAG_INT = 2 }; /***********/ /* Sorting */ /***********/ typedef int (*CompareFn) _((const void *, const void *)); enum { SORTIT_ANYOLDHOW = 0, /* Defaults */ SORTIT_IGNORING_CASE = 1, SORTIT_NUMERICALLY = 2, SORTIT_BACKWARDS = 4, /* * Ignore backslashes that quote another character---which may * be another backslash; the second backslash is active. */ SORTIT_IGNORING_BACKSLASHES = 8, /* * Ignored by strmetasort(); used by paramsubst() to indicate * there is some sorting to do. */ SORTIT_SOMEHOW = 16, }; /* * Element of array passed to qsort(). */ struct sortelt { /* The original string. */ char *orig; /* The string used for comparison. */ const char *cmp; /* * The length of the string if passed down to the sort algorithm. * Used to sort the lengths together with the strings. */ int origlen; /* * The length of the string, if needed, else -1. * The length is only needed if there are embededded nulls. */ int len; }; typedef struct sortelt *SortElt; /*********************************************************/ /* Structures to save and restore for individual modules */ /*********************************************************/ /* History */ struct hist_stack { int histactive; int histdone; int stophist; int hlinesz; char *hline; char *hptr; short *chwords; int chwordlen; int chwordpos; int (*hgetc) _((void)); void (*hungetc) _((int)); void (*hwaddc) _((int)); void (*hwbegin) _((int)); void (*hwend) _((void)); void (*addtoline) _((int)); unsigned char *cstack; int csp; }; /* * State of a lexical token buffer. * * It would be neater to include the pointer to the start of the buffer, * however the current code structure means that the standard instance * of this, tokstr, is visible in lots of places, so that's not * convenient. */ struct lexbufstate { /* * Next character to be added. * Set to NULL when the buffer is to be visible from elsewhere. */ char *ptr; /* Allocated buffer size */ int siz; /* Length in use */ int len; }; /* Lexical analyser */ struct lex_stack { int dbparens; int isfirstln; int isfirstch; int lexflags; enum lextok tok; char *tokstr; char *zshlextext; struct lexbufstate lexbuf; int lex_add_raw; char *tokstr_raw; struct lexbufstate lexbuf_raw; int lexstop; zlong toklineno; }; /* Parser */ struct parse_stack { struct heredocs *hdocs; int incmdpos; int aliasspaceflag; int incond; int inredir; int incasepat; int isnewlin; int infor; int eclen, ecused, ecnpats; Wordcode ecbuf; Eccstr ecstrs; int ecsoffs, ecssub, ecnfunc; }; /************************/ /* Flags to casemodifiy */ /************************/ enum { CASMOD_NONE, /* dummy for tests */ CASMOD_UPPER, CASMOD_LOWER, CASMOD_CAPS }; /*******************************************/ /* Flags to third argument of getkeystring */ /*******************************************/ /* * By default handles some subset of \-escapes. The following bits * turn on extra features. */ enum { /* * Handle octal where the first digit is non-zero e.g. \3, \33, \333 * Otherwise \0333 etc. is handled, i.e. one of \0123 or \123 will * work, but not both. */ GETKEY_OCTAL_ESC = (1 << 0), /* * Handle Emacs-like key sequences \C-x etc. * Also treat \E like \e and use backslashes to escape the * next character if not special, i.e. do all the things we * don't do with the echo builtin. */ GETKEY_EMACS = (1 << 1), /* Handle ^X etc. */ GETKEY_CTRL = (1 << 2), /* Handle \c (uses misc arg to getkeystring()) */ GETKEY_BACKSLASH_C = (1 << 3), /* Do $'...' quoting (len arg to getkeystring() not used) */ GETKEY_DOLLAR_QUOTE = (1 << 4), /* Handle \- (uses misc arg to getkeystring()) */ GETKEY_BACKSLASH_MINUS = (1 << 5), /* Parse only one character (len arg to getkeystring() not used) */ GETKEY_SINGLE_CHAR = (1 << 6), /* * If beyond offset in misc arg, add 1 to it for each character removed. * Yes, I know that doesn't seem to make much sense. * It's for use in completion, comprenez? */ GETKEY_UPDATE_OFFSET = (1 << 7), /* * When replacing numeric escapes for printf format strings, % -> %% */ GETKEY_PRINTF_PERCENT = (1 << 8) }; /* * Standard combinations used within the shell. * Note GETKEYS_... instead of GETKEY_...: this is important in some cases. */ /* echo builtin */ #define GETKEYS_ECHO (GETKEY_BACKSLASH_C) /* printf format string: \123 -> S, \0123 -> NL 3, \045 -> %% */ #define GETKEYS_PRINTF_FMT \ (GETKEY_OCTAL_ESC|GETKEY_BACKSLASH_C|GETKEY_PRINTF_PERCENT) /* printf argument: \123 -> \123, \0123 -> S */ #define GETKEYS_PRINTF_ARG (GETKEY_BACKSLASH_C) /* Full print without -e */ #define GETKEYS_PRINT (GETKEY_OCTAL_ESC|GETKEY_BACKSLASH_C|GETKEY_EMACS) /* bindkey */ #define GETKEYS_BINDKEY (GETKEY_OCTAL_ESC|GETKEY_EMACS|GETKEY_CTRL) /* $'...' */ #define GETKEYS_DOLLARS_QUOTE (GETKEY_OCTAL_ESC|GETKEY_EMACS|GETKEY_DOLLAR_QUOTE) /* Single character for math processing */ #define GETKEYS_MATH \ (GETKEY_OCTAL_ESC|GETKEY_EMACS|GETKEY_CTRL|GETKEY_SINGLE_CHAR) /* Used to process separators etc. with print-style escapes */ #define GETKEYS_SEP (GETKEY_OCTAL_ESC|GETKEY_EMACS) /* Used for suffix removal */ #define GETKEYS_SUFFIX \ (GETKEY_OCTAL_ESC|GETKEY_EMACS|GETKEY_CTRL|GETKEY_BACKSLASH_MINUS) /**********************************/ /* 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 */ #define ZLRF_IGNOREEOF 0x04 /* Ignore an EOF from the keyboard */ /***************************/ /* Context of zleread call */ /***************************/ enum { ZLCON_LINE_START, /* Command line at PS1 */ ZLCON_LINE_CONT, /* Command line at PS2 */ ZLCON_SELECT, /* Select loop */ ZLCON_VARED /* Vared command */ }; /****************/ /* Entry points */ /****************/ /* compctl entry point pointers */ typedef int (*CompctlReadFn) _((char *, char **, Options, char *)); /* ZLE entry point pointer */ typedef char * (*ZleEntryPoint)(int cmd, va_list ap); /* Commands to pass to entry point */ enum { ZLE_CMD_GET_LINE, ZLE_CMD_READ, ZLE_CMD_ADD_TO_LINE, ZLE_CMD_TRASH, ZLE_CMD_RESET_PROMPT, ZLE_CMD_REFRESH, ZLE_CMD_SET_KEYMAP, ZLE_CMD_GET_KEY, ZLE_CMD_SET_HIST_LINE }; /***************************************/ /* Hooks in core. */ /***************************************/ #define EXITHOOK (zshhooks + 0) #define BEFORETRAPHOOK (zshhooks + 1) #define AFTERTRAPHOOK (zshhooks + 2) #ifdef MULTIBYTE_SUPPORT #define nicezputs(str, outs) (void)mb_niceformat((str), (outs), NULL, 0) #define MB_METACHARINIT() mb_metacharinit() typedef wint_t convchar_t; #define MB_METACHARLENCONV(str, cp) mb_metacharlenconv((str), (cp)) #define MB_METACHARLEN(str) mb_metacharlenconv(str, NULL) #define MB_METASTRLEN(str) mb_metastrlen(str, 0) #define MB_METASTRWIDTH(str) mb_metastrlen(str, 1) #define MB_METASTRLEN2(str, widthp) mb_metastrlen(str, widthp) /* * We replace broken implementations with one that uses Unicode * characters directly as wide characters. In principle this is only * likely to work if __STDC_ISO_10646__ is defined, since that's pretty * much what the definition tells us. However, we happen to know this * works on MacOS which doesn't define that. */ #if defined(BROKEN_WCWIDTH) && (defined(__STDC_ISO_10646__) || defined(__APPLE__)) #define WCWIDTH(wc) mk_wcwidth(wc) #else #define WCWIDTH(wc) wcwidth(wc) #endif /* * Note WCWIDTH_WINT() takes wint_t, typically as a convchar_t. * It's written to use the wint_t from mb_metacharlenconv() without * further tests. * * This version has a non-multibyte definition that simply returns * 1. We never expose WCWIDTH() in the non-multibyte world since * it's just a proxy for wcwidth() itself. */ #define WCWIDTH_WINT(wc) zwcwidth(wc) #define MB_INCOMPLETE ((size_t)-2) #define MB_INVALID ((size_t)-1) /* * MB_CUR_MAX is the maximum number of bytes that a single wide * character will convert into. We use it to keep strings * sufficiently long. It should always be defined, but if it isn't * just assume we are using Unicode which requires 6 characters. * (Note that it's not necessarily defined to a constant.) */ #ifndef MB_CUR_MAX #define MB_CUR_MAX 6 #endif /* Convert character or string to wide character or string */ #define ZWC(c) L ## c #define ZWS(s) L ## s /* * Test for a combining character. * * wc is assumed to be a wchar_t (i.e. we don't need zwcwidth). * * Pedantic note: in Unicode, a combining character need not be * zero length. However, we are concerned here about display; * we simply need to know whether the character will be displayed * on top of another one. We use "combining character" in this * sense throughout the shell. I am not aware of a way of * detecting the Unicode trait in standard libraries. */ #ifdef BROKEN_WCWIDTH /* * We can't be quite sure the wcwidth we've provided is entirely * in agreement with the system's, so be extra safe. */ #define IS_COMBINING(wc) (WCWIDTH(wc) == 0 && !iswcntrl(wc)) #else #define IS_COMBINING(wc) (WCWIDTH(wc) == 0) #endif /* * Test for the base of a combining character. * * We assume a combining character can be successfully displayed with * any non-space printable character, which is what a graphic character * is, as long as it has non-zero width. We need to avoid all forms of * space because the shell will split words on any whitespace. */ #define IS_BASECHAR(wc) (iswgraph(wc) && WCWIDTH(wc) > 0) #else /* not MULTIBYTE_SUPPORT */ #define MB_METACHARINIT() typedef int convchar_t; #define MB_METACHARLENCONV(str, cp) metacharlenconv((str), (cp)) #define MB_METACHARLEN(str) (*(str) == Meta ? 2 : 1) #define MB_METASTRLEN(str) ztrlen(str) #define MB_METASTRWIDTH(str) ztrlen(str) #define MB_METASTRLEN2(str, widthp) ztrlen(str) #define WCWIDTH_WINT(c) (1) /* Leave character or string as is. */ #define ZWC(c) c #define ZWS(s) s #endif /* MULTIBYTE_SUPPORT */