home *** CD-ROM | disk | FTP | other *** search
- From: netnews@netcom.UUCP (USENET Administration)
- Newsgroups: alt.sources
- Subject: Public Domain Korn Shell - Part.03 of 7
- Message-ID: <18608@netcom.UUCP>
- Date: 12 Dec 90 11:36:21 GMT
-
- #!/bin/sh
- # This is part 03 of ksh-pd
- # ============= src/lex.c ==============
- if test ! -d 'src'; then
- echo 'x - creating directory src'
- mkdir 'src'
- fi
- if test -f 'src/lex.c' -a X"$1" != X"-c"; then
- echo 'x - skipping src/lex.c (File already exists)'
- else
- echo 'x - extracting src/lex.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'src/lex.c' &&
- X/*
- X * lexical analysis and source input
- X */
- X
- Xstatic char *RCSid = "$Header: /tmp/egisin/src/RCS/lex.c,v 3.4 88/12/17 21:19:21 egisin Exp $";
- X
- X#include <stddef.h>
- X#include <stdio.h>
- X#include <string.h>
- X#include <errno.h>
- X#include <setjmp.h>
- X#include <unistd.h>
- X#include "sh.h"
- X#include "lex.h"
- X#include "tree.h"
- X#include "table.h"
- X#include "expand.h"
- X
- X int ttyfd = -1; /* tty fd for edit and jobs */
- X char *history[HISTORY]; /* saved commands */
- X char **histptr = history - 1; /* last history item */
- X int histpush; /* number of pushed fc commands */
- X
- Xstatic int alias;
- Xstatic int getsc_ ARGS((void));
- X
- X/* optimized getsc_() */
- X#define getsc() ((*source->str != 0) ? *source->str++ : getsc_())
- X#define ungetsc() (source->str--)
- X
- X/*
- X * Lexical analyzer
- X *
- X * tokens are not regular expressions, they are LL(1).
- X * for example, "${var:-${PWD}}", and "$(size $(whence ksh))".
- X * hence the state stack.
- X */
- X
- Xint
- Xyylex(cf)
- X int cf;
- X{
- X register int c, state;
- X char states [64], *statep = states;
- X XString ws; /* expandable output word */
- X register char *wp; /* output word pointer */
- X register char *sp, *dp;
- X int istate;
- X int c2;
- X
- X Again:
- X Xinit(ws, wp, 256);
- X if (alias) { /* trailing ' ' in alias definition */
- X alias = 0;
- X cf |= ALIAS;
- X }
- X
- X if (cf&ONEWORD)
- X istate = SWORD;
- X else { /* normal lexing */
- X istate = SBASE;
- X while ((c = getsc()) == ' ' || c == '\t')
- X ;
- X if (c == '#')
- X while ((c = getsc()) != 0 && c != '\n')
- X ;
- X ungetsc();
- X }
- X
- X /* collect non-special or quoted characters to form word */
- X for (*statep = state = istate;
- X !((c = getsc()) == 0 || state == SBASE && ctype(c, C_LEX1)); ) {
- X Xcheck(ws, wp);
- X switch (state) {
- X case SBASE:
- X Sbase:
- X switch (c) {
- X case '\\':
- X c = getsc();
- X if (c != '\n')
- X *wp++ = QCHAR, *wp++ = c;
- X else
- X if (wp == Xstring(ws, wp))
- X goto Again;
- X break;
- X case '\'':
- X *++statep = state = SSQUOTE;
- X *wp++ = OQUOTE;
- X break;
- X case '"':
- X *++statep = state = SDQUOTE;
- X *wp++ = OQUOTE;
- X break;
- X default:
- X goto Subst;
- X }
- X break;
- X
- X Subst:
- X switch (c) {
- X case '\\':
- X c = getsc();
- X switch (c) {
- X case '\n':
- X break;
- X case '"': case '\\':
- X case '$': case '`':
- X *wp++ = QCHAR, *wp++ = c;
- X break;
- X default:
- X *wp++ = CHAR, *wp++ = '\\';
- X *wp++ = CHAR, *wp++ = c;
- X break;
- X }
- X break;
- X case '$':
- X c = getsc();
- X if (c == '(') {
- X *++statep = state = SPAREN;
- X *wp++ = COMSUB;
- X } else
- X if (c == '{') {
- X *++statep = state = SBRACE;
- X *wp++ = OSUBST;
- X c = getsc();
- X do {
- X Xcheck(ws, wp);
- X *wp++ = c;
- X c = getsc();
- X } while (ctype(c, C_ALPHA|C_DIGIT));
- X *wp++ = 0;
- X /* todo: more compile-time checking */
- X if (c == '}')
- X ungetsc();
- X else if (c == '#' || c == '%') {
- X /* Korn pattern trimming */
- X if (getsc() == c)
- X c |= 0x80;
- X else
- X ungetsc();
- X *wp++ = c;
- X } else if (c == ':')
- X *wp++ = 0x80|getsc();
- X else
- X *wp++ = c;
- X } else if (ctype(c, C_ALPHA)) {
- X *wp++ = OSUBST;
- X do {
- X *wp++ = c;
- X c = getsc();
- X } while (ctype(c, C_ALPHA|C_DIGIT));
- X *wp++ = 0;
- X *wp++ = CSUBST;
- X ungetsc();
- X } else if (ctype(c, C_DIGIT|C_VAR1)) {
- X *wp++ = OSUBST;
- X *wp++ = c;
- X *wp++ = 0;
- X *wp++ = CSUBST;
- X } else {
- X *wp++ = CHAR, *wp++ = '$';
- X ungetsc();
- X }
- X break;
- X case '`':
- X *++statep = state = SBQUOTE;
- X *wp++ = COMSUB;
- X break;
- X default:
- X *wp++ = CHAR, *wp++ = c;
- X }
- X break;
- X
- X case SSQUOTE:
- X if (c == '\'') {
- X state = *--statep;
- X *wp++ = CQUOTE;
- X } else
- X *wp++ = QCHAR, *wp++ = c;
- X break;
- X
- X case SDQUOTE:
- X if (c == '"') {
- X state = *--statep;
- X *wp++ = CQUOTE;
- X } else
- X goto Subst;
- X break;
- X
- X case SPAREN:
- X if (c == '(')
- X *++statep = state;
- X else if (c == ')')
- X state = *--statep;
- X if (state == SPAREN)
- X *wp++ = c;
- X else
- X *wp++ = 0; /* end of COMSUB */
- X break;
- X
- X case SBRACE:
- X if (c == '}') {
- X state = *--statep;
- X *wp++ = CSUBST;
- X } else
- X goto Sbase;
- X break;
- X
- X case SBQUOTE:
- X if (c == '`') {
- X *wp++ = 0;
- X state = *--statep;
- X } else /* todo: handle silly `\`` escapes */
- X /* todo: both \" and \` in "`...`" */
- X *wp++ = c;
- X break;
- X
- X case SWORD: /* ONEWORD */
- X goto Subst;
- X }
- X }
- X if (state != istate)
- X yyerror("no closing quote");
- X
- X if (c == '<' || c == '>') {
- X char *cp = Xstring(ws, wp);
- X if (wp > cp && cp[0] == CHAR && digit(cp[1])) {
- X wp = cp; /* throw away word */
- X c2/*unit*/ = cp[1] - '0';
- X } else
- X c2/*unit*/ = c == '>'; /* 0 for <, 1 for > */
- X }
- X
- X if (wp == Xstring(ws, wp) && state == SBASE) {
- X Xfree(ws, sp); /* free word */
- X /* no word, process LEX1 character */
- X switch (c) {
- X default:
- X return c;
- X
- X case '|':
- X case '&':
- X case ';':
- X if (getsc() == c)
- X c = (c == ';') ? BREAK :
- X (c == '|') ? LOGOR :
- X (c == '&') ? LOGAND :
- X YYERRCODE;
- X else
- X ungetsc();
- X return c;
- X
- X case '>':
- X case '<': {
- X register struct ioword *iop;
- X
- X iop = (struct ioword *) alloc(sizeof(*iop), ATEMP);
- X iop->unit = c2/*unit*/;
- X
- X c2 = getsc();
- X if (c2 == '>' || c2 == '<') {
- X iop->flag = c != c2 ? IORDWR : c == '>' ? IOCAT : IOHERE;
- X c2 = getsc();
- X } else
- X iop->flag = c == '>' ? IOWRITE : IOREAD;
- X
- X if (iop->flag == IOHERE)
- X if (c2 == '-')
- X iop->flag |= IOSKIP;
- X else
- X ungetsc();
- X else
- X if (c2 == '&')
- X iop->flag = IODUP;
- X else if (c2 == '!' && iop->flag == IOWRITE)
- X iop->flag |= IOCLOB;
- X else
- X ungetsc();
- X yylval.iop = iop;
- X return REDIR;
- X }
- X case '\n':
- X gethere();
- X if (cf & CONTIN)
- X goto Again;
- X return c;
- X
- X case '(':
- X c2 = getsc();
- X if (c2 == ')')
- X c = MPAREN;
- X else if (c2 == '(')
- X yyerror("(( not supported");
- X else
- X ungetsc();
- X case ')':
- X return c;
- X }
- X }
- X
- X *wp++ = EOS; /* terminate word */
- X yylval.cp = Xclose(ws, wp);
- X if (state == SWORD) /* ONEWORD? */
- X return LWORD;
- X ungetsc(); /* unget terminator */
- X
- X /* copy word to unprefixed string ident */
- X for (sp = yylval.cp, dp = ident; dp < ident+IDENT && (c = *sp++) == CHAR; )
- X *dp++ = *sp++;
- X *dp = 0;
- X#if 0
- X if (*ident == '~' || (dp = strchr(ident, '=')) != NULL && dp[1] == '~')
- X "Tilde expansion";
- X#endif
- X if (c != EOS)
- X *ident = 0; /* word is not unquoted */
- X
- X if (*ident != 0 && (cf&(KEYWORD|ALIAS))) {
- X register struct tbl *p;
- X
- X p = tsearch(&lexicals, ident, hash(ident));
- X if (p != NULL && (p->flag&ISSET))
- X if (p->type == CKEYWD && (cf&KEYWORD)) {
- X afree(yylval.cp, ATEMP);
- X return p->val.i;
- X } else
- X if (p->type == CALIAS && (cf&ALIAS)) {
- X register Source *s;
- X
- X /* check for recursive aliasing */
- X for (s = source; s->type == SALIAS; s = s->next)
- X if (s->u.tblp == p)
- X return LWORD;
- X afree(yylval.cp, ATEMP);
- X
- X /* push alias expansion */
- X s = pushs(SALIAS);
- X s->str = p->val.s;
- X s->u.tblp = p;
- X s->next = source;
- X source = s;
- X goto Again;
- X }
- X }
- X
- X return LWORD;
- X}
- X
- Xstatic void readhere();
- X
- Xgethere()
- X{
- X register struct ioword **p;
- X
- X for (p = heres; p < herep; p++)
- X readhere(*p);
- X herep = heres;
- X}
- X
- X/*
- X * read "<<word" text into temp file
- X * todo: set up E_ERR to fclose(f) on unwind
- X */
- X
- Xstatic void
- Xreadhere(iop)
- X register struct ioword *iop;
- X{
- X register FILE *f;
- X struct temp *h;
- X register int c;
- X char *eof;
- X register char *cp;
- X char line [LINE+1];
- X
- X eof = evalstr(iop->name, 0);
- X
- X h = maketemp(ATEMP);
- X h->next = e.temps; e.temps = h;
- X iop->name = h->name;
- X f = fopen(h->name, "w");
- X if (f == NULL)
- X errorf("Cannot create temporary file\n");
- X setvbuf(f, (char *)NULL, _IOFBF, BUFSIZ);
- X
- X for (;;) {
- X cp = line;
- X while ((c = getsc()) != '\n') {
- X if (c == 0)
- X errorf("here document `%s' unclosed\n", eof);
- X if (cp >= line+LINE)
- X break;
- X *cp++ = c;
- X }
- X ungetsc();
- X *cp = 0;
- X for (cp = line; iop->flag&IOSKIP && *cp == '\t'; cp++)
- X ;
- X if (strcmp(eof, cp) == 0 || c == 0)
- X break;
- X while ((c = *cp++) != '\0')
- X putc(c, f);
- X while ((c = getsc()) != '\n') {
- X if (c == 0)
- X errorf("here document `%s' unclosed\n", eof);
- X putc(c, f);
- X }
- X putc(c, f);
- X }
- X fclose(f);
- X}
- X
- Xvoid
- Xyyerror(msg)
- X Const char *msg;
- X{
- X yynerrs++;
- X while (source->type == SALIAS) /* pop aliases */
- X source = source->next;
- X if (source->file != NULL)
- X shellf("%s[%d]: ", source->file, source->line);
- X source->str = null; /* zap pending input */
- X errorf("%s\n", msg);
- X}
- X
- X/*
- X * input for yylex with alias expansion
- X */
- X
- XSource *
- Xpushs(type)
- X int type;
- X{
- X register Source *s;
- X
- X s = (Source *) alloc(sizeof(Source), ATEMP);
- X s->type = type;
- X s->str = null; /* "" */
- X s->line = 0;
- X s->file = NULL;
- X s->echo = 0;
- X s->next = NULL;
- X return s;
- X}
- X
- Xstatic int
- Xgetsc_()
- X{
- X register Source *s = source;
- X register int c;
- X
- X while ((c = *s->str++) == 0) {
- X s->str = NULL; /* return 0 for EOF by default */
- X switch (s->type) {
- X case SEOF:
- X s->str = null;
- X return 0;
- X
- X case STTY:
- X if (histpush < 0) { /* commands pushed by dofc */
- X s->type = SHIST;
- X s->str = null;
- X continue;
- X }
- X s->line++;
- X s->str = line;
- X line[0] = '\0';
- X pprompt(prompt);
- X flushshf(1); flushshf(2);
- X#if EDIT
- X if (flag[FEMACS])
- X c = x_read(ttyfd, line, LINE);
- X else
- X#endif
- X c = read(ttyfd, line, LINE);
- X if (c < 0) /* read error */
- X c = 0;
- X if (c == 0) /* EOF */
- X s->str = NULL;
- X prompt = strval(global("PS2"));
- X line[c] = '\0';
- X if (line[0] != '\n')
- X histsave(line);
- X else
- X s->line--;
- X break;
- X
- X case SHIST:
- X if (histpush == 0) {
- X s->type = STTY;
- X s->str = null;
- X continue;
- X }
- X s->line++;
- X s->str = histptr[++histpush];
- X pprompt("!< "); /* todo: PS9 */
- X shellf("%s\n", s->str);
- X strcpy(line, s->str);
- X s->str = strchr(line, 0);
- X *s->str++ = '\n';
- X *s->str = 0;
- X s->str = line;
- X break;
- X
- X case SFILE:
- X s->line++;
- X s->str = fgets(line, LINE, s->u.file);
- X if (s->str == NULL)
- X if (s->u.file != stdin)
- X fclose(s->u.file);
- X break;
- X
- X case SWSTR:
- X break;
- X
- X case SSTRING:
- X s->str = "\n";
- X s->type = SEOF;
- X break;
- X
- X case SWORDS:
- X s->str = *s->u.strv++;
- X s->type = SWORDSEP;
- X break;
- X
- X case SWORDSEP:
- X if (*s->u.strv == NULL) {
- X s->str = "\n";
- X s->type = SEOF;
- X } else {
- X s->str = " ";
- X s->type = SWORDS;
- X }
- X break;
- X
- X case SALIAS:
- X s->str = s->u.tblp->val.s;
- X if (s->str[0] != 0 && strchr(s->str, 0)[-1] == ' ')
- X alias = 1; /* trailing ' ' */
- X source = s = s->next; /* pop source stack */
- X continue;
- X }
- X if (s->str == NULL) {
- X s->type = SEOF;
- X s->str = null; /* "" */
- X return 0;
- X }
- X if (s->echo)
- X fputs(s->str, shlout);
- X }
- X return c;
- X}
- X
- Xpprompt(cp)
- X register char *cp;
- X{
- X while (*cp != 0)
- X if (*cp != '!')
- X putc(*cp++, shlout);
- X else
- X if (*++cp == '!')
- X putc(*cp++, shlout);
- X else
- X shellf("%d", source->line);
- X fflush(shlout);
- X}
- X
- SHAR_EOF
- true || echo 'restore of src/lex.c failed'
- fi
- # ============= src/edit.c ==============
- if test -f 'src/edit.c' -a X"$1" != X"-c"; then
- echo 'x - skipping src/edit.c (File already exists)'
- else
- echo 'x - extracting src/edit.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'src/edit.c' &&
- X/*
- X * EDIT.C -- Emacs-like command line editing and history
- X *
- X * created by Ron Natalie at BRL
- X * modified by Doug Kingston, Doug Gwyn, and Lou Salkind
- X * adapted to PD ksh by Eric Gisin
- X */
- X
- X#if EDIT
- X
- Xstatic char *RCSid = "$Header: /tmp/egisin/src/RCS/edit.c,v 3.2 88/12/14 20:11:44 egisin Exp $";
- X
- X#include <stddef.h>
- X#include <stdlib.h>
- X#include <string.h>
- X#include <stdio.h>
- X#include <unistd.h>
- X#include <signal.h>
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include <dirent.h>
- X#include <fcntl.h>
- X#include <ctype.h>
- X#include <errno.h>
- X#include <setjmp.h>
- X#include "sh.h"
- X#include "lex.h"
- X#include "tree.h" /* DOTILDE */
- X#include "tty.h"
- X#include "table.h"
- X#include "expand.h"
- X
- XArea aedit;
- X#define AEDIT &aedit /* area for kill ring and macro defns */
- X
- X#undef CTRL /* _BSD brain damage */
- X#define CTRL(x) ((x) == '?' ? 0x7F : (x) & 0x1F) /* ASCII */
- X#define UNCTRL(x) ((x) == 0x7F ? '?' : (x) | 0x40) /* ASCII */
- X
- X#if ! defined S_ISDIR
- X#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
- X#endif
- X
- X#if ! defined S_ISREG
- X#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
- X#endif
- X
- X#if defined _CRAY2
- Xextern unsigned sleep();
- X#endif
- X
- X/* values returned by keyboard functions */
- X#define KSTD 0
- X#define KPREF 1 /* ^[, ^X */
- X#define KEOL 2 /* ^M, ^J */
- X#define KINTR 3 /* ^G, ^C */
- X
- Xstruct x_ftab {
- X int (*xf_func)();
- X char *xf_name;
- X char xf_db_tab;
- X char xf_db_char;
- X short xf_flags;
- X};
- X
- X#define XF_NINPUT 1
- X#define XF_ALLOC 2
- X#define XF_NOBIND 4
- X
- X#define isfs(c) (c == ' ' || c == '\t')
- X#define BEL 0x07
- X#define CMASK 0x7F /* 7-bit ASCII character mask */
- X
- Xtypedef int bool_t;
- X#define FALSE 0
- X#define TRUE 1
- X
- Xstatic bool_t x_mode = FALSE;
- Xstatic int x_prefix1 = CTRL('['), x_prefix2 = CTRL('X');
- Xstatic char **x_histp; /* history position */
- Xstatic char *xbuf; /* beg input buffer */
- Xstatic char *xend; /* end input buffer */
- Xstatic char *xcp;
- Xstatic char *xep;
- Xstatic int (*x_last_command)();
- X/*static struct x_ftab *x_tab[3][128];*/
- Xstatic struct x_ftab Const *(*x_tab)[128] = NULL; /* key definition */
- Xstatic char *(*x_atab)[128] = NULL; /* macro definitions */
- X#define KILLSIZE 20
- Xstatic char *killstack[KILLSIZE];
- Xstatic int killsp, killtp;
- Xstatic int x_curprefix;
- Xstatic char *macroptr;
- Xstatic int first_time = 1;
- Xstatic int x_maxlen; /* to determine column width */
- Xstatic int x_cols = 80; /* todo: $COLUMNS */
- X
- Xstatic void x_flush(), x_putc(), x_puts();
- Xstatic void x_goto(), x_bs(), x_delete(), x_ins(), x_mapin();
- Xstatic int x_fword(), x_bword(), x_size(), x_size_str();
- Xstatic void x_zotc(), x_zots(), x_push(), x_redraw(), x_load_hist();
- Xstatic void compl_command(), compl_dec(), compl_file();
- Xstatic int x_insert(), x_ins_string(), x_del_back();
- Xstatic int x_del_char(), x_del_bword(), x_mv_bword(), x_mv_fword();
- Xstatic int x_del_fword(), x_mv_back(), x_mv_forw(), x_search_char();
- Xstatic int x_newline(), x_end_of_text(), x_abort(), x_error();
- Xstatic int x_beg_hist(), x_end_hist(), x_prev_com(), x_next_com();
- Xstatic int x_search_hist(), x_del_line(), x_mv_end(), x_mv_begin();
- Xstatic int x_draw_line(), x_transpose(), x_meta1(), x_meta2();
- Xstatic int x_kill(), x_yank(), x_meta_yank(), x_literal();
- Xstatic int x_stuffreset(), x_stuff(), x_complete(), x_enumerate();
- X#if SILLY
- Xstatic int x_game_of_life();
- X#endif
- Xstatic int x_comp_file(), x_comp_comm();
- Xstatic int x_list_file(), x_list_comm();
- Xstatic int strmatch();
- X
- Xstatic struct x_ftab Const x_ftab[] = {
- X {x_insert, "auto-insert", 0, 0, 0 },
- X {x_error, "error", 0, 0, 0 },
- X {x_ins_string, "macro-string", 0, 0, XF_NOBIND|XF_ALLOC},
- X/* Do not move the above! */
- X {x_del_back, "delete-char-backward", 0, CTRL('H'), 0 },
- X {x_del_char, "delete-char-forward", 0, CTRL('D'), 0 },
- X {x_del_bword, "delete-word-backward", 0, CTRL('W'), 0 },
- X {x_mv_bword, "backward-word", 1, 'b', 0 },
- X {x_mv_fword, "forward-word", 1, 'f', 0 },
- X {x_del_fword, "delete-word-forward", 1, 'd', 0 },
- X {x_mv_back, "backward-char", 0, CTRL('B'), 0 },
- X {x_mv_forw, "forward-char", 0, CTRL('F'), 0 },
- X {x_search_char, "search-character", 0, CTRL(']'), 0 },
- X {x_newline, "newline", 0, CTRL('M'), 0 },
- X {x_newline, "newline", 0, CTRL('J'), 0 },
- X {x_end_of_text, "eot", 0, CTRL('_'), 0 },
- X {x_abort, "abort", 0, CTRL('G'), 0 },
- X {x_prev_com, "up-history", 0, CTRL('P'), XF_NINPUT},
- X {x_next_com, "down-history", 0, CTRL('N'), XF_NINPUT},
- X {x_search_hist, "search-history", 0, CTRL('R'), XF_NINPUT},
- X {x_beg_hist, "beginning-of-history", 1, '<', XF_NINPUT},
- X {x_end_hist, "end-of-history", 1, '>', XF_NINPUT},
- X {x_del_line, "kill-line", 0, CTRL('U'), 0 },
- X {x_mv_end, "end-of-line", 0, CTRL('E'), 0 },
- X {x_mv_begin, "beginning-of-line", 0, CTRL('A'), 0 },
- X {x_draw_line, "redraw", 0, CTRL('L'), 0 },
- X {x_meta1, "prefix-1", 0, CTRL('['), 0 },
- X {x_meta2, "prefix-2", 0, CTRL('X'), 0 },
- X {x_kill, "kill-to-eol", 0, CTRL('K'), 0 },
- X {x_yank, "yank", 0, CTRL('Y'), 0 },
- X {x_meta_yank, "yank-pop", 1, 'y', 0 },
- X {x_literal, "quote", 0, CTRL('^'), 0 },
- X {x_stuffreset, "stuff-reset", 0, 0, 0 },
- X#if BRL && defined(TIOCSTI)
- X {x_stuff, "stuff", 0, CTRL('T'), 0 },
- X {x_transpose, "transpose-chars", 0, 0, 0 },
- X#else
- X {x_stuff, "stuff", 0, 0, 0 },
- X {x_transpose, "transpose-chars", 0, CTRL('T'), 0 },
- X#endif
- X {x_complete, "complete", 1, CTRL('['), 0 },
- X {x_enumerate, "list", 1, '?', 0 },
- X {x_comp_file, "complete-file", 2, CTRL('X'), 0 },
- X {x_comp_comm, "complete-command", 2, CTRL('['), 0 },
- X {x_list_file, "list-file", 0, 0, 0 },
- X {x_list_comm, "list-command", 2, '?', 0 },
- X#if SILLY
- X {x_game_of_life, "play-game-of-life", 0, 0, 0 },
- X#endif
- X { 0 }
- X};
- X
- X#define xft_insert &x_ftab[0]
- X#define xft_error &x_ftab[1]
- X#define xft_ins_string &x_ftab[2]
- X
- Xint
- Xx_read(fd, buf, len)
- X int fd; /* not used */
- X char *buf;
- X size_t len;
- X{
- X char c;
- X int i;
- X int (*func)();
- X extern x_insert();
- X
- X (void)set_xmode(TRUE);
- X xbuf = buf; xend = buf + len;
- X xcp = xep = buf;
- X *xcp = 0;
- X x_curprefix = 0;
- X macroptr = null;
- X x_histp = histptr + 1;
- X
- X while (1) {
- X x_flush();
- X if (*macroptr) {
- X c = *macroptr++;
- X if (*macroptr == 0)
- X macroptr = null;
- X }
- X else {
- X i = read(ttyfd, &c, 1);
- X if (i != 1)
- X goto Exit;
- X }
- X
- X if (x_curprefix == -1)
- X func = x_insert;
- X else
- X func = x_tab[x_curprefix][c&CMASK]->xf_func;
- X if (func == NULL)
- X func = x_error;
- X i = c | (x_curprefix << 8);
- X x_curprefix = 0;
- X switch (i = (*func)(i)) {
- X case KSTD:
- X x_last_command = func;
- X case KPREF:
- X break;
- X case KEOL:
- X i = xep - xbuf;
- X x_last_command = 0;
- X /* XXX -- doesn't get them all */
- X if (strncmp(xbuf, "stty", 4) == 0)
- X first_time = 1;
- X goto Exit;
- X case KINTR: /* special case for interrupt */
- X i = -1;
- X errno = EINTR;
- X goto Exit;
- X }
- X }
- X Exit:
- X (void)set_xmode(FALSE);
- X if (i < 0 && errno == EINTR)
- X trapsig(SIGINT);
- X return i;
- X}
- X
- Xstatic int
- Xx_insert(c) {
- X char str[2];
- X
- X /*
- X * Should allow tab and control chars.
- X */
- X if (c == 0) {
- X x_putc(BEL);
- X return KSTD;
- X }
- X str[0] = c;
- X str[1] = 0;
- X x_ins(str);
- X return KSTD;
- X}
- X
- Xstatic int
- Xx_ins_string(c)
- X{
- X if (*macroptr) {
- X x_putc(BEL);
- X return KSTD;
- X }
- X macroptr = x_atab[c>>8][c & CMASK];
- X return KSTD;
- X}
- X
- Xstatic void
- Xx_ins(cp)
- X char *cp;
- X{
- X int count, i;
- X
- X count = strlen(cp);
- X if (xep+count >= xend) {
- X x_putc(BEL);
- X return;
- X }
- X
- X if (xcp != xep)
- X memmove(xcp+count, xcp, xep - xcp + 1);
- X else
- X xcp[count] = 0;
- X memmove(xcp, cp, count);
- X x_zots(xcp);
- X xcp += count;
- X xep += count;
- X i = xep - xcp;
- X cp = xep;
- X while (i--)
- X x_bs(*--cp);
- X return;
- X}
- X
- Xstatic int
- Xx_del_back(c) {
- X if (xcp == xbuf) {
- X x_putc(BEL);
- X return KSTD;
- X }
- X x_goto(xcp - 1);
- X x_delete(1);
- X return KSTD;
- X}
- X
- Xstatic int
- Xx_del_char(c) {
- X if (xcp == xep) {
- X x_putc(BEL);
- X return KSTD;
- X }
- X x_delete(1);
- X return KSTD;
- X}
- X
- Xstatic void
- Xx_delete(nc) {
- X int i,j;
- X char *cp;
- X
- X if (nc == 0)
- X return;
- X xep -= nc;
- X cp = xcp;
- X j = 0;
- X i = nc;
- X while (i--) {
- X j += x_size(*cp++);
- X }
- X memmove(xcp, xcp+nc, xep - xcp + 1); /* Copies the null */
- X x_zots(xcp);
- X i = j;
- X while (i--)
- X x_putc(' ');
- X i = j;
- X while (i--)
- X x_putc('\b');
- X /*x_goto(xcp);*/
- X i = xep - xcp;
- X cp = xep;
- X while (i--)
- X x_bs(*--cp);
- X return;
- X}
- X
- Xstatic int
- Xx_del_bword(c) {
- X x_delete(x_bword());
- X return KSTD;
- X}
- X
- Xstatic int
- Xx_mv_bword(c) {
- X (void)x_bword();
- X return KSTD;
- X}
- X
- Xstatic int
- Xx_mv_fword(c) {
- X x_goto(xcp + x_fword());
- X return KSTD;
- X}
- X
- Xstatic int
- Xx_del_fword(c) {
- X x_delete(x_fword());
- X return KSTD;
- X}
- X
- Xstatic int
- Xx_bword() {
- X int nc = 0;
- X register char *cp = xcp;
- X
- X if (cp == xbuf) {
- X x_putc(BEL);
- X return 0;
- X }
- X while (cp != xbuf && isfs(cp[-1])) {
- X cp--;
- X nc++;
- X }
- X while (cp != xbuf && !isfs(cp[-1])) {
- X cp--;
- X nc++;
- X }
- X x_goto(cp);
- X return nc;
- X}
- X
- Xstatic int
- Xx_fword() {
- X int nc = 0;
- X char *cp = xcp;
- X
- X if (cp == xep) {
- X x_putc(BEL);
- X return 0;
- X }
- X while (cp != xep && !isfs(*cp)) {
- X cp++;
- X nc++;
- X }
- X while (cp != xep && isfs(*cp)) {
- X cp++;
- X nc++;
- X }
- X return nc;
- X}
- X
- Xstatic void
- Xx_goto(cp)
- X register char *cp;
- X{
- X if (cp < xcp) { /* move back */
- X while (cp < xcp)
- X x_bs(*--xcp);
- X } else
- X if (cp > xcp) { /* move forward */
- X while (cp > xcp)
- X x_zotc(*xcp++);
- X }
- X}
- X
- Xstatic void
- Xx_bs(c) {
- X register i;
- X i = x_size(c);
- X while (i--)
- X x_putc('\b');
- X}
- X
- Xstatic int
- Xx_size_str(cp)
- X register char *cp;
- X{
- X register size = 0;
- X while (*cp)
- X size += x_size(*cp++);
- X return size;
- X}
- X
- Xstatic int
- Xx_size(c) {
- X if (c=='\t')
- X return 4; /* Kludge, tabs are always four spaces. */
- X if (c < ' ' || c == 0x7F) /* ASCII control char */
- X return 2;
- X return 1;
- X}
- X
- Xstatic void
- Xx_zots(str)
- X register char *str;
- X{
- X while (*str)
- X x_zotc(*str++);
- X}
- X
- Xstatic void
- Xx_zotc(c)
- X int c;
- X{
- X if (c == '\t') {
- X /* Kludge, tabs are always four spaces. */
- X x_puts(" ");
- X } else if (c < ' ' || c == 0x7F) { /* ASCII */
- X x_putc('^');
- X x_putc(UNCTRL(c));
- X } else
- X x_putc(c);
- X}
- X
- X/* tty output */
- X
- Xstatic void
- Xx_flush()
- X{
- X fflush(stdout);
- X}
- X
- Xstatic void
- Xx_putc(c)
- X int c;
- X{
- X putc(c, stdout);
- X}
- X
- Xstatic void
- Xx_puts(s)
- X register char *s;
- X{
- X while (*s != 0)
- X putc(*s++, stdout);
- X}
- X
- Xstatic int
- Xx_mv_back(c) {
- X if (xcp == xbuf) {
- X x_putc(BEL);
- X return KSTD;
- X }
- X x_goto(xcp-1);
- X return KSTD;
- X}
- X
- Xstatic int
- Xx_mv_forw(c) {
- X if (xcp == xep) {
- X x_putc(BEL);
- X return KSTD;
- X }
- X x_goto(xcp+1);
- X return KSTD;
- X}
- X
- Xstatic int
- Xx_search_char(c) {
- X char ci, *cp;
- X
- X *xep = '\0';
- X if (read(ttyfd, &ci, 1) != 1 ||
- X /* we search forward, I don't know what Korn does */
- X (cp = (xcp == xep) ? NULL : strchr(xcp+1, ci)) == NULL &&
- X (cp = strchr(xbuf, ci)) == NULL) {
- X x_putc(BEL);
- X return KSTD;
- X }
- X x_goto(cp);
- X return KSTD;
- X}
- X
- Xstatic int
- Xx_newline(c) {
- X x_putc('\n');
- X x_flush();
- X *xep++ = '\n';
- X return KEOL;
- X}
- X
- Xstatic int
- Xx_end_of_text(c) {
- X#if 0
- X x_store_hist();
- X#endif
- X return KEOL;
- X}
- X
- Xstatic int x_beg_hist(c) {x_load_hist(history); return KSTD;}
- X
- Xstatic int x_end_hist(c) {x_load_hist(histptr); return KSTD;}
- X
- Xstatic int x_prev_com(c) {x_load_hist(x_histp-1); return KSTD;}
- X
- Xstatic int x_next_com(c) {x_load_hist(x_histp+1); return KSTD;}
- X
- Xstatic void
- Xx_load_hist(hp)
- X register char **hp;
- X{
- X int oldsize;
- X
- X if (hp < history || hp > histptr) {
- X x_putc(BEL);
- X return;
- X }
- X x_histp = hp;
- X oldsize = x_size_str(xbuf);
- X (void)strcpy(xbuf, *hp);
- X xep = xcp = xbuf + strlen(*hp);
- X x_redraw(oldsize);
- X}
- X
- Xstatic int x_search(), x_match();
- X
- X/* reverse incremental history search */
- Xstatic int
- Xx_search_hist(ci)
- X{
- X int offset = -1; /* offset of match in xbuf, else -1 */
- X static char c[2]; /* input buffer */
- X char pat [256+1]; /* pattern buffer */
- X register char *p = pat;
- X int (*func)();
- X
- X *p = 0;
- X while (1) {
- X if (offset < 0) {
- X x_puts("\nI-search: ");
- X x_zots(pat);
- X }
- X x_flush();
- X if (read(ttyfd, c, 1) < 1)
- X return KSTD;
- X func = x_tab[0][*c&CMASK]->xf_func;
- X if (*c == CTRL('['))
- X break;
- X else if (func == x_search_hist)
- X offset = x_search(pat, offset);
- X else if (func == x_del_back)
- X continue; /* todo */
- X else if (func == x_insert) {
- X /* add char to pattern */
- X *p++ = *c, *p = 0;
- X if (offset >= 0) {
- X /* already have partial match */
- X offset = x_match(xbuf, pat);
- X if (offset >= 0) {
- X x_goto(xbuf + offset + (p - pat) - (*pat == '^'));
- X continue;
- X }
- X }
- X offset = x_search(pat, offset);
- X } else { /* other command */
- X macroptr = c; /* push command */
- X break;
- X }
- X }
- X if (offset < 0)
- X x_redraw(-1);
- X return KSTD;
- X}
- X
- X/* search backward from current line */
- Xstatic int
- Xx_search(pat, offset)
- X char *pat;
- X int offset;
- X{
- X register char **hp;
- X int i;
- X
- X for (hp = x_histp; --hp >= history; ) {
- X i = x_match(*hp, pat);
- X if (i >= 0) {
- X if (offset < 0)
- X x_putc('\n');
- X x_load_hist(hp);
- X x_goto(xbuf + i + strlen(pat) - (*pat == '^'));
- X return i;
- X }
- X }
- X x_putc(BEL);
- X x_histp = histptr;
- X return -1;
- X}
- X
- X/* return position of first match of pattern in string, else -1 */
- Xstatic int
- Xx_match(str, pat)
- X char *str, *pat;
- X{
- X if (*pat == '^') {
- X return (strncmp(str, pat+1, strlen(pat+1)) == 0) ? 0 : -1;
- X } else {
- X char *q = strstr(str, pat);
- X return (q == NULL) ? -1 : q - str;
- X }
- X}
- X
- Xstatic int
- Xx_del_line(c) {
- X int i, j;
- X
- X *xep = 0;
- X i = xep- xbuf;
- X j = x_size_str(xbuf);
- X xcp = xbuf;
- X x_push(i);
- X xep = xbuf;
- X *xcp = 0;
- X x_redraw(j);
- X return KSTD;
- X}
- X
- Xstatic int
- Xx_mv_end(c) {
- X x_goto(xep);
- X return KSTD;
- X}
- X
- Xstatic int
- Xx_mv_begin(c) {
- X x_goto(xbuf);
- X return KSTD;
- X}
- X
- Xstatic int
- Xx_draw_line(c)
- X{
- X x_redraw(-1);
- X return KSTD;
- X
- X}
- X
- Xstatic void
- Xx_redraw(limit) {
- X int i, j;
- X char *cp;
- X
- X if (limit == -1)
- X x_putc('\n');
- X else
- X x_putc('\r');
- X x_flush();
- X pprompt(prompt);
- X x_zots(xbuf);
- X if (limit != -1) {
- X i = limit - x_size_str(xbuf);
- X j = 0;
- X while (j < i) {
- X x_putc(' ');
- X j++;
- X }
- X while (j--)
- X x_putc('\b');
- X }
- X i = xep - xcp;
- X cp = xep;
- X while (i--)
- X x_bs(*--cp);
- X return;
- X}
- X
- Xstatic int
- Xx_transpose(c) {
- X char tmp;
- X if (xcp == xbuf || xcp == xep) {
- X x_putc(BEL);
- X return KSTD;
- X }
- X x_bs(xcp[-1]);
- X x_zotc(xcp[0]);
- X x_zotc(xcp[-1]);
- X tmp = xcp[-1];
- X xcp[-1] = xcp[0];
- X xcp[0] = tmp;
- X x_bs(xcp[0]);
- X return KSTD;
- X}
- X
- Xstatic int
- Xx_literal(c) {
- X x_curprefix = -1;
- X return KSTD;
- X}
- X
- Xstatic int
- Xx_meta1(c) {
- X x_curprefix = 1;
- X return KPREF;
- X}
- X
- Xstatic int
- Xx_meta2(c) {
- X x_curprefix = 2;
- X return KPREF;
- X}
- X
- Xstatic int
- Xx_kill(c) {
- X int i;
- X
- X i = xep - xcp;
- X x_push(i);
- X x_delete(i);
- X return KSTD;
- X}
- X
- Xstatic void
- Xx_push(nchars) {
- X char *cp;
- X cp = alloc((size_t)(nchars+1), AEDIT);
- X memmove(cp, xcp, nchars);
- X cp[nchars] = 0;
- X if (killstack[killsp])
- X afree((Void *)killstack[killsp], AEDIT);
- X killstack[killsp] = cp;
- X killsp = (killsp + 1) % KILLSIZE;
- X}
- X
- Xstatic int
- Xx_yank(c) {
- X if (killsp == 0)
- X killtp = KILLSIZE;
- X else
- X killtp = killsp;
- X killtp --;
- X if (killstack[killtp] == 0) {
- X x_puts("\nnothing to yank");
- X x_redraw(-1);
- X return KSTD;
- X }
- X x_ins(killstack[killtp]);
- X return KSTD;
- X}
- X
- Xstatic int
- Xx_meta_yank(c) {
- X int len;
- X if (x_last_command != x_yank && x_last_command != x_meta_yank) {
- X x_puts("\nyank something first");
- X x_redraw(-1);
- X return KSTD;
- X }
- X len = strlen(killstack[killtp]);
- X x_goto(xcp - len);
- X x_delete(len);
- X do {
- X if (killtp == 0)
- X killtp = KILLSIZE - 1;
- X else
- X killtp--;
- X } while (killstack[killtp] == 0);
- X x_ins(killstack[killtp]);
- X return KSTD;
- X}
- X
- Xstatic int
- Xx_abort(c) {
- X /* x_zotc(c); */
- X return KINTR;
- X}
- X
- Xstatic int
- Xx_error(c) {
- X x_putc(BEL);
- X return KSTD;
- X}
- X
- X#if _BSD
- X#if defined TIOCGATC
- Xstatic struct ttychars lchars, lcharsorig;
- X#else
- Xstatic struct tchars tchars, tcharsorig;
- Xstatic struct ltchars ltchars, ltcharsorig;
- X#endif
- X#endif
- X
- X#if _BSD
- Xbool_t
- Xset_xmode(onoff)
- Xbool_t onoff;
- X{
- X bool_t prev;
- Xtypedef struct sgttyb Sgttyb;
- X static Sgttyb cb;
- X static Sgttyb orig;
- X
- X if (x_mode == onoff) return x_mode;
- X prev = x_mode;
- X x_mode = onoff;
- X if (onoff) {
- X if (first_time) {
- X (void)ioctl(0, TIOCGETP, &cb);
- X orig = cb;
- X cb.sg_flags &= ~ECHO;
- X cb.sg_flags |= CBREAK;
- X#if defined TIOCGATC
- X (void)ioctl(0, TIOCGATC, &lcharsorig);
- X lchars = lcharsorig;
- X lchars.tc_suspc = -1;
- X lchars.tc_dsuspc = -1;
- X lchars.tc_lnextc = -1;
- X lchars.tc_statc = -1;
- X lchars.tc_intrc = -1;
- X lchars.tc_quitc = -1;
- X lchars.tc_rprntc = -1;
- X#else
- X (void)ioctl(0, TIOCGETC, &tcharsorig);
- X (void)ioctl(0, TIOCGLTC, <charsorig);
- X tchars = tcharsorig;
- X ltchars = ltcharsorig;
- X ltchars.t_suspc = -1;
- X ltchars.t_dsuspc = -1;
- X ltchars.t_lnextc = -1;
- X tchars.t_intrc = -1;
- X tchars.t_quitc = -1;
- X ltchars.t_rprntc = -1;
- X#endif
- X first_time = 0;
- X }
- X (void)ioctl(0, TIOCSETN, &cb);
- X#if defined TIOCGATC
- X (void)ioctl(0, TIOCSATC, &lchars);
- X#else
- X (void)ioctl(0, TIOCSETC, &tchars);
- X (void)ioctl(0, TIOCSLTC, <chars);
- X#endif
- X }
- X else {
- X (void)ioctl(0, TIOCSETN, &orig);
- X#if defined TIOCGATC
- X (void)ioctl(0, TIOCSATC, &lcharsorig);
- X#else
- X (void)ioctl(0, TIOCSETC, &tcharsorig);
- X (void)ioctl(0, TIOCSLTC, <charsorig);
- X#endif
- X }
- X return prev;
- X}
- X
- X#else /* !_BSD */
- X
- Xbool_t
- Xset_xmode(onoff)
- Xbool_t onoff;
- X{
- X bool_t prev;
- X static struct termio cb, orig;
- X
- X if (x_mode == onoff) return x_mode;
- X prev = x_mode;
- X x_mode = onoff;
- X
- X if (onoff) {
- X if (first_time) {
- X (void)ioctl(0, TCGETA, &cb);
- X orig = cb;
- X#if defined _CRAY2 /* brain-damaged terminal handler */
- X cb.c_lflag &= ~(ICANON|ECHO);
- X /* rely on print routine to map '\n' to CR,LF */
- X#else
- X cb.c_iflag &= ~(INLCR|ICRNL);
- X#if _BSD_SYSV /* need to force CBREAK instead of RAW (need CRMOD on output) */
- X cb.c_lflag &= ~(ICANON|ECHO);
- X#else
- X cb.c_lflag &= ~(ISIG|ICANON|ECHO);
- X#endif
- X cb.c_cc[VTIME] = 0;
- X cb.c_cc[VMIN] = 1;
- X#endif /* _CRAY2 */
- X first_time = 0;
- X }
- X#if ! defined TCSETAW /* e.g. Cray-2 */
- X /* first wait for output to drain */
- X#if defined TCSBRK
- X (void)ioctl(0, TCSBRK, 1);
- X#else /* the following kludge is minimally intrusive, but sometimes fails */
- X (void)sleep((unsigned)1); /* fake it */
- X#endif
- X#endif
- X#if _BSD_SYSV || !defined(TCSETAW)
- X/* _BSD_SYSV needs to force TIOCSETN instead of TIOCSETP (preserve type-ahead) */
- X (void)ioctl(0, TCSETA, &cb);
- X#else
- X (void)ioctl(0, TCSETAW, &cb);
- X#endif
- X }
- X else {
- X#if ! defined TCSETAW /* e.g. Cray-2 */
- X /* first wait for output to drain */
- X#if defined TCSBRK
- X (void)ioctl(0, TCSBRK, 1);
- X#else
- X/* doesn't seem to be necessary when leaving xmode */
- X/* (void)sleep((unsigned)1); /* fake it */
- X#endif
- X#endif
- X#if _BSD_SYSV || !defined(TCSETAW)
- X/* _BSD_SYSV needs to force TIOCSETN instead of TIOCSETP (preserve type-ahead) */
- X (void)ioctl(0, TCSETA, &orig);
- X#else
- X (void)ioctl(0, TCSETAW, &orig);
- X#endif
- X }
- X return prev;
- X}
- X#endif /* _BSD */
- X
- Xstatic int
- Xx_stuffreset(c)
- X{
- X#if defined TIOCSTI
- X (void)x_stuff(c);
- X return KINTR;
- X#else
- X x_zotc(c);
- X xcp = xep = xbuf;
- X *xcp = 0;
- X x_redraw(-1);
- X return KSTD;
- X#endif
- X}
- X
- Xstatic int
- Xx_stuff(c)
- X{
- X#if defined TIOCSTI
- X char ch = c;
- X bool_t savmode = set_xmode(FALSE);
- X
- X (void)ioctl(0, TIOCSTI, &ch);
- X (void)set_xmode(savmode);
- X x_redraw(-1);
- X#endif
- X return KSTD;
- X}
- X
- Xstatic void
- Xx_mapin(cp)
- X char *cp;
- X{
- X char *op;
- X
- X op = cp;
- X while (*cp) {
- X /* XXX -- should handle \^ escape? */
- X if (*cp == '^') {
- X cp++;
- X if (*cp >= '?') /* includes '?'; ASCII */
- X *op++ = CTRL(*cp);
- X else {
- X *op++ = '^';
- X cp--;
- X }
- X } else
- X *op++ = *cp;
- X cp++;
- X }
- X *op = 0;
- X}
- X
- Xstatic char *
- Xx_mapout(c)
- X int c;
- X{
- X static char buf[8];
- X register char *p = buf;
- X
- X if (c < ' ' || c == 0x7F) { /* ASCII */
- X *p++ = '^';
- X *p++ = (c == 0x7F) ? '?' : (c | 0x40);
- X } else
- X *p++ = c;
- X *p = 0;
- X return buf;
- X}
- X
- Xstatic void
- Xx_print(prefix, key)
- X int prefix, key;
- X{
- X if (prefix == 1)
- X shellf("%s", x_mapout(x_prefix1));
- X if (prefix == 2)
- X shellf("%s", x_mapout(x_prefix2));
- X shellf("%s = ", x_mapout(key));
- X if (x_tab[prefix][key]->xf_func != x_ins_string)
- X shellf("%s\n", x_tab[prefix][key]->xf_name);
- X else
- X shellf("'%s'\n", x_atab[prefix][key]);
- X}
- X
- Xvoid
- Xx_bind(a1, a2, macro)
- X char *a1, *a2;
- X int macro; /* bind -m */
- X{
- X struct x_ftab Const *fp;
- X int prefix, key;
- X char *sp = NULL;
- X
- X if (x_tab == NULL)
- X errorf("cannot bind, not a tty\n");
- X
- X if (a1 == NULL) {
- X for (prefix = 0; prefix < 3; prefix++)
- X for (key = 0; key < 0x80; key++) {
- X fp = x_tab[prefix][key];
- X if (fp == NULL ||
- X fp->xf_func == x_insert || fp->xf_func == x_error)
- X continue;
- X x_print(prefix, key);
- X }
- X return;
- X }
- X
- X x_mapin(a1);
- X prefix = key = 0;
- X for (;; a1++) {
- X key = *a1;
- X if (x_tab[prefix][key]->xf_func == x_meta1)
- X prefix = 1;
- X else
- X if (x_tab[prefix][key]->xf_func == x_meta2)
- X prefix = 2;
- X else
- X break;
- X }
- X
- X if (a2 == NULL) {
- X x_print(prefix, key);
- X return;
- X }
- X
- X if (*a2 == 0)
- X fp = xft_insert;
- X else if (!macro) {
- X for (fp = x_ftab; fp->xf_func; fp++)
- X if (strcmp(fp->xf_name, a2) == 0)
- X break;
- X if (fp->xf_func == NULL || (fp->xf_flags & XF_NOBIND))
- X errorf("%s: no such function\n", a2);
- X if (fp->xf_func == x_meta1)
- X x_prefix1 = key;
- X if (fp->xf_func == x_meta2)
- X x_prefix2 = key;
- X } else {
- X fp = xft_ins_string;
- X x_mapin(a2);
- X sp = strsave(a2, AEDIT);
- X }
- X
- X if ((x_tab[prefix][key]->xf_flags & XF_ALLOC) && x_atab[prefix][key])
- X afree((Void *)x_atab[prefix][key], AEDIT);
- X x_tab[prefix][key] = fp;
- X x_atab[prefix][key] = sp;
- X}
- X
- Xvoid
- Xx_init()
- X{
- X register int i, j;
- X struct x_ftab Const *fp;
- X
- X ainit(AEDIT);
- X
- X x_tab = alloc(sizeofN(*x_tab, 3), AEDIT);
- X for (j = 0; j < 128; j++)
- X x_tab[0][j] = xft_insert;
- X for (i = 1; i < 3; i++)
- X for (j = 0; j < 128; j++)
- X x_tab[i][j] = xft_error;
- X for (fp = x_ftab; fp->xf_func; fp++)
- X if (fp->xf_db_char || fp->xf_db_tab)
- X x_tab[fp->xf_db_tab][fp->xf_db_char] = fp;
- X
- X x_atab = alloc(sizeofN(*x_atab, 3), AEDIT);
- X for (i = 1; i < 3; i++)
- X for (j = 0; j < 128; j++)
- X x_atab[i][j] = NULL;
- X}
- X
- X#if SILLY
- Xstatic int
- Xx_game_of_life(c) {
- X char newbuf [256+1];
- X register char *ip, *op;
- X int i, len;
- X
- X i = xep - xbuf;
- X *xep = 0;
- X len = x_size_str(xbuf);
- X xcp = xbuf;
- X memmove(newbuf+1, xbuf, i);
- X newbuf[0] = 'A';
- X newbuf[i] = 'A';
- X for (ip = newbuf+1, op = xbuf; --i >= 0; ip++, op++) {
- X /* Empty space */
- X if (*ip < '@' || *ip == '_' || *ip == 0x7F) {
- X /* Two adults, make whoopee */
- X if (ip[-1] < '_' && ip[1] < '_') {
- X /* Make kid look like parents. */
- X *op = '`' + ((ip[-1] + ip[1])/2)%32;
- X if (*op == 0x7F) /* Birth defect */
- X *op = '`';
- X }
- X else
- X *op = ' '; /* nothing happens */
- X continue;
- X }
- X /* Child */
- X if (*ip > '`') {
- X /* All alone, dies */
- X if (ip[-1] == ' ' && ip[1] == ' ')
- X *op = ' ';
- X else /* Gets older */
- X *op = *ip-'`'+'@';
- X continue;
- X }
- X /* Adult */
- X /* Overcrowded, dies */
- X if (ip[-1] >= '@' && ip[1] >= '@') {
- X *op = ' ';
- X continue;
- X }
- X *op = *ip;
- X }
- X *op = 0;
- X x_redraw(len);
- X return KSTD;
- X}
- X#endif
- X
- X/*
- X * File/command name completion routines
- X */
- X
- X/* type: 0 for list, 1 for completion */
- X
- Xstatic XPtrV words;
- X
- Xstatic void
- Xadd_stash(dirnam, name)
- X char *dirnam; /* directory name, if file */
- X char *name;
- X{
- X char *cp;
- X register int type = 0; /* '*' if executable, '/' if directory, else 0 */
- X register int len = strlen(name);
- X
- X /* determine file type */
- X if (dirnam) {
- X struct stat statb;
- X char *buf = alloc((size_t)(strlen(dirnam)+len+2), ATEMP);
- X
- X if (strcmp(dirnam, ".") == 0)
- X *buf = '\0';
- X else if (strcmp(dirnam, "/") == 0)
- X (void)strcpy(buf, "/");
- X else
- X (void)strcat(strcpy(buf, dirnam), "/");
- X (void)strcat(buf, name);
- X if (stat(buf, &statb)==0)
- X if (S_ISDIR(statb.st_mode))
- X type = '/';
- X else if (S_ISREG(statb.st_mode) && access(buf, 01)==0)
- X type = '*';
- X if (type)
- X ++len;
- X afree((Void *)buf, ATEMP);
- X }
- X
- X if (len > x_maxlen)
- X x_maxlen = len;
- X
- X /* stash name for later sorting */
- X cp = alloc((size_t)(len+1), ATEMP);
- X (void)strcpy(cp = alloc((size_t)(len+1), ATEMP), name);
- X if (dirnam && type) { /* append file type indicator */
- X cp[len-1] = type;
- X cp[len] = '\0';
- X }
- X XPput(words, cp);
- X}
- X
- Xstatic void
- Xlist_stash()
- X{
- X register char **array, **record;
- X int items = 0, tabstop, loc, nrows, jump, offset;
- X
- X items = XPsize(words);
- X array = (char**) XPptrv(words);
- X if (items == 0)
- X return;
- X qsortp(XPptrv(words), (size_t)XPsize(words), xstrcmp);
- X
- X /* print names */
- X x_maxlen = (x_maxlen/8 + 1) * 8; /* column width */
- X nrows = (items-1) / (x_cols/x_maxlen) + 1;
- X for (offset = 0; offset < nrows; ++offset) {
- X tabstop = loc = 0;
- X x_putc('\n');
- X for (jump = 0; offset+jump < items; jump += nrows) {
- X if (jump)
- X while (loc < tabstop) {
- X x_putc('\t');
- X loc = (loc/8 + 1) * 8;
- X }
- X record = array + (offset + jump);
- X x_puts(*record);
- X afree((Void *)*record, ATEMP);
- X loc += strlen(*record);
- X tabstop += x_maxlen; /* next tab stop */
- X }
- X }
- X
- X afree((Void*)array, ATEMP);
- X x_redraw(-1);
- X}
- X
- Xstatic int
- Xx_comp_comm(c) {
- X compl_command(1);
- X return KSTD;
- X}
- Xstatic int
- Xx_list_comm(c) {
- X compl_command(0);
- X return KSTD;
- X}
- Xstatic int
- Xx_complete(c) {
- X compl_dec(1);
- X return KSTD;
- X}
- Xstatic int
- Xx_enumerate(c) {
- X compl_dec(0);
- X return KSTD;
- X}
- Xstatic int
- Xx_comp_file(c) {
- X compl_file(1);
- X return KSTD;
- X}
- Xstatic int
- Xx_list_file(c) {
- X compl_file(0);
- X return KSTD;
- X}
- X
- Xstatic void
- Xcompl_dec(type)
- X{
- X char *cp;
- X cp = xcp;
- X
- X while (cp != xbuf && !isfs(*cp))
- X cp--;
- X if (cp == xbuf && strchr(cp, '/') == NULL)
- X compl_command(type);
- X else
- X compl_file(type);
- X}
- X
- Xstatic void
- Xcompl_file(type)
- X{
- X char *str;
- X register char *cp, *xp;
- X char *lastp;
- X char *dirnam;
- X char buf [256+1];
- X char bug [256+1];
- X DIR *dirp;
- X struct dirent *dp;
- X long loc = -1;
- X int len;
- X int multi = 0;
- X
- X str = xcp;
- X cp = buf;
- X xp = str;
- X while (xp != xbuf) {
- X --xp;
- X if (isfs(*xp)) {
- X xp++;
- X break;
- X }
- X }
- X if (digit(*xp) && (xp[1] == '<' || xp[1] == '>'))
- X xp++;
- X while (*xp == '<' || *xp == '>')
- X xp++;
- X if (type)
- X while (*xcp && !isfs(*xcp))
- X x_zotc(*xcp++);
- X else {
- X x_maxlen = 0;
- X XPinit(words, 16);
- X }
- X while (*xp && !isfs(*xp))
- X *cp++ = *xp++;
- X
- X *cp = 0;
- X strcpy(buf, cp = substitute(buf, DOTILDE));
- X afree((Void*)cp, ATEMP);
- X lastp = strrchr(buf, '/');
- X if (lastp)
- X *lastp = 0;
- X
- X dirnam = (lastp == NULL) ? "." : (lastp == buf) ? "/" : buf;
- X dirp = opendir(dirnam);
- X if (dirp == NULL) {
- X x_putc(BEL);
- X return;
- X }
- X
- X if (lastp == NULL)
- X lastp = buf;
- X else
- X lastp++;
- X len = strlen(lastp);
- X
- X while ((dp = readdir(dirp)) != NULL) {
- X cp = dp->d_name;
- X if (cp[0] == '.' &&
- X (cp[1] == '\0' || cp[1] == '.' && cp[2] == '\0'))
- X continue; /* always ignore . and .. */
- X if (strncmp(lastp, cp, len) == 0)
- X if (type) {
- X if (loc == -1) {
- X (void)strcpy(bug, cp);
- X loc = strlen(cp);
- X } else {
- X multi = 1;
- X loc = strmatch(bug, cp);
- X bug[loc] = 0;
- X }
- X } else
- X add_stash(dirnam, cp);
- X }
- X (void)closedir(dirp);
- X
- X if (type) {
- X if (loc <= 0) {
- X x_putc(BEL);
- X return;
- X }
- X cp = bug + len;
- X x_ins(cp);
- X if (!multi) {
- X struct stat statb;
- X if (lastp == buf)
- X buf[0] = 0;
- X else if (lastp == buf + 1) {
- X buf[1] = 0;
- X buf[0] = '/';
- X } else
- X (void)strcat(buf, "/");
- X (void)strcat(buf, bug);
- X if (stat(buf, &statb) == 0 && S_ISDIR(statb.st_mode))
- X x_ins("/");
- X else
- X x_ins(" ");
- X }
- X } else
- X list_stash();
- X}
- X
- Xstatic void
- Xcompl_command(type)
- X{
- X register struct tbl *tp;
- X char *str;
- X char buf [256+1];
- X char bug [256+1];
- X char *xp;
- X char *cp;
- X int len;
- X int multi;
- X int loc;
- X
- X str = xcp;
- X cp = buf;
- X xp = str;
- X while (xp != xbuf) {
- X --xp;
- X if (isfs(*xp)) {
- X xp++;
- X break;
- X }
- X }
- X if (type)
- X while (*xcp && !isfs(*xcp))
- X x_zotc(*xcp++);
- X else {
- X x_maxlen = 0;
- X XPinit(words, 16);
- X }
- X while (*xp && !isfs(*xp))
- X *cp++ = *xp++;
- X *cp = 0;
- X
- X len = strlen(buf);
- X loc = -1;
- X multi = 0;
- X
- X for (twalk(&commands); (tp = tnext()) != NULL; ) {
- X int klen;
- X
- X if (!(tp->flag&ISSET))
- X continue;
- X klen = strlen(tp->name);
- X if (klen < len)
- X return;
- X if (strncmp(buf, tp->name, len) ==0)
- X if (type) {
- X if (loc == -1) {
- X (void)strcpy(bug, tp->name);
- X loc = klen;
- X } else {
- X multi = 1;
- X loc = strmatch(bug, tp->name);
- X bug[loc] = 0;
- X }
- X } else
- X add_stash((char *)0, tp->name);
- X }
- X
- X if (type) {
- X if (loc <= 0) {
- X x_putc(BEL);
- X return;
- X }
- X cp = bug + len;
- X x_ins(cp);
- X if (!multi)
- X x_ins(" ");
- X } else
- X list_stash();
- X}
- X
- Xstatic int
- Xstrmatch(s1, s2)
- X register char *s1, *s2;
- X{
- X register char *p;
- X
- X for (p = s1; *p == *s2++ && *p != 0; p++)
- X ;
- X return p - s1;
- X}
- X
- X#endif /* EDIT */
- X
- SHAR_EOF
- true || echo 'restore of src/edit.c failed'
- fi
- # ============= src/history.c ==============
- if test -f 'src/history.c' -a X"$1" != X"-c"; then
- echo 'x - skipping src/history.c (File already exists)'
- else
- echo 'x - extracting src/history.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'src/history.c' &&
- X/*
- X * command history
- X *
- X * only implements in-memory history.
- X */
- X
- Xstatic char *RCSid = "$Header: /tmp/egisin/src/RCS/history.c,v 3.2 88/11/21 10:34:30 egisin Exp $";
- X
- X#include <stddef.h>
- X#include <stdio.h>
- X#include <string.h>
- X#include <errno.h>
- X#include <setjmp.h>
- X#include "sh.h"
- X#include "lex.h"
- X
- Xchar **histget();
- Xchar *histrpl();
- X
- Xc_fc(wp)
- X register char **wp;
- X{
- X register char *id;
- X FILE *f;
- X struct temp *tf;
- X register char **hp;
- X char **hbeg, **hend;
- X int lflag = 0, nflag = 0, sflag = 0;
- X
- X for (wp++; (id = *wp) != NULL && *id == '-' && !sflag; wp++)
- X switch (id[1]) {
- X case 'l':
- X lflag++;
- X break;
- X case 'n':
- X nflag++;
- X break;
- X case 's':
- X sflag++;
- X break;
- X }
- X
- X /* fc -s [pat=rep] [cmd], equivalent to Korn's fc -e - [pat=rep] */
- X if (sflag) {
- X char *pat = NULL, *rep = NULL;
- X
- X hp = histptr - 1;
- X while ((id = *wp++) != NULL)
- X /* todo: multiple substitutions */
- X if ((rep = strchr(id, '=')) != NULL) {
- X pat = id;
- X *rep++ = '\0';
- X } else
- X hp = histget(id);
- X
- X if (hp == NULL || hp < history)
- X errorf("cannot find history\n");
- X if (pat == NULL)
- X strcpy(line, *hp);
- X else
- X histrpl(*hp, pat, rep);
- X histsave(line);
- X histpush--;
- X line[0] = '\0';
- X return 0;
- X }
- X
- X if (*wp != NULL) {
- X hbeg = histget(*wp++); /* first */
- X if (*wp != NULL)
- X hend = histget(*wp++); /* last */
- X else
- X hend = hbeg;
- X } else {
- X if (lflag)
- X hbeg = histptr - 12, hend = histptr;
- X else
- X hbeg = hend = histptr - 1;
- X if (hbeg < history)
- X hbeg = history;
- X }
- X if (hbeg == NULL || hend == NULL)
- X errorf("can't find history\n");
- X
- X if (lflag)
- X f = stdout;
- X else {
- X nflag++;
- X tf = maketemp(ATEMP);
- X tf->next = e.temps; e.temps = tf;
- X f = fopen(tf->name, "w");
- X if (f == NULL)
- X errorf("cannot create temp file %s", tf->name);
- X setvbuf(f, (char *)NULL, _IOFBF, BUFSIZ);
- X }
- X
- X for (hp = hbeg; hp <= hend; hp++) {
- X if (!nflag)
- X fprintf(f, "%3d: ", source->line - (int)(histptr-hp));
- X fprintf(f, "%s\n", *hp);
- X }
- X
- X if (lflag)
- X return 0;
- X else
- X fclose(f);
- X
- X setstr(local("_"), tf->name);
- X command("${FCEDIT:-/bin/ed} $_"); /* edit temp file */
- X
- X f = fopen(tf->name, "r");
- X if (f == NULL)
- X errorf("cannot open temp file %s\n", tf->name);
- X setvbuf(f, (char *)NULL, _IOFBF, BUFSIZ);
- X /* we push the editted lines onto the history list */
- X while (fgets(line, sizeof(line), f) != NULL) {
- X histsave(line);
- X histpush--;
- X }
- X line[0] = '\0';
- X fclose(f);
- X
- X return 0;
- X}
- X
- X/*
- X * save command in history
- X */
- Xvoid
- Xhistsave(cmd)
- X char *cmd;
- X{
- X register char **hp = histptr;
- X char *cp;
- X
- X if (++hp >= history + HISTORY) { /* remove oldest command */
- X afree((Void*)*history, APERM);
- X for (hp = history; hp < history + HISTORY - 1; hp++)
- X hp[0] = hp[1];
- X }
- X *hp = strsave(cmd, APERM);
- X if ((cp = strchr(*hp, '\n')) != NULL)
- X *cp = '\0';
- X histptr = hp;
- X}
- X
- X/*
- X * get pointer to history given pattern
- X * pattern is a number or string
- X */
- Xchar **
- Xhistget(str)
- X char *str;
- X{
- X register char **hp = NULL;
- X
- X if (*str == '-')
- X hp = histptr + getn(str);
- X else
- X if (digit(*str))
- X hp = histptr + (getn(str) - source->line);
- X else
- X if (*str == '?') { /* unanchored match */
- X for (hp = histptr-1; hp >= history; hp--)
- X if (strstr(*hp, str+1) != NULL)
- X break;
- X } else { /* anchored match */
- X for (hp = histptr; hp >= history; hp--)
- X if (strncmp(*hp, str, strlen(str)) == 0)
- X break;
- X }
- X
- X return (history <= hp && hp <= histptr) ? hp : NULL;
- X}
- X
- Xchar *
- Xhistrpl(s, pat, rep)
- X char *s;
- X char *pat, *rep;
- X{
- X char *s1;
- X
- X if (strlen(s) - strlen(pat) + strlen(rep) >= LINE)
- X errorf("substitution too long\n");
- X s1 = strstr(s, pat);
- X if (s1 == NULL)
- X errorf("substitution failed\n");
- X *s1 = '\0';
- X strcpy(line, s); /* first part */
- X strcat(line, rep); /* replacement */
- X strcat(line, s1 + strlen(pat)); /* last part */
- X return line;
- X}
- X
- X#if 0
- X
- X/* History file management routines (by DPK@BRL) */
- X
- Xvoid
- Xhist_init()
- X{
- X register struct namnod *n;
- X int fd;
- X
- X if (hist_fd >= 0 || (flags&oneflg))
- X return;
- X if ((n = findnam(histname)) == (struct namnod *)0
- X || n->namval == (char *)0)
- X return;
- X if ((fd = open(n->namval, O_RDWR)) >= 0) {
- X hist_load(fd);
- X (void)fcntl(fd, F_SETFL, O_APPEND);
- X }
- X hist_fd = fd;
- X}
- X
- Xvoid
- Xhist_finish()
- X{
- X if (hist_fd >= 0)
- X (void)close(hist_fd);
- X hist_fd = -1;
- X}
- X
- Xvoid
- Xhist_record(buf, len)
- Xchar *buf;
- Xint len;
- X{
- X if (hist_fd >= 0)
- X (void)write(hist_fd, buf, (unsigned)len);
- X}
- X
- Xvoid
- Xhist_load(fd)
- Xint fd;
- X{
- X extern long lseek();
- X struct stat sb;
- X char *x;
- X register char *cmdp, *end;
- X register int len;
- X register int i;
- X
- X if (fstat(fd, &sb) < 0 || sb.st_size <= 0)
- X return;
- X if (x = alloc((unsigned)(sb.st_size+1))) {
- X (void)lseek(fd, 0L, 0);
- X if ((len = read(fd, x, (unsigned)sb.st_size)) <= 0) {
- X free((struct blk *)x);
- X return;
- X }
- X x[len] = 0;
- X end = x;
- X for (;;) {
- X while(*end == NL)
- X end++; /* Skip NL */
- X if (*end == 0)
- X break;
- X cmdp = end;
- X while(*end && *end != NL)
- X end++; /* Goto NL */
- X if (*end == 0)
- X break;
- X if ((len = (end - cmdp)) < 2)
- X continue;
- X if (len >= BUFSIZ)
- X len = BUFSIZ - 1; /* Protection */
- X i = curhist % NHISTORY;
- X if(histbuf[i])
- X free((struct blk *)histbuf[i]);
- X histbuf[i] = alloc((unsigned)(len+1));
- X (void)strncpy(histbuf[i], cmdp, len);
- X histbuf[i][len] = 0;
- X curhist++;
- X histpc=curhist;
- X }
- X free((struct blk *)x);
- X }
- X return;
- X}
- X
- X#endif
- X
- SHAR_EOF
- true || echo 'restore of src/history.c failed'
- fi
- true || echo 'restore of src/tree.c failed'
- echo End of part 3, continue with part 4
- exit 0
-