v08i025: The JOVE text editor, Part06/13

sources-request at mirror.UUCP sources-request at mirror.UUCP
Wed Feb 4 15:05:06 AEST 1987


Submitted by: seismo!rochester!jpayne (Jonathan Payne)
Mod.sources: Volume 8, Issue 25
Archive-name: jove/Part06

#! /bin/sh
# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
# If all goes well, you will see the message "End of archive 6 (of 13)."
# Contents:  misc.c move.c paragraph.c portsrv.c proc.c re1.c table.h
PATH=/bin:/usr/bin:/usr/ucb; export PATH
echo shar: extracting "'misc.c'" '(7568 characters)'
if test -f 'misc.c' ; then 
  echo shar: will not over-write existing file "'misc.c'"
else
sed 's/^X//' >misc.c <<'@//E*O*F misc.c//'
X/************************************************************************
X * This program is Copyright (C) 1986 by Jonathan Payne.  JOVE is       *
X * 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 <signal.h>
X#ifdef ANSICODES
X#include "termcap.h"
X#endif
X
XDigit()
X{
X	GetExp(LastKeyStruck);
X}
X
XDigit0()
X{
X	GetExp('0');
X}
X
XDigit1()
X{
X	GetExp('1');
X}
X
XDigit2()
X{
X	GetExp('2');
X}
X
XDigit3()
X{
X	GetExp('3');
X}
X
XDigit4()
X{
X	GetExp('4');
X}
X
XDigit5()
X{
X	GetExp('5');
X}
X
XDigit6()
X{
X	GetExp('6');
X}
X
XDigit7()
X{
X	GetExp('7');
X}
X
XDigit8()
X{
X	GetExp('8');
X}
X
XDigit9()
X{
X	GetExp('9');
X}
X
XprCTIME()
X{
X	s_mess(": %f %s", get_time((time_t *) 0, (char *) 0, 0, -1));
X}
X
Xextern int	alarmed;
X
XFourTime()
X{
X	int	oldc = LastKeyStruck,
X		newc;
X	int	nexp;
X
X	alarmed = 0;
X	exp_p = YES;
X	this_cmd = ARG_CMD;
X	do {
X		if ((nexp = exp * 4) != 0)
X			exp = nexp;
X		if (!alarmed)
X			newc = waitchar();
X		else
X			newc = getch();
X		if (alarmed)
X			message(key_strokes);
X	} while (newc == oldc);
X	Ungetc(newc);
X}
X
Xint	exp_p,
X	exp;
X
XGetExp(c)
X{
X	int	sign = 0;
X	static int	digited;
X
X	if (!isdigit(c) && c != '-')
X		complain((char *) 0);
X	if (exp_p == NO) {	/* if we just got here */
X		exp = 0;	/* start over */
X		digited = NO;
X	} else if (exp_p == YES_NODIGIT) {
X		sign = (exp < 0) ? -1 : 1;
X		exp = 0;
X	}
X
X	if (!sign)
X		sign = (exp < 0) ? -1 : 1;
X	if (sign == -1)
X		exp = -exp;
X	if (c == '-') {
X		sign = -sign;
X		goto goread;
X	}
X	for (;;) {
X		if (alarmed)
X			message(key_strokes);
X		if (isdigit(c)) {
X			exp = (exp * 10) + (c - '0');
X			digited++;
X		} else {
X			if (digited)
X				exp_p = YES;
X			else {
X				exp = 1;
X				if (exp_p == NO)
X					exp_p = YES_NODIGIT;
X			}
X			exp *= sign;
X			this_cmd = ARG_CMD;
X			Ungetc(c);
X			return;
X		}
Xgoread:		if (!alarmed)
X			c = waitchar();
X		else {
X			add_mess(NullStr);
X			c = getch();
X		}
X	}
X}
X
XChrToOct()
X{
X	int	c;
X
X	c = waitchar();
X	if (alarmed)
X		message(key_strokes);
X	ins_str(sprint("\\%03o", c), NO);
X}
X
XStrLength()
X{
X	static char	inquotes[] = "Where are the quotes?";
X	char	*first = StrIndex(-1, linebuf, curchar, '"'),
X		*last = StrIndex(1, linebuf, curchar + 1, '"'),
X		c;
X	int	numchars = 0;
X
X	if (first == 0 || last == 0)
X		complain(inquotes);
X	first++;
X	while (first < last) {
X		c = *first++;
X		if (c == '\\') {
X			int	num;
X
X			if (!isdigit(*first))
X				++first;
X			else {
X				num = 3;
X				while (num-- && isdigit(*first++) && first < last)
X					;
X			}
X		}
X		numchars++;
X	}
X	s_mess("%d characters", numchars);
X}
X
X/* Transpos cur_char with cur_char - 1 */
X
XTransChar()
X{
X	char	before;
X
X	if (curchar == 0 || (eolp() && curchar == 1))
X		complain((char *) 0);	/* BEEP */
X	exp = 1;
X	if (eolp())
X		BackChar();
X	before = linebuf[curchar - 1];
X	DelPChar();
X	ForChar();
X	Insert(before);
X}
X
X/* Switch current line with previous one */
X
XTransLines()
X{
X	disk_line	old_prev;
X
X	if (firstp(curline))
X		return;
X	exp = 1;
X	lsave();
X	old_prev = curline->l_prev->l_dline;
X	curline->l_prev->l_dline = curline->l_dline;
X	curline->l_dline = old_prev;
X	getDOT();
X	if (!lastp(curline))
X		line_move(FORWARD, NO);
X	modify();
X}
X
XLeave()
X{
X	longjmp(mainjmp, QUIT);
X}
X
X/* If argument is specified, kill that many lines down.  Otherwise,
X   if we "appear" to be at the end of a line, i.e. everything to the
X   right of the cursor is white space, we delete the line separator
X   as if we were at the end of the line. */
X
XKillEOL()
X{
X	Line	*line2;
X	int	char2;
X
X	if (exp_p) {
X		if (exp == 0) {	/* Kill to beginning of line */
X			line2 = curline;
X			char2 = 0;
X		} else {
X			line2 = next_line(curline, exp);
X			if ((LineDist(curline, line2) < exp) || (line2 == curline))
X				char2 = length(line2);
X			else
X				char2 = 0;
X		}
X	} else if (blnkp(&linebuf[curchar])) {
X		line2 = next_line(curline, 1);
X		if (line2 == curline)
X			char2 = length(curline);
X		else
X			char2 = 0;
X	} else {
X		line2 = curline;
X		char2 = length(curline);
X	}
X	reg_kill(line2, char2, 0);
X}
X
X/* Kill to beginning of sentence */
X
XKillBos()
X{
X	exp = -exp;
X	KillEos();
X}
X
X/* Kill to end of sentence */
X
XKillEos()
X{
X	Line	*line1;
X	int	char1;
X
X	line1 = curline;
X	char1 = curchar;
X	Eos();
X	reg_kill(line1, char1, 1);
X}
X
XKillExpr()
X{
X	Line	*line1;
X	int	char1;
X
X	line1 = curline;
X	char1 = curchar;
X	FSexpr();
X	reg_kill(line1, char1, 1);
X}
X
XEscPrefix()
X{
X	HandlePref(pref1map);
X}
X
XCtlxPrefix()
X{
X	HandlePref(pref2map);
X}
X
XMiscPrefix()
X{
X	HandlePref(miscmap);
X}
X
XHandlePref(map)
Xdata_obj	**map;
X{
X	register data_obj	*cp;
X	register int	c;
X
X	c = waitchar();
X	if (c == CTL(G)) {
X		message("[Aborted]");
X		rbell();
X		return;
X	}
X
X	if (alarmed)
X		message(key_strokes);
X
X	cp = map[c];
X	if (cp == 0) {
X		s_mess("[%sunbound]", key_strokes);
X		rbell();
X	} else
X		ExecCmd(cp);
X}
X
XYank()
X{
X	Line	*line,
X		*lp;
X	Bufpos	*dot;
X
X	if (killbuf[killptr] == 0)
X		complain("[Nothing to yank!]");
X	lsave();
X	this_cmd = YANKCMD;
X	line = killbuf[killptr];
X	lp = lastline(line);
X	dot = DoYank(line, 0, lp, length(lp), curline, curchar, curbuf);
X	SetMark();
X	SetDot(dot);
X}
X
XWtModBuf()
X{
X	if (!ModBufs(NO))
X		message("[No buffers need saving]");
X	else
X		put_bufs(exp_p);
X}
X
Xput_bufs(askp)
X{
X	register Buffer	*oldb = curbuf,	
X			*b;		
X
X	for (b = world; b != 0; b = b->b_next) {
X		if (!IsModified(b) || b->b_type != B_FILE)
X			continue;
X		SetBuf(b);	/* Make this current Buffer */
X		if (curbuf->b_fname == 0) {
X			char	*newname;
X
X			newname = ask(NullStr, "Buffer \"%s\" needs a file name; type Return to skip: ", b->b_name);
X			if (*newname == 0)
X				continue;
X			setfname(b, newname);
X		}
X		if (askp && (yes_or_no_p("Write %s? ", curbuf->b_fname) == NO))
X			continue;
X		filemunge(curbuf->b_fname);
X		chk_mtime(curbuf, curbuf->b_fname, "save");
X		file_write(curbuf->b_fname, 0);
X		unmodify();
X	}
X	SetBuf(oldb);
X}
X
XToIndent()
X{
X	register char	*cp,
X			c;
X
X	for (cp = linebuf; c = *cp; cp++)
X		if (c != ' ' && c != '\t')
X			break;
X	curchar = cp - linebuf;
X}
X
XGoLine()
X{
X	Line	*newline;
X
X#ifndef ANSICODES
X	if (exp_p == NO)
X		return;
X#else
X	if (exp_p == NO || exp <= 0) {
X		if (SP)
X			putpad(SP, 1);	/* Ask for cursor position */
X		return;
X	}
X#endif
X	newline = next_line(curbuf->b_first, exp - 1);
X	PushPntp(newline);
X	SetLine(newline);
X}
X
X#ifdef ANSICODES
XMoveToCursor(line, col)
X{
X	register struct scrimage *sp = &PhysScreen[line];
X
X	while (sp->s_id == NULL)
X		sp = &PhysScreen[--line];
X	if (sp->s_flags & MODELINE)
X		complain((char *) 0);
X	if (curwind != sp->s_window)
X		SetWind(sp->s_window);
X	SetLine(sp->s_lp);
X	curchar = how_far(sp->s_lp, col);
X}
X
XAnsiCodes()
X{
X	int	c;
X	int	num1 = 0;
X	int	num2;
X	static char *unsupported = "[Unsupported ANSI code received]";
X
X	while (isdigit(c = getch()))
X		num1 = (num1*10) + (c - '0');
X
X	switch (c) {
X	case ';':
X		num2 = 0;
X		while (isdigit(c = getch()))
X			num2 = (num2*10) + (c - '0');
X		switch (c) {
X		case 'R':
X			MoveToCursor(--num1, --num2);
X			break;
X		case 'H':
X			Eow(); Bol();
X			break;
X		default:
X			complain(unsupported);
X		}
X		break;
X	case 'A':
X		line_move(BACKWARD, YES);
X		break;
X	case 'B':
X		line_move(FORWARD, YES);
X		break;
X	case 'C':
X		ForChar();
X		break;
X	case 'D':
X		BackChar();
X		break;
X	case 'H':
X		Bow();
X		break;
X	case 'J':
X		if (num1 == 2) {
X			ClAndRedraw();
X			break;
X		}
X		/* FALL THROUGH */
X	default:
X		complain(unsupported);
X	}
X}
X#endif ANSICODES
X
XNotModified()
X{
X	unmodify();
X}
X
XSetLMargin()
X{
X	LMargin = calc_pos(linebuf, curchar);
X}
X
XSetRMargin()
X{
X	RMargin = calc_pos(linebuf, curchar);
X}
@//E*O*F misc.c//
if test 7568 -ne "`wc -c <'misc.c'`"; then
    echo shar: error transmitting "'misc.c'" '(should have been 7568 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'move.c'" '(4397 characters)'
if test -f 'move.c' ; then 
  echo shar: will not over-write existing file "'move.c'"
else
sed 's/^X//' >move.c <<'@//E*O*F move.c//'
X/************************************************************************
X * This program is Copyright (C) 1986 by Jonathan Payne.  JOVE is       *
X * 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
Xstatic int	line_pos;
X
XForChar()
X{
X	register int	num = exp;
X
X	if (exp < 0) {
X		exp = -exp;
X		BackChar();
X		return;
X	}
X	exp = 1;
X	while (--num >= 0) {
X		if (eolp()) {			/* Go to the next Line */
X			if (curline->l_next == 0)
X				break;
X			SetLine(curline->l_next);
X		} else
X			curchar++;
X	}
X}
X
XBackChar()
X{
X	register int	num = exp;
X
X	if (exp < 0) {
X		exp = -exp;
X		ForChar();
X		return;
X	}
X	exp = 1;
X	while (--num >= 0) {
X		if (bolp()) {
X			if (curline->l_prev == 0)
X				break;
X			SetLine(curline->l_prev);
X			Eol();
X		} else
X			--curchar;
X	}
X}
X
XNextLine()
X{
X	if ((curline == curbuf->b_last) && eolp())
X		complain(NullStr);
X	line_move(FORWARD, YES);
X}
X
XPrevLine()
X{
X	if ((curline == curbuf->b_first) && bolp())
X		complain(NullStr);
X	line_move(BACKWARD, YES);
X}
X
X/* moves to a different line in DIR; LINE_CMD says whether this is
X   being called from NextLine() or PrevLine(), in which case it tries
X   to line up the column with the column of the current line */
X
Xline_move(dir, line_cmd)
X{
X	Line	*(*proc)() = (dir == FORWARD) ? next_line : prev_line;
X	Line	*line;
X
X	line = (*proc)(curline, exp);
X	if (line == curline) {
X		(dir == FORWARD) ? Eol() : Bol();
X		return;
X	}
X
X	if (line_cmd) {
X		this_cmd = LINECMD;
X		if (last_cmd != LINECMD)
X			line_pos = calc_pos(linebuf, curchar);
X	}
X	SetLine(line);		/* curline is in linebuf now */
X	if (line_cmd)
X		curchar = how_far(curline, line_pos);
X}
X
X/* returns what cur_char should be for that position col */
X
Xhow_far(line, col)
XLine	*line;
X{
X	register char	*lp;
X	register int	pos,
X			c;
X	char	*base;
X
X	base = lp = lcontents(line);
X	pos = 0;
X
X	while (pos < col && (c = (*lp & 0177))) {
X		if (c == '\t')
X			pos += (tabstop - (pos % tabstop));
X		else if (isctrl(c))
X			pos += 2;
X		else
X			pos++;
X		lp++;
X	}
X
X	return lp - base;
X}
X
XBol()
X{
X	curchar = 0;
X}
X
XEol()
X{
X	curchar = strlen(linebuf);
X}
X
XEof()
X{
X	PushPntp(curbuf->b_last);
X	ToLast();
X}
X
XBof()
X{
X	PushPntp(curbuf->b_first);
X	ToFirst();
X}
X
X/* Move forward (if dir > 0) or backward (if dir < 0) a sentence.  Deals
X   with all the kludgery involved with paragraphs, and moving backwards
X   is particularly yucky. */
X
Xto_sent(dir)
X{
X	Bufpos	*new,
X		old;
X	extern char	*ParaStr;
X
X	DOTsave(&old);
X
X	new = dosearch("^[ \t]*$\\|[?.!]", dir, 1);
X	if (new == 0) {
X		(dir < 0) ? ToFirst() : ToLast();
X		return;
X	}
X	SetDot(new);
X	if (dir < 0) {
X		to_word(1);
X		if ((old.p_line == curline && old.p_char <= curchar) ||
X		    (inorder(new->p_line, new->p_char, old.p_line, old.p_char) &&
X		     inorder(old.p_line, old.p_char, curline, curchar))) {
X		     	SetDot(new);
X		     	to_sent(dir);
X		}
X		return;		/* We're there? */
X	}
X	if (blnkp(linebuf)) {
X		Bol();
X		BackChar();
X		if (old.p_line == curline && old.p_char >= curchar) {
X			to_word(1);	/* Oh brother this is painful */
X			to_sent(1);
X		}
X	} else {
X		extern int	REbom;
X
X		curchar = REbom + 1;	/* Just after the [?.!] */
X		if (LookingAt("[\")]  *\\|[\")]$", linebuf, curchar))
X			curchar++;
X		else if (!eolp() && !LookingAt("  *", linebuf, curchar))
X			to_sent(dir);
X	}
X}
X
XBos()
X{
X	int	num = exp;
X
X	if (exp < 0) {
X		exp = -exp;
X		Eos();
X		return;
X	}
X
X	exp = 1;
X
X	while (--num >= 0) {
X		to_sent(-1);
X		if (bobp())
X			break;
X	}
X}
X
XEos()
X{
X	int	num = exp;
X
X	if (exp < 0) {
X		exp = -exp;
X		Bos();
X		return;
X	}
X
X	exp = 1;
X
X	while (--num >= 0) {
X		to_sent(1);
X		if (eobp())
X			break;
X	}
X}
X
XForWord()
X{
X	register char	c;
X	register int	num = exp;
X
X	if (exp < 0) {
X		exp = -exp;
X		BackWord();
X		return;
X	}
X	exp = 1;
X	while (--num >= 0) {
X		to_word(1);
X		while ((c = linebuf[curchar]) != 0 && isword(c))
X			curchar++;
X		if (eobp())
X			break;
X	}
X	this_cmd = 0;	/* Semi kludge to stop some unfavorable behavior */
X}
X
XBackWord()
X{
X	register int	num = exp;
X	register char	c;
X
X	if (exp < 0) {
X		exp = -exp;
X		ForWord();
X		return;
X	}
X	exp = 1;
X	while (--num >= 0) {
X		to_word(-1);
X		while (!bolp() && (c = linebuf[curchar - 1], isword(c)))
X			--curchar;
X		if (bobp())
X			break;
X	}
X	this_cmd = 0;
X}
@//E*O*F move.c//
if test 4397 -ne "`wc -c <'move.c'`"; then
    echo shar: error transmitting "'move.c'" '(should have been 4397 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'paragraph.c'" '(13888 characters)'
if test -f 'paragraph.c' ; then 
  echo shar: will not over-write existing file "'paragraph.c'"
else
sed 's/^X//' >paragraph.c <<'@//E*O*F paragraph.c//'
X/************************************************************************
X * This program is Copyright (C) 1986 by Jonathan Payne.  JOVE is       *
X * 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/* Thanks to Brian Harvey for this paragraph boundery finding algorithm.
X   It's really quite hairy figuring it out.  This deals with paragraphs that
X   are seperated by blank lines, lines beginning with a Period (assumed to
X   be an nroff command), lines beginning with BackSlash (assumed to be Tex
X   commands).  Also handles paragraphs that are separated by lines of
X   different indent; and it deals with outdented paragraphs, too.  It's
X   really quite nice.  Here's Brian's algorithm.
X
X   Definitions:
X   
X   THIS means the line containing the cursor.
X   PREV means the line above THIS.
X   NEXT means the line below THIS.
X   
X   BLANK means empty, empty except for spaces and tabs, starts with a period
X   or a backslash, or nonexistent (because the edge of the buffer is
X   reached).  ((BH 12/24/85 A line starting with backslash is blank only if
X   the following line also starts with backslash.  This is so that \noindent
X   is part of a paragraph, but long strings of TeX commands don't get
X   rearranged.  It still isn't perfect but it's better.))
X
X   BSBLANK means BLANK or starts with a backslash.  (BH 12/24/85)
X   
X   HEAD means the first (nonblank) line of the paragraph containing THIS.
X   BODY means all other (nonblank) lines of the paragraph.
X   TAIL means the last (nb) line of the paragraph.  (TAIL is part of BODY.)
X   
X   HEAD INDENT means the indentation of HEAD.  M-J should preserve this.
X   BODY INDENT means the indentation of BODY.  Ditto.
X   
X   Subprocedures:
X   
X   TAILRULE(BODYLINE)
X   If BODYLINE is BLANK, the paragraph has only one line, and there is no
X   BODY and therefore no TAIL.  Return.  Otherwise, starting from BODYLINE,
X   move down until you find a line that either is BSBLANK or has a different
X   indentation from BODYLINE.  The line above that different line is TAIL.
X   Return.
X   
X   Rules:
X   
X   1.  If THIS is BLANK, which command are you doing?  If M-J or M-[, then go
X   up to the first non-BLANK line and start over.  (If there is no non-BLANK
X   line before THIS, ring the bell.)  If M-], then the first non-BLANK line
X   below THIS is HEAD, and the second consecutive non-BSBLANK line (if any) is
X   the beginning of BODY.  (If there is no non-BLANK line after THIS, ring
X   the bell.)  Do TAILRULE(beginning-of-BODY).  Go to rule A.
X
X   2.  If PREV is BLANK or THIS is BSBLANK, then THIS is HEAD, and NEXT (if
X   not BSBLANK) is in BODY.  Do TAILRULE(NEXT).  Go to rule A.
X
X   3.  If NEXT is BSBLANK, then THIS is TAIL, therefore part of BODY.  Go to
X   rule 5 to find HEAD.
X   
X   4.  If either NEXT or PREV has the same indentation as THIS, then THIS is
X   part of BODY.  Do TAILRULE(THIS).  Go to rule 5 to find HEAD.  Otherwise,
X   go to rule 6.
X   
X   5.  Go up until you find a line that is either BSBLANK or has a different
X   indentation from THIS.  If that line is BLANK, the line below it is HEAD.
X   If that line is non-BLANK, then call that new line THIS for what follows.
X   If (the new) PREV has the same indent as THIS, then (the new) NEXT is
X   HEAD.  If PREV has a different indent from THIS, then THIS is HEAD.  Go to
X   rule A.
X   
X   6.  If you got here, then both NEXT and PREV are nonblank and are
X   differently indented from THIS.  This is a tricky case and there is no
X   guarantee that you're going to win.  The most straightforward thing to do
X   is assume that we are not using hanging indentation.  In that case:
X   whichever of PREV and THIS is indented further is HEAD.  Do
X   TAILRULE(HEAD+1).  Go to rule A.
X   
X   6+.  A more complicated variant would be this: if THIS is indented further
X   than PREV, we are using regular indentation and rule 6 applies.  If PREV
X   is indented further than THIS, look at both NEXT and the line after NEXT.
X   If those two lines are indented equally, and more than THIS, then we are
X   using hanging indent, THIS is HEAD, and NEXT is the first line of BODY.
X   Do TAILRULE(NEXT).  Otherwise, rule 6 applies.
X   
X   A.  You now know where HEAD and TAIL are.  The indentation of HEAD is HEAD
X   INDENT; the indentation of TAIL is BODY INDENT.
X   
X   B.  If you are trying to M-J, you are now ready to do it.
X   
X   C.  If you are trying to M-], leave point after the newline that ends
X   TAIL.  In other words, leave the cursor at the beginning of the line
X   after TAIL.  It is not possible for this to leave point where it started
X   unless it was already at the end of the buffer.
X   
X   D.  If you are trying to M-[, if the line before HEAD is not BLANK, then
X   leave point just before HEAD.  That is, leave the cursor at the beginning
X   of HEAD.  If the line before HEAD is BLANK, then leave the cursor at the
X   beginning of that line.  If the cursor didn't move, go up to the first
X   earlier non-BLANK line and start over.
X
X
X   End of Algorithm.  I implemented rule 6+ because it seemed nicer.  */
X
Xint	RMargin = 78,
X	LMargin = 0;
XLine	*para_head,
X	*para_tail;
Xint	head_indent,
X	body_indent;
Xstatic int	use_lmargin;
X
X/* some defines for paragraph boundery checking */
X#define I_EMPTY		-1	/* line "looks" empty (spaces and tabs) */
X#define I_PERIOD	-2	/* line begins with "." or "\" */
X#define I_BUFEDGE	-3	/* line is nonexistent (edge of buffer) */
X
Xstatic int	bslash;		/* Nonzero if get_indent finds line starting
X				   with backslash */
X
Xi_bsblank(lp)
XLine	*lp;
X{
X	if (i_blank(lp))
X		return 1;
X	return bslash;
X}
X
Xi_blank(lp)
XLine	*lp;
X{
X	return (get_indent(lp) < 0);
X}
X
Xstatic 
Xget_indent(lp)
Xregister Line	*lp;
X{
X	Bufpos	save;
X	register int	indent;
X
X	bslash = 0;
X	if (lp == 0)
X		return I_BUFEDGE;
X	DOTsave(&save);
X	SetLine(lp);
X	if (blnkp(linebuf))
X		indent = I_EMPTY;
X 	else if (linebuf[0] == '.')
X		indent = I_PERIOD;
X	else if (linebuf[0] == '\\') {
X		/* BH 12/24/85.  Backslash is BLANK only if next line
X		   also starts with Backslash. */
X		bslash++;
X		SetLine(lp->l_next);
X		if (linebuf[0] == '\\')
X			indent = I_PERIOD;
X		else
X			indent = 0;
X	} else {
X		ToIndent();
X		indent = calc_pos(linebuf, curchar);
X	}
X	SetDot(&save);
X
X	return indent;
X}
X
Xstatic Line *
Xtailrule(lp)
Xregister Line	*lp;
X{
X	int	i;
X
X	i = get_indent(lp);
X	if (i < 0)
X		return lp;	/* one line paragraph */
X	do {
X		if ((get_indent(lp->l_next) != i) || bslash)
X			/* BH line with backslash is head of next para */
X			break;
X	} while ((lp = lp->l_next) != 0);
X	if (lp == 0)
X		complain((char *) 0);
X	return lp;
X}
X
X/* Finds the beginning, end and indent of the current paragraph, and sets
X   the above global variables.  HOW says how to behave when we're between
X   paragraphs.  That is, it's either FORWARD or BACKWARD depending on which
X   way we're favoring. */
X
Xfind_para(how)
X{
X	Line	*this,
X		*prev,
X		*next,
X		*head = 0,
X		*body = 0,
X		*tail = 0;
X	int	this_indent;
X	Bufpos	orig;		/* remember where we were when we started */
X
X	exp = 1;
X	DOTsave(&orig);
Xstrt:
X	this = curline;
X	prev = curline->l_prev;
X	next = curline->l_next;
X	this_indent = get_indent(this);
X
X	if (i_blank(this)) {		/* rule 1 */
X		if (how == BACKWARD) {
X			while (i_blank(curline))
X				if (firstp(curline))
X					complain((char *) 0);
X				else
X					line_move(BACKWARD, NO);
X			goto strt;
X		} else {
X			while (i_blank(curline))
X				if (lastp(curline))
X					complain((char *) 0);
X				else
X					line_move(FORWARD, NO);
X			head = curline;
X			next = curline->l_next;
X			if (!i_bsblank(next))
X				body = next;
X			else
X				body = head;
X		}
X	} else if (i_bsblank(this) || i_blank(prev)) {	/* rule 2 */
X		head = this;
X		if (!i_bsblank(next))
X			body = next;
X	} else if (i_bsblank(next)) {	/* rule 3 */
X		tail = this;
X		body = this;
X	} else if ((get_indent(next) == this_indent) ||	/* rule 4 */
X		   (get_indent(prev) == this_indent))
X		body = this;
X	else {		/* rule 6+ */
X		if (get_indent(prev) > this_indent) {
X			/* hanging indent maybe? */
X			if ((next != 0) &&
X			    (get_indent(next) == get_indent(next->l_next))) {
X				head = this;
X				body = next;
X			}
X		}
X		/* Now we handle hanging indent else and the other
X		   case of this_indent > get_indent(prev).  That is,
X		   if we didn't resolve HEAD in the above if, then
X		   we are not a hanging indent. */
X		if (head == 0) {	/* still don't know */
X			if (this_indent > get_indent(prev))
X				head = this;
X			else
X				head = prev;
X			body = head->l_next;
X		}
X	}
X	/* rule 5 -- find the missing parts */
X	if (head == 0) {    /* haven't found head of paragraph so do so now */
X		Line	*lp;
X		int	i;
X
X		lp = this;
X		do {
X			i = get_indent(lp->l_prev);
X			if (i < 0)	/* is blank */
X				head = lp;
X			else if (i != this_indent || bslash) {
X				Line	*this = lp->l_prev;
X
X				if (get_indent(this->l_prev) == i)
X					head = this->l_next;
X				else
X					head = this;
X			}
X		} while (head == 0 && (lp = lp->l_prev) != 0);
X		if (lp == 0)
X			complain((char *) 0);
X	}
X	if (body == 0)		/* this must be a one line paragraph */
X		body = head;
X	if (tail == 0)
X		tail = tailrule(body);
X	if (tail == 0 || head == 0 || body == 0)
X		complain("BUG! tail(%d),head(%d),body(%d)!", tail, head, body);
X	para_head = head;
X	para_tail = tail;
X	head_indent = get_indent(head);
X	body_indent = get_indent(body);
X
X	SetDot(&orig);
X}
X
XJustify()
X{
X	use_lmargin = (exp_p != NO);
X	find_para(BACKWARD);
X	DoJustify(para_head, 0, para_tail, length(para_tail), NO,
X		  use_lmargin ? LMargin : body_indent);
X}
X
XLine *
Xmax_line(l1, l2)
XLine	*l1,
X	*l2;
X{
X	if (inorder(l1, 0, l2, 0))
X		return l2;
X	return l1;
X}
X
XLine *
Xmin_line(l1, l2)
XLine	*l1,
X	*l2;
X{
X	if (inorder(l1, 0, l2, 0))
X		return l1;
X	return l2;
X}
X
XRegJustify()
X{
X	Mark	*mp = CurMark(),
X		*tailmark;
X	Line	*l1 = curline,
X		*l2 = mp->m_line;
X	int	c1 = curchar,
X		c2 = mp->m_char;
X	Line	*rl1,
X		*rl2;
X
X	use_lmargin = (exp_p != NO);
X	(void) fixorder(&l1, &c1, &l2, &c2);
X	do {
X		DotTo(l1, c1);
X		find_para(FORWARD);
X		rl1 = max_line(l1, para_head);
X		rl2 = min_line(l2, para_tail);
X		tailmark = MakeMark(para_tail, 0, FLOATER);
X		DoJustify(rl1, (rl1 == l1) ? c1 : 0, rl2,
X			  (rl2 == l2) ? c2 : length(rl2),
X			  NO, use_lmargin ? LMargin : body_indent);
X		l1 = tailmark->m_line->l_next;
X		DelMark(tailmark);
X		c1 = 0;
X	} while (l1 != 0 && l2 != rl2);
X}
X
Xdo_rfill()
X{
X	Mark	*mp = CurMark();
X	Line	*l1 = curline,
X		*l2 = mp->m_line;
X	int	c1 = curchar,
X		c2 = mp->m_char;
X
X	use_lmargin = (exp_p != NO);
X	(void) fixorder(&l1, &c1, &l2, &c2);
X	DoJustify(l1, c1, l2, c2, NO, use_lmargin ? LMargin : 0);
X}
X
Xdo_space()
X{
X	int	c1 = curchar,
X		c2 = c1,
X		diff,
X		nspace;
X	char	ch;
X
X	while (c1 > 0 && ((ch = linebuf[c1 - 1]) == ' ' || ch == '\t'))
X		c1--;
X	while ((ch = linebuf[c2]) == ' ' || ch == '\t')
X		c2++;
X	diff = (c2 - c1);
X	curchar = c2;
X
X	if (diff == 0)
X		return;
X	if (c1 > 0) {
X		int	topunct = c1 - 1;
X
X		nspace = 1;
X		if (diff >= 2) {
X			while (index("\")]", linebuf[topunct])) {
X				if (topunct == 0)
X					break;
X				topunct--;
X			}
X			if (index("?!.:", linebuf[topunct]))
X				nspace = 2;
X		}
X	} else
X		nspace = 0;
X
X	if (diff > nspace)
X		DoTimes(DelPChar(), (diff - nspace));
X	else if (diff < nspace)
X		DoTimes(Insert(' '), (nspace - diff));
X}
X
XDoJustify(l1, c1, l2, c2, scrunch, indent)
XLine	*l1,
X	*l2;
X{
X	int	okay_char = -1;
X	char	*cp;
X	Mark	*savedot = MakeMark(curline, curchar, FLOATER),
X		*endmark;
X
X	exp = 1;
X	(void) fixorder(&l1, &c1, &l2, &c2);	/* l1/c1 will be before l2/c2 */
X	DotTo(l1, c1);
X	if (get_indent(l1) >= c1) {
X		if (use_lmargin) {
X			n_indent(indent + (head_indent - body_indent));
X			use_lmargin = 0;	/* turn this off now */
X		}
X		ToIndent();
X	}
X	endmark = MakeMark(l2, c2, FLOATER);
X
X	for (;;) {
X		cp = StrIndex(1, linebuf, curchar, ' ');
X		if (cp == 0)
X			Eol();
X		else
X			curchar = (cp - linebuf);
X		if (curline == endmark->m_line && curchar >= endmark->m_char)
X			goto outahere;
X		if (eolp()) {
X			ins_str("  ", NO);
X			DelNChar();	/* delete line separator */
X			curchar -= 2;	/* back over the spaces */
X		}
X		/* at this point we are ALWAYS sitting right after
X		   a word - that is, just before some spaces or the
X		   end of the line */
X		if (calc_pos(linebuf, curchar) <= RMargin) {
X			okay_char = curchar;
X			do_space();
X			continue;
X		}
X
X		/* if we get here, we have done all we can for
X		   this line - now we split the line, or just move
X		   to the next one */
X		if (okay_char > 0)
X			curchar = okay_char;			
X		if (curline == endmark->m_line && curchar >= endmark->m_char)
X			goto outahere;
X		/* can't fit in small margin, so we do the best we can */
X		if (eolp()) {
X			line_move(FORWARD, NO);
X			n_indent(indent);
X		} else {
X			/* insert a line break - line WAS too long */
X			DelWtSpace();
X			LineInsert(1);
X			if (scrunch && TwoBlank()) {
X				Eol();
X				DelNChar();
X			}
X			n_indent(indent);
X		}
X	}
Xoutahere:
X	ToMark(savedot);	/* Back to where we were */
X	DelMark(endmark);	/* Free up marks */
X	DelMark(savedot);
X	this_cmd = last_cmd = 0; /* So everything is under control */
X	f_mess("");
X}
X
Xextern Line	*para_head,
X		*para_tail;
X
XDoPara(dir)
X{
X	register int	num = exp,
X			first_time = TRUE;	
X
X	while (--num >= 0) {
Xtryagain:	find_para(dir);		/* find paragraph bounderies */
X		if ((dir == BACKWARD) &&
X		    ((!first_time) || ((para_head == curline) && bolp()))) {
X		    	if (bobp())
X		    		complain((char *) 0);
X			BackChar();
X			first_time = !first_time;
X			goto tryagain;
X		}
X		SetLine((dir == BACKWARD) ? para_head : para_tail);
X		if (dir == BACKWARD && !firstp(curline) &&
X		    i_blank(curline->l_prev))
X			line_move(BACKWARD, NO);
X		else if (dir == FORWARD) {
X			if (lastp(curline)) {
X				Eol();
X				break;
X			}
X			/* otherwise */
X			line_move(FORWARD, NO);
X		}
X	}
X}
X
XBackPara()
X{
X	DoPara(BACKWARD);
X}
X
XForPara()
X{
X	DoPara(FORWARD);
X}
@//E*O*F paragraph.c//
if test 13888 -ne "`wc -c <'paragraph.c'`"; then
    echo shar: error transmitting "'paragraph.c'" '(should have been 13888 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'portsrv.c'" '(3209 characters)'
if test -f 'portsrv.c' ; then 
  echo shar: will not over-write existing file "'portsrv.c'"
else
sed 's/^X//' >portsrv.c <<'@//E*O*F portsrv.c//'
X/************************************************************************
X * This program is Copyright (C) 1986 by Jonathan Payne.  JOVE is       *
X * 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/* This is a server for jove sub processes.  It runs the command and
X   signals jove when there is some output ready to send to jove. By the
X   time we get here, out standard output goes to jove's process input. */
X
X#include "tune.h"
X
X#ifdef PIPEPROCS	/* the whole file! */
X
X#include "jove.h"
X
X#include <signal.h>
X#include <sys/ioctl.h>
X#ifdef BSD4_2
X#   include <sys/wait.h>
X#else
X#   include <wait.h>
X#endif
X
Xstruct header {
X	int	pid;
X	int	nbytes;
X	char	buf[512];
X} header;
X
X#define HEADSIZE	((sizeof header.pid) + sizeof (header.nbytes))
X
Xerror(str)
Xchar	*str;
X{
X	header.pid = getpid();
X	header.nbytes = strlen(str);
X	strcpy(header.buf, str);
X	proc_write(&header, header.nbytes + 8);
X	exit(-2);
X}
X
Xint	ppid,
X	InputFD,
X	JovesInput;
X
Xp_inform()
X{
X	long	nbytes;
X
X	ioctl(JovesInput, FIONREAD, (char *) &nbytes);
X	if (nbytes > 0)
X		kill(ppid, INPUT_SIG);
X}
X
Xproc_write(ptr, n)
Xchar	*ptr;
X{
X	long	nbytes;
X
X	ioctl(1, FIONREAD, (char *) &nbytes);
X	
X	if (nbytes == 0)
X		kill(ppid, INPUT_SIG);
X
X	(void) write(1, ptr, n);
X	alarm(1);
X}
X
Xread_pipe()
X{
X	register int	n;
X	
X	(void) signal(SIGALRM, p_inform);
X
X	while ((header.nbytes = read(InputFD, header.buf, sizeof header.buf)) > 0) {
X		n = HEADSIZE + header.nbytes;
X		proc_write(&header, n);
X	}
X}
X
X/* ARGSUSED */
Xmain(argc, argv)
Xchar	*argv[];
X{
X	int	p[2];
X	int	pid;
X
X	if (pipe(p) == -1)
X		error("Cannot pipe jove portsrv.\n");
X
X	ppid = getppid();
X	switch (pid = fork()) {
X	case -1:
X		error("portsrv: cannot fork.\n");
X
X	case 0:
X		/* We'll intercept childs output in p[0] */
X		(void) dup2(p[1], 1);
X		(void) dup2(p[1], 2);
X		(void) close(p[0]);
X		(void) close(p[1]);
X			
X		(void) setpgrp(getpid(), getpid());
X		execv(argv[2], &argv[3]);
X		_exit(-4);
X
X	default:
X		(void) close(0);
X				/* Don't want this guy to read anything
X				   jove sends to our soon to be created
X				   child */
X
X		JovesInput = atoi(argv[1]);
X		(void) signal(SIGINT, SIG_IGN);
X		(void) signal(SIGQUIT, SIG_IGN);
X		(void) close(p[1]);
X
X		/* Tell jove the pid of the real child as opposed to us. */
X		header.pid = getpid();
X		header.nbytes = sizeof (int);
X		*(int *) header.buf = pid;
X		(void) write(1, (char *) &header, sizeof pid + HEADSIZE);
X		p_inform();	/* Inform jove */
X
X		/* Read proc's output and send it to jove */
X		InputFD = p[0];
X		read_pipe();
X		(void) close(p[0]);
X		header.pid = getpid();
X		header.nbytes = EOF;	/* Tell jove we are finished */
X		(void) write(1, (char *) &header, HEADSIZE);
X		p_inform();
X		/* Try to exit like our child did ... */
X		{
X			union wait	w;
X
X#ifndef VMUNIX
X			while (wait2(&w.w_status, 0) != pid)
X#else
X			while (wait3(&w.w_status, 0, 0) != pid)
X#endif
X				;
X			if (WIFEXITED(w))
X				exit(w.w_retcode);
X			else if (WIFSIGNALED(w))
X				kill(getpid(), w.w_termsig);
X		}
X	}
X}
X
X#else PIPEPROCS
Xmain()
X{
X}
X#endif
@//E*O*F portsrv.c//
if test 3209 -ne "`wc -c <'portsrv.c'`"; then
    echo shar: error transmitting "'portsrv.c'" '(should have been 3209 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'proc.c'" '(14390 characters)'
if test -f 'proc.c' ; then 
  echo shar: will not over-write existing file "'proc.c'"
else
sed 's/^X//' >proc.c <<'@//E*O*F proc.c//'
X/************************************************************************
X * This program is Copyright (C) 1986 by Jonathan Payne.  JOVE is       *
X * 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 "termcap.h"
X
X#include <signal.h>
X#include <varargs.h>
X
X/* This disgusting RE search string parses output from the GREP
X   family, from the pdp11 compiler, pcc, and lint.  Jay (HACK)
X   Fenlasen changed this to work for the lint errors. */
Xprivate char
X	*errfmt = "^\\{\",\\}\\([^:\"( \t]*\\)\\{\"\\, line ,:,(\\} *\\([0-9][0-9]*\\)[:)]\
X\\|::  *\\([^(]*\\)(\\([0-9]*\\))$\
X\\|( \\([^(]*\\)(\\([0-9]*\\)) ),";
X
Xstruct error {
X	Buffer		*er_buf;	/* Buffer error is in */
X	Line		*er_mess,	/* Actual error message */
X			*er_text;	/* Actual error */
X	int		er_char;	/* char pos of error */
X	struct error	*er_prev,	/* List of errors */
X			*er_next;
X};
X
Xstruct error	*cur_error = 0,
X		*errorlist = 0;
XBuffer		*perr_buf = 0;	/* Buffer with error messages */
X
Xint	WtOnMk = 1;		/* Write the modified files when we make */
X
X/* Add an error to the end of the list of errors.  This is used for
X   parse-{C,LINT}-errors and for the spell-buffer command */
X
Xprivate struct error *
XAddError(laste, errline, buf, line, charpos)
Xstruct error	*laste;
XLine	*errline,
X	*line;
XBuffer	*buf;
X{
X	struct error	*new = (struct error *) emalloc(sizeof *new);
X
X	new->er_prev = laste;
X	if (laste)
X		laste->er_next = new;
X	else {
X		if (errorlist)		/* Free up old errors */
X			ErrFree();
X		cur_error = errorlist = new;
X	}
X	laste = new;
X	new->er_next = 0;
X	new->er_buf = buf;
X	new->er_text = line;
X	new->er_char = charpos;
X	new->er_mess = errline;
X
X	return new;
X}
X
XParseAll()
X{
X	ErrParse(errfmt);
X}
X
XXParse()
X{
X	char	*sstr;
X
X	sstr = ask(errfmt, ProcFmt);
X	ErrParse(sstr);
X}
X
X/* Parse for {C,LINT} errors (or anything that matches fmtstr) in the
X   current buffer.  Set up for the next-error command.  This is neat
X   because this will work for any kind of output that prints a file
X   name and a line number on the same line. */
X
XErrParse(fmtstr)
Xchar	*fmtstr;
X{
X	Bufpos	*bp;
X	char	fname[FILESIZE],
X		lineno[10],
X		REbuf[256],
X		*REalts[10];
X	int	lnum,
X		last_lnum = -1;
X	struct error	*ep = 0;
X	Buffer	*buf,
X		*lastb = 0;
X	Line	*err_line;	
X
X	ErrFree();		/* This is important! */
X	ToFirst();
X	perr_buf = curbuf;
X	REcompile(fmtstr, 1, REbuf, REalts);
X	/* Find a line with a number on it. */
X	while (bp = docompiled(FORWARD, REbuf, REalts)) {
X		SetDot(bp);
X		putmatch(1, fname, sizeof fname);
X		putmatch(2, lineno, sizeof lineno);
X		buf = do_find((Window *) 0, fname, 1);
X		if (buf != lastb) {
X			lastb = buf;
X			last_lnum = -1;		/* signals new file */
X			err_line = buf->b_first;
X		}
X		lnum = chr_to_int(lineno, 10, 0);
X		if (lnum == last_lnum)	/* one error per line is nicer */
X			continue;
X		if (last_lnum == -1)
X			last_lnum = 1;	/* that's where we really are */
X		err_line = next_line(err_line, lnum - last_lnum);
X		ep = AddError(ep, curline, buf, err_line, 0);
X		last_lnum = lnum;
X	}
X	if (cur_error != 0)
X		ShowErr();
X	exp = 1;
X}
X
X/* Free up all the errors */
X
XErrFree()
X{
X	register struct error	*ep;
X
X	for (ep = errorlist; ep != 0; ep = ep->er_next)
X		free((char *) ep);
X	errorlist = cur_error = 0;
X}
X
X/* Internal next error sets cur_error to the next error, taking the
X   argument count, supplied by the user, into consideration. */
X
Xprivate char	errbounds[] = "You're at the %s error.",
X		noerrs[] = "No errors!";
X
Xprivate
Xtoerror(forward)
X{
X	register int	i;
X	register struct error	*e = cur_error;
X
X	if (e == 0)
X		complain(noerrs);
X	if ((forward && (e->er_next == 0)) ||
X	    (!forward && (e->er_prev == 0)))
X		complain(errbounds, forward ? "last" : "first");
X
X	for (i = 0; i < exp; i++) {
X		if ((e = forward ? e->er_next : e->er_prev) == 0)
X			break;
X		cur_error = e;
X	}
X}
X
XNextError()
X{
X	ToError(1);
X}
X
XPrevError()
X{
X	ToError(0);
X}
X
Xprivate
Xokay_error()
X{
X	return ((inlist(perr_buf->b_first, cur_error->er_mess)) &&
X		(inlist(cur_error->er_buf->b_first, cur_error->er_text)));
X}
X
X/* Go the the next error, if there is one.  Put the error buffer in
X   one window and the buffer with the error in another window.
X   It checks to make sure that the error actually exists. */
X
XToError(forward)
X{
X	do {
X		toerror(forward);
X		exp = 1;
X	} while (!okay_error());
X	ShowErr();
X}
X
Xint	EWSize = 20;	/* percentage of screen the error window
X			   should be */
X
Xset_wsize(wsize)
Xint	wsize;
X{
X	wsize = (LI * wsize) / 100;
X	if (wsize >= 1 && !one_windp())
X		WindSize(curwind, wsize - (curwind->w_height - 1));
X}
X
X/* Show the current error, i.e. put the line containing the error message
X   in one window, and the buffer containing the actual error in another
X   window. */
X
XShowErr()
X{
X	Window	*err_wind,
X		*buf_wind;
X
X	if (cur_error == 0)
X		complain(noerrs);
X	if (!okay_error()) {
X		rbell();
X		return;
X	}
X	err_wind = windbp(perr_buf);
X	buf_wind = windbp(cur_error->er_buf);
X
X	if (err_wind && !buf_wind) {
X		SetWind(err_wind);
X		pop_wind(cur_error->er_buf->b_name, NO, -1);
X		buf_wind = curwind;
X	} else if (!err_wind && buf_wind) {
X		SetWind(buf_wind);
X		pop_wind(perr_buf->b_name, NO, -1);
X		err_wind = curwind;
X	} else if (!err_wind && !buf_wind) {
X		pop_wind(perr_buf->b_name, NO, -1);
X		err_wind = curwind;
X		pop_wind(cur_error->er_buf->b_name, NO, -1);
X		buf_wind = curwind;
X	}
X
X	/* Put the current error message at the top of its Window */
X	SetWind(err_wind);
X	SetLine(cur_error->er_mess);
X	SetTop(curwind, (curwind->w_line = cur_error->er_mess));
X	set_wsize(EWSize);
X
X	/* now go to the the line with the error in the other window */
X	SetWind(buf_wind);
X	DotTo(cur_error->er_text, cur_error->er_char);
X}
X
Xchar	ShcomBuf[128] = {0};
X
X/* Make a buffer name given the command `command', i.e. "fgrep -n foo *.c"
X   will return the buffer name "fgrep".  */
X
Xchar *
XMakeName(command)
Xchar	*command;
X{
X	static char	bufname[50];
X	register char	*cp = bufname,
X			c;
X
X	while ((c = *command++) && (c == ' ' || c == '\t'))
X		;
X	do
X		*cp++ = c;
X	while ((c = *command++) && (c != ' ' && c != '\t'));
X	*cp = 0;
X	strcpy(bufname, basename(bufname));
X
X	return bufname;
X}
X
X/* Run make, first writing all the modified buffers (if the WtOnMk flag is
X   non-zero), parse the errors, and go the first error. */
X
Xchar	make_cmd[128] = "make";
X
XMakeErrors()
X{
X	Window	*old = curwind;
X	int	status,
X		compilation;
X	
X	if (WtOnMk)
X		put_bufs(0);
X	/* When we're not doing make or cc (i.e., the last command
X	   was probably a grep or something) and the user just types
X	   C-X C-E, he probably (possibly, hopefully, usually (in my
X	   case)) doesn't want to do the grep again but rather wants
X	   to do a make again; so we ring the bell and insert the
X	   default command and let the person decide. */
X
X	compilation = (sindex("make", make_cmd) || sindex("cc", make_cmd));
X	if (exp_p || !compilation) {
X		if (!compilation) {
X			rbell();
X			Inputp = make_cmd;	/* insert the default for the
X						   user */
X		}
X		null_ncpy(make_cmd, ask(make_cmd, "Compilation command: "),
X				sizeof (make_cmd) - 1);
X	}
X	status = UnixToBuf(MakeName(make_cmd), YES, EWSize, YES, Shell, ShFlags, make_cmd, (char *) 0);
X	com_finish(status, make_cmd);
X
X	ErrParse(errfmt);
X
X	if (!cur_error)
X		SetWind(old);
X}
X
X#ifdef SPELL
X
XSpelBuffer()
X{
X	char	*Spell = "Spell",
X		com[100];
X	Window	*savewp = curwind;
X
X	put_bufs(0);
X	sprintf(com, "spell %s", curbuf->b_fname);
X	(void) UnixToBuf(Spell, YES, EWSize, YES, Shell, ShFlags, com, (char *) 0);
X	message("[Delete the irrelevant words and then type C-X C-C]");
X	Recur();
X	SetWind(savewp);
X	SpelParse(Spell);
X}
X
XSpelWords()
X{
X	char	*buftospel;
X	Buffer	*wordsb = curbuf;
X
X	if ((buftospel = ask_buf((Buffer *) 0)) == 0)
X		return;
X	SetBuf(do_select(curwind, buftospel));
X	SpelParse(wordsb->b_name);
X}
X
XSpelParse(bname)
Xchar	*bname;
X{
X	Buffer	*buftospel,
X		*wordsb;
X	char	wordspel[100];
X	Bufpos	*bp;
X	struct error	*ep = 0;
X
X	ErrFree();		/* This is important! */
X
X	buftospel = curbuf;
X	wordsb = buf_exists(bname);
X	perr_buf = wordsb;	/* This is important (buffer containing
X				   error messages) */
X	SetBuf(wordsb);
X	ToFirst();
X	f_mess("Finding misspelled words ... ");
X	while (!lastp(curline)) {
X		sprintf(wordspel, "\\<%s\\>", linebuf);
X		SetBuf(buftospel);
X		ToFirst();
X		while (bp = dosearch(wordspel, 1, 1)) {
X			SetDot(bp);
X			ep = AddError(ep, wordsb->b_dot, buftospel,
X					  curline, curchar);
X		}
X		SetBuf(wordsb);
X		line_move(FORWARD, NO);
X	}
X	add_mess("Done.");
X	SetBuf(buftospel);
X	ShowErr();
X}
X
X#endif SPELL
X
XShToBuf()
X{
X	char	bufname[100];
X
X	strcpy(bufname, ask((char *) 0, "Buffer: "));
X	DoShell(bufname, ask(ShcomBuf, "Command: "));
X}
X
XShellCom()
X{
X	null_ncpy(ShcomBuf, ask(ShcomBuf, ProcFmt), (sizeof ShcomBuf) - 1);
X	DoShell(MakeName(ShcomBuf), ShcomBuf);
X}
X
X/* Run the shell command into `bufname'.  Empty the buffer except when we
X   give a numeric argument, in which case it inserts the output at the
X   current position in the buffer.  */
X
Xprivate
XDoShell(bufname, command)
Xchar	*bufname,
X	*command;
X{
X	Window	*savewp = curwind;
X	int	status;
X
X	exp = 1;
X	status = UnixToBuf(bufname, YES, 0, !exp_p, Shell,
X			   ShFlags, command, (char *) 0);
X	com_finish(status, command);
X	SetWind(savewp);
X}
X
Xprivate
Xcom_finish(status, cmd)
Xregister int	status;
Xchar	*cmd;
X{
X	s_mess("[%s: ", cmd);
X	if (status == 0)
X		add_mess("completed successfully");
X	else
X		add_mess("exited (%d)", status);
X	add_mess("]");
X}
X
Xdowait(pid, status)
Xint	pid,
X	*status;
X{
X#ifndef IPROCS
X
X	int	rpid;
X
X	while ((rpid = wait(status)) != pid)
X		;
X#else
X
X#ifdef BSD4_2
X#   include <sys/wait.h>
X#else
X#   include <wait.h>
X#endif
X
X	union wait	w;
X	int	rpid;
X
X	for (;;) {
X#ifndef VMUNIX
X		rpid = wait2(&w.w_status, 0);
X#else
X		rpid = wait3(&w, 0, (struct rusage *) 0);
X#endif
X		if (rpid == pid) {
X			if (status)
X				*status = w.w_status;
X			break;
X		} else
X			kill_off(rpid, w);
X	}
X#endif IPROCS
X}
X
X/* Run the command to bufname, erase the buffer if clobber is non-zero,
X   and redisplay if disp is non-zero.  Leaves current buffer in `bufname'
X   and leaves any windows it creates lying around.  It's up to the caller
X   to fix everything up after we're done.  (Usually there's nothing to
X   fix up.) */
X
X/* VARARGS5 */
X
XUnixToBuf(bufname, disp, wsize, clobber, va_alist)
Xchar	*bufname;
Xva_dcl
X{
X	int	p[2],
X		pid,
X		eof,
X		status;
X	va_list	ap;
X	char	*argv[32],
X		*mess;
X	File	*fp;
X	int	(*old_int)();
X
X	va_start(ap);
X	make_argv(argv, ap);
X	va_end(ap);
X	if (clobber)
X		isprocbuf(bufname);
X	if (disp) {
X		message("Starting up...");
X		pop_wind(bufname, clobber, clobber ? B_PROCESS : B_FILE);
X		set_wsize(wsize);
X		redisplay();
X	}
X	/* Now I will attempt to describe how I deal with signals during
X	   the execution of the shell command.  My desire was to be able
X	   to interrupt the shell command AS SOON AS the window pops up.
X	   So, if we have JOB_CONTROL (i.e., the new signal mechanism) I
X	   hold SIGINT, meaning if we interrupt now, we will eventually
X	   see the interrupt, but not before we are ready for it.  We
X	   fork, the child releases the interrupt, it then sees the
X	   interrupt, and so exits.  Meanwhile the parent ignores the
X	   signal, so if there was a pending one, it's now lost.
X
X	   With no JOB_CONTROL, the best behavior you can expect is, when
X	   you type ^] too very quickly after the window pops up, it may
X	   be ignored.  The behavior BEFORE was that it would interrupt
X	   JOVE and then you would have to continue JOVE and wait a
X	   little while longer before trying again.  Now that is fixed,
X	   in that you just have to type it twice. */
X
X#ifdef IPROCS
X	sighold(SIGCHLD);
X#endif
X#ifdef JOB_CONTROL
X	sighold(SIGINT);
X#else
X	old_int = signal(SIGINT, SIG_IGN),
X#endif
X	exp = 1;
X	dopipe(p);
X	pid = fork();
X	if (pid == -1) {
X		pclose(p);
X		complain("[Fork failed]");
X	}
X	if (pid == 0) {
X#ifdef IPROCS
X		sigrelse(SIGCHLD);   /* don't know if this matters */
X#endif IPROCS
X		(void) signal(SIGINT, SIG_DFL);
X#ifdef JOB_CONTROL
X		sigrelse(SIGINT);
X#endif
X		(void) close(0);
X		(void) open("/dev/null", 0);
X		(void) close(1);
X		(void) close(2);
X		(void) dup(p[1]);
X		(void) dup(p[1]);
X		pclose(p);
X		execv(argv[0], &argv[1]);
X		(void) write(1, "Execl failed.\n", 14);
X		_exit(1);
X	}
X#ifdef JOB_CONTROL
X	old_int = signal(SIGINT, SIG_IGN);
X#endif	
X	(void) close(p[1]);
X	fp = fd_open(argv[1], F_READ, p[0], iobuff, LBSIZE);
X	do {
X		inIOread = 1;
X 		eof = f_gets(fp, genbuf, LBSIZE);
X		inIOread = 0;
X		ins_str(genbuf, YES);
X		if (!eof)
X			LineInsert(1);
X		if (disp != 0 && fp->f_cnt <= 0) {
X#ifdef LOAD_AV
X		    {
X		    	double	theavg;
X
X			get_la(&theavg);
X			if (theavg < 2.0)
X				mess = "Screaming along...";
X			else if (theavg < 5.0)
X				mess = "Chugging along...";
X			else
X				mess = "Crawling along...";
X		    }
X#else
X			mess = "Chugging along...";
X#endif LOAD_AV
X			message(mess);
X			redisplay();
X		}
X	} while (!eof);
X	if (disp)
X		DrawMesg(NO);
X	close_file(fp);
X	dowait(pid, &status);
X#ifdef JOB_CONTROL
X	(void) sigrelse(SIGINT);
X#endif
X	(void) signal(SIGINT, old_int);
X#ifdef IPROCS
X	sigrelse(SIGCHLD);
X#endif
X	return status;
X}
X
X#ifdef BSD4_2
X
Xprivate int	SigMask = 0;
X
Xsighold(sig)
X{
X	(void) sigblock(SigMask |= (1 << (sig - 1)));
X}
X
Xsigrelse(sig)
X{
X	(void) sigsetmask(SigMask &= ~(1 << (sig - 1)));
X}
X
X#endif
X
XFilterRegion()
X{
X	char	*cmd = ask((char *) 0, ": %f (through command) ", ProcFmt);
X
X	RegToUnix(curbuf, cmd);
X}
X
X/* Send the current region to CMD and insert the output from the
X   command into OUT_BUF. */
X
XRegToUnix(outbuf, cmd)
XBuffer	*outbuf;
Xchar	*cmd;
X{
X	Mark	*m = CurMark();
X	char	*tname = mktemp("/tmp/jfilterXXXXXX"),
X		combuf[130];
X	Window	*save_wind = curwind;
X	int	status;
X	File	*fp;
X
X    CATCH
X	fp = open_file(tname, iobuff, F_WRITE, COMPLAIN, QUIET);
X	putreg(fp, m->m_line, m->m_char, curline, curchar, YES);
X	DelReg();
X	sprintf(combuf, "%s < %s", cmd, tname);
X	status = UnixToBuf(outbuf->b_name, NO, 0, outbuf->b_type == B_SCRATCH,
X			   Shell, ShFlags, combuf, (char *) 0);
X    ONERROR
X	;	/* Do nothing ... but fall through and delete the tmp
X		   file. */
X    ENDCATCH
X	f_close(fp);
X	(void) unlink(tname);
X	SetWind(save_wind);
X	com_finish(status, combuf);
X}
X
Xisprocbuf(bufname)
Xchar	*bufname;
X{
X	Buffer	*bp;
X
X	if ((bp = buf_exists(bufname)) != 0 && bp->b_type != B_PROCESS)
X		confirm("Over-write buffer %s?", bufname);
X}
@//E*O*F proc.c//
if test 14390 -ne "`wc -c <'proc.c'`"; then
    echo shar: error transmitting "'proc.c'" '(should have been 14390 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'re1.c'" '(9617 characters)'
if test -f 're1.c' ; then 
  echo shar: will not over-write existing file "'re1.c'"
else
sed 's/^X//' >re1.c <<'@//E*O*F re1.c//'
X/************************************************************************
X * This program is Copyright (C) 1986 by Jonathan Payne.  JOVE is       *
X * 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 "re.h"
X
Xstatic
Xsubstitute(query, l1, char1, l2, char2)
XLine	*l1,
X	*l2;
X{
X	Line	*lp;
X	int	numdone = 0,
X		offset = curchar,
X		stop = 0;
X	disk_line	UNDO_da = 0;
X	Line		*UNDO_lp = 0;
X
X	lsave();
X	REdirection = FORWARD;
X
X	lp = l1;
X	for (lp = l1; (lp != l2->l_next) && !stop; lp = lp->l_next) {
X		offset = (lp == l1) ? char1 : 0;
X		while (!stop && re_lindex(lp, offset, compbuf, alternates, 0)) {
X			if (lp == l2 && REeom > char2)	/* nope, leave this alone */
X				break;
X			DotTo(lp, REeom);
X			offset = curchar;
X			if (query) {
X				message("Replace (Type '?' for help)? ");
Xreswitch:			redisplay();
X				switch (Upper(getchar())) {
X				case '.':
X					stop++;
X					/* Fall into ... */
X
X				case ' ':
X				case 'Y':
X					break;
X
X				case BS:
X				case RUBOUT:
X				case 'N':
X					if (linebuf[offset++] == '\0')
X						goto nxtline;
X					continue;
X
X				case CTL(W):
X					re_dosub(linebuf, YES);
X					numdone++;
X					offset = curchar = REbom;
X					makedirty(curline);
X					/* Fall into ... */
X
X				case CTL(R):
X				case 'R':
X					RErecur();
X					offset = curchar;
X					lp = curline;
X					continue;
X
X				case CTL(U):
X				case 'U':
X					if (UNDO_lp == 0)
X						continue;
X					lp = UNDO_lp;
X					lp->l_dline = UNDO_da | DIRTY;
X					offset = 0;
X					numdone--;
X					continue;
X
X				case 'P':
X				case '!':
X					query = 0;
X					break;
X
X				case CR:
X				case LF:
X				case 'Q':
X					goto done;
X
X				case CTL(L):
X					RedrawDisplay();
X					goto reswitch;
X
X				default:
X					rbell();
Xmessage("Space or Y, Period, Rubout or N, C-R or R, C-W, C-U or U, P or !, Return.");
X					goto reswitch;
X				}
X			}
X			re_dosub(linebuf, NO);
X			numdone++;
X			modify();
X			offset = curchar = REeom;
X			makedirty(curline);
X			if (query) {
X				message(mesgbuf);	/* No blinking. */
X				redisplay();		/* Show the change. */
X			}
X			UNDO_da = curline->l_dline;
X			UNDO_lp = curline;
X			if (linebuf[offset] == 0)
Xnxtline:			break;
X		}
X	}
X	SetMark();
Xdone:	s_mess("%d substitution%n.", numdone, numdone);
X}
X
X/* Prompt for search and replacement strings and do the substitution.  The
X   point is restored when we're done. */
X
Xstatic
Xreplace(query, inreg)
X{
X	Mark	*save = MakeMark(curline, curchar, FLOATER),
X		*m;
X	char	*rep_ptr;
X	Line	*l1 = curline,
X		*l2 = curbuf->b_last;
X	int	char1 = curchar,
X		char2 = length(curbuf->b_last);
X
X	if (inreg) {
X		m = CurMark();
X		l2 = m->m_line;
X		char2 = m->m_char;
X		(void) fixorder(&l1, &char1, &l2, &char2);
X	}
X
X	/* Get search string. */
X	strcpy(rep_search, ask(rep_search[0] ? rep_search : (char *) 0, ProcFmt));
X	REcompile(rep_search, UseRE, compbuf, alternates);
X	/* Now the replacement string.  Do_ask() so the user can play with
X	   the default (previous) replacement string by typing C-R in ask(),
X	   OR, he can just hit Return to replace with nothing. */
X	rep_ptr = do_ask("\r\n", (int (*)()) 0, rep_str, ": %f %s with ", rep_search);
X	if (rep_ptr == 0)
X		rep_ptr = NullStr;
X	strcpy(rep_str, rep_ptr);
X
X	substitute(query, l1, char1, l2, char2);
X	ToMark(save);
X	DelMark(save);
X}
X
XRegReplace()
X{
X	replace(0, YES);
X}
X
XQRepSearch()
X{
X	replace(1, NO);
X}
X
XRepSearch()
X{
X	replace(0, NO);
X}
X
X/* C tags package. */
X
Xstatic
Xlookup(searchbuf, filebuf, tag, file)
Xchar	*searchbuf,
X	*filebuf,
X	*tag,
X	*file;
X{
X	register int	taglen = strlen(tag);
X	char	line[128],
X		pattern[100];
X	File	*fp;
X
X	fp = open_file(file, iobuff, F_READ, !COMPLAIN, QUIET);
X	if (fp == NIL)
X		return 0;
X	sprintf(pattern, "^%s[^\t]*\t\\([^\t]*\\)\t[?/]\\(.*\\)[?/]$", tag);
X	while (f_gets(fp, line, sizeof line) != EOF) {
X		if (line[0] != *tag || strncmp(tag, line, taglen) != 0)
X			continue;
X		if (!LookingAt(pattern, line, 0)) {
X			complain("I thought I saw it!");
X			break;
X		} else {
X			putmatch(2, searchbuf, 100);
X			putmatch(1, filebuf, 100);
X			close_file(fp);
X			return 1;
X		}
X	}
X	f_close(fp);
X	s_mess("Can't find tag \"%s\".", tag);
X	return 0;
X}
X
Xchar	TagFile[128] = "./tags";
X
Xfind_tag(tag, localp)
Xchar	*tag;
X{
X	char	filebuf[FILESIZE],
X		sstr[100],
X		tfbuf[FILESIZE];
X	register Bufpos	*bp;
X	register Buffer	*b;
X	char	*tagfname;
X
X	if (!localp) {
X		char	prompt[128];
X
X		sprintf(prompt, "With tag file (%s default): ", TagFile);
X		tagfname = ask_file(prompt, TagFile, tfbuf);
X	} else
X		tagfname = TagFile;
X	if (lookup(sstr, filebuf, tag, tagfname) == 0)
X		return;
X	SetMark();
X	b = do_find(curwind, filebuf, 0);
X	if (curbuf != b)
X		SetABuf(curbuf);
X	SetBuf(b);
X	if ((bp = dosearch(sstr, BACKWARD, 0)) == 0 &&
X	    (WrapScan || ((bp = dosearch(sstr, FORWARD, 0)) == 0)))
X		message("Well, I found the file, but the tag is missing.");
X	else
X		SetDot(bp);
X}
X
XFindTag()
X{
X	int	localp = !exp_p;
X	char	tag[128];
X
X	strcpy(tag, ask((char *) 0, ProcFmt));
X	find_tag(tag, localp);
X}
X
X/* Find Tag at Dot. */
X
XFDotTag()
X{
X	int	c1 = curchar,
X		c2 = c1;
X	char	tagname[50];
X
X	if (!ismword(linebuf[curchar]))
X		complain("Not a tag!");
X	while (c1 > 0 && ismword(linebuf[c1 - 1]))
X		c1--;
X	while (ismword(linebuf[c2]))
X		c2++;
X
X	null_ncpy(tagname, linebuf + c1, c2 - c1);
X	find_tag(tagname, !exp_p);
X}
X
X/* I-search returns a code saying what to do:
X   STOP:	We found the match, so unwind the stack and leave
X		where it is.
X   DELETE:	Rubout the last command.
X   BACKUP:	Back up to where the isearch was last NOT failing.
X
X   When a character is typed it is appended to the search string, and
X   then, isearch is called recursively.  When C-S or C-R is typed, isearch
X   is again called recursively. */
X
X#define STOP	1
X#define DELETE	2
X#define BACKUP	3
X#define TOSTART	4
X
Xstatic char	ISbuf[128],
X		*incp = 0;
Xint	SExitChar = CR;
X
X#define cmp_char(a, b)	((a) == (b) || (CaseIgnore && (Upper(a) == Upper(b))))
X
Xstatic Bufpos *
Xdoisearch(dir, c, failing)
Xregister int	c,
X		dir,
X		failing;
X{
X	static Bufpos	buf;
X	Bufpos	*bp;
X	extern int	okay_wrap;
X
X	if (c == CTL(S) || c == CTL(R))
X		goto dosrch;
X
X	if (failing)
X		return 0;
X	DOTsave(&buf);
X	if (dir == FORWARD) {
X		if (cmp_char(linebuf[curchar], c)) {
X			buf.p_char = curchar + 1;
X			return &buf;
X		}
X	} else {
X		if (look_at(ISbuf))
X			return &buf;
X	}
Xdosrch:	okay_wrap = YES;
X	if ((bp = dosearch(ISbuf, dir, 0)) == 0)
X		rbell();	/* ring the first time there's no match */
X	okay_wrap = NO;
X	return bp;
X}
X
XIncFSearch()
X{
X	IncSearch(FORWARD);
X}
X
XIncRSearch()
X{
X	IncSearch(BACKWARD);
X}
X
Xstatic
XIncSearch(dir)
X{
X	Bufpos	save_env;
X
X	DOTsave(&save_env);
X	ISbuf[0] = 0;
X	incp = ISbuf;
X	if (isearch(dir, &save_env) == TOSTART)
X		SetDot(&save_env);
X	else {
X		if (LineDist(curline, save_env.p_line) >= MarkThresh)
X			DoSetMark(save_env.p_line, save_env.p_char);
X	}
X	setsearch(ISbuf);
X}
X
X/* Nicely recursive. */
X
Xstatic
Xisearch(dir, bp)
XBufpos	*bp;
X{
X	Bufpos	pushbp;
X	int	c,
X		ndir,
X		failing;
X	char	*orig_incp;
X
X	if (bp != 0) {		/* Move to the new position. */
X		pushbp.p_line = bp->p_line;
X		pushbp.p_char = bp->p_char;
X		SetDot(bp);
X		failing = 0;
X	} else {
X		DOTsave(&pushbp);
X		failing = 1;
X	}
X	orig_incp = incp;
X	ndir = dir;		/* Same direction as when we got here, unless
X				   we change it with C-S or C-R. */
X	for (;;) {
X		SetDot(&pushbp);
X		message(NullStr);
X		if (failing)
X			add_mess("Failing ");
X		if (dir == BACKWARD)
X			add_mess("reverse-");
X		add_mess("I-search: %s", ISbuf);
X		DrawMesg(NO);
X		add_mess(NullStr);	/* tell me this is disgusting ... */
X		c = getch();
X		if (c == SExitChar)
X			return STOP;
X		switch (c) {
X		case RUBOUT:
X		case BS:
X			return DELETE;
X
X		case CTL(G):
X			/* If we're failing, we backup until we're no longer
X			   failing or we've reached the beginning; else, we
X			   just about the search and go back to the start. */
X			if (failing)
X				return BACKUP;
X			return TOSTART;
X
X		case CTL(\\):
X			c = CTL(S);
X		case CTL(S):
X		case CTL(R):
X			/* If this is the first time through and we have a
X			   search string left over from last time, use that
X			   one now. */
X			if (incp == ISbuf) {
X				strcpy(ISbuf, getsearch());
X				incp = &ISbuf[strlen(ISbuf)];
X			}
X			ndir = (c == CTL(S)) ? FORWARD : BACKWARD;
X			/* If we're failing and we're not changing our
X			   direction, don't recur since there's no way
X			   the search can work. */
X			if (failing && ndir == dir) {
X				rbell();
X				continue;
X			}
X			break;
X
X		case '\\':
X			if (incp > &ISbuf[(sizeof ISbuf) - 1]) {
X				rbell();
X				continue;
X			}
X			*incp++ = '\\';
X			add_mess("\\");
X			/* Fall into ... */
X
X		case CTL(Q):
X		case CTL(^):
X			add_mess("");
X			c = getch() | 0400;
X			/* Fall into ... */
X
X		default:
X			if (c & 0400)
X				c &= 0177;
X			else {
X				if (c > RUBOUT || (c < ' ' && c != '\t')) {
X					Ungetc(c);
X					return STOP;
X				}
X			}
X			if (incp > &ISbuf[(sizeof ISbuf) - 1]) {
X				rbell();
X				continue;
X			}
X			*incp++ = c;
X			*incp = 0;
X			break;
X		}
X		add_mess("%s", orig_incp);
X		add_mess(" ...");	/* so we know what's going on */
X		DrawMesg(NO);		/* do it now */
X		switch (isearch(ndir, doisearch(ndir, c, failing))) {
X		case TOSTART:
X			return TOSTART;
X
X		case STOP:
X			return STOP;
X
X		case BACKUP:
X			/* If we're not failing, we just continue to to the
X			   for loop; otherwise we keep returning to the 
X			   previous levels until we find one that isn't
X			   failing OR we reach the beginning. */
X			if (failing)
X				return BACKUP;
X			/* Fall into ... */
X
X		case DELETE:
X			incp = orig_incp;
X			*incp = 0;
X			continue;
X		}
X	}
X}
@//E*O*F re1.c//
if test 9617 -ne "`wc -c <'re1.c'`"; then
    echo shar: error transmitting "'re1.c'" '(should have been 9617 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'table.h'" '(870 characters)'
if test -f 'table.h' ; then 
  echo shar: will not over-write existing file "'table.h'"
else
sed 's/^X//' >table.h <<'@//E*O*F table.h//'
X/************************************************************************
X * This program is Copyright (C) 1986 by Jonathan Payne.  JOVE is       *
X * 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
Xtypedef struct word	Word;
Xtypedef struct table	Table;
X
Xstruct word {
X	Word	*wd_next;
X	char	*wd_text;
X};
X
Xstruct table {
X	Table	*t_next;
X	Word	*t_wordlist;
X};
X
Xextern Table	*make_table();
Xextern Word	*word_in_table();
X
X#define	table_top(table)	(table->t_wordlist)
X#define next_word(w)		(w->wd_next)
X#define last_word_p(w)		(w->wd_next == NIL)
X#define word_text(w)		(w->wd_text)
X#define word_length(w)		(strlen(word_text(w)))
@//E*O*F table.h//
if test 870 -ne "`wc -c <'table.h'`"; then
    echo shar: error transmitting "'table.h'" '(should have been 870 characters)'
fi
fi # end of overwriting check
echo shar: "End of archive 6 (of 13)."
cp /dev/null ark6isdone
DONE=true
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13; do
    if test -f ark${I}isdone; then
        echo "You have run archive ${I}."
    else
        echo "You still need to run archive ${I}."
        DONE=false
    fi
done
case $DONE in
    true)
        echo "You have run all 13 archives."
        echo 'Now read the README and Makefile.'
        ;;
esac
##  End of shell archive.
exit 0



More information about the Mod.sources mailing list