summaryrefslogtreecommitdiff
path: root/dotfiles/system/.zsh/modules/Src/zsh.h
diff options
context:
space:
mode:
Diffstat (limited to 'dotfiles/system/.zsh/modules/Src/zsh.h')
-rw-r--r--dotfiles/system/.zsh/modules/Src/zsh.h3305
1 files changed, 3305 insertions, 0 deletions
diff --git a/dotfiles/system/.zsh/modules/Src/zsh.h b/dotfiles/system/.zsh/modules/Src/zsh.h
new file mode 100644
index 0000000..8e7f20b
--- /dev/null
+++ b/dotfiles/system/.zsh/modules/Src/zsh.h
@@ -0,0 +1,3305 @@
+/*
+ * 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;
+#if defined(ZLONG_IS_LONG_LONG) && defined(LLONG_MAX)
+#define ZLONG_MAX LLONG_MAX
+#else
+#ifdef ZLONG_IS_LONG_64
+#define ZLONG_MAX LONG_MAX
+#else
+/* umm... */
+#define ZLONG_MAX ((zlong)9223372036854775807)
+#endif
+#endif
+#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;
+#define ZLONG_MAX LONG_MAX
+#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)
+#define Dash ((char) 0x9b) /* Only in patterns */
+#define Bang ((char) 0x9c) /* Only in patterns */
+/*
+ * Marks the last of the group above.
+ * Remaining tokens are even more special.
+ */
+#define LAST_NORMAL_TOK Bang
+/*
+ * Null arguments: placeholders for single and double quotes
+ * and backslashes.
+ */
+#define Snull ((char) 0x9d)
+#define Dnull ((char) 0x9e)
+#define Bnull ((char) 0x9f)
+/*
+ * Backslash which will be returned to "\" instead of being stripped
+ * when we turn the string into a printable format.
+ */
+#define Bnullkeep ((char) 0xa0)
+/*
+ * 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) 0xa1)
+
+/*
+ * Take care to update the use of IMETA appropriately when adding
+ * tokens here.
+ */
+/*
+ * Marker is used in the following special circumstances:
+ * - In paramsubst for rc_expand_param.
+ * - In pattern character arrays as guaranteed not to mark a character in
+ * a string.
+ * - In assignments with the ASSPM_KEY_VALUE flag set in order to
+ * mark that there is a key / value pair following. If this
+ * comes from [key]=value the Marker is followed by a null;
+ * if from [key]+=value the Marker is followed by a '+' then a null.
+ * All the above are local uses --- any case where the Marker has
+ * escaped beyond the context in question is an error.
+ */
+#define Marker ((char) 0xa2)
+
+/* chars that need to be quoted if meant literally */
+
+#define SPECCHARS "#$^*()=|{}[]`<>?~;&\n\t \\\'\""
+
+/* chars that need to be quoted for pattern matching */
+
+#define PATCHARS "#^*()|[]<>?~\\"
+
+/*
+ * Check for a possibly tokenized dash.
+ *
+ * A dash only needs to be a token in a character range, [a-z], but
+ * it's difficult in general to ensure that. So it's turned into
+ * a token at the usual point in the lexer. However, we need
+ * to check for a literal dash at many points.
+ */
+#define IS_DASH(x) ((x) == '-' || (x) == Dash)
+
+/*
+ * 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,
+ /*
+ * Only quote pattern characters.
+ * ${(b)foo} guarantees that ${~foo} matches the string
+ * contained in foo.
+ */
+ QT_BACKSLASH_PATTERN,
+ /*
+ * As QT_BACKSLASH, but a NULL string is shown as ''.
+ */
+ QT_BACKSLASH_SHOWNULL,
+ /*
+ * Quoting as produced by quotedzputs(), used for human
+ * readability of parameter values.
+ */
+ QT_QUOTEDZPUTS
+};
+
+#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 */
+ TYPESET /* typeset or similar */
+};
+
+/* 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 visible to other processes but controlled by a module.
+ * The difference from FDT_EXTERNAL is that closing this using
+ * standard fd syntax will fail as there is some tidying up that
+ * needs to be done by the module's own mechanism.
+ */
+#define FDT_MODULE 3
+/*
+ * Entry used by output from the XTRACE option.
+ */
+#define FDT_XTRACE 4
+/*
+ * Entry used for file locking.
+ */
+#define FDT_FLOCK 5
+/*
+ * 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 6
+/*
+ * Entry used by a process substition.
+ * This marker is not tested internally as we associated the file
+ * descriptor with a job for closing.
+ *
+ * This is not used unless PATH_DEV_FD is defined.
+ */
+#define FDT_PROC_SUBST 7
+/*
+ * Mask to get the basic FDT type.
+ */
+#define FDT_TYPE_MASK 15
+
+/*
+ * Bit flag that fd is saved for later restoration.
+ * Currently this is only use with FDT_INTERNAL. We use this fact so as
+ * not to have to mask checks against other types.
+ */
+#define FDT_SAVED_MASK 16
+
+/* 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 */
+#define INP_RAW_KEEP (1<<8) /* Input needed in raw mode even if alias */
+
+/* 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 execcmd_params *Execcmd_params;
+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 imatchdata *Imatchdata;
+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 patstralloc *Patstralloc;
+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.
+ *
+ * Careful when changing these: both cond_binary_ops in text.c and
+ * condstr in cond.c depend on these. (The zsh motto is "two instances
+ * are better than one". Or something.)
+ */
+
+#define COND_NOT 0
+#define COND_AND 1
+#define COND_OR 2
+#define COND_STREQ 3
+#define COND_STRDEQ 4
+#define COND_STRNEQ 5
+#define COND_STRLT 6
+#define COND_STRGTR 7
+#define COND_NT 8
+#define COND_OT 9
+#define COND_EF 10
+#define COND_EQ 11
+#define COND_NE 12
+#define COND_LT 13
+#define COND_GT 14
+#define COND_LE 15
+#define COND_GE 16
+#define COND_REGEX 17
+#define COND_MOD 18
+#define COND_MODI 19
+
+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 */
+};
+
+/* 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;
+ int hashval;
+};
+
+#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_TYPESET 7
+#define WC_SUBSH 8
+#define WC_CURSH 9
+#define WC_TIMED 10
+#define WC_FUNCDEF 11
+#define WC_FOR 12
+#define WC_SELECT 13
+#define WC_WHILE 14
+#define WC_REPEAT 15
+#define WC_CASE 16
+#define WC_IF 17
+#define WC_COND 18
+#define WC_ARITH 19
+#define WC_AUTOFN 20
+#define WC_TRY 21
+
+/* increment as necessary */
+#define WC_COUNT 22
+
+#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
+/*
+ * In normal assignment, this indicate += to append.
+ * In assignment following a typeset, where that's not allowed,
+ * we overload this to indicate a variable without an
+ * assignment.
+ */
+#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_TYPESET_ARGC(C) wc_data(C)
+#define WCB_TYPESET(N) wc_bld(WC_TYPESET, (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 (SUPERJOB)
+ * or subshell pid (SUBJOB) */
+ 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 STAT_SUBJOB_ORPHANED (0x8000)
+ /* STAT_SUBJOB with STAT_SUPERJOB exited */
+#define STAT_DISOWN (0x10000) /* STAT_SUPERJOB with disown pending */
+
+#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;
+ pid_t procsubstpid;
+ int trap_return;
+ int trap_state;
+ int trapisfunc;
+ int traplocallevel;
+ int noerrs;
+ int this_noerrexit;
+ 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)
+
+/* structure for foo=bar assignments */
+
+struct asgment {
+ struct linknode node;
+ char *name;
+ int flags;
+ union {
+ char *scalar;
+ LinkList array;
+ } value;
+};
+
+/* Flags for flags element of asgment */
+enum {
+ /* Array value */
+ ASG_ARRAY = 1,
+ /* Key / value array pair */
+ ASG_KEY_VALUE = 2
+};
+
+/*
+ * Assignment is array?
+ */
+#define ASG_ARRAYP(asg) ((asg)->flags & ASG_ARRAY)
+
+/*
+ * Assignment has value?
+ * If the assignment is an arrray, then it certainly has a value --- we
+ * can only tell if there's an expicit assignment.
+ */
+
+#define ASG_VALUEP(asg) (ASG_ARRAYP(asg) || \
+ ((asg)->value.scalar != (char *)0))
+
+/* 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.
+ For not yet autoloaded file, name
+ of explicit directory, if not NULL. */
+ 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;
+};
+
+/* Flags to parseargs() */
+
+enum {
+ PARSEARGS_TOPLEVEL = 0x1, /* Call to initialise shell */
+ PARSEARGS_LOGIN = 0x2 /* Shell is login shell */
+};
+
+
+/*
+ * 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));
+typedef int (*HandlerFuncAssign) _((char *, char **, LinkList, 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)
+/*
+ * Handles the assignement interface. The argv list actually contains
+ * two nested litsts, the first of normal arguments, and the second of
+ * assignment structures.
+ */
+#define BINF_ASSIGN (1<<19)
+
+/**
+ * Parameters passed to execcmd().
+ * These are not opaque --- they are also used by the pipeline manager.
+ */
+struct execcmd_params {
+ LinkList args; /* All command prefixes, arguments & options */
+ LinkList redir; /* Redirections */
+ Wordcode beg; /* The code at the start of the command */
+ Wordcode varspc; /* The code for assignment parsed as such */
+ Wordcode assignspc; /* The code for assignment parsed as typeset */
+ int type; /* The WC_* type of the command */
+ int postassigns; /* The number of assignspc assiguments */
+ int htok; /* tokens in parameter list */
+};
+
+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;
+};
+
+struct patstralloc {
+ int unmetalen; /* Unmetafied length of trial string */
+ int unmetalenp; /* Unmetafied length of path prefix.
+ If 0, no path prefix. */
+ char *alloced; /* Allocated string, may be NULL */
+ char *progstrunmeta; /* Unmetafied pure string in pattern, cached */
+ int progstrunmetalen; /* Length of the foregoing */
+};
+
+/* Flags used in pattern matchers (Patprog) and passed down to patcompile */
+
+#define PAT_HEAPDUP 0x0000 /* Dummy flag for default behavior */
+#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_BANG2, /* ! for !(...) in KSH_GLOB, untokenised */
+ 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 assume ZPC_COUNT is no greater
+ * than the number of bits in 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
+#define PP_INCOMPLETE 18
+#define PP_INVALID 19
+/* Special value for last definition */
+#define PP_LAST 19
+
+/* Unknown type. Not used in a valid token. */
+#define PP_UNKWN 20
+/* Range: token followed by the (possibly multibyte) start and end */
+#define PP_RANGE 21
+
+/*
+ * Argument to get_match_ret() in glob.c
+ */
+struct imatchdata {
+ /* Metafied trial string */
+ char *mstr;
+ /* Its length */
+ int mlen;
+ /* Unmetafied string */
+ char *ustr;
+ /* Its length */
+ int ulen;
+ /* Flags (SUB_*) */
+ int flags;
+ /* Replacement string (metafied) */
+ char *replstr;
+ /*
+ * List of bits of matches to concatenate with replacement string.
+ * The data is a struct repldata. It is not used in cases like
+ * ${...//#foo/bar} even though SUB_GLOBAL is set, since the match
+ * is anchored. It goes on the heap.
+ */
+ LinkList repllist;
+};
+
+/* 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 */
+
+enum {
+ /* Valid multibyte character from charref */
+ ZMB_VALID,
+ /* Incomplete multibyte character from charref */
+ ZMB_INCOMPLETE,
+ /* Invalid multibyte character charref */
+ ZMB_INVALID
+};
+
+/* 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 */
+#define PM_ABSPATH_USED (1<<12) /* (function): loaded using absolute path */
+
+/* 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_CUR_FPATH (1<<14) /* (function): can use $fpath with filename */
+#define PM_HIDEVAL (1<<15) /* Value not shown in `typeset' commands */
+#define PM_WARNNESTED (1<<15) /* (function): non-recursive WARNNESTEDVAR */
+#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_DONTIMPORT_SUID (1<<19) /* do not import if running setuid */
+#define PM_LOADDIR (1<<19) /* (function) filename gives load directory */
+#define PM_SINGLE (1<<20) /* special can only have a single instance */
+#define PM_ANONYMOUS (1<<20) /* (function) anonymous function */
+#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_CHECKING (1<<10) /* Check if set, no need to create */
+/* "$foo[@]"-style substitution
+ * Only sign bit is significant
+ */
+#define SCANPM_ISVAR_AT ((int)(((unsigned int)-1)<<15))
+
+/*
+ * 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 */
+enum {
+ /* argument handled like typeset foo=bar */
+ PREFORK_TYPESET = 0x01,
+ /* argument handled like the RHS of foo=bar */
+ PREFORK_ASSIGN = 0x02,
+ /* single word substitution */
+ PREFORK_SINGLE = 0x04,
+ /* explicitly split nested substitution */
+ PREFORK_SPLIT = 0x08,
+ /* SHWORDSPLIT in parameter expn */
+ PREFORK_SHWORDSPLIT = 0x10,
+ /* SHWORDSPLIT forced off in nested subst */
+ PREFORK_NOSHWORDSPLIT = 0x20,
+ /* Prefork is part of a parameter subexpression */
+ PREFORK_SUBEXP = 0x40,
+ /* Prefork detected an assignment list with [key]=value syntax,
+ * Only used on return from prefork, not meaningful passed down.
+ * Also used as flag to globlist.
+ */
+ PREFORK_KEY_VALUE = 0x80,
+ /* No untokenise: used only as flag to globlist */
+ PREFORK_NO_UNTOK = 0x100
+};
+
+/*
+ * Bit flags passed back from multsub() to paramsubst().
+ * Some flags go from a nested parmsubst() through the enclosing
+ * stringsubst() and prefork().
+ */
+enum {
+ /*
+ * Set if the string had whitespace at the start
+ * that should cause word splitting against any preceeding string.
+ */
+ MULTSUB_WS_AT_START = 1,
+ /*
+ * Set if the string had whitespace at the end
+ * that should cause word splitting against any following string.
+ */
+ MULTSUB_WS_AT_END = 2,
+ /*
+ * Set by nested paramsubst() to indicate the return
+ * value is a parameter name, rather than a value.
+ */
+ MULTSUB_PARAM_NAME = 4
+};
+
+/*
+ * 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 }
+
+/*
+ * Flags for assignsparam and assignaparam.
+ */
+enum {
+ /* Add to rather than override value */
+ ASSPM_AUGMENT = 1 << 0,
+ /* Test for warning if creating global variable in function */
+ ASSPM_WARN_CREATE = 1 << 1,
+ /* Test for warning if using nested variable in function */
+ ASSPM_WARN_NESTED = 1 << 2,
+ ASSPM_WARN = (ASSPM_WARN_CREATE|ASSPM_WARN_NESTED),
+ /* Import from environment, so exercise care evaluating value */
+ ASSPM_ENV_IMPORT = 1 << 3,
+ /* Array is key / value pairs.
+ * This is normal for associative arrays but variant behaviour for
+ * normal arrays.
+ */
+ ASSPM_KEY_VALUE = 1 << 4
+};
+
+/* 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)
+#define PRINT_LINE (1<<6)
+
+/* flags for printing for the whence builtin */
+#define PRINT_WHENCE_CSH (1<<7)
+#define PRINT_WHENCE_VERBOSE (1<<8)
+#define PRINT_WHENCE_SIMPLE (1<<9)
+#define PRINT_WHENCE_FUNCDEF (1<<10)
+#define PRINT_WHENCE_WORD (1<<11)
+
+/* 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
+};
+
+enum noerrexit_bits {
+ /* Suppress ERR_EXIT and traps: global */
+ NOERREXIT_EXIT = 1,
+ /* Suppress ERR_RETURN: per function call */
+ NOERREXIT_RETURN = 2,
+ /* NOERREXIT only needed on way down */
+ NOERREXIT_UNTIL_EXEC = 4,
+ /* Force exit on SIGINT */
+ NOERREXIT_SIGNAL = 8
+};
+
+/***********************************/
+/* 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,
+ ALIASFUNCDEF,
+ 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,
+ CHECKRUNNINGJOBS,
+ CLOBBER,
+ APPENDCREATE,
+ 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,
+ GLOBSTARSHORT,
+ 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,
+ WARNNESTEDVAR,
+ 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 &= ~(Y), *T |= (X))))
+
+/*
+ * 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,
+ /*
+ * Hard error --- return to top-level prompt in interactive
+ * shell. In non-interactive shell we'll typically already
+ * have exited. This is reset by "errflag = 0" in
+ * loop(toplevel = 1, ...).
+ */
+ ERRFLAG_HARD = 4
+};
+
+/***********/
+/* 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;
+ zlong defev;
+ char *hline;
+ char *hptr;
+ short *chwords;
+ int chwordlen;
+ int chwordpos;
+ int (*hgetc) _((void));
+ void (*hungetc) _((int));
+ void (*hwaddc) _((int));
+ void (*hwbegin) _((int));
+ void (*hwabort) _((void));
+ void (*hwend) _((void));
+ void (*addtoline) _((int));
+ unsigned char *cstack;
+ int csp;
+ int hist_keep_comment;
+};
+
+/*
+ * 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 inrepeat_;
+ int intypeset;
+
+ 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
+/* Final argument to mb_niceformat() */
+enum {
+ NICEFLAG_HEAP = 1, /* Heap allocation where needed */
+ NICEFLAG_QUOTE = 2, /* Result will appear in $'...' */
+ NICEFLAG_NODUP = 4, /* Leave allocated */
+};
+
+/* Metafied input */
+#define nicezputs(str, outs) (void)mb_niceformat((str), (outs), NULL, 0)
+#define MB_METACHARINIT() mb_charinit()
+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_metastrlenend(str, 0, NULL)
+#define MB_METASTRWIDTH(str) mb_metastrlenend(str, 1, NULL)
+#define MB_METASTRLEN2(str, widthp) mb_metastrlenend(str, widthp, NULL)
+#define MB_METASTRLEN2END(str, widthp, eptr) \
+ mb_metastrlenend(str, widthp, eptr)
+
+/* Unmetafined input */
+#define MB_CHARINIT() mb_charinit()
+#define MB_CHARLENCONV(str, len, cp) mb_charlenconv((str), (len), (cp))
+#define MB_CHARLEN(str, len) mb_charlenconv((str), (len), NULL)
+
+/*
+ * 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.
+ */
+#ifdef ENABLE_UNICODE9
+#define WCWIDTH(wc) u9_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.
+ */
+#define IS_COMBINING(wc) (wc != 0 && WCWIDTH(wc) == 0)
+/*
+ * 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 MB_METASTRLEN2END(str, widthp, eptr) ztrlenend(str, eptr)
+
+#define MB_CHARINIT()
+#define MB_CHARLENCONV(str, len, cp) charlenconv((str), (len), (cp))
+#define MB_CHARLEN(str, len) ((len) ? 1 : 0)
+
+#define WCWIDTH_WINT(c) (1)
+
+/* Leave character or string as is. */
+#define ZWC(c) c
+#define ZWS(s) s
+
+#endif /* MULTIBYTE_SUPPORT */