v14i059: Jove, an emacs variant, version 4.9, Part03/21
Rich Salz
rsalz at bbn.com
Tue Apr 26 09:34:08 AEST 1988
Submitted-by: Jonathan Payne <jpayne at cs.rochester.edu>
Posting-number: Volume 14, Issue 59
Archive-name: jove4.9/part03
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 3 (of 21)."
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f './Ovmakefile' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'./Ovmakefile'\"
else
echo shar: Extracting \"'./Ovmakefile'\" \(6758 characters\)
sed "s/^X//" >'./Ovmakefile' <<'END_OF_FILE'
X###########################################################################
X# This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne. JOVE #
X# is provided to you without charge, and with no warranty. You may give #
X# away copies of JOVE, including sources, provided that this notice is #
X# included in all the files. #
X###########################################################################
X
X# TMPDIR is where the tmp files get stored, usually /tmp or /tmp/jove. If
X# your system does not remove subdirectories of /tmp on reboot (lots do
X# remove them these days) then it makes sense to make TMPDIR be /tmp/jove.
X# But if you want to recover buffers on system crashes, you should create a
X# directory that doesn't get clearned upon reboot, and use that instead.
X# You would probably want to clean out that directory periodically with
X# /etc/cron. LIBDIR is for online documentation, the PORTSRV process,
X# RECOVER, and the system-wide .joverc file. BINDIR is where to put the
X# executables JOVE and TEACHJOVE. MANDIR is where the manual pages go for
X# JOVE, RECOVER and TEACHJOVE. MANEXT is the extension for the man pages,
X# e.g., jove.1 or jove.l or jove.m.
X
DESTDIR =
TMPDIR = /tmp
LIBDIR = /usr/lib/jove
BINDIR = /bin
MANDIR = /usr/man/man1
MANEXT = 1
SHELL = /bin/csh
X
X# These should all just be right if the above ones are.
JOVE = $(DESTDIR)$(BINDIR)/jove
RECOVER = $(DESTDIR)$(LIBDIR)/recover
TEACHJOVE = $(DESTDIR)$(BINDIR)/teachjove
JOVERC = $(DESTDIR)$(LIBDIR)/.joverc
CMDS.DOC = $(DESTDIR)$(LIBDIR)/cmds.doc
TEACH-JOVE = $(DESTDIR)$(LIBDIR)/teach-jove
PORTSRV = $(DESTDIR)$(LIBDIR)/portsrv
JOVEM = $(DESTDIR)$(MANDIR)/jove.$(MANEXT)
RECOVERM = $(DESTDIR)$(MANDIR)/recover.$(MANEXT)
TEACHJOVEM = $(DESTDIR)$(MANDIR)/teachjove.$(MANEXT)
X
X# Select the right libraries for your system.
X# 2.9BSD: LIBS = -ltermlib -ljobs
X# v7: LIBS = -ltermlib
X# 4.1BSD: LIBS = -ltermlib -ljobs
X# 4.2BSD: LIBS = -ltermlib
X# 4.3BSD: LIBS = -ltermlib
X
OVLIBS = -lovtermcap -lovjobs
LIBS = -ltermcap -ljobs
X
X# If you are not VMUNIX (vax running Berkeley Version 4), you must specify
X# the -i flags (split I/D space) and maybe the -x option (for adb to work).
X# 2.9BSD: LDFLAGS = -x -i
X# v7: LDFLAGS = -x -i
X# 4.1BSD: LDFLAGS =
X# 4.2BSD: LDFLAGS =
X# 4.3BSD: LDFLAGS =
X
LDFLAGS = -x -i
X
CFLAGS = -O -V
X
COFLAGS = -rworking -q
X
BASESEG = funcdefs.o keymaps.o argcount.o ask.o buf.o ctype.o delete.o disp.o fmt.o fp.o \
X insert.o io.o jove.o malloc.o marks.o misc.o move.o re.o \
X screen.o table.o tune.o util.o version.o
OVLAY1 = abbrev.o rec.o paragraph.o macros.o
OVLAY2 = c.o wind.o vars.o
OVLAY3 = extend.o
OVLAY4 = iproc.o re1.o
OVLAY5 = proc.o scandir.o term.o case.o
X
OBJECTS = $(BASESEG) $(OVLAY1) $(OVLAY2) $(OVLAY3) $(OVLAY4) $(OVLAY5)
X
C-FILES = funcdefs.c abbrev.c argcount.c ask.c buf.c c.c case.c ctype.c delete.c disp.c \
X extend.c fmt.c fp.c insert.c io.c iproc.c iproc-pipes.c iproc-ptys.c \
X jove.c macros.c malloc.c marks.c misc.c move.c paragraph.c proc.c \
X re.c re1.c rec.c scandir.c screen.c table.c term.c util.c vars.c version.c \
X wind.c
X
H-FILES = ctype.h io.h jove.h re.h rec.h table.h temp.h termcap.h tune.h
X
BACKUPS = $(C-FILES) $(H-FILES) $(DOCS) teachjove.c recover.c setmaps.c portsrv.c \
X tune.template Makefile Ovmakefile keymaps.txt README tags
X
DOCS = doc/cmds.doc.nr doc/example.rc doc/jove.1 doc/jove.2 doc/jove.3 \
X doc/jove.4 doc/jove.nr doc/recover.nr doc/system.rc doc/teach-jove \
X doc/teachjove.nr doc/README
X
all: xjove recover teachjove portsrv
X
xjove: $(OBJECTS)
X ld $(LDFLAGS) /lib/crt0.o \
X -Z $(OVLAY1) \
X -Z $(OVLAY2) \
X -Z $(OVLAY3) \
X -Z $(OVLAY4) \
X -Z $(OVLAY5) \
X -L $(BASESEG) \
X -o xjove $(OVLIBS) -lovc
X checkobj xjove
X @-size xjove
X @-date
X
portsrv: portsrv.c
X cc -o portsrv -n -O portsrv.c $(LIBS)
X
recover: recover.c tune.o rec.h temp.h
X cc -o recover -n -O recover.c tune.o -ljobs
X
teachjove: teachjove.c
X cc -o teachjove -n -O -DTEACHJOVE=\"$(TEACH-JOVE)\" teachjove.c
X
setmaps: setmaps.c funcdefs.c
X cc -o setmaps setmaps.c
X
keymaps.c: setmaps keymaps.txt
X setmaps < keymaps.txt > keymaps.c
X
tune.c: Makefile tune.template
X @echo "/* Changes should be made in Makefile, not to this file! */" > tune.c
X @echo "" >> tune.c
X @sed -e 's;TMPDIR;$(TMPDIR);' \
X -e 's;LIBDIR;$(LIBDIR);' \
X -e 's;BINDIR;$(BINDIR);' \
X -e 's;SHELL;$(SHELL);' tune.template >> tune.c
X
install: $(LIBDIR) $(TEACH-JOVE) $(CMDS.DOC) $(JOVERC) $(PORTSRV) $(RECOVER) \
X $(JOVE) $(TEACHJOVE) $(JOVEM) $(RECOVERM) $(TEACHJOVEM)
X
X$(DESTDIR)$(LIBDIR):
X -mkdir (DESTDIR)$(LIBDIR)
X
X$(TEACH-JOVE): doc/teach-jove
X install -c -m 644 doc/teach-jove $(TEACH-JOVE)
X
X$(CMDS.DOC): doc/cmds.doc
X install -c -m 644 doc/cmds.doc $(CMDS.DOC)
X
X$(JOVERC): doc/system.rc
X install -c -m 644 doc/system.rc $(JOVERC)
X
X$(PORTSRV): portsrv
X install -c -m 755 portsrv $(PORTSRV)
X
X$(RECOVER): recover
X install -c -m 755 recover $(RECOVER)
X
X$(JOVE): xjove
X install -c -m 755 xjove $(JOVE)
X
X$(TEACHJOVE): teachjove
X install -c -m 755 teachjove $(TEACHJOVE)
X
X$(JOVEM): doc/jove.nr
X @sed -e 's;TMPDIR;$(TMPDIR);' \
X -e 's;LIBDIR;$(LIBDIR);' \
X -e 's;SHELL;$(SHELL);' doc/jove.nr > /tmp/jove.nr
X install -m 644 /tmp/jove.nr $(JOVEM)
X
X$(RECOVERM): doc/recover.nr
X @sed -e 's;TMPDIR;$(TMPDIR);' \
X -e 's;LIBDIR;$(LIBDIR);' \
X -e 's;SHELL;$(SHELL);' doc/recover.nr > /tmp/recover.nr
X install -m 644 /tmp/recover.nr $(RECOVERM)
X
X$(TEACHJOVEM): doc/teachjove.nr
X @sed -e 's;TMPDIR;$(TMPDIR);' \
X -e 's;LIBDIR;$(LIBDIR);' \
X -e 's;SHELL;$(SHELL);' doc/teachjove.nr > /tmp/teachjove.nr
X install -m 644 /tmp/teachjove.nr $(TEACHJOVEM)
X
echo:
X @echo $(C-FILES) $(H-FILES)
X
lint:
X lint -x $(C-FILES)
X echo Done
X
tags:
X ctags -w $(C-FILES) $(H-FILES)
X
X
jove.shar:
X shar $(BACKUPS) doc/* > jove.shar
X
backup:
X tar cf backup $(BACKUPS)
X
tape-backup:
X tar cbf 20 /dev/rmt0 $(BACKUPS)
X
clean:
X rm -f a.out core $(OBJECTS) keymaps.c xjove \
X portsrv recover setmaps teachjove
X
X# abbrev.o: jove.h tune.h
X# ask.o: jove.h tune.h
X# buf.o: jove.h tune.h
X# c.o: jove.h tune.h
X# delete.o: jove.h tune.h
X# disp.o: jove.h tune.h termcap.h
X# extend.o: jove.h tune.h
X# fmt.o: jove.h tune.h termcap.h
X# funcdefs.o: jove.h tune.h
X# insert.o: jove.h tune.h
X# io.o: jove.h tune.h termcap.h temp.h
X# iproc.o: jove.h tune.h
X# jove.o: jove.h tune.h termcap.h
X# macros.o: jove.h tune.h
X# marks.o: jove.h tune.h
X# misc.o: jove.h tune.h
X# move.o: jove.h tune.h
X# portsrv.o: jove.h tune.h
X# proc.o: jove.h tune.h
X# re.o: jove.h tune.h
X# rec.o: jove.h tune.h temp.h rec.h
X# recover.o: jove.h tune.h temp.h rec.h
X# screen.o: jove.h tune.h temp.h termcap.h
X# setmaps.o: jove.h tune.h
X# term.o: jove.h tune.h
X# tune.o: tune.h
X# util.o: jove.h tune.h
X# wind.o: jove.h tune.h termcap.h
END_OF_FILE
if test 6758 -ne `wc -c <'./Ovmakefile'`; then
echo shar: \"'./Ovmakefile'\" unpacked with wrong size!
fi
# end of './Ovmakefile'
fi
if test -f './abbrev.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'./abbrev.c'\"
else
echo shar: Extracting \"'./abbrev.c'\" \(6522 characters\)
sed "s/^X//" >'./abbrev.c' <<'END_OF_FILE'
X/***************************************************************************
X * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne. JOVE *
X * is provided to you without charge, and with no warranty. You may give *
X * away copies of JOVE, including sources, provided that this notice is *
X * included in all the files. *
X ***************************************************************************/
X
X#include "jove.h"
X
X#ifdef ABBREV
X
X#include "io.h"
X#include "ctype.h"
X
X#ifdef MSDOS
X#include <io.h>
X#endif
X#define HASHSIZE 20
X
struct abbrev {
X unsigned int a_hash;
X char *a_abbrev,
X *a_phrase;
X struct abbrev *a_next;
X data_obj *a_cmdhook;
X};
X
X#ifdef MAC
X# undef private
X# define private
X#endif
X
X#ifdef LINT_ARGS
private void
X define(struct abbrev **, char *, char *),
X def_abbrev(struct abbrev **),
X rest_abbrevs(char *),
X save_abbrevs(char *);
X
private unsigned int hash(char *);
private struct abbrev * lookup(struct abbrev **, char *);
X#else
private void
X define(),
X def_abbrev(),
X rest_abbrevs(),
X save_abbrevs();
X
private unsigned int hash();
private struct abbrev * lookup();
X#endif /* LINT_ARGS */
X
X#ifdef MAC
X# undef private
X# define private static
X#endif
X
X#define GLOBAL NMAJORS
private struct abbrev *A_tables[NMAJORS + 1][HASHSIZE] = {0};
X
int AutoCaseAbbrev = 1;
X
private unsigned int
hash(a)
register char *a;
X{
X register unsigned int hashval = 0;
X register int c;
X
X while (c = *a++)
X hashval = (hashval << 2) + c;
X
X return hashval;
X}
X
private void
def_abbrev(table)
struct abbrev *table[HASHSIZE];
X{
X char abbrev[100],
X phrase[100];
X
X strcpy(abbrev, ask((char *) 0, "abbrev: "));
X strcpy(phrase, ask((char *) 0, "abbrev: %s phrase: ", abbrev));
X define(table, abbrev, phrase);
X}
X
private struct abbrev *
lookup(table, abbrev)
register struct abbrev *table[HASHSIZE];
register char *abbrev;
X{
X register struct abbrev *ap;
X unsigned int h;
X
X h = hash(abbrev);
X for (ap = table[h % HASHSIZE]; ap; ap = ap->a_next)
X if (ap->a_hash == h && strcmp(ap->a_abbrev, abbrev) == 0)
X break;
X return ap;
X}
X
private void
define(table, abbrev, phrase)
register struct abbrev *table[HASHSIZE];
char *abbrev,
X *phrase;
X{
X register struct abbrev *ap;
X
X ap = lookup(table, abbrev);
X if (ap == 0) {
X register unsigned int h = hash(abbrev);
X
X ap = (struct abbrev *) emalloc(sizeof *ap);
X ap->a_hash = h;
X ap->a_abbrev = copystr(abbrev);
X h %= HASHSIZE;
X ap->a_next = table[h];
X ap->a_cmdhook = 0;
X table[h] = ap;
X } else
X free(ap->a_phrase);
X ap->a_phrase = copystr(phrase);
X}
X
void
AbbrevExpand()
X{
X Bufpos point;
X char wordbuf[100];
X register char *wp = wordbuf,
X *cp;
X#if !(defined(IBMPC) || defined(MAC))
X register int c;
X#else
X int c;
X#endif
X int UC_count = 0;
X struct abbrev *ap;
X
X DOTsave(&point);
X WITH_TABLE(curbuf->b_major)
X b_word(1);
X while (curchar < point.p_char && ismword(c = linebuf[curchar])) {
X if (AutoCaseAbbrev) {
X if (isupper(c)) {
X UC_count += 1;
X#if (defined(IBMPC) || defined(MAC))
X lower(&c);
X#else
X c = tolower(c);
X#endif
X }
X }
X *wp++ = c;
X curchar += 1;
X }
X *wp = '\0';
X END_TABLE();
X
X if ((ap = lookup(A_tables[curbuf->b_major], wordbuf)) == 0 &&
X (ap = lookup(A_tables[GLOBAL], wordbuf)) == 0) {
X SetDot(&point);
X return;
X }
X del_char(BACKWARD, (wp - wordbuf));
X
X for (cp = ap->a_phrase; c = *cp; ) {
X if (AutoCaseAbbrev) {
X insert_c(islower(c) && UC_count &&
X (cp == ap->a_phrase || (UC_count > 1 && (cp[-1] == ' '))) ?
X toupper(c) : c, 1);
X } else
X insert_c(c, 1);
X cp += 1;
X }
X if (ap->a_cmdhook != 0)
X ExecCmd(ap->a_cmdhook);
X}
X
private char *mode_names[NMAJORS + 1] = {
X "Fundamental Mode",
X "Text Mode",
X "C Mode",
X#ifdef LISP
X "Lisp Mode",
X#endif
X "Global"
X};
X
private void
save_abbrevs(file)
char *file;
X{
X File *fp;
X struct abbrev *ap,
X **tp;
X char buf[LBSIZE];
X int i,
X count = 0;
X
X fp = open_file(file, buf, F_WRITE, COMPLAIN, QUIET);
X for (i = 0; i <= GLOBAL; i++) {
X fprintf(fp, "------%s abbrevs------\n", mode_names[i]);
X for (tp = A_tables[i]; tp < &A_tables[i][HASHSIZE]; tp++)
X for (ap = *tp; ap; ap = ap->a_next) {
X fprintf(fp, "%s:%s\n",
X ap->a_abbrev,
X ap->a_phrase);
X count += 1;
X }
X }
X f_close(fp);
X add_mess(" %d written.", count);
X}
X
private void
rest_abbrevs(file)
char *file;
X{
X int eof = 0,
X mode = -1, /* Will be ++'d immediately */
X lnum = 0;
X char *phrase_p;
X File *fp;
X char buf[LBSIZE];
X
X fp = open_file(file, buf, F_READ, COMPLAIN, QUIET);
X while (mode <= GLOBAL) {
X eof = f_gets(fp, genbuf, LBSIZE);
X if (eof || genbuf[0] == '\0')
X break;
X lnum += 1;
X if (strncmp(genbuf, "------", 6) == 0) {
X mode += 1;
X continue;
X }
X if (mode == -1)
fmterr: complain("Abbrev. format error, line %d.", file, lnum);
X phrase_p = index(genbuf, ':');
X if (phrase_p == 0)
X goto fmterr;
X *phrase_p++ = '\0'; /* Null terminate the abbrev. */
X define(A_tables[mode], genbuf, phrase_p);
X }
X f_close(fp);
X message(NullStr);
X}
X
void
DefGAbbrev()
X{
X def_abbrev(A_tables[GLOBAL]);
X}
X
void
DefMAbbrev()
X{
X def_abbrev(A_tables[curbuf->b_major]);
X}
X
void
SaveAbbrevs()
X{
X char filebuf[FILESIZE];
X
X save_abbrevs(ask_file((char *) 0, (char *) 0, filebuf));
X}
X
void
RestAbbrevs()
X{
X char filebuf[FILESIZE];
X
X rest_abbrevs(ask_file((char *) 0, (char *) 0, filebuf));
X}
X
void
EditAbbrevs()
X{
X char *tname = "jove_wam.$$$",
X *EditName = "Abbreviation Edit";
X Buffer *obuf = curbuf,
X *ebuf;
X
X if (ebuf = buf_exists(EditName)) {
X if (ebuf->b_type != B_SCRATCH)
X confirm("Over-write buffer %b?", ebuf);
X }
X SetBuf(ebuf = do_select(curwind, EditName));
X ebuf->b_type = B_SCRATCH;
X initlist(ebuf);
X /* Empty buffer. Save the definitions to a tmp file
X and read them into this buffer so we can edit them. */
X save_abbrevs(tname);
X read_file(tname, NO);
X message("[Edit definitions and then type C-X C-C]");
X Recur(); /* We edit them ... now */
X /* RESetBuf in case we deleted the buffer while we were editing. */
X SetBuf(ebuf = do_select(curwind, EditName));
X if (IsModified(ebuf)) {
X SetBuf(ebuf);
X file_write(tname, 0);
X rest_abbrevs(tname);
X unmodify();
X }
X (void) unlink(tname);
X SetBuf(do_select(curwind, obuf->b_name));
X}
X
void
BindMtoW()
X{
X struct abbrev *ap;
X char *word;
X data_obj *hook;
X
X word = ask((char *) 0, "Word: ");
X
X if ((ap = lookup(A_tables[curbuf->b_major], word)) == 0 &&
X (ap = lookup(A_tables[GLOBAL], word)) == 0)
X complain("%s: unknown abbrev.", word);
X
X hook = findmac("Macro: ");
X if (hook == 0)
X complain("[Undefined macro]");
X ap->a_cmdhook = hook;
X}
X
X#endif /* ABBREV */
END_OF_FILE
if test 6522 -ne `wc -c <'./abbrev.c'`; then
echo shar: \"'./abbrev.c'\" unpacked with wrong size!
fi
# end of './abbrev.c'
fi
if test -f './delete.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'./delete.c'\"
else
echo shar: Extracting \"'./delete.c'\" \(6544 characters\)
sed "s/^X//" >'./delete.c' <<'END_OF_FILE'
X/***************************************************************************
X * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne. JOVE *
X * is provided to you without charge, and with no warranty. You may give *
X * away copies of JOVE, including sources, provided that this notice is *
X * included in all the files. *
X ***************************************************************************/
X
X/* Routines to perform all kinds of deletion. */
X
X#include "jove.h"
X
X/* Assumes that either line1 or line2 is actual the current line, so it can
X put its result into linebuf. */
X
void
patchup(line1, char1, line2, char2)
Line *line1,
X *line2;
register int char1,
X char2;
X{
X if (line1 != line2)
X ChkWindows(line1, line2);
X DotTo(line1, char1);
X modify();
X linecopy(linebuf, curchar, lcontents(line2) + char2);
X
X /* The following is a redisplay optimization. */
X if (line1 != line2 && (char1 == 0 && char2 == 0))
X line1->l_dline = line2->l_dline;
X
X DFixMarks(line1, char1, line2, char2);
X makedirty(curline);
X}
X
X/* Deletes the region by unlinking the lines in the middle,
X and patching things up. The unlinked lines are still in
X order. */
X
Line *
reg_delete(line1, char1, line2, char2)
Line *line1,
X *line2;
X{
X register Line *retline;
X
X if ((line1 == line2 && char1 == char2) || line2 == 0)
X complain((char *) 0);
X (void) fixorder(&line1, &char1, &line2, &char2);
X
X retline = nbufline(); /* New buffer line */
X
X (void) ltobuf(line1, genbuf);
X if (line1 == line2)
X genbuf[char2] = '\0';
X
X retline->l_prev = 0;
X retline->l_dline = putline(&genbuf[char1]);
X patchup(line1, char1, line2, char2);
X
X if (line1 == line2)
X retline->l_next = 0;
X else {
X retline->l_next = line1->l_next;
X (void) ltobuf(line2, genbuf);
X genbuf[char2] = '\0';
X line2->l_dline = putline(genbuf);
X /* Shorten this line */
X }
X
X if (line1 != line2) {
X line1->l_next = line2->l_next;
X if (line1->l_next)
X line1->l_next->l_prev = line1;
X else
X curbuf->b_last = line1;
X line2->l_next = 0;
X }
X
X return retline;
X}
X
void
lremove(line1, line2)
register Line *line1,
X *line2;
X{
X Line *next = line1->l_next;
X
X if (line1 == line2)
X return;
X line1->l_next = line2->l_next;
X if (line1->l_next)
X line1->l_next->l_prev = line1;
X else
X curbuf->b_last = line1;
X lfreereg(next, line2); /* Put region at end of free line list. */
X}
X
X/* Delete character forward */
X
void
DelNChar()
X{
X del_char(FORWARD, arg_value());
X}
X
X/* Delete character backward */
X
void
DelPChar()
X{
X if (MinorMode(OverWrite)) {
X int count = min(arg_value(), curchar);
X
X b_char(count);
X
X /* overwrite with spaces */
X set_arg_value(count);
X LastKeyStruck = ' ';
X SelfInsert();
X
X b_char(count);
X } else
X del_char(BACKWARD, arg_value());
X}
X
X/* Delete some characters. If deleting forward then call for_char
X to the final position otherwise call back_char. Then delete the
X region between the two with patchup(). */
X
void
del_char(dir, num)
X{
X Bufpos before,
X after;
X int killp = (abs(num) > 1);
X
X DOTsave(&before);
X if (dir == FORWARD) f_char(num);
X else b_char(num);
X if (before.p_line == curline && before.p_char == curchar)
X complain((char *) 0);
X if (killp)
X reg_kill(before.p_line, before.p_char, 1);
X else {
X DOTsave(&after);
X (void) fixorder(&before.p_line, &before.p_char, &after.p_line, &after.p_char);
X patchup(before.p_line, before.p_char, after.p_line, after.p_char);
X lremove(before.p_line, after.p_line);
X }
X}
X
X/* This kills a region between point, and line1/char1 and puts it on
X the kill-ring. If the last command was one of the kill commands,
X the region is appended (prepended if backwards) to the last entry. */
X
int killptr = 0;
Line *killbuf[NUMKILLS];
X
void
reg_kill(line2, char2, dot_moved)
Line *line2;
X{
X Line *nl,
X *line1 = curline;
X int char1 = curchar;
X int backwards;
X
X backwards = !fixorder(&line1, &char1, &line2, &char2);
X /* This is a kludge! But it possible for commands that don't
X know which direction they are deleting in (e.g., delete
X previous word could have been called with a negative argument
X in which case, it wouldn't know that it really deleted
X forward. */
X
X if (!dot_moved)
X backwards = !backwards;
X
X DotTo(line1, char1);
X
X nl = reg_delete(line1, char1, line2, char2);
X
X if (last_cmd != KILLCMD) {
X killptr = ((killptr + 1) % NUMKILLS);
X lfreelist(killbuf[killptr]);
X killbuf[killptr] = nl;
X } else {
X Line *lastln = lastline(nl);
X
X if (backwards)
X (void) DoYank(nl, 0, lastln, length(lastln), killbuf[killptr], 0, (Buffer *) 0);
X else {
X Line *olastln = lastline(killbuf[killptr]);
X
X (void) DoYank(nl, 0, lastln, length(lastln), olastln, length(olastln), (Buffer *) 0);
X }
X }
X this_cmd = KILLCMD;
X}
X
void
DelReg()
X{
X register Mark *mp = CurMark();
X
X reg_kill(mp->m_line, mp->m_char, 0);
X}
X
X/* Save a region. A pretend kill. */
X
void
CopyRegion()
X{
X register Line *nl;
X register Mark *mp;
X register int status;
X
X mp = CurMark();
X if (mp->m_line == curline && mp->m_char == curchar)
X complain((char *) 0);
X
X killptr = ((killptr + 1) % NUMKILLS);
X if (killbuf[killptr])
X lfreelist(killbuf[killptr]);
X nl = killbuf[killptr] = nbufline();
X SavLine(nl, NullStr);
X nl->l_next = nl->l_prev = 0;
X
X status = inorder(mp->m_line, mp->m_char, curline, curchar);
X if (status == -1)
X return;
X
X if (status)
X (void) DoYank(mp->m_line, mp->m_char, curline, curchar,
X nl, 0, (Buffer *) 0);
X else
X (void) DoYank(curline, curchar, mp->m_line, mp->m_char,
X nl, 0, (Buffer *) 0);
X}
X
void
DelWtSpace()
X{
X register char *ep = &linebuf[curchar],
X *sp = &linebuf[curchar];
X
X while (*ep == ' ' || *ep == '\t')
X ep += 1;
X while (sp > linebuf && *(sp - 1) == ' ' || *(sp - 1) == '\t')
X sp -= 1;
X if (sp != ep) {
X curchar = sp - linebuf;
X DFixMarks(curline, curchar, curline, curchar + (ep - sp));
X strcpy(sp, ep);
X makedirty(curline);
X modify();
X }
X}
X
void
DelBlnkLines()
X{
X register Mark *dot;
X int all;
X
X if (!blnkp(&linebuf[curchar]))
X return;
X dot = MakeMark(curline, curchar, M_FLOATER);
X all = !blnkp(linebuf);
X while (blnkp(linebuf) && curline->l_prev)
X SetLine(curline->l_prev);
X all |= (firstp(curline));
X Eol();
X DelWtSpace();
X line_move(FORWARD, 1, NO);
X while (blnkp(linebuf) && !eobp()) {
X DelWtSpace();
X del_char(FORWARD, 1);
X }
X if (!all && !eobp())
X open_lines(1);
X ToMark(dot);
X DelMark(dot);
X}
X
void
DelNWord()
X{
X dword(1);
X}
X
void
DelPWord()
X{
X dword(0);
X}
X
void
dword(forward)
X{
X Bufpos savedot;
X
X DOTsave(&savedot);
X if(forward) ForWord();
X else BackWord();
X reg_kill(savedot.p_line, savedot.p_char, 1);
X}
END_OF_FILE
if test 6544 -ne `wc -c <'./delete.c'`; then
echo shar: \"'./delete.c'\" unpacked with wrong size!
fi
# end of './delete.c'
fi
if test -f './fp.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'./fp.c'\"
else
echo shar: Extracting \"'./fp.c'\" \(7807 characters\)
sed "s/^X//" >'./fp.c' <<'END_OF_FILE'
X/***************************************************************************
X * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne. JOVE *
X * is provided to you without charge, and with no warranty. You may give *
X * away copies of JOVE, including sources, provided that this notice is *
X * included in all the files. *
X ***************************************************************************/
X
X#include "jove.h"
X#include "io.h"
X#include "ctype.h"
X#include "termcap.h"
X
X#ifdef MAC
X# include "mac.h"
X#else
X# include <sys/stat.h>
X# ifndef MSDOS
X# include <sys/file.h>
X# else /* MSDOS */
X# include <fcntl.h>
X# include <io.h>
X# endif /* MSDOS */
X#endif /* MAC */
X
X#include <errno.h>
X
X#ifdef MAC
X# undef private
X# define private
X#endif
X
X#ifdef LINT_ARGS
private File * f_alloc(char *, int, int, char *, int);
X#ifdef RAINBOW
private int rbwrite(int, char *, int);
X#endif
X#else
private File * f_alloc();
X#ifdef RAINBOW
private int rbwrite();
X#endif
X#endif /* LINT_ARGS */
X
X#ifdef MAC
X# undef private
X# define private static
X#endif
X
X#ifndef L_SET
X# define L_SET 0
X#endif
X
X#define MAXFILES 20 /* good enough for my purposes */
X
private File _openfiles[MAXFILES] = {0};
X
private File *
f_alloc(name, flags, fd, buffer, buf_size)
char *name,
X *buffer;
X{
X register File *fp;
X register int i;
X
X for (fp = _openfiles, i = 0; i < MAXFILES; i++, fp++)
X if (fp->f_flags == 0)
X break;
X if (i == MAXFILES)
X complain("[Too many open files!]");
X fp->f_bufsize = buf_size;
X fp->f_cnt = 0;
X fp->f_fd = fd;
X fp->f_flags = flags;
X if (buffer == 0) {
X buffer = emalloc(buf_size);
X fp->f_flags |= F_MYBUF;
X }
X fp->f_base = fp->f_ptr = buffer;
X fp->f_name = copystr(name);
X
X return fp;
X}
X
void
gc_openfiles()
X{
X register File *fp;
X
X for (fp = _openfiles; fp < &_openfiles[MAXFILES]; fp++)
X if (fp->f_flags != 0 && (fp->f_flags & F_LOCKED) == 0)
X f_close(fp);
X}
X
File *
fd_open(name, flags, fd, buffer, bsize)
char *name,
X *buffer;
X{
X return f_alloc(name, flags, fd, buffer, bsize);
X}
X
File *
f_open(name, flags, buffer, buf_size)
char *name,
X *buffer;
X{
X register int fd;
X int mode = F_MODE(flags);
X
X if (mode == F_READ)
X fd = open(name, 0);
X if (mode == F_APPEND) {
X fd = open(name, 1);
X if (fd == -1)
X mode = F_WRITE;
X else
X (void) lseek(fd, 0L, 2);
X }
X if (mode == F_WRITE)
X fd = creat(name, CreatMode);
X if (fd == -1)
X return NIL;
X#ifdef MSDOS
X else
X setmode(fd, 0x8000);
X#endif /* MSDOS */
X return f_alloc(name, flags, fd, buffer, buf_size);
X}
X
void
f_close(fp)
File *fp;
X{
X flush(fp);
X#ifdef BSD4_2
X if (fp->f_flags & (F_WRITE|F_APPEND))
X (void) fsync(fp->f_fd);
X#endif
X (void) close(fp->f_fd);
X if (fp->f_flags & F_MYBUF)
X free(fp->f_base);
X free(fp->f_name);
X fp->f_flags = 0; /* indicates that we're available */
X}
X
int
filbuf(fp)
File *fp;
X{
X if (fp->f_flags & (F_EOF|F_ERR))
X return EOF;
X fp->f_ptr = fp->f_base;
X#ifndef MSDOS
X do
X#endif /* MSDOS */
X fp->f_cnt = read(fp->f_fd, fp->f_base, fp->f_bufsize);
X#ifndef MSDOS
X while (fp->f_cnt == -1 && errno == EINTR);
X#endif /* MSDOS */
X if (fp->f_cnt == -1) {
X printf("[Read error %d]", errno);
X fp->f_flags |= F_ERR;
X }
X if (fp->f_cnt == 0) {
X fp->f_flags |= F_EOF;
X return EOF;
X }
X io_chars += fp->f_cnt;
X return getc(fp);
X}
X
void
putstr(s)
register char *s;
X{
X#ifndef IBMPC
X register int c;
X
X while (c = *s++)
X putchar(c);
X#else /* IBMPC */
X write_emif(s);
X#endif /* IBMPC */
X}
X
void
fputnchar(s, n, fp)
register char *s;
register int n;
register File *fp;
X{
X while (--n >= 0)
X putc(*s++, fp);
X}
X
void
flusho()
X{
X#ifndef IBMPC
X _flush(EOF, stdout);
X#endif /* IBMPC */
X}
X
void
flush(fp)
File *fp;
X{
X _flush(EOF, fp);
X}
X
void
f_seek(fp, offset)
register File *fp;
off_t offset;
X{
X if (fp->f_flags & F_WRITE)
X flush(fp);
X fp->f_cnt = 0; /* next read will filbuf(), next write
X will flush() with no bad effects */
X lseek(fp->f_fd, (long) offset, L_SET);
X}
X
int /* is void - but for lints sake */
X_flush(c, fp)
register File *fp;
X{
X register int n;
X
X if (fp->f_flags & (F_READ | F_STRING | F_ERR))
X return EOF;
X if (((n = (fp->f_ptr - fp->f_base)) > 0) &&
X#ifndef RAINBOW
X (write(fp->f_fd, fp->f_base, n) != n) &&
X#else
X (rbwrite(fp->f_fd, fp->f_base, n) != n) &&
X#endif
X (fp != stdout)) {
X fp->f_flags |= F_ERR;
X error("[I/O error(%d); file = %s, fd = %d]",
X errno, fp->f_name, fp->f_fd);
X }
X
X fp->f_cnt = fp->f_bufsize;
X fp->f_ptr = fp->f_base;
X if (c != EOF)
X return putc(c, fp);
X}
X
int
f_gets(fp, buf, max)
register File *fp;
char *buf;
X{
X register char *cp = buf;
X register int c;
X char *endp = buf + max - 1;
X
X if (fp->f_flags & F_EOF)
X return EOF;
X while (((c = getc(fp)) != EOF) && (c != '\n')) {
X if (c == '\0') /* possibly different from NULL */
X break; /* sorry we don't read nulls */
X#ifdef MSDOS
X if (c == '\r') {
X if ((c = getc(fp)) == '\n')
X break;
X else
X *cp++ = '\r';
X }
X#endif /* MSDOS */
X if (cp >= endp) {
X add_mess(" [Line too long]");
X rbell();
X return EOF;
X }
X *cp++ = c;
X }
X *cp = '\0';
X if (c == EOF) {
X if (cp != buf)
X add_mess(" [Incomplete last line]");
X fp->f_flags |= F_EOF;
X return EOF;
X }
X io_lines += 1;
X return 0; /* this means okay */
X}
X
X/* skip to beginning of next line, i.e., next read returns first
X character of new line */
X
void
f_toNL(fp)
register File *fp;
X{
X register int c;
X
X if (fp->f_flags & F_EOF)
X return;
X while (((c = getc(fp)) != EOF) && (c != '\n'))
X ;
X if (c == EOF)
X fp->f_flags |= F_EOF;
X}
X
void
f_readn(fp, addr, n)
register File *fp;
register char *addr;
register int n;
X{
X while (--n >= 0)
X *addr++ = getc(fp);
X}
X
int
f_getint(fp)
File *fp;
X{
X int n = 0,
X c;
X
X while (isdigit(c = getc(fp)))
X n = (n * 10) + c;
X return n;
X}
X
X/* Deals with output to the terminal, setting up the amount of characters
X to be buffered depending on the output baud rate. Why it's in a
X separate file I don't know ... */
X
private char one_buf;
X
int BufSize = 1;
X
private File _stdout = {1, 1, 1, F_WRITE, &one_buf, &one_buf};
File *stdout = &_stdout;
X
X/* put a string with padding */
X
X#ifndef IBMPC
void
tputc(c)
X{
X putchar(c);
X}
X
X#undef putchar /* for files which forget to include io.h,
X here's a real putchar procedure. */
void
putchar(c)
X{
X putc(c, stdout);
X}
X
X#endif /* IBMPC */
X#ifndef MAC
void
putpad(str, lines)
char *str;
X{
X#ifndef IBMPC
X if (str)
X tputs(str, lines, tputc);
X#else /* IBMPC */
X write_emif(str);
X#endif /* IBMPC */
X}
X#endif
X
X/* Determine the number of characters to buffer at each baud rate. The
X lower the number, the quicker the response when new input arrives. Of
X course the lower the number, the more prone the program is to stop in
X output. Decide what matters most to you. This sets BufSize to the right
X number or chars, and initiaizes `stdout'. */
X
void
settout(ttbuf)
char *ttbuf;
X{
X#ifndef MAC
X#ifndef MSDOS
X static int speeds[] = {
X 1, /* 0 */
X 1, /* 50 */
X 1, /* 75 */
X 1, /* 110 */
X 1, /* 134 */
X 1, /* 150 */
X 1, /* 200 */
X 2, /* 300 */
X 4, /* 600 */
X 8, /* 1200 */
X 16, /* 1800 */
X 32, /* 2400 */
X 128, /* 4800 */
X 256, /* 9600 */
X 512, /* EXTA */
X 1024 /* EXT */
X };
X flusho(); /* flush the one character buffer */
X BufSize = min(MAXTTYBUF, speeds[ospeed] * max(LI / 24, 1));
X stdout = fd_open("/dev/tty", F_WRITE|F_LOCKED, 1, ttbuf, BufSize);
X#else /* MSDOS */
X#ifndef IBMPC
X flusho(); /* flush the one character buffer */
X BufSize = BUFSIZ;
X stdout = fd_open("con", F_WRITE|F_LOCKED, 1, ttbuf, BufSize);
X#endif /* IBMPC */
X#endif /* MSDOS */
X#endif /* MAC */
X}
X
X#ifdef RAINBOW
X
X/*
X * use the Rainbow's video output function
X */
X
X#include <dos.h>
X
private int
rbwrite(fd, buf, cnt)
char *buf;
X{
X union REGS vr;
X
X if (fd != 1) {
X write(fd, buf, cnt);
X } else {
X while (cnt-- > 0) {
X vr.x.ax = *buf++;
X vr.x.di = 0;
X int86(0x18, &vr, &vr);
X }
X }
X}
X#endif /* RAINBOW */
END_OF_FILE
if test 7807 -ne `wc -c <'./fp.c'`; then
echo shar: \"'./fp.c'\" unpacked with wrong size!
fi
# end of './fp.c'
fi
if test -f './iproc-pipes.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'./iproc-pipes.c'\"
else
echo shar: Extracting \"'./iproc-pipes.c'\" \(5928 characters\)
sed "s/^X//" >'./iproc-pipes.c' <<'END_OF_FILE'
X/***************************************************************************
X * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne. JOVE *
X * is provided to you without charge, and with no warranty. You may give *
X * away copies of JOVE, including sources, provided that this notice is *
X * included in all the files. *
X ***************************************************************************/
X
X#ifdef BSD4_2
X# include <sys/wait.h>
X#else
X# include <wait.h>
X#endif
X#include <signal.h>
X#include <sgtty.h>
X
X#define DEAD 1 /* Dead but haven't informed user yet */
X#define STOPPED 2 /* Job stopped */
X#define RUNNING 3 /* Just running */
X#define NEW 4 /* This process is brand new */
X
X/* If process is dead, flags says how. */
X#define EXITED 1
X#define KILLED 2
X
X#define isdead(p) (p == 0 || proc_state(p) == DEAD || p->p_toproc == -1)
X#define makedead(p) (proc_state(p) = DEAD)
X
X#define proc_buf(p) (p->p_buffer->b_name)
X#define proc_cmd(p) (p->p_name)
X#define proc_state(p) (p->p_state)
X
private Process *procs = 0;
X
int ProcInput,
X ProcOutput,
X NumProcs = 0;
X
char *
pstate(p)
Process *p;
X{
X switch (proc_state(p)) {
X case NEW:
X return "Pre-birth";
X
X case STOPPED:
X return "Stopped";
X
X case RUNNING:
X return "Running";
X
X case DEAD:
X if (p->p_howdied == EXITED) {
X if (p->p_reason == 0)
X return "Done";
X return sprint("Exit %d", p->p_reason);
X }
X return sprint("Killed %d", p->p_reason);
X
X default:
X return "Unknown state";
X }
X}
X
static Process *
proc_pid(pid)
X{
X register Process *p;
X
X for (p = procs; p != 0; p = p->p_next)
X if (p->p_portpid == pid)
X break;
X
X return p;
X}
X
procs_read()
X{
X struct header {
X int pid;
X int nbytes;
X } header;
X int n;
X long nbytes;
X static int here = NO;
X
X if (here)
X return;
X sighold(SIGCHLD); /* block any other children */
X here = YES;
X for (;;) {
X (void) ioctl(ProcInput, FIONREAD, (struct sgttyb *) &nbytes);
X if (nbytes < sizeof header)
X break;
X n = read(ProcInput, (char *) &header, sizeof header);
X if (n != sizeof header)
X finish(1);
X read_proc(header.pid, header.nbytes);
X }
X here = NO;
X sigrelse(SIGCHLD);
X}
X
read_proc(pid, nbytes)
int pid;
register int nbytes;
X{
X register Process *p;
X int n;
X char ibuf[512];
X
X if ((p = proc_pid(pid)) == 0) {
X printf("\riproc: unknown pid (%d)", pid);
X return;
X }
X if (proc_state(p) == NEW) {
X int rpid;
X /* pid of real child, not of portsrv */
X
X doread(ProcInput, (char *) &rpid, nbytes);
X nbytes -= sizeof rpid;
X p->p_pid = rpid;
X p->p_state = RUNNING;
X }
X
X if (nbytes == EOF) { /* okay to clean up this process */
X proc_close(p);
X makedead(p);
X return;
X }
X
X while (nbytes > 0) {
X n = min((sizeof ibuf) - 1, nbytes);
X doread(ProcInput, ibuf, n);
X ibuf[n] = 0; /* Null terminate for convenience */
X nbytes -= n;
X proc_rec(p, ibuf);
X }
X}
X
ProcKill()
X{
X proc_kill(curbuf->b_process, SIGKILL);
X}
X
ProcInt()
X{
X proc_kill(curbuf->b_process, SIGINT);
X}
X
ProcQuit()
X{
X proc_kill(curbuf->b_process, SIGQUIT);
X}
X
private
proc_close(p)
Process *p;
X{
X sighold(SIGCHLD);
X
X if (p->p_toproc >= 0) {
X (void) close(p->p_toproc);
X p->p_toproc = -1; /* writes will fail */
X NumProcs -= 1;
X }
X
X sigrelse(SIGCHLD);
X}
X
do_rtp(mp)
register Mark *mp;
X{
X register Process *p = curbuf->b_process;
X Line *line1 = curline,
X *line2 = mp->m_line;
X int char1 = curchar,
X char2 = mp->m_char;
X char *gp;
X
X if (isdead(p) || p->p_buffer != curbuf)
X return;
X
X (void) fixorder(&line1, &char1, &line2, &char2);
X while (line1 != line2->l_next) {
X gp = ltobuf(line1, genbuf) + char1;
X if (line1 == line2)
X gp[char2] = '\0';
X else
X strcat(gp, "\n");
X (void) write(p->p_toproc, gp, strlen(gp));
X line1 = line1->l_next;
X char1 = 0;
X }
X}
X
X/* VARARGS3 */
X
private
proc_strt(bufname, clobber, va_alist)
char *bufname;
va_dcl
X{
X Window *owind = curwind;
X int toproc[2],
X pid;
X Process *newp;
X Buffer *newbuf;
X char *argv[32],
X *cp,
X foo[10],
X cmdbuf[128];
X int i;
X va_list ap;
X
X isprocbuf(bufname); /* make sure BUFNAME is either nonexistant
X or is of type B_PROCESS */
X dopipe(toproc);
X
X sighold(SIGCHLD);
X#ifdef SIGWINCH
X sighold(SIGWINCH);
X#endif
X switch (pid = fork()) {
X case -1:
X pclose(toproc);
X complain("[Fork failed.]");
X
X case 0:
X sigrelse(SIGCHLD);
X#ifdef SIGWINCH
X sigrelse(SIGWINCH);
X#endif
X argv[0] = "portsrv";
X argv[1] = foo;
X sprintf(foo, "%d", ProcInput);
X va_start(ap);
X make_argv(&argv[2], ap);
X va_end(ap);
X (void) dup2(toproc[0], 0);
X (void) dup2(ProcOutput, 1);
X (void) dup2(ProcOutput, 2);
X pclose(toproc);
X execv(Portsrv, argv);
X printf("execl failed\n");
X _exit(1);
X }
X
X newp = (Process *) malloc(sizeof *newp);
X newp->p_next = procs;
X newp->p_state = NEW;
X newp->p_cmd = 0;
X
X cmdbuf[0] = '\0';
X va_start(ap);
X while (cp = va_arg(ap, char *))
X sprintf(&cmdbuf[strlen(cmdbuf)], "%s ", cp);
X va_end(ap);
X newp->p_name = copystr(cmdbuf);
X procs = newp;
X newp->p_portpid = pid;
X newp->p_pid = -1;
X
X newbuf = do_select((Window *) 0, bufname);
X newbuf->b_type = B_PROCESS;
X newp->p_buffer = newbuf;
X newbuf->b_process = newp; /* sorta circular, eh? */
X pop_wind(bufname, clobber, B_PROCESS);
X ToLast();
X if (!bolp())
X LineInsert(1);
X /* Pop_wind() after everything is set up; important!
X Bindings won't work right unless newbuf->b_process is already
X set up BEFORE NEWBUF is first SetBuf()'d. */
X newp->p_mark = MakeMark(curline, curchar, M_FLOATER);
X
X newp->p_toproc = toproc[1];
X newp->p_reason = 0;
X NumProcs += 1;
X (void) close(toproc[0]);
X SetWind(owind);
X sigrelse(SIGCHLD);
X#ifdef SIGWINCH
X sigrelse(SIGWINCH);
X#endif
X}
X
pinit()
X{
X int p[2];
X
X (void) signal(SIGCHLD, proc_child);
X (void) pipe(p);
X ProcInput = p[0];
X ProcOutput = p[1];
X (void) signal(INPUT_SIG, procs_read);
X sighold(INPUT_SIG); /* Released during terminal read */
X}
X
doread(fd, buf, n)
char *buf;
X{
X int nread;
X
X if ((nread = read(fd, buf, n)) != n)
X complain("Cannot read %d (got %d) bytes.", n, nread);
X}
END_OF_FILE
if test 5928 -ne `wc -c <'./iproc-pipes.c'`; then
echo shar: \"'./iproc-pipes.c'\" unpacked with wrong size!
fi
# end of './iproc-pipes.c'
fi
if test -f './iproc-ptys.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'./iproc-ptys.c'\"
else
echo shar: Extracting \"'./iproc-ptys.c'\" \(7915 characters\)
sed "s/^X//" >'./iproc-ptys.c' <<'END_OF_FILE'
X/***************************************************************************
X * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne. JOVE *
X * is provided to you without charge, and with no warranty. You may give *
X * away copies of JOVE, including sources, provided that this notice is *
X * included in all the files. *
X ***************************************************************************/
X
X#ifdef BSD4_2
X# include <sys/wait.h>
X#else
X# include <wait.h>
X#endif
X#include <signal.h>
X#include <sgtty.h>
X#include <errno.h>
X
X#define DEAD 1 /* dead but haven't informed user yet */
X#define STOPPED 2 /* job stopped */
X#define RUNNING 3 /* just running */
X#define NEW 4 /* brand new, never been ... received no input */
X
X/* If process is dead, flags says how. */
X#define EXITED 1
X#define KILLED 2
X
X#define isdead(p) (p == 0 || proc_state(p) == DEAD || p->p_fd == -1)
X#define makedead(p) (proc_state(p) = DEAD)
X
X#define proc_buf(p) (p->p_buffer->b_name)
X#define proc_cmd(p) (p->p_name)
X#define proc_state(p) (p->p_state)
X
private Process *procs = 0;
X
long global_fd = 1;
int NumProcs = 0;
X
X#ifdef BRLUNIX
X extern struct sg_brl sg1;
X#else
X extern struct sgttyb sg1;
X#endif
X
extern struct tchars tc1;
X
X#ifdef TIOCSLTC
X extern struct ltchars ls1;
X#endif
X
char *
pstate(p)
Process *p;
X{
X switch (proc_state(p)) {
X case STOPPED:
X return "Stopped";
X
X case RUNNING:
X return "Running";
X
X case DEAD:
X if (p->p_howdied == EXITED) {
X if (p->p_reason == 0)
X return "Done";
X return sprint("Exit %d", p->p_reason);
X }
X return sprint("Killed %d", p->p_reason);
X
X case NEW:
X return "New";
X
X default:
X return "Unknown state";
X }
X}
X
static Process *
proc_pid(pid)
X{
X register Process *p;
X
X for (p = procs; p != 0; p = p->p_next)
X if (p->p_pid == pid)
X break;
X
X return p;
X}
X
read_proc(fd)
register int fd;
X{
X register Process *p;
X unsigned int n;
X char ibuf[1024];
X
X for (p = procs; p != 0; p = p->p_next)
X if (p->p_fd == fd)
X break;
X
X if (p == 0) {
X printf("\riproc: unknown fd %d", fd);
X return;
X }
X
X n = read(fd, ibuf, sizeof(ibuf) - 1);
X if (n == -1 && errno == EIO) {
X if (proc_state(p) == NEW)
X return;
X proc_close(p);
X makedead(p);
X return;
X } else {
X if (proc_state(p) != RUNNING) {
X proc_state(p) = RUNNING;
X UpdModLine = YES;
X }
X }
X if (n <= 0) {
X if (n == 0)
X strcpy(ibuf, "[Process EOF]");
X else
X sprintf(ibuf, "\n[pty read error: %d]\n", errno);
X } else
X ibuf[n] = '\0';
X proc_rec(p, ibuf);
X}
X
ProcKill()
X{
X register Buffer *b;
X Process *buf_to_proc();
X char *bname;
X
X bname = ask_buf(curbuf);
X
X if ((b = buf_exists(bname)) == 0)
X complain("[No such buffer]");
X if (b->b_process == 0)
X complain("%s not tied to a process.", bname);
X proc_kill(b->b_process, SIGKILL);
X}
X
ProcCont()
X{
X Process *p;
X
X if ((p = curbuf->b_process) == 0)
X complain("[No process]");
X if (p->p_state != DEAD) {
X proc_kill(p, SIGCONT);
X p->p_state = RUNNING;
X }
X}
X
ProcEof()
X{
X send_p(tc1.t_eofc);
X}
X
ProcInt()
X{
X send_p(tc1.t_intrc);
X}
X
ProcQuit()
X{
X send_p(tc1.t_quitc);
X}
X
ProcStop()
X{
X send_p(ls1.t_suspc);
X}
X
ProcDStop()
X{
X send_p(ls1.t_dsuspc);
X}
X
send_p(c)
char c;
X{
X Process *p;
X char buf[2];
X
X if ((p = curbuf->b_process) == 0)
X complain("[No process]");
X ToLast();
X buf[0] = c;
X buf[1] = '\0';
X proc_rec(p, buf);
X (void) write(p->p_fd, &c, 1);
X}
X
private
proc_close(p)
Process *p;
X{
X sighold(SIGCHLD); /* be mutually exclusive */
X
X if (p->p_fd >= 0) {
X (void) close(p->p_fd);
X global_fd &= ~(1L << p->p_fd);
X NumProcs -= 1;
X p->p_fd = -1;
X }
X
X sigrelse(SIGCHLD);
X}
X
do_rtp(mp)
register Mark *mp;
X{
X register Process *p = curbuf->b_process;
X Line *line1 = curline,
X *line2 = mp->m_line;
X int char1 = curchar,
X char2 = mp->m_char;
X char *gp;
X int nbytes;
X
X if (isdead(p) || p->p_buffer != curbuf)
X return;
X
X (void) fixorder(&line1, &char1, &line2, &char2);
X while (line1 != line2->l_next) {
X gp = ltobuf(line1, genbuf) + char1;
X if (line1 == line2)
X gp[char2] = '\0';
X else
X strcat(gp, "\n");
X if (nbytes = strlen(gp))
X (void) write(p->p_fd, gp, nbytes);
X line1 = line1->l_next;
X char1 = 0;
X }
X}
X
X/* VARARGS2 */
X
private
proc_strt(bufname, clobber, va_alist)
char *bufname;
va_dcl
X{
X va_list ap;
X char *argv[32],
X *cp;
X Window *owind = curwind;
X int pid;
X Process *newp;
X Buffer *newbuf;
X int i,
X ptyfd,
X ttyfd,
X ldisc,
X lmode;
X register char *s,
X *t;
X extern int errno;
X static char ttybuf[11],
X ptybuf[11];
X char cmdbuf[128];
X#ifdef BRLUNIX
X struct sg_brl sg;
X#else
X struct sgttyb sg;
X#endif
X
X#ifdef TIOCGWINSZ
X struct winsize win;
X#else
X# ifdef BTL_BLIT
X# include <sys/jioctl.h>
X struct jwinsize jwin;
X# endif
X#endif
X
X isprocbuf(bufname); /* make sure BUFNAME is either nonexistant
X or is of type B_PROCESS */
X for (s = "pqrs"; *s; s++) {
X for (t = "0123456789abcdef"; *t; t++) {
X sprintf(ptybuf, "/dev/pty%c%c", *s, *t);
X if ((ptyfd = open(ptybuf, 2)) >= 0) {
X strcpy(ttybuf, ptybuf);
X ttybuf[5] = 't';
X /* make sure both ends are available */
X if ((i = open(ttybuf, 2)) < 0)
X continue;
X (void) close(i);
X goto out;
X }
X }
X }
X
out: if (s == 0 && t == 0)
X complain("[Out of ptys!]");
X
X#ifdef TIOCGETD
X (void) ioctl(0, TIOCGETD, (struct sgttyb *) &ldisc);
X#endif
X#ifdef TIOCLGET
X (void) ioctl(0, TIOCLGET, (struct sgttyb *) &lmode);
X#endif
X#ifdef TIOCGWINSZ
X (void) ioctl(0, TIOCGWINSZ, (struct sgttyb *) &win);
X#else
X# ifdef BTL_BLIT
X (void) ioctl(0, JWINSIZE, (struct sgttyb *) &jwin);
X# endif /* BTL_BLIT */
X#endif
X
X sighold(SIGCHLD);
X#ifdef SIGWINCH
X sighold(SIGWINCH);
X#endif
X switch (pid = fork()) {
X case -1:
X (void) close(ptyfd);
X message("[Fork failed!]");
X goto fail;
X
X case 0:
X sigrelse(SIGCHLD);
X#ifdef SIGWINCH
X sigrelse(SIGWINCH);
X#endif
X for (i = 0; i < 32; i++)
X (void) close(i);
X
X#ifdef TIOCNOTTY
X if ((i = open("/dev/tty", 2)) >= 0) {
X (void) ioctl(i, TIOCNOTTY, (struct sgttyb *) 0);
X (void) close(i);
X }
X#endif
X if ((ttyfd = open(ttybuf, 2)) < 0)
X exit(-1);
X (void) dup2(ttyfd, 1);
X (void) dup2(ttyfd, 2);
X
X#ifdef TIOCSETD
X (void) ioctl(0, TIOCSETD, (struct sgttyb *) &ldisc);
X#endif
X#ifdef TIOCLSET
X (void) ioctl(0, TIOCLSET, (struct sgttyb *) &lmode);
X#endif
X#ifdef TIOCSETC
X (void) ioctl(0, TIOCSETC, (struct sgttyb *) &tc1);
X#endif
X#ifdef TIOCSLTC
X (void) ioctl(0, TIOCSLTC, (struct sgttyb *) &ls1);
X#endif
X
X#ifdef TIOCGWINSZ
X# ifdef SIGWINCH
X (void) signal(SIGWINCH, SIG_IGN);
X# endif
X win.ws_row = curwind->w_height;
X (void) ioctl(0, TIOCSWINSZ, (struct sgttyb *) &win);
X#else
X# ifdef BTL_BLIT
X jwin.bytesy = curwind->w_height;
X (void) ioctl(0, JSWINSIZE, (struct sgttyb *) &jwin);
X# endif
X#endif
X
X sg = sg1;
X sg.sg_flags &= ~(ECHO | CRMOD);
X (void) stty(0, &sg);
X
X i = getpid();
X (void) ioctl(0, TIOCSPGRP, (struct sgttyb *) &i);
X (void) setpgrp(0, i);
X va_start(ap);
X make_argv(argv, ap);
X va_end(ap);
X execv(argv[0], &argv[1]);
X (void) write(1, "execve failed!\n", 15);
X _exit(errno + 1);
X }
X
X newp = (Process *) emalloc(sizeof *newp);
X
X newp->p_fd = ptyfd;
X newp->p_pid = pid;
X
X newbuf = do_select((Window *) 0, bufname);
X newbuf->b_type = B_PROCESS;
X newp->p_buffer = newbuf;
X newbuf->b_process = newp; /* sorta circular, eh? */
X pop_wind(bufname, clobber, B_PROCESS);
X /* Pop_wind() after everything is set up; important!
X Bindings won't work right unless newbuf->b_process is already
X set up BEFORE NEWBUF is first SetBuf()'d. */
X ToLast();
X if (!bolp())
X LineInsert(1);
X
X cmdbuf[0] = '\0';
X va_start(ap);
X while (cp = va_arg(ap, char *))
X sprintf(&cmdbuf[strlen(cmdbuf)], "%s ", cp++);
X va_end(ap);
X
X newp->p_name = copystr(cmdbuf);
X newp->p_state = NEW;
X newp->p_reason = 0;
X newp->p_mark = MakeMark(curline, curchar, M_FLOATER);
X
X newp->p_next = procs;
X procs = newp;
X NumProcs += 1;
X global_fd |= 1L << newp->p_fd;
X SetWind(owind);
X
fail: sigrelse(SIGCHLD);
X#ifdef SIGWINCH
X sigrelse(SIGWINCH);
X#endif
X}
X
pinit()
X{
X (void) signal(SIGCHLD, proc_child);
X}
X
END_OF_FILE
if test 7915 -ne `wc -c <'./iproc-ptys.c'`; then
echo shar: \"'./iproc-ptys.c'\" unpacked with wrong size!
fi
# end of './iproc-ptys.c'
fi
if test -f './macros.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'./macros.c'\"
else
echo shar: Extracting \"'./macros.c'\" \(7870 characters\)
sed "s/^X//" >'./macros.c' <<'END_OF_FILE'
X/***************************************************************************
X * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne. JOVE *
X * is provided to you without charge, and with no warranty. You may give *
X * away copies of JOVE, including sources, provided that this notice is *
X * included in all the files. *
X ***************************************************************************/
X
X#include "jove.h"
X#include "ctype.h"
X#include "io.h"
X
X#ifdef MAC
X# undef private
X# define private
X#endif
X
X#ifdef LINT_ARGS
private void
X add_mac(struct macro *),
X del_mac(struct macro *),
X pop_macro_stack(void),
X push_macro_stack(struct macro *, int);
X
private int
X PrefChar(int);
X
private struct macro * mac_exists(char *);
X#else
private void
X add_mac(),
X del_mac(),
X pop_macro_stack(),
X push_macro_stack();
X
private int
X PrefChar();
X
private struct macro * mac_exists();
X#endif /* LINT_ARGS */
X
X#ifdef MAC
X# undef private
X# define private static
X#endif
X
struct macro *macros = 0; /* macros */
int InMacDefine = NO;
X
private void
add_mac(new)
struct macro *new;
X{
X register struct macro *mp,
X *prev = 0;
X
X for (mp = macros; mp != 0; prev = mp, mp = mp->m_nextm)
X if (mp == new)
X return;
X
X if (prev)
X prev->m_nextm = new;
X else
X macros = new;
X new->m_nextm = 0;
X new->Type = MACRO;
X}
X
private void
del_mac(mac)
struct macro *mac;
X{
X register struct macro *m;
X
X for (m = macros; m != 0; m = m->m_nextm)
X if (m->m_nextm == mac) {
X m->m_nextm = mac->m_nextm;
X break;
X }
X free(mac->Name);
X free(mac->m_body);
X free((char *) mac);
X}
X
struct macro KeyMacro; /* Macro used for defining */
X
X/* To execute a macro, we have a "stack" of running macros. Whenever
X we execute a macro, we push it on the stack, run it, then pop it
X from the stack. */
struct m_thread {
X struct m_thread *mt_prev;
X struct macro *mt_mp;
X int mt_offset,
X mt_count;
X};
X
private struct m_thread *mac_stack = 0;
X
void
unwind_macro_stack()
X{
X while (mac_stack != 0)
X pop_macro_stack();
X}
X
private void
pop_macro_stack()
X{
X register struct m_thread *m;
X
X if ((m = mac_stack) == 0)
X return;
X mac_stack = m->mt_prev;
X free_mthread(m);
X}
X
struct m_thread *
alloc_mthread()
X{
X return (struct m_thread *) emalloc(sizeof (struct m_thread));
X}
X
void
free_mthread(t)
struct m_thread *t;
X{
X free((char *) t);
X}
X
private void
push_macro_stack(m, count)
struct macro *m;
X{
X struct m_thread *t;
X
X t = alloc_mthread();
X t->mt_prev = mac_stack;
X mac_stack = t;
X t->mt_offset = 0;
X t->mt_mp = m;
X t->mt_count = count;
X}
X
void
do_macro(mac)
struct macro *mac;
X{
X push_macro_stack(mac, arg_value());
X}
X
private struct macro *
mac_exists(name)
char *name;
X{
X register struct macro *mp;
X
X for (mp = macros; mp; mp = mp->m_nextm)
X if (strcmp(mp->Name, name) == 0)
X return mp;
X return 0;
X}
X
void
mac_init()
X{
X add_mac(&KeyMacro);
X KeyMacro.Name = "keyboard-macro";
X KeyMacro.m_len = 0;
X KeyMacro.m_buflen = 16;
X KeyMacro.m_body = emalloc(KeyMacro.m_buflen);
X}
X
void
mac_putc(c)
int c;
X{
X if (KeyMacro.m_len >= KeyMacro.m_buflen) {
X KeyMacro.m_buflen += 16;
X KeyMacro.m_body = realloc(KeyMacro.m_body, (unsigned) KeyMacro.m_buflen);
X if (KeyMacro.m_body == 0) {
X KeyMacro.m_buflen = KeyMacro.m_len = 0;
X complain("[Can't allocate storage for keyboard macro]");
X }
X }
X KeyMacro.m_body[KeyMacro.m_len++] = c;
X}
X
int
in_macro()
X{
X return (mac_stack != 0);
X}
X
int
mac_getc()
X{
X struct m_thread *mthread;
X struct macro *m;
X
X if ((mthread = mac_stack) == 0)
X return -1;
X m = mthread->mt_mp;
X if (mthread->mt_offset == m->m_len) {
X mthread->mt_offset = 0;
X if (--mthread->mt_count == 0)
X pop_macro_stack();
X return mac_getc();
X }
X return m->m_body[mthread->mt_offset++];
X}
X
void
NameMac()
X{
X char *name;
X struct macro *m;
X
X if (KeyMacro.m_len == 0)
X complain("[No keyboard macro to name!]");
X if (in_macro() || InMacDefine)
X complain("[Can't name while defining/executing]");
X if ((m = mac_exists(name = ask((char *) 0, ProcFmt))) == 0)
X m = (struct macro *) emalloc(sizeof *m);
X else {
X if (strcmp(name, KeyMacro.Name) == 0)
X complain("[Can't name it that!]");
X free(m->Name);
X free(m->m_body);
X }
X name = copystr(name);
X m->Type = KeyMacro.Type;
X m->m_len = KeyMacro.m_len;
X m->m_buflen = KeyMacro.m_buflen;
X m->m_body = emalloc(m->m_buflen);
X byte_copy(KeyMacro.m_body, m->m_body, m->m_len);
X m->m_flags = SAVE;
X m->Name = name;
X add_mac(m);
X}
X
void
RunMacro()
X{
X struct macro *m;
X
X if (m = (struct macro *) findmac(ProcFmt))
X do_macro(m);
X}
X
void
pr_putc(c, fp)
File *fp;
X{
X if (c == '\\' || c == '^')
X putc('\\', fp);
X else if (isctrl(c)) {
X putc('^', fp);
X c = (c == RUBOUT) ? '?' : (c + '@');
X }
X putc(c, fp);
X}
X
void
WriteMacs()
X{
X struct macro *m;
X char *file,
X filebuf[FILESIZE];
X File *fp;
X int i;
X
X file = ask_file((char *) 0, (char *) 0, filebuf);
X fp = open_file(file, iobuff, F_WRITE, COMPLAIN, QUIET);
X
X /* Don't write the keyboard macro which is always the first */
X for (m = macros->m_nextm; m != 0; m = m->m_nextm) {
X fprintf(fp, "define-macro %s ", m->Name);
X for (i = 0; i < m->m_len; i++)
X pr_putc(m->m_body[i], fp);
X putc('\n', fp);
X m->m_flags &= ~SAVE;
X }
X close_file(fp);
X}
X
void
DefKBDMac()
X{
X char *macro_name,
X *macro_body,
X nextc,
X c,
X macro_buffer[LBSIZE];
X int i;
X struct macro *m;
X
X macro_name = do_ask(" \r\n", (int (*)()) 0, (char *) 0, ProcFmt);
X if (macro_name == 0)
X complain("[No default]");
X macro_name = copystr(macro_name);
X if (m = mac_exists(macro_name))
X del_mac(m);
X macro_body = ask((char *) 0, ": %f %s enter body: ", macro_name);
X i = 0;
X while ((c = *macro_body++) != '\0') {
X if (c == '\\') {
X if ((nextc = *macro_body++) == LF)
X complain("[Premature end of line]");
X c = nextc;
X } else if (c == '^') {
X if ((nextc = *macro_body++) == '?')
X c = RUBOUT;
X else if (isalpha(nextc) || index("@[\\]^_", nextc))
X c = CTL(nextc);
X else
X complain("Bad control-character: '%c'", nextc);
X }
X macro_buffer[i++] = c;
X }
X m = (struct macro *) emalloc(sizeof (*m));
X m->Name = macro_name;
X m->m_len = m->m_buflen = i;
X m->m_body = emalloc(i);
X m->m_flags = InJoverc ? 0 : SAVE;
X byte_copy(macro_buffer, m->m_body, i);
X add_mac(m);
X}
X
void
Remember()
X{
X /* We're already executing the macro; ignore any attempts
X to define the keyboard macro while we are executing. */
X if (in_macro())
X return;
X if (InMacDefine)
X message("[Already defining ... continue with definition]");
X else {
X UpdModLine = YES;
X InMacDefine = YES;
X KeyMacro.m_len = 0;
X message("Defining...");
X }
X}
X
X/* Is `c' a prefix character */
X
private int
PrefChar(c)
X{
X return (int) IsPrefix(mainmap[c]);
X}
X
void
Forget()
X{
X char *cp;
X struct macro *m = &KeyMacro;
X
X UpdModLine = YES;
X if (InMacDefine) {
X message("Keyboard macro defined.");
X InMacDefine = NO;
X
X /* try and strip off the key sequence that invoked us */
X cp = &m->m_body[m->m_len - 2];
X if (PrefChar(*cp))
X m->m_len -= 2;
X else if (commands[cp[1]].c_proc == Forget)
X m->m_len -= 1;
X } else
X complain("[end-kbd-macro: not currently defining macro!]");
X}
X
void
ExecMacro()
X{
X do_macro(&KeyMacro);
X}
X
void
MacInter()
X{
X extern int Interactive;
X
X if (!Asking)
X return;
X Interactive = 1;
X}
X
int
ModMacs()
X{
X register struct macro *m;
X
X for (m = macros->m_nextm; m != 0; m = m->m_nextm)
X if (m->m_flags & SAVE)
X return YES;
X return NO;
X}
X
data_obj *
findmac(prompt)
char *prompt;
X{
X char *strings[100];
X register char **strs = strings;
X register int com;
X register struct macro *m = macros;
X
X for (; m != 0; m = m->m_nextm)
X *strs++ = m->Name;
X *strs = 0;
X
X if ((com = complete(strings, prompt, NOTHING)) < 0)
X return 0;
X m = macros;
X while (--com >= 0)
X m = m->m_nextm;
X return (data_obj *) m;
X}
X
void
DelMacro()
X{
X struct macro *m;
X
X if ((m = (struct macro *) findmac(ProcFmt)) == 0)
X return;
X if (m == &KeyMacro)
X complain("[It's illegal to delete the keyboard-macro!]");
X del_mac(m);
X}
END_OF_FILE
if test 7870 -ne `wc -c <'./macros.c'`; then
echo shar: \"'./macros.c'\" unpacked with wrong size!
fi
# end of './macros.c'
fi
echo shar: End of archive 3 \(of 21\).
cp /dev/null ark3isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 21 archives.
rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0
--
Please send comp.sources.unix-related mail to rsalz at uunet.uu.net.
More information about the Comp.sources.unix
mailing list