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