zsh/Src/zsh.h
2015-09-29 19:47:21 +01:00

3132 lines
92 KiB
C

/*
* 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)
/*
* Null arguments: placeholders for single and double quotes
* and backslashes.
*/
#define Snull ((char) 0x9b)
#define Dnull ((char) 0x9c)
#define Bnull ((char) 0x9d)
/*
* Backslash which will be returned to "\" instead of being stripped
* when we turn the string into a printable format.
*/
#define Bnullkeep ((char) 0x9e)
/*
* Null argument that does not correspond to any character.
* This should be last as it does not appear in ztokens and
* is used to initialise the IMETA type in inittyptab().
*/
#define Nularg ((char) 0x9f)
/*
* Take care to update the use of IMETA appropriately when adding
* tokens here.
*/
/*
* Marker used in paramsubst for rc_expand_param.
* Also used in pattern character arrays as guaranteed not to
* mark a character in a string.
*/
#define Marker ((char) 0xa0)
/* chars that need to be quoted if meant literally */
#define SPECCHARS "#$^*()=|{}[]`<>?~;&\n\t \\\'\""
/* chars that need to be quoted for pattern matching */
#define PATCHARS "#^*()|[]<>?~\\"
/*
* 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
};
#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 used by output from the XTRACE option.
*/
#define FDT_XTRACE 3
/*
* Entry used for file locking.
*/
#define FDT_FLOCK 4
/*
* As above, but the fd is not marked for closing on exec,
* so the shell can still exec the last process.
*/
#define FDT_FLOCK_EXEC 5
#ifdef PATH_DEV_FD
/*
* Entry used by a process substition.
* This marker is not tested internally as we associated the file
* descriptor with a job for closing.
*/
#define FDT_PROC_SUBST 6
#endif
/* Flags for input stack */
#define INP_FREE (1<<0) /* current buffer can be free'd */
#define INP_ALIAS (1<<1) /* expanding alias or history */
#define INP_HIST (1<<2) /* expanding history */
#define INP_CONT (1<<3) /* continue onto previously stacked input */
#define INP_ALCONT (1<<4) /* stack is continued from alias expn. */
#define INP_HISTCONT (1<<5) /* stack is continued from history expn. */
#define INP_LINENO (1<<6) /* update line number */
#define INP_APPEND (1<<7) /* Append new lines to allow backup */
#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 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. */
#define COND_NOT 0
#define COND_AND 1
#define COND_OR 2
#define COND_STREQ 3
#define COND_STRNEQ 4
#define COND_STRLT 5
#define COND_STRGTR 6
#define COND_NT 7
#define COND_OT 8
#define COND_EF 9
#define COND_EQ 10
#define COND_NE 11
#define COND_LT 12
#define COND_GT 13
#define COND_LE 14
#define COND_GE 15
#define COND_REGEX 16
#define COND_MOD 17
#define COND_MODI 18
typedef int (*CondHandler) _((char **, int));
struct conddef {
Conddef next; /* next in list */
char *name; /* the condition name */
int flags; /* see CONDF_* below */
CondHandler handler; /* handler function */
int min; /* minimum number of strings */
int max; /* maximum number of strings */
int condid; /* for overloading handler functions */
char *module; /* module to autoload */
};
/* Condition is an infix */
#define CONDF_INFIX 1
/* Condition has been loaded from library */
#define CONDF_ADDED 2
/* When autoloading, enable all features in library */
#define CONDF_AUTOALL 4
#define CONDDEF(name, flags, handler, min, max, condid) \
{ NULL, name, flags, handler, min, max, condid, NULL }
/* Flags for redirections */
enum {
/* Mark a here-string that came from a here-document */
REDIRF_FROM_HEREDOC = 1
};
/* tree element for redirection lists */
struct redir {
int type;
int flags;
int fd1, fd2;
char *name;
char *varid;
char *here_terminator;
char *munged_here_terminator;
};
/* The number of fds space is allocated for *
* each time a multio must increase in size. */
#define MULTIOUNIT 8
/* A multio is a list of fds associated with a certain fd. *
* Thus if you do "foo >bar >ble", the multio for fd 1 will have *
* two fds, the result of open("bar",...), and the result of *
* open("ble",....). */
/* structure used for multiple i/o redirection */
/* one for each fd open */
struct multio {
int ct; /* # of redirections on this fd */
int rflag; /* 0 if open for reading, 1 if open for writing */
int pipe; /* fd of pipe if ct > 1 */
int fds[MULTIOUNIT]; /* list of src/dests redirected to/from this fd */
};
/* lvalue for variable assignment/expansion */
struct value {
int isarr;
Param pm; /* parameter node */
int flags; /* flags defined below */
int start; /* first element of array slice, or -1 */
int end; /* 1-rel last element of array slice, or -1 */
char **arr; /* cache for hash turned into array */
};
enum {
VALFLAG_INV = 0x0001, /* We are performing inverse subscripting */
VALFLAG_EMPTY = 0x0002, /* Subscripted range is empty */
VALFLAG_SUBST = 0x0004 /* Substitution, so apply padding, case flags */
};
#define MAX_ARRLEN 262144
/********************************************/
/* Definitions for word code */
/********************************************/
typedef unsigned int wordcode;
typedef wordcode *Wordcode;
typedef struct funcdump *FuncDump;
typedef struct eprog *Eprog;
struct funcdump {
FuncDump next; /* next in list */
dev_t dev; /* device */
ino_t ino; /* indoe number */
int fd; /* file descriptor */
Wordcode map; /* pointer to header */
Wordcode addr; /* mapped region */
int len; /* length */
int count; /* reference count */
char *filename;
};
/*
* A note on the use of reference counts in Eprogs.
*
* When an Eprog is created, nref is set to -1 if the Eprog is on the
* heap; then no attempt is ever made to free it. (This information is
* already present in EF_HEAP; we use the redundancy for debugging
* checks.)
*
* Otherwise, nref is initialised to 1. Calling freeprog() decrements
* nref and frees the Eprog if the count is now zero. When the Eprog
* is in use, we call useeprog() at the start and freeprog() at the
* end to increment and decrement the reference counts. If an attempt
* is made to free the Eprog from within, this will then take place
* when execution is finished, typically in the call to freeeprog()
* in execode(). If the Eprog was on the heap, neither useeprog()
* nor freeeprog() has any effect.
*/
struct eprog {
int flags; /* EF_* below */
int len; /* total block length */
int npats; /* Patprog cache size */
int nref; /* number of references: delete when zero */
Patprog *pats; /* the memory block, the patterns */
Wordcode prog; /* memory block ctd, the code */
char *strs; /* memory block ctd, the strings */
Shfunc shf; /* shell function for autoload */
FuncDump dump; /* dump file this is in */
};
#define EF_REAL 1
#define EF_HEAP 2
#define EF_MAP 4
#define EF_RUN 8
typedef struct estate *Estate;
struct estate {
Eprog prog; /* the eprog executed */
Wordcode pc; /* program counter, current pos */
char *strs; /* strings from prog */
};
typedef struct eccstr *Eccstr;
struct eccstr {
Eccstr left, right;
char *str;
wordcode offs, aoffs;
int nfunc;
};
#define EC_NODUP 0
#define EC_DUP 1
#define EC_DUPTOK 2
#define WC_CODEBITS 5
#define wc_code(C) ((C) & ((wordcode) ((1 << WC_CODEBITS) - 1)))
#define wc_data(C) ((C) >> WC_CODEBITS)
#define wc_bdata(D) ((D) << WC_CODEBITS)
#define wc_bld(C,D) (((wordcode) (C)) | (((wordcode) (D)) << WC_CODEBITS))
#define WC_END 0
#define WC_LIST 1
#define WC_SUBLIST 2
#define WC_PIPE 3
#define WC_REDIR 4
#define WC_ASSIGN 5
#define WC_SIMPLE 6
#define WC_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 or subshell pid */
int stat; /* see STATs below */
char *pwd; /* current working dir of shell when *
* this job was spawned */
struct process *procs; /* list of processes */
struct process *auxprocs; /* auxiliary processes e.g multios */
LinkList filelist; /* list of files to delete when done */
/* elements are struct jobfile */
int stty_in_env; /* if STTY=... is present */
struct ttyinfo *ty; /* the modes specified by STTY */
};
#define STAT_CHANGED (0x0001) /* status changed and not reported */
#define STAT_STOPPED (0x0002) /* all procs stopped or exited */
#define STAT_TIMED (0x0004) /* job is being timed */
#define STAT_DONE (0x0008) /* job is done */
#define STAT_LOCKED (0x0010) /* shell is finished creating this job, */
/* may be deleted from job table */
#define STAT_NOPRINT (0x0020) /* job was killed internally, */
/* we don't want to show that */
#define STAT_INUSE (0x0040) /* this job entry is in use */
#define STAT_SUPERJOB (0x0080) /* job has a subjob */
#define STAT_SUBJOB (0x0100) /* job is a subjob */
#define STAT_WASSUPER (0x0200) /* was a super-job, sub-job needs to be */
/* deleted */
#define STAT_CURSH (0x0400) /* last command is in current shell */
#define STAT_NOSTTY (0x0800) /* the tty settings are not inherited */
/* from this job when it exits. */
#define STAT_ATTACH (0x1000) /* delay reattaching shell to tty */
#define STAT_SUBLEADER (0x2000) /* is super-job, but leader is sub-shell */
#define STAT_BUILTIN (0x4000) /* job at tail of pipeline is a builtin */
#define SP_RUNNING -1 /* fake status for jobs currently running */
struct timeinfo {
long ut; /* user space time */
long st; /* system space time */
};
#define JOBTEXTSIZE 80
/* Size to initialise the job table to, and to increment it by when needed. */
#define MAXJOBS_ALLOC (50)
/* node in job process lists */
#ifdef HAVE_GETRUSAGE
typedef struct rusage child_times_t;
#else
typedef struct timeinfo child_times_t;
#endif
struct process {
struct process *next;
pid_t pid; /* process id */
char text[JOBTEXTSIZE]; /* text to print when 'jobs' is run */
int status; /* return code from waitpid/wait3() */
child_times_t ti;
struct timeval bgtime; /* time job was spawned */
struct timeval endtime; /* time job exited */
};
struct execstack {
struct execstack *next;
pid_t list_pipe_pid;
int nowait;
int pline_level;
int list_pipe_child;
int list_pipe_job;
char list_pipe_text[JOBTEXTSIZE];
int lastval;
int noeval;
int badcshglob;
pid_t cmdoutpid;
int cmdoutval;
int use_cmdoutval;
int trap_return;
int trap_state;
int trapisfunc;
int traplocallevel;
int noerrs;
char *underscore;
};
struct heredocs {
struct heredocs *next;
int type;
int pc;
char *str;
};
struct dirsav {
int dirfd, level;
char *dirname;
dev_t dev;
ino_t ino;
};
#define MAX_PIPESTATS 256
/*******************************/
/* Definitions for Hash Tables */
/*******************************/
typedef void *(*VFunc) _((void *));
typedef void (*FreeFunc) _((void *));
typedef unsigned (*HashFunc) _((const char *));
typedef void (*TableFunc) _((HashTable));
/*
* Note that this is deliberately "char *", not "const char *",
* since the AddNodeFunc is passed a pointer to a string that
* will be stored and later freed.
*/
typedef void (*AddNodeFunc) _((HashTable, char *, void *));
typedef HashNode (*GetNodeFunc) _((HashTable, const char *));
typedef HashNode (*RemoveNodeFunc) _((HashTable, const char *));
typedef void (*FreeNodeFunc) _((HashNode));
typedef int (*CompareFunc) _((const char *, const char *));
/* type of function that is passed to *
* scanhashtable or scanmatchtable */
typedef void (*ScanFunc) _((HashNode, int));
typedef void (*ScanTabFunc) _((HashTable, ScanFunc, int));
typedef void (*PrintTableStats) _((HashTable));
/* hash table for standard open hashing */
struct hashtable {
/* HASHTABLE DATA */
int hsize; /* size of nodes[] (number of hash values) */
int ct; /* number of elements */
HashNode *nodes; /* array of size hsize */
void *tmpdata;
/* HASHTABLE METHODS */
HashFunc hash; /* pointer to hash function for this table */
TableFunc emptytable; /* pointer to function to empty table */
TableFunc filltable; /* pointer to function to fill table */
CompareFunc cmpnodes; /* pointer to function to compare two nodes */
AddNodeFunc addnode; /* pointer to function to add new node */
GetNodeFunc getnode; /* pointer to function to get an enabled node */
GetNodeFunc getnode2; /* pointer to function to get node */
/* (getnode2 will ignore DISABLED flag) */
RemoveNodeFunc removenode; /* pointer to function to delete a node */
ScanFunc disablenode; /* pointer to function to disable a node */
ScanFunc enablenode; /* pointer to function to enable a node */
FreeNodeFunc freenode; /* pointer to function to free a node */
ScanFunc printnode; /* pointer to function to print a node */
ScanTabFunc scantab; /* pointer to function to scan table */
#ifdef HASHTABLE_INTERNAL_MEMBERS
HASHTABLE_INTERNAL_MEMBERS /* internal use in hashtable.c */
#endif
};
/* generic hash table node */
struct hashnode {
HashNode next; /* next in hash chain */
char *nam; /* hash key */
int flags; /* various flags */
};
/* The flag to disable nodes in a hash table. Currently *
* you can disable builtins, shell functions, aliases and *
* reserved words. */
#define DISABLED (1<<0)
/* node in shell option table */
struct optname {
struct hashnode node;
int optno; /* option number */
};
/* node in shell reserved word hash table (reswdtab) */
struct reswd {
struct hashnode node;
int token; /* corresponding lexer token */
};
/* node in alias hash table (aliastab) */
struct alias {
struct hashnode node;
char *text; /* expansion of alias */
int inuse; /* alias is being expanded */
};
/* bit 0 of flags is the DISABLED flag */
/* is this alias global? */
#define ALIAS_GLOBAL (1<<1)
/* is this an alias for suffix handling? */
#define ALIAS_SUFFIX (1<<2)
/* structure for foo=bar assignments */
struct asgment {
struct linknode node;
char *name;
int is_array;
union {
char *scalar;
LinkList array;
} value;
};
/*
* Assignment is array?
*/
#define ASG_ARRAYP(asg) ((asg)->is_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 */
zlong lineno; /* line number in above file */
Eprog funcdef; /* function definition */
Eprog redir; /* redirections to apply */
Emulation_options sticky; /* sticky emulation definitions, if any */
};
/* Shell function context types. */
#define SFC_NONE 0 /* no function running */
#define SFC_DIRECT 1 /* called directly from the user */
#define SFC_SIGNAL 2 /* signal handler */
#define SFC_HOOK 3 /* one of the special functions */
#define SFC_WIDGET 4 /* user defined widget */
#define SFC_COMPLETE 5 /* called from completion code */
#define SFC_CWIDGET 6 /* new style completion widget */
#define SFC_SUBST 7 /* used to perform substitution task */
/* tp in funcstack */
enum {
FS_SOURCE,
FS_FUNC,
FS_EVAL
};
/* node in function stack */
struct funcstack {
Funcstack prev; /* previous in stack */
char *name; /* name of function/sourced file called */
char *filename; /* file function resides in */
char *caller; /* name of caller */
zlong flineno; /* line number in file */
zlong lineno; /* line offset from beginning of function */
int tp; /* type of entry: sourced file, func, eval */
};
/* node in list of function call wrappers */
typedef int (*WrapFunc) _((Eprog, FuncWrap, char *));
struct funcwrap {
FuncWrap next;
int flags;
WrapFunc handler;
Module module;
};
#define WRAPF_ADDED 1
#define WRAPDEF(func) \
{ NULL, 0, func, NULL }
/*
* User-defined hook arrays
*/
/* Name appended to function name to get hook array */
#define HOOK_SUFFIX "_functions"
/* Length of that including NUL byte */
#define HOOK_SUFFIX_LEN 11
/* node in builtin command hash table (builtintab) */
/*
* Handling of options.
*
* Option strings are standard in that a trailing `:' indicates
* a mandatory argument. In addition, `::' indicates an optional
* argument which must immediately follow the option letter if it is present.
* `:%' indicates an optional numeric argument which may follow
* the option letter or be in the next word; the only test is
* that the next character is a digit, and no actual conversion is done.
*/
#define MAX_OPS 128
/* Macros taking struct option * and char argument */
/* Option was set as -X */
#define OPT_MINUS(ops,c) ((ops)->ind[c] & 1)
/* Option was set as +X */
#define OPT_PLUS(ops,c) ((ops)->ind[c] & 2)
/*
* Option was set any old how, maybe including an argument
* (cheap test when we don't care). Some bits of code
* expect this to be 1 or 0.
*/
#define OPT_ISSET(ops,c) ((ops)->ind[c] != 0)
/* Option has an argument */
#define OPT_HASARG(ops,c) ((ops)->ind[c] > 3)
/* The argument for the option; not safe if it doesn't have one */
#define OPT_ARG(ops,c) ((ops)->args[((ops)->ind[c] >> 2) - 1])
/* Ditto, but safely returns NULL if there is no argument. */
#define OPT_ARG_SAFE(ops,c) (OPT_HASARG(ops,c) ? OPT_ARG(ops,c) : NULL)
struct options {
unsigned char ind[MAX_OPS];
char **args;
int argscount, argsalloc;
};
/*
* Handler arguments are: builtin name, null-terminated argument
* list excluding command name, option structure, the funcid element from the
* builtin structure.
*/
typedef int (*HandlerFunc) _((char *, char **, Options, int));
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)
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_FILE 0x0001 /* Pattern is a file name */
#define PAT_FILET 0x0002 /* Pattern is top level file, affects ~ */
#define PAT_ANY 0x0004 /* Match anything (cheap "*") */
#define PAT_NOANCH 0x0008 /* Not anchored at end */
#define PAT_NOGLD 0x0010 /* Don't glob dots */
#define PAT_PURES 0x0020 /* Pattern is a pure string: set internally */
#define PAT_STATIC 0x0040 /* Don't copy pattern to heap as per default */
#define PAT_SCAN 0x0080 /* Scanning, so don't try must-match test */
#define PAT_ZDUP 0x0100 /* Copy pattern in real memory */
#define PAT_NOTSTART 0x0200 /* Start of string is not real start */
#define PAT_NOTEND 0x0400 /* End of string is not real end */
#define PAT_HAS_EXCLUDP 0x0800 /* (internal): top-level path1~path2. */
#define PAT_LCMATCHUC 0x1000 /* equivalent to setting (#l) */
/**
* Indexes into the array of active pattern characters.
* This must match the array zpc_chars in pattern.c.
*/
enum zpc_chars {
/*
* These characters both terminate a pattern segment and
* a pure string segment.
*/
ZPC_SLASH, /* / active as file separator */
ZPC_NULL, /* \0 as string terminator */
ZPC_BAR, /* | for "or" */
ZPC_OUTPAR, /* ) for grouping */
ZPC_TILDE, /* ~ for exclusion (extended glob) */
ZPC_SEG_COUNT, /* No. of the above characters */
/*
* These characters terminate a pure string segment.
*/
ZPC_INPAR = ZPC_SEG_COUNT, /* ( for grouping */
ZPC_QUEST, /* ? as wildcard */
ZPC_STAR, /* * as wildcard */
ZPC_INBRACK, /* [ for character class */
ZPC_INANG, /* < for numeric glob */
ZPC_HAT, /* ^ for exclusion (extended glob) */
ZPC_HASH, /* # for repetition (extended glob) */
ZPC_BNULLKEEP, /* Special backslashed null not removed */
/*
* These characters are only valid before a parenthesis
*/
ZPC_NO_KSH_GLOB,
ZPC_KSH_QUEST = ZPC_NO_KSH_GLOB, /* ? for ?(...) in KSH_GLOB */
ZPC_KSH_STAR, /* * for *(...) in KSH_GLOB */
ZPC_KSH_PLUS, /* + for +(...) in KSH_GLOB */
ZPC_KSH_BANG, /* ! for !(...) in KSH_GLOB */
ZPC_KSH_AT, /* @ for @(...) in KSH_GLOB */
ZPC_COUNT /* Number of special chararacters */
};
/*
* Structure to save disables special characters for function scope.
*/
struct zpc_disables_save {
struct zpc_disables_save *next;
/*
* Bit vector of ZPC_COUNT disabled characters.
* We'll live dangerously and assumed ZPC_COUNT is no greater
* than the number of bits an an unsigned int.
*/
unsigned int disables;
};
typedef struct zpc_disables_save *Zpc_disables_save;
/*
* Special match types used in character classes. These
* are represented as tokens, with Meta added. The character
* class is represented as a metafied string, with only these
* tokens special. Note that an active leading "!" or "^" for
* negation is not part of the string but is flagged in the
* surrounding context.
*
* These types are also used in character and equivalence classes
* in completion matching.
*
* This must be kept ordered by the array colon_stuffs in pattern.c.
*/
/* Special value for first definition */
#define PP_FIRST 1
/* POSIX-defined types: [:alpha:] etc. */
#define PP_ALPHA 1
#define PP_ALNUM 2
#define PP_ASCII 3
#define PP_BLANK 4
#define PP_CNTRL 5
#define PP_DIGIT 6
#define PP_GRAPH 7
#define PP_LOWER 8
#define PP_PRINT 9
#define PP_PUNCT 10
#define PP_SPACE 11
#define PP_UPPER 12
#define PP_XDIGIT 13
/* Zsh additions: [:IDENT:] etc. */
#define PP_IDENT 14
#define PP_IFS 15
#define PP_IFSSPACE 16
#define PP_WORD 17
#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 */
/* The following are the same since they *
* both represent -U option to typeset */
#define PM_UNIQUE (1<<13) /* remove duplicates */
#define PM_UNALIASED (1<<13) /* do not expand aliases when autoloading */
#define PM_HIDE (1<<14) /* Special behaviour hidden by local */
#define PM_HIDEVAL (1<<15) /* Value not shown in `typeset' commands */
#define PM_TIED (1<<16) /* array tied to colon-path or v.v. */
#define PM_TAGGED_LOCAL (1<<16) /* (function): non-recursive PM_TAGGED */
#define PM_KSHSTORED (1<<17) /* function stored in ksh form */
#define PM_ZSHSTORED (1<<18) /* function stored in zsh form */
/* Remaining flags do not correspond directly to command line arguments */
#define PM_LOCAL (1<<21) /* this parameter will be made local */
#define PM_SPECIAL (1<<22) /* special builtin parameter */
#define PM_DONTIMPORT (1<<23) /* do not import this variable */
#define PM_RESTRICTED (1<<24) /* cannot be changed in restricted mode */
#define PM_UNSET (1<<25) /* has null value */
#define PM_REMOVABLE (1<<26) /* special can be removed from paramtab */
#define PM_AUTOLOAD (1<<27) /* autoloaded from module */
#define PM_NORESTORE (1<<28) /* do not restore value of local special */
#define PM_AUTOALL (1<<28) /* autoload all features in module
* when loading: valid only if PM_AUTOLOAD
* is also present.
*/
#define PM_HASHELEM (1<<29) /* is a hash-element */
#define PM_NAMEDDIR (1<<30) /* has a corresponding nameddirtab entry */
/* The option string corresponds to the first of the variables above */
#define TYPESET_OPTSTR "aiEFALRZlurtxUhHTkz"
/* These typeset options take an optional numeric argument */
#define TYPESET_OPTNUM "LRZiEF"
/* Flags for extracting elements of arrays and associative arrays */
#define SCANPM_WANTVALS (1<<0) /* Return value includes hash values */
#define SCANPM_WANTKEYS (1<<1) /* Return value includes hash keys */
#define SCANPM_WANTINDEX (1<<2) /* Return value includes array index */
#define SCANPM_MATCHKEY (1<<3) /* Subscript matched against key */
#define SCANPM_MATCHVAL (1<<4) /* Subscript matched against value */
#define SCANPM_MATCHMANY (1<<5) /* Subscript matched repeatedly, return all */
#define SCANPM_ASSIGNING (1<<6) /* Assigning whole array/hash */
#define SCANPM_KEYMATCH (1<<7) /* keys of hash treated as patterns */
#define SCANPM_DQUOTED (1<<8) /* substitution was double-quoted
* (only used for testing early end of
* subscript)
*/
#define SCANPM_ARRONLY (1<<9) /* value is array but we don't
* necessarily want to match multiple
* elements
*/
/* "$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 */
/* argument handled like typeset foo=bar */
#define PREFORK_TYPESET 0x01
/* argument handled like the RHS of foo=bar */
#define PREFORK_ASSIGN 0x02
/* single word substitution */
#define PREFORK_SINGLE 0x04
/* explicitly split nested substitution */
#define PREFORK_SPLIT 0x08
/* SHWORDSPLIT in parameter expn */
#define PREFORK_SHWORDSPLIT 0x10
/* SHWORDSPLIT forced off in nested subst */
#define PREFORK_NOSHWORDSPLIT 0x20
/*
* Structure for adding parameters in a module.
* The flags should declare the type; note PM_SCALAR is zero.
*
* Special hashes are recognized by getnfn so the PM_HASHED
* is optional. These get slightly non-standard attention:
* the function createspecialhash is used to create them.
*
* The get/set/unset attribute may be NULL; in that case the
* parameter is assigned methods suitable for handling the
* tie variable var, if that is not NULL, else standard methods.
*
* pm is set when the parameter is added to the parameter table
* and serves as a flag that the parameter has been added.
*/
struct paramdef {
char *name;
int flags;
void *var; /* tied internal variable, if any */
const void *gsu; /* get/set/unset structure, if special */
GetNodeFunc getnfn; /* function to get node, if special hash */
ScanTabFunc scantfn; /* function to scan table, if special hash */
Param pm; /* structure inserted into param table */
};
/*
* Shorthand for common uses of adding parameters, with no special
* hash properties.
*/
#define PARAMDEF(name, flags, var, gsu) \
{ name, flags, (void *) var, (void *) gsu, \
NULL, NULL, NULL \
}
/*
* Note that the following definitions are appropriate for defining
* parameters that reference a variable (var). Hence the get/set/unset
* methods used will assume var needs dereferencing to get the value.
*/
#define INTPARAMDEF(name, var) \
{ name, PM_INTEGER, (void *) var, NULL, NULL, NULL, NULL }
#define STRPARAMDEF(name, var) \
{ name, PM_SCALAR, (void *) var, NULL, NULL, NULL, NULL }
#define ARRPARAMDEF(name, var) \
{ name, PM_ARRAY, (void *) var, NULL, NULL, NULL, NULL }
/*
* The following is appropriate for a module function that behaves
* in a special fashion. Parameters used in a module that don't
* have special behaviour shouldn't be declared in a table but
* should just be added with the standard parameter functions.
*
* These parameters are not marked as removable, since they
* shouldn't be loaded as local parameters, unlike the special
* Zle parameters that are added and removed on each call to Zle.
* We add the PM_REMOVABLE flag when removing the feature corresponding
* to the parameter.
*/
#define SPECIALPMDEF(name, flags, gsufn, getfn, scanfn) \
{ name, flags | PM_SPECIAL | PM_HIDE | PM_HIDEVAL, \
NULL, gsufn, getfn, scanfn, NULL }
#define setsparam(S,V) assignsparam(S,V,0)
#define setaparam(S,V) assignaparam(S,V,0)
/*
* Flags for assignsparam and assignaparam.
*/
enum {
ASSPM_AUGMENT = 1 << 0,
ASSPM_WARN_CREATE = 1 << 1,
ASSPM_ENV_IMPORT = 1 << 2
};
/* node for named directory hash table (nameddirtab) */
struct nameddir {
struct hashnode node;
char *dir; /* the directory in full */
int diff; /* strlen(.dir) - strlen(.nam) */
};
/* flags for named directories */
/* DISABLED is defined (1<<0) */
#define ND_USERNAME (1<<1) /* nam is actually a username */
#define ND_NOABBREV (1<<2) /* never print as abbrev (PWD or OLDPWD) */
/* Storage for single group/name mapping */
typedef struct {
/* Name of group */
char *name;
/* Group identifier */
gid_t gid;
} groupmap;
typedef groupmap *Groupmap;
/* Storage for a set of group/name mappings */
typedef struct {
/* The set of name to gid mappings */
Groupmap array;
/* A count of the valid entries in groupmap. */
int num;
} groupset;
typedef groupset *Groupset;
/* flags for controlling printing of hash table nodes */
#define PRINT_NAMEONLY (1<<0)
#define PRINT_TYPE (1<<1)
#define PRINT_LIST (1<<2)
#define PRINT_KV_PAIR (1<<3)
#define PRINT_INCLUDEVALUE (1<<4)
#define PRINT_TYPESET (1<<5)
/* flags for printing for the whence builtin */
#define PRINT_WHENCE_CSH (1<<6)
#define PRINT_WHENCE_VERBOSE (1<<7)
#define PRINT_WHENCE_SIMPLE (1<<8)
#define PRINT_WHENCE_FUNCDEF (1<<9)
#define PRINT_WHENCE_WORD (1<<10)
/* Return values from loop() */
enum loop_return {
/* Loop executed OK */
LOOP_OK,
/* Loop executed no code */
LOOP_EMPTY,
/* Loop encountered an error */
LOOP_ERROR
};
/* Return values from source() */
enum source_return {
/* Source ran OK */
SOURCE_OK = 0,
/* File not found */
SOURCE_NOT_FOUND = 1,
/* Internal error sourcing file */
SOURCE_ERROR = 2
};
/***********************************/
/* Definitions for history control */
/***********************************/
/* history entry */
struct histent {
struct hashnode node;
Histent up; /* previous line (moving upward) */
Histent down; /* next line (moving downward) */
char *zle_text; /* the edited history line,
* a metafied, NULL-terminated string,
* i.e the same format as the original
* entry
*/
time_t stim; /* command started time (datestamp) */
time_t ftim; /* command finished time */
short *words; /* Position of words in history */
/* line: as pairs of start, end */
int nwords; /* Number of words in history line */
zlong histnum; /* A sequential history number */
};
#define HIST_MAKEUNIQUE 0x00000001 /* Kill this new entry if not unique */
#define HIST_OLD 0x00000002 /* Command is already written to disk*/
#define HIST_READ 0x00000004 /* Command was read back from disk*/
#define HIST_DUP 0x00000008 /* Command duplicates a later line */
#define HIST_FOREIGN 0x00000010 /* Command came from another shell */
#define HIST_TMPSTORE 0x00000020 /* Kill when user enters another cmd */
#define HIST_NOWRITE 0x00000040 /* Keep internally but don't write */
#define GETHIST_UPWARD (-1)
#define GETHIST_DOWNWARD 1
#define GETHIST_EXACT 0
/* Parts of the code where history expansion is disabled *
* should be within a pair of STOPHIST ... ALLOWHIST */
#define STOPHIST (stophist += 4);
#define ALLOWHIST (stophist -= 4);
#define HISTFLAG_DONE 1
#define HISTFLAG_NOEXEC 2
#define HISTFLAG_RECALL 4
#define HISTFLAG_SETTY 8
#define HFILE_APPEND 0x0001
#define HFILE_SKIPOLD 0x0002
#define HFILE_SKIPDUPS 0x0004
#define HFILE_SKIPFOREIGN 0x0008
#define HFILE_FAST 0x0010
#define HFILE_NO_REWRITE 0x0020
#define HFILE_USE_OPTIONS 0x8000
/*
* Flags argument to bufferwords() used
* also by lexflags variable.
*/
/*
* Kick the lexer into special string-analysis
* mode without parsing. Any bit set in
* the flags has this effect, but this
* has otherwise all the default effects.
*/
#define LEXFLAGS_ACTIVE 0x0001
/*
* Being used from zle. This is slightly more intrusive
* (=> grotesquely non-modular) than use from within
* the main shell, so it's a separate flag.
*/
#define LEXFLAGS_ZLE 0x0002
/*
* Parse comments and treat each comment as a single string
*/
#define LEXFLAGS_COMMENTS_KEEP 0x0004
/*
* Parse comments and strip them.
*/
#define LEXFLAGS_COMMENTS_STRIP 0x0008
/*
* Either of the above
*/
#define LEXFLAGS_COMMENTS (LEXFLAGS_COMMENTS_KEEP|LEXFLAGS_COMMENTS_STRIP)
/*
* Treat newlines as whitespace
*/
#define LEXFLAGS_NEWLINE 0x0010
/******************************************/
/* Definitions for programable completion */
/******************************************/
/* Nothing special. */
#define IN_NOTHING 0
/* In command position. */
#define IN_CMD 1
/* In a mathematical environment. */
#define IN_MATH 2
/* In a condition. */
#define IN_COND 3
/* In a parameter assignment (e.g. `foo=bar'). */
#define IN_ENV 4
/* In a parameter name in an assignment. */
#define IN_PAR 5
/******************************/
/* Definition for zsh options */
/******************************/
/* Possible values of emulation */
#define EMULATE_CSH (1<<1) /* C shell */
#define EMULATE_KSH (1<<2) /* Korn shell */
#define EMULATE_SH (1<<3) /* Bourne shell */
#define EMULATE_ZSH (1<<4) /* `native' mode */
/* Test for a shell emulation. Use this rather than emulation directly. */
#define EMULATION(X) (emulation & (X))
/* Return only base shell emulation field. */
#define SHELL_EMULATION() (emulation & ((1<<5)-1))
/* Additional flags */
#define EMULATE_FULLY (1<<5) /* "emulate -R" in effect */
/*
* Higher bits are used in options.c, record lowest unused bit...
*/
#define EMULATE_UNUSED (1<<6)
/* option indices */
enum {
OPT_INVALID,
ALIASESOPT,
ALLEXPORT,
ALWAYSLASTPROMPT,
ALWAYSTOEND,
APPENDHISTORY,
AUTOCD,
AUTOCONTINUE,
AUTOLIST,
AUTOMENU,
AUTONAMEDIRS,
AUTOPARAMKEYS,
AUTOPARAMSLASH,
AUTOPUSHD,
AUTOREMOVESLASH,
AUTORESUME,
BADPATTERN,
BANGHIST,
BAREGLOBQUAL,
BASHAUTOLIST,
BASHREMATCH,
BEEP,
BGNICE,
BRACECCL,
BSDECHO,
CASEGLOB,
CASEMATCH,
CBASES,
CDABLEVARS,
CHASEDOTS,
CHASELINKS,
CHECKJOBS,
CLOBBER,
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,
GLOBSUBST,
HASHCMDS,
HASHDIRS,
HASHEXECUTABLESONLY,
HASHLISTALL,
HISTALLOWCLOBBER,
HISTBEEP,
HISTEXPIREDUPSFIRST,
HISTFCNTLLOCK,
HISTFINDNODUPS,
HISTIGNOREALLDUPS,
HISTIGNOREDUPS,
HISTIGNORESPACE,
HISTLEXWORDS,
HISTNOFUNCTIONS,
HISTNOSTORE,
HISTREDUCEBLANKS,
HISTSAVEBYCOPY,
HISTSAVENODUPS,
HISTSUBSTPATTERN,
HISTVERIFY,
HUP,
IGNOREBRACES,
IGNORECLOSEBRACES,
IGNOREEOF,
INCAPPENDHISTORY,
INCAPPENDHISTORYTIME,
INTERACTIVE,
INTERACTIVECOMMENTS,
KSHARRAYS,
KSHAUTOLOAD,
KSHGLOB,
KSHOPTIONPRINT,
KSHTYPESET,
KSHZEROSUBSCRIPT,
LISTAMBIGUOUS,
LISTBEEP,
LISTPACKED,
LISTROWSFIRST,
LISTTYPES,
LOCALLOOPS,
LOCALOPTIONS,
LOCALPATTERNS,
LOCALTRAPS,
LOGINSHELL,
LONGLISTJOBS,
MAGICEQUALSUBST,
MAILWARNING,
MARKDIRS,
MENUCOMPLETE,
MONITOR,
MULTIBYTE,
MULTIFUNCDEF,
MULTIOS,
NOMATCH,
NOTIFY,
NULLGLOB,
NUMERICGLOBSORT,
OCTALZEROES,
OVERSTRIKE,
PATHDIRS,
PATHSCRIPT,
PIPEFAIL,
POSIXALIASES,
POSIXARGZERO,
POSIXBUILTINS,
POSIXCD,
POSIXIDENTIFIERS,
POSIXJOBS,
POSIXSTRINGS,
POSIXTRAPS,
PRINTEIGHTBIT,
PRINTEXITVALUE,
PRIVILEGED,
PROMPTBANG,
PROMPTCR,
PROMPTPERCENT,
PROMPTSP,
PROMPTSUBST,
PUSHDIGNOREDUPS,
PUSHDMINUS,
PUSHDSILENT,
PUSHDTOHOME,
RCEXPANDPARAM,
RCQUOTES,
RCS,
RECEXACT,
REMATCHPCRE,
RESTRICTED,
RMSTARSILENT,
RMSTARWAIT,
SHAREHISTORY,
SHFILEEXPANSION,
SHGLOB,
SHINSTDIN,
SHNULLCMD,
SHOPTIONLETTERS,
SHORTLOOPS,
SHWORDSPLIT,
SINGLECOMMAND,
SINGLELINEZLE,
SOURCETRACE,
SUNKEYBOARDHACK,
TRANSIENTRPROMPT,
TRAPSASYNC,
TYPESETSILENT,
UNSET,
VERBOSE,
VIMODE,
WARNCREATEGLOBAL,
XTRACE,
USEZLE,
DVORAK,
OPT_SIZE
};
/*
* Size required to fit an option number.
* If OPT_SIZE goes above 256 this will need to expand.
*/
typedef unsigned char OptIndex;
#undef isset
#define isset(X) (opts[X])
#define unset(X) (!opts[X])
#define interact (isset(INTERACTIVE))
#define jobbing (isset(MONITOR))
#define islogin (isset(LOGINSHELL))
/*
* Record of emulation and options that need to be set
* for a full "emulate".
*/
struct emulation_options {
/* The emulation itself */
int emulation;
/* The number of options in on_opts. */
int n_on_opts;
/* The number of options in off_opts. */
int n_off_opts;
/*
* Array of options to be turned on.
* Only options specified explicitly in the emulate command
* are recorded. Null if n_on_opts is zero.
*/
OptIndex *on_opts;
/* Array of options to be turned off, similar. */
OptIndex *off_opts;
};
/***********************************************/
/* Definitions for terminal and display control */
/***********************************************/
/* tty state structure */
struct ttyinfo {
#ifdef HAVE_TERMIOS_H
struct termios tio;
#else
# ifdef HAVE_TERMIO_H
struct termio tio;
# else
struct sgttyb sgttyb;
int lmodes;
struct tchars tchars;
struct ltchars ltchars;
# endif
#endif
#ifdef TIOCGWINSZ
struct winsize winsize;
#endif
};
#ifndef __INTERIX
/* defines for whether tabs expand to spaces */
#if defined(HAVE_TERMIOS_H) || defined(HAVE_TERMIO_H)
#define SGTTYFLAG shttyinfo.tio.c_oflag
#else /* we're using sgtty */
#define SGTTYFLAG shttyinfo.sgttyb.sg_flags
#endif
# ifdef TAB3
#define SGTABTYPE TAB3
# else
# ifdef OXTABS
#define SGTABTYPE OXTABS
# else
# ifdef XTABS
#define SGTABTYPE XTABS
# endif
# endif
# endif
#endif
/* flags for termflags */
#define TERM_BAD 0x01 /* terminal has extremely basic capabilities */
#define TERM_UNKNOWN 0x02 /* unknown terminal type */
#define TERM_NOUP 0x04 /* terminal has no up capability */
#define TERM_SHORT 0x08 /* terminal is < 3 lines high */
#define TERM_NARROW 0x10 /* terminal is < 3 columns wide */
/* interesting termcap strings */
#define TCCLEARSCREEN 0
#define TCLEFT 1
#define TCMULTLEFT 2
#define TCRIGHT 3
#define TCMULTRIGHT 4
#define TCUP 5
#define TCMULTUP 6
#define TCDOWN 7
#define TCMULTDOWN 8
#define TCDEL 9
#define TCMULTDEL 10
#define TCINS 11
#define TCMULTINS 12
#define TCCLEAREOD 13
#define TCCLEAREOL 14
#define TCINSLINE 15
#define TCDELLINE 16
#define TCNEXTTAB 17
#define TCBOLDFACEBEG 18
#define TCSTANDOUTBEG 19
#define TCUNDERLINEBEG 20
#define TCALLATTRSOFF 21
#define TCSTANDOUTEND 22
#define TCUNDERLINEEND 23
#define TCHORIZPOS 24
#define TCUPCURSOR 25
#define TCDOWNCURSOR 26
#define TCLEFTCURSOR 27
#define TCRIGHTCURSOR 28
#define TCSAVECURSOR 29
#define TCRESTRCURSOR 30
#define TCBACKSPACE 31
#define TCFGCOLOUR 32
#define TCBGCOLOUR 33
#define TC_COUNT 34
#define tccan(X) (tclen[X])
/*
* Text attributes for displaying in ZLE
*/
#define TXTBOLDFACE 0x0001
#define TXTSTANDOUT 0x0002
#define TXTUNDERLINE 0x0004
#define TXTFGCOLOUR 0x0008
#define TXTBGCOLOUR 0x0010
#define TXT_ATTR_ON_MASK 0x001F
#define txtisset(X) (txtattrmask & (X))
#define txtset(X) (txtattrmask |= (X))
#define txtunset(X) (txtattrmask &= ~(X))
#define TXTNOBOLDFACE 0x0020
#define TXTNOSTANDOUT 0x0040
#define TXTNOUNDERLINE 0x0080
#define TXTNOFGCOLOUR 0x0100
#define TXTNOBGCOLOUR 0x0200
#define TXT_ATTR_OFF_MASK 0x03E0
/* Bits to shift off right to get on */
#define TXT_ATTR_OFF_ON_SHIFT 5
#define TXT_ATTR_OFF_FROM_ON(attr) \
(((attr) & TXT_ATTR_ON_MASK) << TXT_ATTR_OFF_ON_SHIFT)
#define TXT_ATTR_ON_FROM_OFF(attr) \
(((attr) & TXT_ATTR_OFF_MASK) >> TXT_ATTR_OFF_ON_SHIFT)
/*
* Indicates to zle_refresh.c that the character entry is an
* index into the list of multiword symbols.
*/
#define TXT_MULTIWORD_MASK 0x0400
/* Mask for colour to use in foreground */
#define TXT_ATTR_FG_COL_MASK 0x000FF000
/* Bits to shift the foreground colour */
#define TXT_ATTR_FG_COL_SHIFT (12)
/* Mask for colour to use in background */
#define TXT_ATTR_BG_COL_MASK 0x0FF00000
/* Bits to shift the background colour */
#define TXT_ATTR_BG_COL_SHIFT (20)
/* Flag to use termcap AF sequence to set colour, if available */
#define TXT_ATTR_FG_TERMCAP 0x10000000
/* Flag to use termcap AB sequence to set colour, if available */
#define TXT_ATTR_BG_TERMCAP 0x20000000
/* Things to turn on, including values for the colour elements */
#define TXT_ATTR_ON_VALUES_MASK \
(TXT_ATTR_ON_MASK|TXT_ATTR_FG_COL_MASK|TXT_ATTR_BG_COL_MASK|\
TXT_ATTR_FG_TERMCAP|TXT_ATTR_BG_TERMCAP)
/* Mask out everything to do with setting a foreground colour */
#define TXT_ATTR_FG_ON_MASK \
(TXTFGCOLOUR|TXT_ATTR_FG_COL_MASK|TXT_ATTR_FG_TERMCAP)
/* Mask out everything to do with setting a background colour */
#define TXT_ATTR_BG_ON_MASK \
(TXTBGCOLOUR|TXT_ATTR_BG_COL_MASK|TXT_ATTR_BG_TERMCAP)
/* Mask out everything to do with activating colours */
#define TXT_ATTR_COLOUR_ON_MASK \
(TXT_ATTR_FG_ON_MASK|TXT_ATTR_BG_ON_MASK)
#define txtchangeisset(T,X) ((T) & (X))
#define txtchangeget(T,A) (((T) & A ## _MASK) >> A ## _SHIFT)
#define txtchangeset(T, X, Y) ((void)(T && (*T |= (X), *T &= ~(Y))))
/*
* For outputting sequences to change colour: specify foreground
* or background.
*/
#define COL_SEQ_FG (0)
#define COL_SEQ_BG (1)
#define COL_SEQ_COUNT (2)
/*
* Flags to testcap() and set_colour_attribute (which currently only
* handles TSC_PROMPT).
*/
enum {
/* Raw output: use stdout rather than shout */
TSC_RAW = 0x0001,
/* Output to current prompt buffer: only used when assembling prompt */
TSC_PROMPT = 0x0002,
/* Mask to get the output mode */
TSC_OUTPUT_MASK = 0x0003,
/* Change needs reset of other attributes */
TSC_DIRTY = 0x0004
};
/****************************************/
/* Definitions for the %_ prompt escape */
/****************************************/
#define CMDSTACKSZ 256
#define CS_FOR 0
#define CS_WHILE 1
#define CS_REPEAT 2
#define CS_SELECT 3
#define CS_UNTIL 4
#define CS_IF 5
#define CS_IFTHEN 6
#define CS_ELSE 7
#define CS_ELIF 8
#define CS_MATH 9
#define CS_COND 10
#define CS_CMDOR 11
#define CS_CMDAND 12
#define CS_PIPE 13
#define CS_ERRPIPE 14
#define CS_FOREACH 15
#define CS_CASE 16
#define CS_FUNCDEF 17
#define CS_SUBSH 18
#define CS_CURSH 19
#define CS_ARRAY 20
#define CS_QUOTE 21
#define CS_DQUOTE 22
#define CS_BQUOTE 23
#define CS_CMDSUBST 24
#define CS_MATHSUBST 25
#define CS_ELIFTHEN 26
#define CS_HEREDOC 27
#define CS_HEREDOCD 28
#define CS_BRACE 29
#define CS_BRACEPAR 30
#define CS_ALWAYS 31
/* Increment as necessary */
#define CS_COUNT 32
/*********************
* Memory management *
*********************/
/*
* A Heapid is a type for identifying, uniquely up to the point where
* the count of new identifiers wraps. all heaps that are or
* (importantly) have been valid. Each valid heap is given an
* identifier, and every time we push a heap we save the old identifier
* and give the heap a new identifier so that when the heap is popped
* or freed we can spot anything using invalid memory from the popped
* heap.
*
* We could make this unsigned long long if we wanted a big range.
*/
typedef unsigned int Heapid;
#ifdef ZSH_HEAP_DEBUG
/* printf format specifier corresponding to Heapid */
#define HEAPID_FMT "%x"
/* Marker that memory is permanently allocated */
#define HEAPID_PERMANENT (UINT_MAX)
/*
* Heap debug verbosity.
* Bits to be 'or'ed into the variable also called heap_debug_verbosity.
*/
enum heap_debug_verbosity {
/* Report when we push a heap */
HDV_PUSH = 0x01,
/* Report when we pop a heap */
HDV_POP = 0x02,
/* Report when we create a new heap from which to allocate */
HDV_CREATE = 0x04,
/* Report every time we free a complete heap */
HDV_FREE = 0x08,
/* Report when we temporarily install a new set of heaps */
HDV_NEW = 0x10,
/* Report when we restore an old set of heaps */
HDV_OLD = 0x20,
/* Report when we temporarily switch heaps */
HDV_SWITCH = 0x40,
/*
* Report every time we allocate memory from the heap.
* This is very verbose, and arguably not very useful: we
* would expect to allocate memory from a heap we create.
* For much debugging heap_debug_verbosity = 0x7f should be sufficient.
*/
HDV_ALLOC = 0x80
};
#define HEAP_ERROR(heap_id) \
fprintf(stderr, "%s:%d: HEAP DEBUG: invalid heap: " HEAPID_FMT ".\n", \
__FILE__, __LINE__, heap_id)
#endif
/* heappush saves the current heap state using this structure */
struct heapstack {
struct heapstack *next; /* next one in list for this heap */
size_t used;
#ifdef ZSH_HEAP_DEBUG
Heapid heap_id;
#endif
};
/* A zsh heap. */
struct heap {
struct heap *next; /* next one */
size_t size; /* size of heap */
size_t used; /* bytes used from the heap */
struct heapstack *sp; /* used by pushheap() to save the value used */
#ifdef ZSH_HEAP_DEBUG
unsigned int heap_id;
#endif
/* Uncomment the following if the struct needs padding to 64-bit size. */
/* Make sure sizeof(heap) is a multiple of 8
#if defined(PAD_64_BIT) && !defined(__GNUC__)
size_t dummy;
#endif
*/
#define arena(X) ((char *) (X) + sizeof(struct heap))
}
#if defined(PAD_64_BIT) && defined(__GNUC__)
__attribute__ ((aligned (8)))
#endif
;
# define NEWHEAPS(h) do { Heap _switch_oldheaps = h = new_heaps(); do
# define OLDHEAPS while (0); old_heaps(_switch_oldheaps); } while (0);
# define SWITCHHEAPS(o, h) do { o = switch_heaps(h); do
# define SWITCHBACKHEAPS(o) while (0); switch_heaps(o); } while (0);
/****************/
/* Debug macros */
/****************/
#ifdef DEBUG
#define STRINGIFY_LITERAL(x) # x
#define STRINGIFY(x) STRINGIFY_LITERAL(x)
#define ERRMSG(x) (__FILE__ ":" STRINGIFY(__LINE__) ": " x)
# define DPUTS(X,Y) if (!(X)) {;} else dputs(ERRMSG(Y))
# define DPUTS1(X,Y,Z1) if (!(X)) {;} else dputs(ERRMSG(Y), Z1)
# define DPUTS2(X,Y,Z1,Z2) if (!(X)) {;} else dputs(ERRMSG(Y), Z1, Z2)
# define DPUTS3(X,Y,Z1,Z2,Z3) if (!(X)) {;} else dputs(ERRMSG(Y), Z1, Z2, Z3)
#else
# define DPUTS(X,Y)
# define DPUTS1(X,Y,Z1)
# define DPUTS2(X,Y,Z1,Z2)
# define DPUTS3(X,Y,Z1,Z2,Z3)
#endif
/**************************/
/* Signal handling macros */
/**************************/
/* These used in the sigtrapped[] array */
#define ZSIG_TRAPPED (1<<0) /* Signal is trapped */
#define ZSIG_IGNORED (1<<1) /* Signal is ignored */
#define ZSIG_FUNC (1<<2) /* Trap is a function, not an eval list */
/* Mask to get the above flags */
#define ZSIG_MASK (ZSIG_TRAPPED|ZSIG_IGNORED|ZSIG_FUNC)
/* No. of bits to shift local level when storing in sigtrapped */
#define ZSIG_ALIAS (1<<3) /* Trap is stored under an alias */
#define ZSIG_SHIFT 4
/*
* State of traps, stored in trap_state.
*/
enum trap_state {
/* Traps are not active; trap_return is not useful. */
TRAP_STATE_INACTIVE,
/*
* Traps are set but haven't triggered; trap_return gives
* minus function depth.
*/
TRAP_STATE_PRIMED,
/*
* Trap has triggered to force a return; trap_return givens
* return value.
*/
TRAP_STATE_FORCE_RETURN
};
#define IN_EVAL_TRAP() \
(intrap && !trapisfunc && traplocallevel == locallevel)
/*
* Bits in the errflag variable.
*/
enum errflag_bits {
/*
* Standard internal error bit.
*/
ERRFLAG_ERROR = 1,
/*
* User interrupt.
*/
ERRFLAG_INT = 2
};
/***********/
/* Sorting */
/***********/
typedef int (*CompareFn) _((const void *, const void *));
enum {
SORTIT_ANYOLDHOW = 0, /* Defaults */
SORTIT_IGNORING_CASE = 1,
SORTIT_NUMERICALLY = 2,
SORTIT_BACKWARDS = 4,
/*
* Ignore backslashes that quote another character---which may
* be another backslash; the second backslash is active.
*/
SORTIT_IGNORING_BACKSLASHES = 8,
/*
* Ignored by strmetasort(); used by paramsubst() to indicate
* there is some sorting to do.
*/
SORTIT_SOMEHOW = 16,
};
/*
* Element of array passed to qsort().
*/
struct sortelt {
/* The original string. */
char *orig;
/* The string used for comparison. */
const char *cmp;
/*
* The length of the string if passed down to the sort algorithm.
* Used to sort the lengths together with the strings.
*/
int origlen;
/*
* The length of the string, if needed, else -1.
* The length is only needed if there are embededded nulls.
*/
int len;
};
typedef struct sortelt *SortElt;
/*********************************************************/
/* Structures to save and restore for individual modules */
/*********************************************************/
/* History */
struct hist_stack {
int histactive;
int histdone;
int stophist;
int hlinesz;
char *hline;
char *hptr;
short *chwords;
int chwordlen;
int chwordpos;
int (*hgetc) _((void));
void (*hungetc) _((int));
void (*hwaddc) _((int));
void (*hwbegin) _((int));
void (*hwend) _((void));
void (*addtoline) _((int));
unsigned char *cstack;
int csp;
};
/*
* State of a lexical token buffer.
*
* It would be neater to include the pointer to the start of the buffer,
* however the current code structure means that the standard instance
* of this, tokstr, is visible in lots of places, so that's not
* convenient.
*/
struct lexbufstate {
/*
* Next character to be added.
* Set to NULL when the buffer is to be visible from elsewhere.
*/
char *ptr;
/* Allocated buffer size */
int siz;
/* Length in use */
int len;
};
/* Lexical analyser */
struct lex_stack {
int dbparens;
int isfirstln;
int isfirstch;
int lexflags;
enum lextok tok;
char *tokstr;
char *zshlextext;
struct lexbufstate lexbuf;
int lex_add_raw;
char *tokstr_raw;
struct lexbufstate lexbuf_raw;
int lexstop;
zlong toklineno;
};
/* Parser */
struct parse_stack {
struct heredocs *hdocs;
int incmdpos;
int aliasspaceflag;
int incond;
int inredir;
int incasepat;
int isnewlin;
int infor;
int 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
/* 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.
*/
#if defined(BROKEN_WCWIDTH) && (defined(__STDC_ISO_10646__) || defined(__APPLE__))
#define WCWIDTH(wc) mk_wcwidth(wc)
#else
#define WCWIDTH(wc) wcwidth(wc)
#endif
/*
* Note WCWIDTH_WINT() takes wint_t, typically as a convchar_t.
* It's written to use the wint_t from mb_metacharlenconv() without
* further tests.
*
* This version has a non-multibyte definition that simply returns
* 1. We never expose WCWIDTH() in the non-multibyte world since
* it's just a proxy for wcwidth() itself.
*/
#define WCWIDTH_WINT(wc) zwcwidth(wc)
#define MB_INCOMPLETE ((size_t)-2)
#define MB_INVALID ((size_t)-1)
/*
* MB_CUR_MAX is the maximum number of bytes that a single wide
* character will convert into. We use it to keep strings
* sufficiently long. It should always be defined, but if it isn't
* just assume we are using Unicode which requires 6 characters.
* (Note that it's not necessarily defined to a constant.)
*/
#ifndef MB_CUR_MAX
#define MB_CUR_MAX 6
#endif
/* Convert character or string to wide character or string */
#define ZWC(c) L ## c
#define ZWS(s) L ## s
/*
* Test for a combining character.
*
* wc is assumed to be a wchar_t (i.e. we don't need zwcwidth).
*
* Pedantic note: in Unicode, a combining character need not be
* zero length. However, we are concerned here about display;
* we simply need to know whether the character will be displayed
* on top of another one. We use "combining character" in this
* sense throughout the shell. I am not aware of a way of
* detecting the Unicode trait in standard libraries.
*/
#ifdef BROKEN_WCWIDTH
/*
* We can't be quite sure the wcwidth we've provided is entirely
* in agreement with the system's, so be extra safe.
*/
#define IS_COMBINING(wc) (wc != 0 && WCWIDTH(wc) == 0 && !iswcntrl(wc))
#else
#define IS_COMBINING(wc) (wc != 0 && WCWIDTH(wc) == 0)
#endif
/*
* Test for the base of a combining character.
*
* We assume a combining character can be successfully displayed with
* any non-space printable character, which is what a graphic character
* is, as long as it has non-zero width. We need to avoid all forms of
* space because the shell will split words on any whitespace.
*/
#define IS_BASECHAR(wc) (iswgraph(wc) && WCWIDTH(wc) > 0)
#else /* not MULTIBYTE_SUPPORT */
#define MB_METACHARINIT()
typedef int convchar_t;
#define MB_METACHARLENCONV(str, cp) metacharlenconv((str), (cp))
#define MB_METACHARLEN(str) (*(str) == Meta ? 2 : 1)
#define MB_METASTRLEN(str) ztrlen(str)
#define MB_METASTRWIDTH(str) ztrlen(str)
#define MB_METASTRLEN2(str, widthp) ztrlen(str)
#define 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 */