1 /* $OpenBSD: sh.h,v 1.58 2016/09/08 15:50:50 millert Exp $ */ 2 3 /* 4 * Public Domain Bourne/Korn shell 5 */ 6 7 /* $From: sh.h,v 1.2 1994/05/19 18:32:40 michael Exp michael $ */ 8 9 #include "config.h" /* system and option configuration info */ 10 11 /* Start of common headers */ 12 13 #include <setjmp.h> 14 #include <stdarg.h> 15 #include <signal.h> 16 #include <stdbool.h> 17 18 /* end of common headers */ 19 20 #define NELEM(a) (sizeof(a) / sizeof((a)[0])) 21 #define BIT(i) (1<<(i)) /* define bit in flag */ 22 23 #define NUFILE 32 /* Number of user-accessible files */ 24 #define FDBASE 10 /* First file usable by Shell */ 25 26 #define BITS(t) (CHAR_BIT * sizeof(t)) 27 28 /* Make MAGIC a char that might be printed to make bugs more obvious, but 29 * not a char that is used often. Also, can't use the high bit as it causes 30 * portability problems (calling strchr(x, 0x80|'x') is error prone). 31 */ 32 #define MAGIC (7) /* prefix for *?[!{,} during expand */ 33 #define ISMAGIC(c) ((unsigned char)(c) == MAGIC) 34 35 #define LINE 2048 /* input line size */ 36 #define PATH 1024 /* pathname size (todo: PATH_MAX/pathconf()) */ 37 38 extern const char *kshname; /* $0 */ 39 extern pid_t kshpid; /* $$, shell pid */ 40 extern pid_t procpid; /* pid of executing process */ 41 extern uid_t ksheuid; /* effective uid of shell */ 42 extern int exstat; /* exit status */ 43 extern int subst_exstat; /* exit status of last $(..)/`..` */ 44 extern const char *safe_prompt; /* safe prompt if PS1 substitution fails */ 45 extern char username[]; /* username for \u prompt expansion */ 46 47 /* 48 * Area-based allocation built on malloc/free 49 */ 50 typedef struct Area { 51 struct link *freelist; /* free list */ 52 } Area; 53 54 extern Area aperm; /* permanent object space */ 55 #define APERM &aperm 56 #define ATEMP &genv->area 57 58 #ifdef KSH_DEBUG 59 # define kshdebug_init() kshdebug_init_() 60 # define kshdebug_printf(a) kshdebug_printf_ a 61 # define kshdebug_dump(a) kshdebug_dump_ a 62 #else /* KSH_DEBUG */ 63 # define kshdebug_init() 64 # define kshdebug_printf(a) 65 # define kshdebug_dump(a) 66 #endif /* KSH_DEBUG */ 67 68 /* 69 * parsing & execution environment 70 */ 71 struct env { 72 short type; /* environment type - see below */ 73 short flags; /* EF_* */ 74 Area area; /* temporary allocation area */ 75 struct block *loc; /* local variables and functions */ 76 short *savefd; /* original redirected fd's */ 77 struct env *oenv; /* link to previous environment */ 78 sigjmp_buf jbuf; /* long jump back to env creator */ 79 struct temp *temps; /* temp files */ 80 }; 81 extern struct env *genv; 82 83 /* struct env.type values */ 84 #define E_NONE 0 /* dummy environment */ 85 #define E_PARSE 1 /* parsing command # */ 86 #define E_FUNC 2 /* executing function # */ 87 #define E_INCL 3 /* including a file via . # */ 88 #define E_EXEC 4 /* executing command tree */ 89 #define E_LOOP 5 /* executing for/while # */ 90 #define E_ERRH 6 /* general error handler # */ 91 /* # indicates env has valid jbuf (see unwind()) */ 92 93 /* struct env.flag values */ 94 #define EF_FUNC_PARSE BIT(0) /* function being parsed */ 95 #define EF_BRKCONT_PASS BIT(1) /* set if E_LOOP must pass break/continue on */ 96 #define EF_FAKE_SIGDIE BIT(2) /* hack to get info from unwind to quitenv */ 97 98 /* Do breaks/continues stop at env type e? */ 99 #define STOP_BRKCONT(t) ((t) == E_NONE || (t) == E_PARSE \ 100 || (t) == E_FUNC || (t) == E_INCL) 101 /* Do returns stop at env type e? */ 102 #define STOP_RETURN(t) ((t) == E_FUNC || (t) == E_INCL) 103 104 /* values for siglongjmp(e->jbuf, 0) */ 105 #define LRETURN 1 /* return statement */ 106 #define LEXIT 2 /* exit statement */ 107 #define LERROR 3 /* errorf() called */ 108 #define LLEAVE 4 /* untrappable exit/error */ 109 #define LINTR 5 /* ^C noticed */ 110 #define LBREAK 6 /* break statement */ 111 #define LCONTIN 7 /* continue statement */ 112 #define LSHELL 8 /* return to interactive shell() */ 113 #define LAEXPR 9 /* error in arithmetic expression */ 114 115 /* option processing */ 116 #define OF_CMDLINE 0x01 /* command line */ 117 #define OF_SET 0x02 /* set builtin */ 118 #define OF_SPECIAL 0x04 /* a special variable changing */ 119 #define OF_INTERNAL 0x08 /* set internally by shell */ 120 #define OF_ANY (OF_CMDLINE | OF_SET | OF_SPECIAL | OF_INTERNAL) 121 122 struct option { 123 const char *name; /* long name of option */ 124 char c; /* character flag (if any) */ 125 short flags; /* OF_* */ 126 }; 127 extern const struct option options[]; 128 129 /* 130 * flags (the order of these enums MUST match the order in misc.c(options[])) 131 */ 132 enum sh_flag { 133 FEXPORT = 0, /* -a: export all */ 134 #ifdef BRACE_EXPAND 135 FBRACEEXPAND, /* enable {} globbing */ 136 #endif 137 FBGNICE, /* bgnice */ 138 FCOMMAND, /* -c: (invocation) execute specified command */ 139 FCSHHISTORY, /* csh-style history enabled */ 140 #ifdef EMACS 141 FEMACS, /* emacs command editing */ 142 FEMACSUSEMETA, /* use 8th bit as meta */ 143 #endif 144 FERREXIT, /* -e: quit on error */ 145 #ifdef EMACS 146 FGMACS, /* gmacs command editing */ 147 #endif 148 FIGNOREEOF, /* eof does not exit */ 149 FTALKING, /* -i: interactive */ 150 FKEYWORD, /* -k: name=value anywhere */ 151 FLOGIN, /* -l: a login shell */ 152 FMARKDIRS, /* mark dirs with / in file name completion */ 153 FMONITOR, /* -m: job control monitoring */ 154 FNOCLOBBER, /* -C: don't overwrite existing files */ 155 FNOEXEC, /* -n: don't execute any commands */ 156 FNOGLOB, /* -f: don't do file globbing */ 157 FNOHUP, /* -H: don't kill running jobs when login shell exits */ 158 FNOLOG, /* don't save functions in history (ignored) */ 159 #ifdef JOBS 160 FNOTIFY, /* -b: asynchronous job completion notification */ 161 #endif 162 FNOUNSET, /* -u: using an unset var is an error */ 163 FPHYSICAL, /* -o physical: don't do logical cd's/pwd's */ 164 FPOSIX, /* -o posix: be posixly correct */ 165 FPRIVILEGED, /* -p: use suid_profile */ 166 FRESTRICTED, /* -r: restricted shell */ 167 FSH, /* -o sh: favor sh behaviour */ 168 FSTDIN, /* -s: (invocation) parse stdin */ 169 FTRACKALL, /* -h: create tracked aliases for all commands */ 170 FVERBOSE, /* -v: echo input */ 171 #ifdef VI 172 FVI, /* vi command editing */ 173 FVIRAW, /* always read in raw mode (ignored) */ 174 FVISHOW8, /* display chars with 8th bit set as is (versus M-) */ 175 FVITABCOMPLETE, /* enable tab as file name completion char */ 176 FVIESCCOMPLETE, /* enable ESC as file name completion in command mode */ 177 #endif 178 FXTRACE, /* -x: execution trace */ 179 FTALKING_I, /* (internal): initial shell was interactive */ 180 FNFLAGS /* (place holder: how many flags are there) */ 181 }; 182 183 #define Flag(f) (shell_flags[(int) (f)]) 184 185 extern char shell_flags[FNFLAGS]; 186 187 extern char null[]; /* null value for variable */ 188 189 enum temp_type { 190 TT_HEREDOC_EXP, /* expanded heredoc */ 191 TT_HIST_EDIT /* temp file used for history editing (fc -e) */ 192 }; 193 typedef enum temp_type Temp_type; 194 /* temp/heredoc files. The file is removed when the struct is freed. */ 195 struct temp { 196 struct temp *next; 197 struct shf *shf; 198 int pid; /* pid of process parsed here-doc */ 199 Temp_type type; 200 char *name; 201 }; 202 203 /* 204 * stdio and our IO routines 205 */ 206 207 #define shl_spare (&shf_iob[0]) /* for c_read()/c_print() */ 208 #define shl_stdout (&shf_iob[1]) 209 #define shl_out (&shf_iob[2]) 210 extern int shl_stdout_ok; 211 212 /* 213 * trap handlers 214 */ 215 typedef struct trap { 216 int signal; /* signal number */ 217 const char *name; /* short name */ 218 const char *mess; /* descriptive name */ 219 char *trap; /* trap command */ 220 volatile sig_atomic_t set; /* trap pending */ 221 int flags; /* TF_* */ 222 sig_t cursig; /* current handler (valid if TF_ORIG_* set) */ 223 sig_t shtrap; /* shell signal handler */ 224 } Trap; 225 226 /* values for Trap.flags */ 227 #define TF_SHELL_USES BIT(0) /* shell uses signal, user can't change */ 228 #define TF_USER_SET BIT(1) /* user has (tried to) set trap */ 229 #define TF_ORIG_IGN BIT(2) /* original action was SIG_IGN */ 230 #define TF_ORIG_DFL BIT(3) /* original action was SIG_DFL */ 231 #define TF_EXEC_IGN BIT(4) /* restore SIG_IGN just before exec */ 232 #define TF_EXEC_DFL BIT(5) /* restore SIG_DFL just before exec */ 233 #define TF_DFL_INTR BIT(6) /* when received, default action is LINTR */ 234 #define TF_TTY_INTR BIT(7) /* tty generated signal (see j_waitj) */ 235 #define TF_CHANGED BIT(8) /* used by runtrap() to detect trap changes */ 236 #define TF_FATAL BIT(9) /* causes termination if not trapped */ 237 238 /* values for setsig()/setexecsig() flags argument */ 239 #define SS_RESTORE_MASK 0x3 /* how to restore a signal before an exec() */ 240 #define SS_RESTORE_CURR 0 /* leave current handler in place */ 241 #define SS_RESTORE_ORIG 1 /* restore original handler */ 242 #define SS_RESTORE_DFL 2 /* restore to SIG_DFL */ 243 #define SS_RESTORE_IGN 3 /* restore to SIG_IGN */ 244 #define SS_FORCE BIT(3) /* set signal even if original signal ignored */ 245 #define SS_USER BIT(4) /* user is doing the set (ie, trap command) */ 246 #define SS_SHTRAP BIT(5) /* trap for internal use (CHLD,ALRM,WINCH) */ 247 248 #define SIGEXIT_ 0 /* for trap EXIT */ 249 #define SIGERR_ NSIG /* for trap ERR */ 250 251 extern volatile sig_atomic_t trap; /* traps pending? */ 252 extern volatile sig_atomic_t intrsig; /* pending trap interrupts command */ 253 extern volatile sig_atomic_t fatal_trap; /* received a fatal signal */ 254 extern volatile sig_atomic_t got_sigwinch; 255 extern Trap sigtraps[NSIG+1]; 256 257 /* 258 * TMOUT support 259 */ 260 /* values for ksh_tmout_state */ 261 enum tmout_enum { 262 TMOUT_EXECUTING = 0, /* executing commands */ 263 TMOUT_READING, /* waiting for input */ 264 TMOUT_LEAVING /* have timed out */ 265 }; 266 extern unsigned int ksh_tmout; 267 extern enum tmout_enum ksh_tmout_state; 268 269 /* For "You have stopped jobs" message */ 270 extern int really_exit; 271 272 /* 273 * fast character classes 274 */ 275 #define C_ALPHA BIT(0) /* a-z_A-Z */ 276 /* was C_DIGIT */ 277 #define C_LEX1 BIT(2) /* \0 \t\n|&;<>() */ 278 #define C_VAR1 BIT(3) /* *@#!$-? */ 279 #define C_IFSWS BIT(4) /* \t \n (IFS white space) */ 280 #define C_SUBOP1 BIT(5) /* "=-+?" */ 281 #define C_SUBOP2 BIT(6) /* "#%" */ 282 #define C_IFS BIT(7) /* $IFS */ 283 #define C_QUOTE BIT(8) /* \n\t"#$&'()*;<>?[\`| (needing quoting) */ 284 285 extern short ctypes []; 286 287 #define ctype(c, t) !!(ctypes[(unsigned char)(c)]&(t)) 288 #define letter(c) ctype(c, C_ALPHA) 289 #define digit(c) isdigit((unsigned char)(c)) 290 #define letnum(c) (ctype(c, C_ALPHA) || isdigit((unsigned char)(c))) 291 292 extern int ifs0; /* for "$*" */ 293 294 /* Argument parsing for built-in commands and getopts command */ 295 296 /* Values for Getopt.flags */ 297 #define GF_ERROR BIT(0) /* call errorf() if there is an error */ 298 #define GF_PLUSOPT BIT(1) /* allow +c as an option */ 299 #define GF_NONAME BIT(2) /* don't print argv[0] in errors */ 300 301 /* Values for Getopt.info */ 302 #define GI_MINUS BIT(0) /* an option started with -... */ 303 #define GI_PLUS BIT(1) /* an option started with +... */ 304 #define GI_MINUSMINUS BIT(2) /* arguments were ended with -- */ 305 306 typedef struct { 307 int optind; 308 int uoptind;/* what user sees in $OPTIND */ 309 char *optarg; 310 int flags; /* see GF_* */ 311 int info; /* see GI_* */ 312 unsigned int p; /* 0 or index into argv[optind - 1] */ 313 char buf[2]; /* for bad option OPTARG value */ 314 } Getopt; 315 316 extern Getopt builtin_opt; /* for shell builtin commands */ 317 extern Getopt user_opt; /* parsing state for getopts builtin command */ 318 319 /* This for co-processes */ 320 321 typedef int Coproc_id; /* something that won't (realistically) wrap */ 322 struct coproc { 323 int read; /* pipe from co-process's stdout */ 324 int readw; /* other side of read (saved temporarily) */ 325 int write; /* pipe to co-process's stdin */ 326 Coproc_id id; /* id of current output pipe */ 327 int njobs; /* number of live jobs using output pipe */ 328 void *job; /* 0 or job of co-process using input pipe */ 329 }; 330 extern struct coproc coproc; 331 332 /* Used in jobs.c and by coprocess stuff in exec.c */ 333 extern sigset_t sm_default, sm_sigchld; 334 335 extern const char ksh_version[]; 336 337 /* name of called builtin function (used by error functions) */ 338 extern char *builtin_argv0; 339 extern int builtin_flag; /* flags of called builtin (SPEC_BI, etc.) */ 340 341 /* current working directory, and size of memory allocated for same */ 342 extern char *current_wd; 343 extern int current_wd_size; 344 345 #ifdef EDIT 346 /* Minimum required space to work with on a line - if the prompt leaves less 347 * space than this on a line, the prompt is truncated. 348 */ 349 # define MIN_EDIT_SPACE 7 350 /* Minimum allowed value for x_cols: 2 for prompt, 3 for " < " at end of line 351 */ 352 # define MIN_COLS (2 + MIN_EDIT_SPACE + 3) 353 extern int x_cols; /* tty columns */ 354 #else 355 # define x_cols 80 /* for pr_menu(exec.c) */ 356 #endif 357 358 /* These to avoid bracket matching problems */ 359 #define OPAREN '(' 360 #define CPAREN ')' 361 #define OBRACK '[' 362 #define CBRACK ']' 363 #define OBRACE '{' 364 #define CBRACE '}' 365 366 /* Determine the location of the system (common) profile */ 367 #define KSH_SYSTEM_PROFILE "/etc/profile" 368 369 /* Used by v_evaluate() and setstr() to control action when error occurs */ 370 #define KSH_UNWIND_ERROR 0x0 /* unwind the stack (longjmp) */ 371 #define KSH_RETURN_ERROR 0x1 /* return 1/0 for success/failure */ 372 #define KSH_IGNORE_RDONLY 0x4 /* ignore the read-only flag */ 373 374 #include "shf.h" 375 #include "table.h" 376 #include "tree.h" 377 #include "expand.h" 378 #include "lex.h" 379 380 /* alloc.c */ 381 Area * ainit(Area *); 382 void afreeall(Area *); 383 void * alloc(size_t, Area *); 384 void * areallocarray(void *, size_t, size_t, Area *); 385 void * aresize(void *, size_t, Area *); 386 void afree(void *, Area *); 387 /* c_ksh.c */ 388 int c_cd(char **); 389 int c_pwd(char **); 390 int c_print(char **); 391 int c_whence(char **); 392 int c_command(char **); 393 int c_typeset(char **); 394 int c_alias(char **); 395 int c_unalias(char **); 396 int c_let(char **); 397 int c_jobs(char **); 398 int c_fgbg(char **); 399 int c_kill(char **); 400 void getopts_reset(int); 401 int c_getopts(char **); 402 int c_bind(char **); 403 /* c_sh.c */ 404 int c_label(char **); 405 int c_shift(char **); 406 int c_umask(char **); 407 int c_dot(char **); 408 int c_wait(char **); 409 int c_read(char **); 410 int c_eval(char **); 411 int c_trap(char **); 412 int c_brkcont(char **); 413 int c_exitreturn(char **); 414 int c_set(char **); 415 int c_unset(char **); 416 int c_ulimit(char **); 417 int c_times(char **); 418 int timex(struct op *, int, volatile int *); 419 void timex_hook(struct op *, char ** volatile *); 420 int c_exec(char **); 421 int c_builtin(char **); 422 /* c_test.c */ 423 int c_test(char **); 424 /* edit.c: most prototypes in edit.h */ 425 void x_init(void); 426 int x_read(char *, size_t); 427 void set_editmode(const char *); 428 /* emacs.c: most prototypes in edit.h */ 429 int x_bind(const char *, const char *, int, int); 430 /* eval.c */ 431 char * substitute(const char *, int); 432 char ** eval(char **, int); 433 char * evalstr(char *cp, int); 434 char * evalonestr(char *cp, int); 435 char *debunk(char *, const char *, size_t); 436 void expand(char *, XPtrV *, int); 437 int glob_str(char *, XPtrV *, int); 438 /* exec.c */ 439 int execute(struct op * volatile, volatile int, volatile int *); 440 int shcomexec(char **); 441 struct tbl * findfunc(const char *, unsigned int, int); 442 int define(const char *, struct op *); 443 void builtin(const char *, int (*)(char **)); 444 struct tbl * findcom(const char *, int); 445 void flushcom(int); 446 char * search(const char *, const char *, int, int *); 447 int search_access(const char *, int, int *); 448 int pr_menu(char *const *); 449 int pr_list(char *const *); 450 /* expr.c */ 451 int evaluate(const char *, long *, int, bool); 452 int v_evaluate(struct tbl *, const char *, volatile int, bool); 453 /* history.c */ 454 void init_histvec(void); 455 void hist_init(Source *); 456 void hist_finish(void); 457 void histsave(int, const char *, int); 458 #ifdef HISTORY 459 int c_fc(char **); 460 void sethistsize(int); 461 void sethistfile(const char *); 462 char ** histpos(void); 463 int histnum(int); 464 int findhist(int, int, const char *, int); 465 int findhistrel(const char *); 466 char **hist_get_newest(int); 467 468 #endif /* HISTORY */ 469 /* io.c */ 470 void errorf(const char *, ...) 471 __attribute__((__noreturn__, __format__ (printf, 1, 2))); 472 void warningf(bool, const char *, ...) 473 __attribute__((__format__ (printf, 2, 3))); 474 void bi_errorf(const char *, ...) 475 __attribute__((__format__ (printf, 1, 2))); 476 void internal_errorf(int, const char *, ...) 477 __attribute__((__format__ (printf, 2, 3))); 478 void error_prefix(int); 479 void shellf(const char *, ...) 480 __attribute__((__format__ (printf, 1, 2))); 481 void shprintf(const char *, ...) 482 __attribute__((__format__ (printf, 1, 2))); 483 #ifdef KSH_DEBUG 484 void kshdebug_init_(void); 485 void kshdebug_printf_(const char *, ...) 486 __attribute__((__format__ (printf, 1, 2))); 487 void kshdebug_dump_(const char *, const void *, int); 488 #endif /* KSH_DEBUG */ 489 int can_seek(int); 490 void initio(void); 491 int ksh_dup2(int, int, int); 492 int savefd(int); 493 void restfd(int, int); 494 void openpipe(int *); 495 void closepipe(int *); 496 int check_fd(char *, int, const char **); 497 void coproc_init(void); 498 void coproc_read_close(int); 499 void coproc_readw_close(int); 500 void coproc_write_close(int); 501 int coproc_getfd(int, const char **); 502 void coproc_cleanup(int); 503 struct temp *maketemp(Area *, Temp_type, struct temp **); 504 /* jobs.c */ 505 void j_init(int); 506 void j_suspend(void); 507 void j_exit(void); 508 void j_change(void); 509 int exchild(struct op *, int, volatile int *, int); 510 void startlast(void); 511 int waitlast(void); 512 int waitfor(const char *, int *); 513 int j_kill(const char *, int); 514 int j_resume(const char *, int); 515 int j_jobs(const char *, int, int); 516 int j_njobs(void); 517 void j_notify(void); 518 pid_t j_async(void); 519 int j_stopped_running(void); 520 /* mail.c */ 521 void mcheck(void); 522 void mcset(long); 523 void mbset(char *); 524 void mpset(char *); 525 /* main.c */ 526 int include(const char *, int, char **, int); 527 int command(const char *, int); 528 int shell(Source *volatile, int volatile); 529 void unwind(int) __attribute__((__noreturn__)); 530 void newenv(int); 531 void quitenv(struct shf *); 532 void cleanup_parents_env(void); 533 void cleanup_proc_env(void); 534 /* misc.c */ 535 void setctypes(const char *, int); 536 void initctypes(void); 537 char * ulton(unsigned long, int); 538 char * str_save(const char *, Area *); 539 char * str_nsave(const char *, int, Area *); 540 int option(const char *); 541 char * getoptions(void); 542 void change_flag(enum sh_flag, int, int); 543 int parse_args(char **, int, int *); 544 int getn(const char *, int *); 545 int bi_getn(const char *, int *); 546 int gmatch(const char *, const char *, int); 547 int has_globbing(const char *, const char *); 548 const unsigned char *pat_scan(const unsigned char *, const unsigned char *, 549 int); 550 void qsortp(void **, size_t, int (*)(const void *, const void *)); 551 int xstrcmp(const void *, const void *); 552 void ksh_getopt_reset(Getopt *, int); 553 int ksh_getopt(char **, Getopt *, const char *); 554 void print_value_quoted(const char *); 555 void print_columns(struct shf *, int, char *(*)(void *, int, char *, int), 556 void *, int, int prefcol); 557 int strip_nuls(char *, int); 558 int blocking_read(int, char *, int); 559 int reset_nonblock(int); 560 char *ksh_get_wd(char *, int); 561 /* path.c */ 562 int make_path(const char *, const char *, char **, XString *, int *); 563 void simplify_path(char *); 564 char *get_phys_path(const char *); 565 void set_current_wd(char *); 566 /* syn.c */ 567 void initkeywords(void); 568 struct op * compile(Source *); 569 /* trap.c */ 570 void inittraps(void); 571 void alarm_init(void); 572 Trap * gettrap(const char *, int); 573 void trapsig(int); 574 void intrcheck(void); 575 int fatal_trap_check(void); 576 int trap_pending(void); 577 void runtraps(int intr); 578 void runtrap(Trap *); 579 void cleartraps(void); 580 void restoresigs(void); 581 void settrap(Trap *, char *); 582 int block_pipe(void); 583 void restore_pipe(int); 584 int setsig(Trap *, sig_t, int); 585 void setexecsig(Trap *, int); 586 /* var.c */ 587 void newblock(void); 588 void popblock(void); 589 void initvar(void); 590 struct tbl * global(const char *); 591 struct tbl * local(const char *, bool); 592 char * str_val(struct tbl *); 593 long intval(struct tbl *); 594 int setstr(struct tbl *, const char *, int); 595 struct tbl *setint_v(struct tbl *, struct tbl *, bool); 596 void setint(struct tbl *, long); 597 int getint(struct tbl *, long *, bool); 598 struct tbl *typeset(const char *, int, int, int, int); 599 void unset(struct tbl *, int); 600 char * skip_varname(const char *, int); 601 char *skip_wdvarname(const char *, int); 602 int is_wdvarname(const char *, int); 603 int is_wdvarassign(const char *); 604 char ** makenv(void); 605 void change_random(void); 606 int array_ref_len(const char *); 607 char * arrayname(const char *); 608 void set_array(const char *, int, char **); 609 /* vi.c: see edit.h */ 610