rsalz@uunet.uu.net (Rich Salz) (11/11/88)
Submitted-by: Kazumasa Utashiro <kddlab!sra.junet!utashiro> Posting-number: Volume 16, Issue 61 Archive-name: fep/part01 Dear moderator, FEP is a general purpose front end for any line-oriented command on UNIX. This command was developed on Berkeley UNIX, but will probably run on most UNIX system which have pseudo tty and the select system call. Kazumasa Utashiro Software Research Associates, Inc. 1-1-1 Hirakawa-cho, Chiyoda-ku, Tokyo 102, Japan UUCP: kddlab!srava.sra.junet!utashiro ARPA: utashiro%sra.junet@uunet.uu.net JUNET: utashiro@sra.junet #!/bin/sh # to extract, remove the header and type "sh filename" if `test ! -s ./fep_funcs.c` then echo "writing ./fep_funcs.c" cat > ./fep_funcs.c << '\End\Of\File\' /* Copyright (c) 1987, 1988 by Software Research Associates, Inc. */ #ifndef lint static char rcsid[]= "$Header: fep_funcs.c,v 4.0 88/08/05 20:22:12 utashiro Rel $ (SRA)"; #endif lint #include <stdio.h> #include "fep_funcs.h" /* * FunctionNameTable */ FunctionTableEnt FunctionNameTable[] = { {mark, "mark", "Mark position"}, {abort, "abort", "Abort function"}, {self_insert, "self-insert", "Insert the character"}, {beginning_of_line, "beginning-of-line", "Jump to beginning of line"}, {backward_character, "backward-character", "Backward character"}, {backward_word, "backward-word", "Backward word (alpha-numeric)"}, {backward_Word, "backward-Word", "Backward word (non-space)"}, {end_of_line, "end-of-line", "Jump to end of line"}, {forward_character, "forward-character", "Forward character"}, {forward_word, "forward-word", "Forward word (alpha-numeric)"}, {forward_Word, "forward-Word", "Forward word (non-space)"}, {forward_to_end_of_word, "forward-to-end-of-word", "Forward to end of word (alpha-numeric)"}, {forward_to_end_of_Word, "forward-to-end-of-Word", "Forward to end of word (non-space)"}, {delete_previous_character, "delete-previous-character", "Delete previous character"}, {delete_next_character, "delete-next-character", "Delete next character"}, {insert_tab, "insert-tab", "Insert tab"}, {new_line, "new-line", "Insert newline"}, {insert_and_flush, "insert-and-flush", "Insert the character and flush buffer"}, {send_eof, "send-eof", "Send eof"}, {kill_to_end_of_line, "kill-to-end-of-line", "Delete current position to eol"}, {kill_to_top_of_line, "kill-to-top-of-line", "Delete tol to current position"}, {delete_to_kill_buffer, "delete-to-kill-buffer", "Delete resion to buffer"}, {yank_from_kill_buffer, "yank-from-kill-buffer", "Yank from kill buffer"}, {clear_screen, "clear-screen", "Clear screen"}, {next_history, "next-history", "Get next history"}, {previous_history, "previous-history", "Get previous history"}, {ignore, "ignore", "Ignore"}, {delete_line, "delete-line", "Delete whole line"}, {literal_next, "literal-next", "Treat next character as literal"}, {delete_previous_word, "delete-previous-word", "Delete previous word (alpha-numeric)"}, {delete_previous_Word, "delete-previous-Word", "Delete previous word (non-space)"}, {delete_next_word, "delete-next-word", "Delete next word (alpha-numeric)"}, {delete_next_Word, "delete-next-Word", "Delete next word (non-space)"}, {reprint, "reprint", "Reprint line"}, {show_history, "show-history", "Show history"}, {show_bindings, "show-bindings", "Show binding table"}, {expand_file_name, "expand-file-name", "Expand file name"}, {list_file_name, "list-file-name", "List file name"}, {terminate, "terminate", "Terminate fep"}, {suspend, "suspend", "Suspend fep"}, {toggle_transparency, "toggle-transparency", "Change transparency mode"}, {fix_transparency, "fix-transparency", "Check tty and change transparency mode"}, {invoke_shell, "invoke-shell", "Invoke shell process"}, {search_reverse, "search-reverse", "Search backward last !history"}, {search_forward, "search-forward", "Search forward last !history"}, {fep_start_script, "start-script", "Start script"}, {fep_end_script, "end-script", "End script"}, {fep_repaint, "repaint", "Repaint screen"}, {show_help, "help", "Show help"}, {vi_c, "vi-c", "Vi c? commands"}, {vi_d, "vi-d", "Vi d? commands"}, {vi_edit, "vi-edit", "Vi edit commands"}, {vi_ins_edit, "vi-ins-edit", "Vi insert mode"}, {vi_motion, "vi-motion", "Vi cursor motion commands"}, {vi_new_line, "vi-new-line", "Vi new line"}, {vi_num, "vi-num", "Vi prefix number"}, {NULL, NULL} }; /* * Table of built-in functions */ FunctionTableEnt BuiltinFuncTable[] = { {bind_to_key, "fep-bind", "Change binding table"}, {alias, "fep-alias", "Set or show aliases"}, {unalias, "fep-unalias", "Delete alias"}, {set, "fep-set", "Set or show variables"}, {unset, "fep-unset", "Unset variables"}, {fep_chdir, "fep-cd", "Change directory"}, {fep_chdir, "fep-chdir", "Change directory"}, {fep_pwd, "fep-pwd", "Print working directory"}, {fep_history, "fep-history", "Show history"}, {fep_echo, "fep-echo", "Print arguments"}, {fep_source, "fep-source", "Read and execute file"}, {fep_command, "fep-command", "Invoke unix command"}, {fep_command, "fep-!", "Same as fep_command"}, {fep_save_history, "fep-save-history", "Save history to file"}, {fep_read_history, "fep-read-history", "Read history from file"}, {fep_read_from_file, "fep-read-from-file", "Send file contens to slave command"}, {fep_read_from_file, "fep-<", "Same as fep_read_from_file"}, {fep_read_from_command, "fep-read-from-command", "Send output of command to slave command"}, {fep_read_from_command, "fep-<!", "Same as fep_read_from_command"}, {fep_start_script, "fep-start-script", "Start script"}, {fep_start_script, "fep-script", "Start script"}, {fep_end_script, "fep-end-script", "End script"}, {fep_if, "fep-if", "Operation \"if\""}, {fep_if, "fep-elseif", "Operation \"endif\""}, {fep_else, "fep-else", "Operation \"else\""}, {fep_endif, "fep-endif", "Operation \"endif\""}, {terminate, "fep-exit", "Terminate fep"}, {suspend, "fep-suspend", "Suspend fep"}, {show_bindings, "fep-show-bind", "Print bindings"}, {show_bindings, "fep-showbind", "Print bindings"}, {fep_repaint, "fep-repaint", "Repaint screen"}, #ifdef STAT {fep_showstat, "fep-showstat", "Show statistical information"}, #endif {NULL, NULL} }; \End\Of\File\ else echo "will not over write ./fep_funcs.c" fi if `test ! -s ./fep_set.c` then echo "writing ./fep_set.c" cat > ./fep_set.c << '\End\Of\File\' /* Copyright (c) 1987, 1988 by Software Research Associates, Inc. */ #ifndef lint static char rcsid[]= "$Header: fep_set.c,v 4.0 88/08/05 20:22:22 utashiro Rel $ (SRA)"; #endif lint #include <stdio.h> #include "fep_defs.h" #include "fep_glob.h" VAR default_set_vars [] = { {"expand-tilde", "", "Expand ~ to home directory name", (VAR*)0}, {"ignore-empty-line", "", "Don't put empty line to history", (VAR*)0}, {"ignore-same-line", "", "Don't put same line to history", (VAR*)0}, {"editmode", "emacs", "Fep command line edit mode", (VAR*)0}, {"history-file", ".fephistory", "Name of history file", (VAR*)0}, {"shell", "/bin/sh", "Shell name used by invoke-shell", (VAR*)0}, {"auto-tty-fix", "", "Fix tty mode automatically", (VAR*)0}, {"script-file", "fepscript", "Script file name", (VAR*)0}, {"crt", "24", "Terminal lines", (VAR*)0}, {"showhist", "24", "History length used by show-history", (VAR*)0}, {"delimiters", " \t", "Argument delemiter characters", (VAR*)0}, {NULL, NULL, NULL, (VAR*)0} }; VAR default_unset_vars [] = { /* below from here is unset by default */ {"alarm-on-eof", "", "Alarm once to eof character", (VAR*)0}, {"ignore-eof", "", "Never treat eof character as eof", (VAR*)0}, {"savehist", "", "Length of save history", (VAR*)0}, {"verbose", "", NULL, (VAR*)0}, {"search-string", "", NULL, (VAR*)0}, {"noalias", "", "Not use alias", (VAR*)0}, {"tty-fix-bell", "", "Ring bell when tty mode changed", (VAR*)0}, {"auto-repaint", "", "Repaint screen when restarting", (VAR*)0}, {"clear-repaint", "", "Clear screen before repaint", (VAR*)0}, {NULL, NULL, NULL, (VAR*)0} }; #ifdef HASH #define HASHNUM 10 VAR *var_htab[HASHNUM]; #else HASH VAR var_top = {"top", "top", (char *)0, (VAR *)0}; VAR *var_list = &var_top; #endif HASH /* * Functions */ int set_var (/* char *name, char *value */); char *look_var (/* char *name */); int lookd_var (/* char *name */); VAR *getvp (/* char *name */); extern char *allocAndCopyThere(); extern char *prompt; /* * Set default variables */ set_default_vars () { register VAR *vp; for (vp = default_set_vars; vp->v_name; vp++) set_only_var (vp->v_name, vp->v_value); } /* * Set variable */ set_var (name, value) char *name; char *value; { set_only_var (name, value); /* * Process special variable */ if (eq (name, "history")) changeHistorySize (lookd_var ("history")); if (eq (name, "prompt")) { free (prompt); prompt = allocAndCopyThere (value); } if (eq (name, "editmode")) { if (eq (value, "emacs")) { editmode = EMACS; initEmacsBindings (curFuncTab, altFuncTab); } else if (eq (value, "vi")) { editmode = VI; initViBindings (curFuncTab, altFuncTab); } else printf ("%s: Unknown editmode\n", value); } if (eq (name, "auto-tty-fix")) auto_tty_fix = ON; if (eq (name, "debug")) debug = ON; if (eq (name, "tty-fix-bell")) tty_fix_bell = ON; if (eq (name, "delimiters")) delimiters = look_var ("delimiters"); if (eq (name, "crt")) lines = atoi (look_var("crt")); } set_only_var (name, value) char *name, *value; { VAR *vp; vp = getvp (name, 1, 0); if (vp->v_value) free (vp->v_value); vp->v_value = allocAndCopyThere (value); } /* * Unset variable */ unset_var (name) char *name; { VAR *vp, *prev; vp = getvp (name, 0, &prev); if (!vp) return; prev->v_next = vp->v_next; free (vp->v_name); free (vp->v_value); free (vp); if (eq (name, "auto-tty-fix")) auto_tty_fix = OFF; if (eq (name, "debug")) debug = OFF; if (eq (name, "tty-fix-bell")) tty_fix_bell = OFF; if (eq (name, "delimiters")) delimiters = DEFAULT_DELIMITERS; return; } /* * Look up variable */ char * look_var (name) char *name; { VAR *vp; vp = getvp (name, 0, 0); if (vp && vp->v_value) return (vp->v_value); else return ((char *)0); } /* * Look up variable and get integer result */ int lookd_var (name) char *name; { VAR *vp; vp = getvp (name, 0, 0); if (vp && vp->v_value) return (atoi (vp->v_value)); else return (0); } /* * Show variable list */ show_varlist () { #ifdef HASH register int i; for (i = 0; i< HASHNUM; i++) { register VAR *vp; vp = var_htab[i]; if (vp == (VAR *)0) continue; for (; vp != (VAR *)0; vp = vp->v_next) printf ("%-16s %s\n", vp->v_name, vp->v_value); } #else HASH register VAR *vp; for (vp = var_list->v_next; vp; vp = vp->v_next) printf ("%-16s %s\n", vp->v_name, vp->v_value); #endif HASH } #ifdef HASH /* * Get hash index from variable name */ static getindex (s) register char *s; { register int sum = 0; while (*s) sum += *s++; return (sum % HASHNUM); } #endif HASH /* * Get pointer to VAR. * If there is no memoly associated to the variable and alloc argument is 1, * allocate the area and initialize name field. */ VAR * getvp (name, alloc, lastvp) char *name; int alloc; VAR **lastvp; { #ifdef HASH register i = getindex (name); #endif HASH VAR *vp, *last = (VAR *)0; #ifdef HASH for (vp = var_htab[i]; vp; last = vp, vp->v_next) { if (strcmp (name, vp->v_value) == 0) return (vp); } #else HASH for (vp = var_list->v_next, last = var_list; vp; last = vp, vp = vp->v_next) { int r; r = strcmp (name, vp->v_name); if (r == 0) { if (lastvp) *lastvp = last; return (vp); } else if (r < 0) break; } #endif HASH if (alloc == 0) return (0); vp = (VAR *) calloc (sizeof (VAR), 1); vp->v_value = (char *)0; vp->v_next = (VAR *) 0; vp->v_name = allocAndCopyThere (name); #ifdef HASH if (last) { vp->v_next = last->v_next; last->v_next = vp; } else { var_htab[i] = vp; } #else HASH vp->v_next = last->v_next; last->v_next = vp; #endif HASH return (vp); } \End\Of\File\ else echo "will not over write ./fep_set.c" fi if `test ! -s ./fep_vi.c` then echo "writing ./fep_vi.c" cat > ./fep_vi.c << '\End\Of\File\' /* Copyright (c) 1987, 1988 by Software Research Associates, Inc. */ #ifndef lint static char rcsid[]= "$Header: fep_vi.c,v 4.0 88/08/05 20:22:27 utashiro Rel $ (SRA)"; #endif lint #include <stdio.h> #include <sgtty.h> #include <ctype.h> #include "fep_defs.h" #include "fep_glob.h" #include "fep_funcs.h" enum {INSERTMODE, COMMANDMODE} vi_mode = COMMANDMODE; int vi_count; extern char *CommandLine; extern int CurrentPosition; /* * Default binding table */ BINDENT viComBindings[] = { /* 1 */ {"1", vi_num}, /* 2 */ {"2", vi_num}, /* 3 */ {"3", vi_num}, /* 4 */ {"4", vi_num}, /* 5 */ {"5", vi_num}, /* 6 */ {"6", vi_num}, /* 7 */ {"7", vi_num}, /* 8 */ {"8", vi_num}, /* 9 */ {"9", vi_num}, /* ~ */ {"~", vi_edit}, /* A */ {"A", vi_edit}, /* C */ {"C", vi_edit}, /* D */ {"D", vi_edit}, /* P */ {"P", vi_edit}, /* S */ {"S", vi_edit}, /* I */ {"I", vi_edit}, /* a */ {"a", vi_edit}, /* i */ {"i", vi_edit}, /* p */ {"p", vi_edit}, /* r */ {"r", vi_edit}, /* s */ {"s", vi_edit}, /* x */ {"x", vi_edit}, /* X */ {"X", vi_edit}, /* ^U */ {"\\^U", vi_edit}, /* */ {" ", vi_motion}, /* ^H */ {"\b", vi_motion}, /* l */ {"l", vi_motion}, /* h */ {"h", vi_motion}, /* k */ {"k", vi_motion}, /* j */ {"j", vi_motion}, /* b */ {"b", vi_motion}, /* B */ {"B", vi_motion}, /* e */ {"e", vi_motion}, /* E */ {"E", vi_motion}, /* w */ {"w", vi_motion}, /* W */ {"W", vi_motion}, /* n */ {"n", vi_motion}, /* N */ {"N", vi_motion}, /* 0 */ {"0", vi_motion}, /* ^ */ {"^", vi_motion}, /* $ */ {"$", vi_motion}, /* | */ {"|", vi_motion}, /* - */ {"-", vi_motion}, /* + */ {"+", vi_motion}, /* cb */ {"cb", vi_c}, /* cB */ {"cb", vi_c}, /* cw */ {"cw", vi_c}, /* cW */ {"cW", vi_c}, /* c0 */ {"c0", vi_c}, /* c^ */ {"c^", vi_c}, /* c$ */ {"c$", vi_c}, /* cc */ {"cc", vi_c}, /* db */ {"db", vi_d}, /* dB */ {"dB", vi_d}, /* dw */ {"dw", vi_d}, /* dW */ {"dW", vi_d}, /* d0 */ {"d0", vi_d}, /* d^ */ {"d^", vi_d}, /* d$ */ {"d$", vi_d}, /* dd */ {"dd", vi_d}, /* ^E */ {"\\^E", expand_file_name}, /* ^J */ {"\\^J", vi_new_line}, /* ^L */ {"\\^L", list_file_name}, /* ^M */ {"\\^M", vi_new_line}, /* ^P */ {"\\^P", previous_history}, /* ^N */ {"\\^N", next_history}, /* ^R */ {"\\^R", reprint}, /* ^^ */ {"\\^^", toggle_transparency}, /* ^X-^B */ {"\\^X\\^B", show_bindings}, /* ^X-B */ {"\\^XB", show_bindings}, /* ^X-b */ {"\\^Xb", show_bindings}, /* ^X-^H */ {"\\^X\\^H", show_history}, /* ^X-h */ {"\\^Xh", show_history}, /* ^X-H */ {"\\^XH", show_history}, /* ^X-l */ {"\\^Xl", list_file_name}, /* ^X-L */ {"\\^XL", list_file_name}, /* ^X-^L */ {"\\^X\\^L", fep_repaint}, /* ^X-^X */ {"\\^X\\^X", expand_file_name}, /* ^X-? */ {"\\^X?", show_bindings}, /* ^X-^C */ {"\\^X\\^C", terminate}, /* ^X-^D */ {"\\^X\\^D", send_eof}, /* ^X-( */ {"\\^X(", fep_start_script}, /* ^X-) */ {"\\^X)", fep_end_script}, /* */ {NULL, NULL} }; BINDENT viInsertBindings[] = { /* ^H */ {"\\^H", vi_ins_edit}, /* ^W */ {"\\^W", vi_ins_edit}, /* ^U */ {"\\^U", vi_ins_edit}, /* ^V */ {"\\^V", vi_ins_edit}, /* ^J */ {"\\^J", vi_new_line}, /* ^L */ {"\\^L", list_file_name}, /* ^M */ {"\\^M", vi_new_line}, /* ^P */ {"\\^P", previous_history}, /* ^N */ {"\\^N", next_history}, /* ESC */ {"\\^[", vi_ins_edit}, /* ^E */ {"\\^E", expand_file_name}, /* ^^ */ {"\\^^", toggle_transparency}, /* ^X-^B */ {"\\^X\\^B", show_bindings}, /* ^X-B */ {"\\^XB", show_bindings}, /* ^X-b */ {"\\^Xb", show_bindings}, /* ^X-^H */ {"\\^X\\^H", show_history}, /* ^X-h */ {"\\^Xh", show_history}, /* ^X-H */ {"\\^XH", show_history}, /* ^X-l */ {"\\^Xl", list_file_name}, /* ^X-L */ {"\\^XL", list_file_name}, /* ^X-^L */ {"\\^X\\^L", fep_repaint}, /* ^X-^X */ {"\\^X\\^X", expand_file_name}, /* ^X-? */ {"\\^X?", show_bindings}, /* ^X-^C */ {"\\^X\\^C", terminate}, /* ^X-^D */ {"\\^X\\^D", send_eof}, /* ^X-( */ {"\\^X(", fep_start_script}, /* ^X-) */ {"\\^X)", fep_end_script}, /* */ {NULL, NULL} }; FUNC *viComTable; FUNC *viInsTable; initViBindings (cft, aft) FUNC cft[], aft[]; { register int i; BINDENT *ftp; for (i = 0; i < 256; i++) aft[i] = abort; for (i = 0; i < 256; i++) cft[i] = self_insert; for (ftp = viComBindings; ftp->bt_s; ftp++) { bind_key (aft, ftp->bt_func, ftp->bt_s, abort); } for (ftp = viInsertBindings; ftp->bt_s; ftp++) { bind_key (cft, ftp->bt_func, ftp->bt_s, abort); } /* Now, using cbreak mode cft[(int) tchars_buf.t_startx] = ignore; cft[(int) tchars_buf.t_stopc] = ignore; */ cft[(int) tchars_buf.t_intrc] = insert_and_flush; aft[(int) tchars_buf.t_intrc] = insert_and_flush; cft[(int) tchars_buf.t_quitc] = insert_and_flush; cft[(int) tchars_buf.t_eofc] = send_eof; cft[(int) tchars_buf.t_brkc] = insert_and_flush; cft[(int) ltchars_buf.t_suspc] = insert_and_flush; cft[(int) ltchars_buf.t_dsuspc] = self_insert; cft[(int) ltchars_buf.t_rprntc] = reprint; cft[(int) ltchars_buf.t_flushc] = self_insert; cft[(int) ltchars_buf.t_werasc] = delete_previous_word; cft[(int) ltchars_buf.t_lnextc] = literal_next; cft[(int) initial_ttymode.sg_erase] = delete_previous_character; cft[(int) initial_ttymode.sg_kill] = delete_line; viInsTable = cft; viComTable = aft; vi_mode = INSERTMODE; } vi_edit (c) int c; { int count = vi_count ? vi_count : 1; switch (c) { case '~': { char c = CommandLine [CurrentPosition]; if (isalpha (c)) { (void) delete_next_character (c); c ^= 0040; (void) self_insert (c); } else (void) forward_character (c); } break; case 'a': if (!is_eol()) (void) forward_character (c); case 'i': (void) altenateEditmode (c); break; case 'A': (void) end_of_line (c); (void) altenateEditmode (); break; case 'I': (void) beginning_of_line (c); (void) altenateEditmode (); break; case 'C': (void) kill_to_end_of_line (c); (void) altenateEditmode (c); break; case 'D': (void) kill_to_end_of_line (c); break; case 'S': (void) delete_line (c); (void) altenateEditmode (); break; case 'r': (void) delete_next_character (c); (void) self_insert (getcharacter ()); break; case 's': (void) delete_next_n_character (count); (void) altenateEditmode (); break; case 'x': (void) delete_next_n_character (count); break; case 'X': (void) delete_previous_n_character (count); break; case 'p': (void) forward_character (); case 'P': (void) yank_from_kill_buffer (); (void) backward_character (); break; case CTRL(U): (void) delete_line (c); (void) altenateEditmode (); break; } vi_count = 0; return (0); } altenateEditmode () { FUNC *tmp; tmp = curFuncTab; curFuncTab = altFuncTab; altFuncTab = tmp; vi_mode = (vi_mode == INSERTMODE) ? COMMANDMODE : INSERTMODE; return (0); } vi_num (c) int c; { vi_count = vi_count * 10 + ((int)c - (int)'0'); return (0); } vi_motion (c) int c; { int count = vi_count ? vi_count : 1; switch (c) { case 'w': (void) forward_n_word (count); break; case 'W': (void) forward_n_Word (count); break; case 'e': (void) forward_to_end_of_n_word (count); break; case 'E': (void) forward_to_end_of_n_Word (count); break; case 'b': (void) backward_n_word (count); break; case 'B': (void) backward_n_Word (count); break; case 'l': case ' ': (void) forward_n_character (count); break; case 'h': case '\b': (void) backward_n_character (count); break; case 'k': case '-': (void) previous_history (c); break; case 'j': case '+': (void) next_history (c); break; case 'n': (void) search_reverse (c); break; case 'N': (void) search_forward (c); break; case '0': if (vi_count) return (vi_num (c)); /* falling down */ case '^': (void) beginning_of_line (c); break; case '$': (void) end_of_line (c); break; case '|': (void) moveto (count - 1); /*** if (strlen (CommandLine) >= count) { (void) beginning_of_line (c); (void) forward_n_character (count - 1); } else (void) end_of_line (c); ***/ break; default: (void) abort (c); break; } vi_count = 0; return (0); } vi_c (c) int c; { int count = vi_count ? vi_count : 1; switch (c) { case '0': case '^': (void) kill_to_top_of_line (c); break; case 'c': delete_line(c); break; case 'w': (void) delete_next_n_word (count); break; case 'W': (void) delete_next_n_Word (count); break; case 'b': (void) delete_previous_n_word (count); break; case 'B': (void) delete_previous_n_Word (count); break; case '$': (void) kill_to_end_of_line(c); break; default: return (abort (c)); } vi_count = 0; altenateEditmode (); return (0); } vi_d (c) int c; { int count = vi_count ? vi_count : 1; switch (c) { case '0': case '^': (void) kill_to_top_of_line (c); break; case 'd': delete_line(c); break; case 'w': (void) delete_next_n_word (count); break; case 'W': (void) delete_next_n_Word (count); break; case 'b': (void) delete_previous_n_word (count); break; case 'B': (void) delete_previous_n_Word (count); break; case '$': (void) kill_to_end_of_line(c); break; default: return (abort (c)); } vi_count = 0; return (0); } vi_new_line (c) int c; { int count = vi_count ? vi_count : 1; vi_count = 0; (void) new_line (c); if (vi_mode == COMMANDMODE) altenateEditmode (); return (1); } vi_ins_edit (c) int c; { switch (c) { case CTRL(H): (void) delete_previous_character (c); break; case CTRL(W): (void) delete_previous_word (c); break; case CTRL(U): (void) delete_line (c); break; case CTRL(V): (void) literal_next (c); break; case '\033': (void) altenateEditmode (); (void) backward_character (); break; } return (0); } \End\Of\File\ else echo "will not over write ./fep_vi.c" fi if `test ! -s ./fep_util.c` then echo "writing ./fep_util.c" cat > ./fep_util.c << '\End\Of\File\' /* Copyright (c) 1987, 1988 by Software Research Associates, Inc. */ #ifndef lint static char rcsid[]= "$Header: fep_util.c,v 4.0 88/08/05 20:22:24 utashiro Rel $ (SRA)"; #endif lint #ifndef MKARGDEBUG #include <stdio.h> #include <pwd.h> #include <sys/types.h> #include <sys/dir.h> #include <ctype.h> #include "fep_defs.h" message(messageString) char *messageString; { write (2, messageString, strlen (messageString)); } errorBell() { write (2, "\007", 1); } ctlprint(string) char *string; { register char *cp; for (cp = string; *cp; cp++) { if (isctlchar (*cp)) { putchar ('^'); putchar (unctl (*cp)); } else putchar (*cp); } fputs ("\r\n", stdout); fflush (stdout); } /* * Print string using "^" for control characters */ printS (string) char *string; { char *cp; for (cp = string; *cp; cp++) putChar (*cp); } /* * Check the line is empty or not */ is_empty_line(line) char *line; { register char *cp; for (cp = line; *cp; cp++) { if (!isspace(*cp)) { return(0); } } return(1); } /* * Put character using "^" for control characters */ putChar(c) char c; { if (isctlchar(c)) { (void) putchar('^'); (void) putchar(unctl(c)); } else (void) putchar(c); } char * x_dirname (dir) char *dir; { static char dirname [256]; char *index(); if (*dir != '~') strcpy (dirname, dir); else { struct passwd *pw; if (*(dir+1) == '/' || *(dir+1) == '\0') { pw = getpwuid (getuid ()); } else { char user [64], *sp, *dp; for (sp = dir+1, dp = user; *sp && *sp != '/'; sp++, dp++) *dp = *sp; *dp = '\0'; pw = getpwnam (user); } if (pw) { strcpy (dirname, pw->pw_dir); if (any ('/', dir)) strcat (dirname, index (dir, '/')); } else { strcpy (dirname, dir); } } return (dirname); } DIR * x_opendir (dir) char *dir; { return (opendir (x_dirname (dir))); } /* * Strring compare for qsort */ scmp (a, b) char **a, **b; { return (strcmp (*a, *b)); } /* * Return 1 if "str" is prefixed by "sub" */ prefix (sub, str) register char *sub, *str; { for (;;) { if (*sub == 0) return (1); if (*str == 0) return (0); if (*sub++ != *str++) return (0); } } /* * Return 1 if s includes character c */ any (c, s) register int c; register char *s; { while (*s) if (*s++ == c) return(1); return(0); } #ifndef max /* * Return maximum number of d1 and d2 */ max (d1, d2) int d1, d2; { return (d1 > d2 ? d1 : d2); } #endif max #else MKARGDEBUG #include <stdio.h> #include <ctype.h> #define MAXARGS 64 main() { char s[128]; char *argv[MAXARGS]; while (gets (s)) { register int c; showArgs (s); } } #endif MKARGDEBUG showArgs (comline) char *comline; { char *argv[MAXARGS]; register int c; register char **argp; register int i; c = mkargv (comline, argv, MAXARGS); if (c < 0) { printf ("%s\n", argv[0]); return; } printf ("argc = %d\n", c); for (i = 0, argp = argv; *argp; argp++, i++) { printf ("\"%s\" ", *argp); } printf ("\n"); } mkargv (s, argv, maxarg) char *s; char *argv[]; int maxarg; { register char *cp; register int argc = 0; int insquot = 0, indquot = 0, ignorenext = 0; enum {STRING, SPACE} status = SPACE; static char buf[1024], *bp; for (cp = s, bp = buf; *cp; cp++) { if (argc > maxarg) return (argc); /* * Found white space */ if (isspace (*cp)) { /* * In outside of quotation */ if (!ignorenext && !insquot && !indquot) { /* * If status was in string, go next arg */ if (status == STRING) { status = SPACE; *bp++ = '\0'; continue; } else continue; } } # define SPECIALCHARS "\"\'\\" if (!ignorenext && index (SPECIALCHARS, *cp)) { switch (*cp) { /* * Literal next character */ case '\\': if (indquot || insquot) goto THROUGH; else { ignorenext = 1; continue; } /* * Double quotation */ case '\"': if (insquot) goto THROUGH; if (indquot && *(bp-1) == '\\') { bp--; goto THROUGH; } indquot = !indquot; break; /* * Single quotation */ case '\'': if (indquot) goto THROUGH; if (insquot && *(bp-1) == '\\') { bp--; goto THROUGH; } insquot = !insquot; break; } /* * Only in " or ' case. */ if (status == SPACE) { status = STRING; argc++; argv[argc-1] = bp; *bp = 0; } continue; } THROUGH: /* * Found non-space character */ ignorenext = 0; if (status == SPACE) { status = STRING; argc++; argv[argc-1] = bp; } *bp++ = *cp; } if (indquot || insquot) { argv[0] = indquot ? "Unmatched \"." : "Unmatched \'."; return (-1); } *bp = '\0'; argv[argc] = (char *)0; return (argc); } reverse_strcpy (to, from) register char *to, *from; { register int len; for (len = strlen (from); len >= 0; len--) *(to + len) = *(from + len); } #ifdef KANJI /* * Uuuuuuuum. I hate search kanji in Shift-JIS code from the end of string * This function check if i'th character is first byte of KANJI code * in string starting from s. * It is assumed that first byte of strint s can't be second byte of KANJI * code. */ iskanji_in_string (s, i) char *s; int i; { register char *cp = s, *target = s + i; if (i < 0) return (0); while (cp < target) { if (iskanji (*cp)) cp += 2; else cp++; } if (cp != target) return (0); else return (iskanji (*cp)); } #endif KANJI \End\Of\File\ else echo "will not over write ./fep_util.c" fi if `test ! -s ./fep_alias.c` then echo "writing ./fep_alias.c" cat > ./fep_alias.c << '\End\Of\File\' /* Copyright (c) 1987, 1988 by Software Research Associates, Inc. */ #ifndef lint static char rcsid[]= "$Header: fep_alias.c,v 4.0 88/08/05 20:22:00 utashiro Rel $ (SRA)"; #endif lint #include <stdio.h> #include <ctype.h> #include "fep_defs.h" #include "fep_glob.h" typedef struct _alias { char *al_name; char *al_value; struct _alias *al_next; } ALIAS; ALIAS alias_top = {"top", "top", (ALIAS *)0}; ALIAS *alias_list = &alias_top; CHAR aliased_line[MAXCOMLEN+1]; /* * Functions */ int set_alias (/* char *name, char *value */); char *look_alias (/* char *name */); ALIAS *getap (/* char *name */); extern char *allocAndCopyThere(); extern char *prompt; /* * Check alias list, and if found alias change command by its value */ CHAR * check_alias (comline) char *comline; { char *argv[MAXARGS]; int argc; char *av; while (isspace (*comline)) ++comline; if (*comline == NULL) return ((CHAR *)0); argc = mkargv (comline, argv, MAXARGS); if (av = look_alias (argv[0])) { int len = strlen (argv[0]); strcpy (aliased_line, av); strcat (aliased_line, comline + len); return (aliased_line); } else return ((CHAR *)0); } /* * Set alias */ set_alias (name, value) char *name, *value; { ALIAS *vp; vp = getap (name, 1, 0); if (vp->al_value) free (vp->al_value); vp->al_value = allocAndCopyThere (value); } /* * Unset alias */ unset_alias (name) char *name; { ALIAS *vp, *prev; vp = getap (name, 0, &prev); if (!vp) return; prev->al_next = vp->al_next; free (vp->al_name); free (vp->al_value); free (vp); return; } /* * Look up alias */ char * look_alias (name) char *name; { ALIAS *vp; vp = getap (name, 0, 0); if (vp && vp->al_value) return (vp->al_value); else return ((char *)0); } /* * Show alias list */ show_aliaslist (a) char *a; { register ALIAS *vp; for (vp = alias_list->al_next; vp; vp = vp->al_next) { if (a && strcmp (a, vp->al_name)) continue; printf ("%-16s %s\n", vp->al_name, vp->al_value); } } /* * Get pointer to ALIAS. * If there is no memoly associated to the alias and alloc argument is 1, * allocate the area and initialize name field. */ ALIAS * getap (name, alloc, lastvp) char *name; int alloc; ALIAS **lastvp; { ALIAS *vp, *last = (ALIAS *)0; for (vp = alias_list->al_next, last = alias_list; vp; last = vp, vp = vp->al_next) { int r; r = strcmp (name, vp->al_name); if (r == 0) { if (lastvp) *lastvp = last; return (vp); } else if (r < 0) break; } if (alloc == 0) return (0); vp = (ALIAS *) calloc (sizeof (ALIAS), 1); vp->al_value = (char *)0; vp->al_next = (ALIAS *) 0; vp->al_name = allocAndCopyThere (name); vp->al_next = last->al_next; last->al_next = vp; return (vp); } \End\Of\File\ else echo "will not over write ./fep_alias.c" fi if `test ! -s ./feprc.sample` then echo "writing ./feprc.sample" cat > ./feprc.sample << '\End\Of\File\' # # This is a sample .feprc file. # set alarm-on-eof set savehist=50 echo "Welcome to fep! Editmode is" $editmode echo "I'm a front end processor for" $command if $editmode == emacs fep-bind delete-to-kill-buffer "\^X\^W" endif if $command == sh set ignore-eof set history-file .fephistdir/sh set delimiters=" \"';&<>()|^%" set auto-repaint set clear-repaint if $editmode == vi fep-bind list-file-name "\^D" endif elseif $command == adb set history-file .fephistdir/adb elseif $command == bc unset alarm-on-eof unset alarm-on-eof elseif $command == dbx set history-file .fephistdir/dbx else echo "History will be saved to" $history-file endif \End\Of\File\ else echo "will not over write ./feprc.sample" fi if `test ! -s ./README` then echo "writing ./README" cat > ./README << '\End\Of\File\' Copyright (c) 1987,1988 by Software Research Associates, Inc. FEP is a general purpose front end for any line-oriented command on UNIX. This command was developed on Berkeley UNIX, but will probably run on most UNIX system which have pseudo tty and the select system call. Making FEP Just type 'make'. If your system is running ASCII UNIX or some compatible system, the -DKANJI flag makes fep handle kanji character input. Using FEP See man page fep.1 for detail. The help command (ESC-?) and show-bindings command (^X-^B) are very convenient when running fep. Distribution Distribution without fee is permitted as long as all copyright notices are included. Any comments will be greatly appreciated. Have fun. Kazumasa Utashiro Software Research Associates, Inc. 1-1-1 Hirakawa-cho, Chiyoda-ku, Tokyo 102, Japan UUCP: kddlab!srava.sra.junet!utashiro ARPA: utashiro%sra.junet@uunet.uu.net JUNET: utashiro@sra.junet \End\Of\File\ else echo "will not over write ./README" fi echo "Finished archive 1 of 5" exit -- Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.