[comp.sources.misc] v07i044: CRISP release 1.9 part 23/32

allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc) (07/23/89)

Posting-number: Volume 7, Issue 44
Submitted-by: fox@marlow.UUCP (Paul Fox)
Archive-name: crisp1.9/part24



#!/bin/sh
# this is part 3 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file ./anchor.c continued
#
CurArch=3
if test ! -r s2_seq_.tmp
then echo "Please unpack part 1 first!"
     exit 1; fi
( read Scheck
  if test "$Scheck" != $CurArch
  then echo "Please unpack part $Scheck next!"
       exit 1;
  else exit 0; fi
) < s2_seq_.tmp || exit 1
echo "x - Continuing file ./anchor.c"
sed 's/^X//' << 'SHAR_EOF' >> ./anchor.c
X
Xint	start_line, start_col;
Xint	end_line, end_col;
Xint	mark_type;
X
Xdrop_anchor()
X{
X	ANCHOR	*ap = (ANCHOR *) chk_alloc(sizeof (ANCHOR));
X	int	previous_anchor = curbp->b_alist != NULL;
X
X	u_raise();
X	ap->a_line = *cur_line;
X	ap->a_offset = *cur_col;
X	ap->a_type = argv[1].l_flags == F_NULL ? 
X			(u_int16) MK_NORMAL : 
X			(u_int16) (argv[1].l_int & 0xffff);
X	ll_push(curbp->b_alist, (char *) ap);
X	curbp->b_anchor = ap;
X	win_modify(previous_anchor ? WFHARD : WFMOVE);
X	return 0;
X}
Xraise_anchor()
X{
X	accumulator = 0;
X	if (curbp->b_anchor == NULL)
X		return 0;
X	u_drop();
X	accumulator = 1;
X	if (ll_pop(curbp->b_alist))
X		curbp->b_anchor = (ANCHOR *) ll_elem(ll_first(curbp->b_alist));
X	else
X		curbp->b_anchor = NULL;
X	win_modify(WFHARD);
X	return 0;
X}
Xmark()
X{
X	if (curbp->b_anchor)
X		raise_anchor();
X	else
X		drop_anchor();
X	return 0;
X}		
Xwrite_block()
X{	char 	*cp;
X	FILE	*fp;
X	char	buf[BUFSIZ];
X	char	*open_mode = argv[2].l_flags == F_NULL ? "w" :
X				argv[2].l_int == 0 ? "w" : "a";
X	accumulator = 0;
X	if (check_mark())
X		return;
X
X	cp = get_arg1("Write marked area as: ", buf, sizeof buf);
X	if (cp == NULL)
X		return;
X	if ((fp = fopen(cp, open_mode)) == NULL) {
X		ewprintf("Write failed.");
X		accumulator = -1;
X		return;
X		}
X	copyregion(fp);
X	fclose(fp);
X	raise_anchor();
X	accumulator = 1;
X	
X}
Xinq_marked()
X{
X	accumulator = 0;
X	if (get_marked_areas((WINDOW *) NULL)) {
X		accumulator = mark_type;
X		if (argv[1].l_flags != F_NULL)
X			int_assign(argv[1].l_sym, (long) start_line);
X		if (argv[2].l_flags != F_NULL)
X			int_assign(argv[2].l_sym, (long) start_col);
X		if (argv[3].l_flags != F_NULL)
X			int_assign(argv[3].l_sym, (long) end_line);
X		if (argv[4].l_flags != F_NULL) {
X			if (mark_type == MK_LINE)
X				end_col = get_longest_line();
X			int_assign(argv[4].l_sym, (long) end_col);
X			}
X		}
X	return 0;
X}
Xget_longest_line()
X{
X	int ln = start_line;
X	int max_ecol = 0;
X	int old_cur_line = *cur_line;
X	int	col;
X
X	while (ln <= end_line) {
X		LINE *lp = linep(ln);
X		*cur_line = ln++;
X		col = current_col(llength(lp));
X		if (col > max_ecol)
X			max_ecol = col;
X		}
X	*cur_line = old_cur_line;
X	return max_ecol;
X}
Xswap_anchor()
X{
X	int	col = *cur_col;
X
X	if (curbp->b_anchor) {
X		*cur_line = curbp->b_anchor->a_line;
X		curbp->b_anchor->a_line = *cur_line;
X		*cur_col = curbp->b_anchor->a_offset;
X		curbp->b_anchor->a_offset = col;
X		}
X	return 0;
X}
Xget_marked_areas(wp)
XWINDOW	*wp;
X{	ANCHOR	*ap;
X	int	tmpl;
X
X	if (wp == NULL)
X		ap = curbp->b_anchor;
X	else
X		ap = wp->w_bufp->b_anchor;
X	if (ap == NULL) {
X		start_line = *cur_line;
X		end_line = curbp->b_numlines;
X		return FALSE;
X		}
X	mark_type = ap->a_type;
X	start_line = ap->a_line;
X	start_col = ap->a_offset;
X	end_line = wp ? wp->w_line : *cur_line;
X	end_col = wp ? wp->w_col : *cur_col;
X
X	if (mark_type == MK_COLUMN) {
X		if (start_line > end_line)
X			SWAP(start_line, end_line, tmpl);
X		if (start_col > end_col)
X			SWAP(start_col, end_col, tmpl);
X		return TRUE;
X		}
X	if (start_line > end_line) {
X		SWAP(start_line, end_line, tmpl);	
X		SWAP(start_col, end_col, tmpl);
X		}
X	if (start_line == end_line && start_col > end_col)
X		SWAP(start_col, end_col, tmpl);
X	if (mark_type == MK_LINE) {
X		end_col = 32767;
X		start_col = 1;
X		}
X	else if (mark_type == MK_NONINC)
X		end_col--;
X	return TRUE;
X}
SHAR_EOF
echo "File ./anchor.c is complete"
chmod 0444 ./anchor.c || echo "restore of ./anchor.c fails"
mkdir . >/dev/null 2>&1
echo "x - extracting ./basic.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > ./basic.c &&
X/**************************************************************
X *
X *	CRISP - Custom Reduced Instruction Set Programmers Editor
X *
X *	(C) Paul Fox, 1989
X *	43, Jerome Close	      Tel: +44 6284 4222
X *	    Marlow
X *	     Bucks.
X *		England SL7 1TX
X *
X *
X *    Please See COPYRIGHT notice.
X *
X **************************************************************/
X#include        "list.h"
X
XSCCSID("@(#) basic.c 1.5, (C) P. Fox");
X/*
X * Go to beginning of line.
X */
X/*ARGSUSED*/
Xbeginning_of_line()
X{
X	u_dot();
X	*cur_col = 1;
X	win_modify(WFMOVE);
X	return 0;
X}
X
X/*
X * Go to end of line.
X */
Xend_of_line()
X{	register LINE *lp = linep(*cur_line);
X	u_dot();
X
X	*cur_col  = current_col(llength(lp));
X	win_modify(WFMOVE);
X	return 0;
X}
Xnext_char()
X{	int	n = argv[1].l_flags == F_INT ? argv[1].l_int : 1;
X
X	if (n < 0) {
X		argv[1].l_int = -n;
X		prev_char();
X		return;
X		}
X	u_dot();
X	win_modify(WFMOVE);
X	while (n > 0 && *cur_line != curbp->b_numlines) {
X		LINE	*lp = linep(*cur_line);
X		int offset = current_offset(*cur_col, FALSE);
X
X		if (n + offset <= llength(lp)) {
X			*cur_col = current_col(offset + n);
X			break;
X			}
X		n -= llength(lp) - offset + 1;
X		*cur_col = 1;
X		(*cur_line)++;
X		}
X	win_modify(WFMOVE);
X	accumulator = 1;
X	return;
X}
Xprev_char()
X{	int	offset;
X	LINE	*lp;
X	int	n = argv[1].l_flags == F_INT ? argv[1].l_int : 1;
X
X	if (n < 0) {
X		argv[1].l_int = -n;
X		next_char();
X		return;
X		}		
X	if (*cur_col == 1 && *cur_line == 1) {
X		accumulator = 0;
X		return;
X		}
X
X	offset = current_offset(*cur_col, FALSE);
X	u_dot();
X	win_modify(WFMOVE);
X	while (n > 0) {
X		if (offset > n) {
X			offset -= n;
X			n = 0;
X			}
X		else if (offset) {
X			n -= offset;
X			offset = 0;
X			}
X		else {
X			if (*cur_line == 1)
X				break;
X			(*cur_line)--;
X			lp = linep(*cur_line);
X			offset = lp->l_used;
X			n--;
X			}
X		}
X	accumulator = 1;
X	win_modify(WFMOVE);
X	*cur_col = current_col(offset);
X	return;
X}
X/*
X * Move cursor forwards. Do the
X * right thing if the count is less than
X * 0.
X */
Xforwchar(n)
X{	int	col = *cur_col;
X
X	u_dot();
X	*cur_col += n;
X	if (*cur_col < 1)
X		*cur_col = 1;
X	if (col != *cur_col) {
X		accumulator = 1;
X		win_modify(WFMOVE);
X		}
X	else
X		accumulator = 0;
X	return 0;
X}
X/*
X * Move cursor backwards. Do the
X * right thing if the count is less than
X * 0. Error if you try to move back from
X * the beginning of the buffer.
X */
Xbackchar(n)
X{
X	u_dot();
X	win_modify(WFMOVE);
X	if (*cur_col == 1 && *cur_line > 1) {
X		(*cur_line)--;
X		return end_of_line();
X		}
X	return forwchar(-n);
X}
X
X
X/*
X * Go to the beginning of the
X * buffer. 
X */
Xgotobob()
X{
X	u_dot();
X	win_modify(WFMOVE);
X	*cur_col = *cur_line = 1;
X	win_modify(WFMOVE);
X	return 0;
X}
X
X/*
X * Go to the end of the buffer.
X */
Xgotoeob()
X{	int	n;
X
X	u_dot();
X	win_modify(WFMOVE);
X	*cur_line = curbp->b_numlines;
X	if (*cur_line > 1)
X		(*cur_line)--;
X	n = end_of_line();
X	if (hooked)
X		set_buffer_bottom(curwp);
X	return n;
X}
X
X/*
X * Move forward by full lines.
X * If the number of lines to move is less
X * than zero, call the backward line function to
X * actually do it. The last command controls how
X * the goal column is set.
X */
Xforwline(n) 
X{
X	int	old_line = *cur_line;
X
X	u_dot();
X	win_modify(WFMOVE);
X	if (n < 0 && *cur_line + n < 1)
X		*cur_line = 1;
X	else if (*cur_line + n > numlines())
X		*cur_line = numlines();
X	else
X		*cur_line += n;
X	accumulator = *cur_line != old_line;
X	win_modify(WFMOVE);
X	return 0;
X}
X
Xbackline(n) 
X{
X	return forwline(-n);
X}
Xnumlines()
X{
X	return curbp->b_numlines;
X}
Xpage_down()
X{
X	forwline(curwp->w_h);
X	return 0;
X}
X
Xpage_up()
X{
X	backline(curwp->w_h);
X	return 0;
X}
Xgotoline(n) 
X{
X
X	u_dot();
X	win_modify(WFMOVE);
X
X	*cur_col = 1;
X	*cur_line = 1;
X	return forwline(n - 1);
X}
Xdist_to_tab()
X{
X	accumulator = next_tab_stop(*cur_col) - *cur_col + 1;
X/*	assert(accumulator >= 0);*/
X	return 0;
X}
SHAR_EOF
chmod 0444 ./basic.c || echo "restore of ./basic.c fails"
mkdir . >/dev/null 2>&1
echo "x - extracting ./bookmark.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > ./bookmark.c &&
X/**************************************************************
X *
X *	CRISP - Custom Reduced Instruction Set Programmers Editor
X *
X *	(C) Paul Fox, 1989
X *	43, Jerome Close	      Tel: +44 6284 4222
X *	    Marlow
X *	     Bucks.
X *		England SL7 1TX
X *
X *
X *    Please See COPYRIGHT notice.
X *
X **************************************************************/
X# include	"list.h"
X
XSCCSID("@(#) bookmark.c 1.2, (C) P. Fox");
X# define	MAX_BOOKMARKS	10
X
Xstruct	bookmark {
X		u_int16		b_buffer;
X		int		b_line;
X		int		b_col;
X		int		b_ref;
X		} bookmarks[MAX_BOOKMARKS];
X
Xdrop_bookmark()
X{	struct bookmark *bk;
X
X	if (argv[1].l_int == 0)
X		argv[1].l_int = 10;
X	if (argv[1].l_int < 1 || argv[1].l_int > MAX_BOOKMARKS) {
X		ewprintf("drop_bookmark: invalid bookmark.");
X		return 0;
X		}
X
X	bk = &bookmarks[argv[1].l_int - 1];
X	if (argv[3].l_flags == F_INT && argv[4].l_flags == F_INT &&
X	    argv[5].l_flags == F_INT) {
X		bk->b_buffer = argv[3].l_int;
X		bk->b_line = argv[4].l_int;
X		bk->b_col = argv[5].l_int;
X		}
X	else {
X		bk->b_buffer = curbp->b_bufnum;
X		bk->b_line = *cur_line;
X		bk->b_col = *cur_col;
X		}
X	bk->b_ref = TRUE;
X	infof("Bookmark dropped.");
X	return	0;
X}
Xgoto_bookmark()
X{
X	struct bookmark *bk;
X	int	move = TRUE;
X	long	book_no;
X
X	accumulator = 0;
X	if (get_iarg1("Go to bookmark [1-10]: ", &book_no))
X		return 0;
X
X	if (book_no == 0)
X		book_no = 10;
X	if (book_no < 1 || book_no > MAX_BOOKMARKS) {
X		ewprintf("goto_bookmark: invalid bookmark.");
X		return 0;
X		}
X
X	bk = &bookmarks[book_no - 1];
X	if (bk->b_ref == FALSE)
X		return 0;
X	if (argv[2].l_flags != F_NULL) {
X		move = FALSE;
X		int_assign(argv[2].l_sym, (long) bk->b_buffer);
X		}
X	if (argv[3].l_flags != F_NULL) {
X		move = FALSE;
X		int_assign(argv[3].l_sym, (long) bk->b_line);
X		}
X	if (argv[4].l_flags != F_NULL) {
X		move = FALSE;
X		int_assign(argv[4].l_sym, (long) bk->b_col);
X		}
X
X	if (move) {
X		WINDOW	*wp;
X		for (wp = wheadp; wp; wp->w_wndp)
X			if (wp->w_bufp->b_bufnum == bk->b_buffer)
X				break;
X		if (wp == NULL) {
X			BUFFER	*bp = numberb(bk->b_buffer);
X			if (bp == NULL) {
X				ewprintf("goto_bookmark: no such buffer.");
X				return 0;
X				}
X			showbuffer(bp, curwp);
X			curbp = bp;
X			}
X		else {
X			curwp = wp;
X			curbp = curwp->w_bufp;
X			}
X		argv[1].l_int = bk->b_line;
X		argv[2].l_int = bk->b_col;
X		move_abs();
X		}
X	accumulator = 1;
X	return	0;
X}
SHAR_EOF
chmod 0444 ./bookmark.c || echo "restore of ./bookmark.c fails"
mkdir . >/dev/null 2>&1
echo "x - extracting ./buffer.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > ./buffer.c &&
X/**************************************************************
X *
X *	CRISP - Custom Reduced Instruction Set Programmers Editor
X *
X *	(C) Paul Fox, 1989
X *	43, Jerome Close	      Tel: +44 6284 4222
X *	    Marlow
X *	     Bucks.
X *		England SL7 1TX
X *
X *
X *    Please See COPYRIGHT notice.
X *
X **************************************************************/
X#include        "list.h"
X
XSCCSID("@(#) buffer.c 1.14, (C) P. Fox");
X
XBUFFER	*
Xnumberb(n)
Xu_int16	n;
X{
X	register BUFFER	*bp;
X
X	for (bp = bheadp; bp; bp = bp->b_bufp)
X		if (bp->b_bufnum == n)
X			return bp;
X	return (BUFFER *) NULL;
X}
X/*
X * Dispose of a buffer, by name.
X */
Xkillbuffer(n)
Xu_int16	n;
X{
X	register BUFFER *bp;
X	register BUFFER *bp1;
X	register WINDOW *wp;
X	extern	BUFFER	*numberb();
X
X	if ((bp = numberb(n)) == NULL)
X		return FALSE;
X
X	if (bclear(bp) != TRUE)
X		return TRUE;
X	p_cleanup(bp);
X	if (bp->b_nwnd != 0) {
X		for (wp = wheadp; wp && bp->b_nwnd; wp = wp->w_wndp) {
X			if (wp->w_bufp == bp) {
X				--bp->b_nwnd;
X				wp->w_bufp = NULL;
X				}
X			}
X		}
X	if (bp->b_title)
X		chk_free(bp->b_title);
X	ll_clear(bp->b_register);
X	ll_free(bp->b_register);
X	ll_free(bp->b_alist);
X	delete_buffer_symbols(bp);
X	free_line(bp->b_linep);
X	if (bheadp == bp)
X		bheadp = bp->b_bufp;
X	else {
X		for (bp1 = bheadp; bp1 && bp1->b_bufp != bp; )
X			bp1 = bp1->b_bufp;
X		if (bp1)
X			bp1->b_bufp = bp->b_bufp;
X		}
X
X	chk_free((char *) bp);
X	if (curbp == bp)
X		curbp = NULL;
X	return (TRUE);
X}
X
X
X
X/*
X * Look through the list of buffers, giving the user
X * a chance to save them.  Return TRUE if there are
X * any changed buffers afterwards. Buffers that don't
X * have an associated file don't count. Return FALSE
X * if there are no changed buffers.
X */
Xanycb() 
X{
X	register BUFFER *bp;
X	int	nbuf = 0;
X	char	buf[80];
X	char	reply[4];
X	extern BUFFER *scrap_bp;
X
X	for (bp = bheadp; bp != NULL; bp = bp->b_bufp)
X		if (*bp->b_fname && bp->b_nummod && bp->b_system == 0 && bp != scrap_bp)
X			nbuf++;
X
X	if (nbuf == 0)
X		return FALSE;
X	(void) sprintf(buf, "%d buffer%s not been saved. Exit [ynw]? ",
X		nbuf, nbuf == 1 ? " has" : "s have");
X
X	reply[0] = NULL;
X	ereply(buf, reply, 1);
X	if (reply[0] == 'Y' || reply[0] == 'y')
X		return FALSE;
X	if (reply[0] != 'W' && reply[0] != 'w')
X		return TRUE;
X
X	for (bp = bheadp; bp != NULL; bp = bp->b_bufp)
X		if (*bp->b_fname && bp->b_nummod && bp->b_system == 0 && bp != scrap_bp)
X			writeout(bp, bp->b_fname, TRUE, FALSE);
X	return FALSE;
X}
Xchar	*
Xfilename(fn)
Xchar	*fn;
X{	static char buf[NFILEN];
X	register char	*cp;
X	extern char *get_cwd();
X	extern char *sys_delim();
X
X	for (cp = fn; *cp; )
X		if (*cp == '/' && cp[1] == '/')
X			strcpy(cp, cp+1);
X		else
X			cp++;
X# if	defined(VMS)
X	{char	buf1[256];
X	if (strchr(fn, '/') != NULL)
X		fn = sys_fname_unix_to_vms(fn, buf1, sizeof buf1);
X	if (strchr(fn, ':') != NULL)
X		return fn;
X	}
X# endif
X	if (fn[0] == '/')
X		return fn;
X	cp = get_cwd();
X	if (cp[0] == '/' && cp[1] == NULL)
X		sprintf(buf, "/%s", fn);
X	else
X		sprintf(buf, "%s%s%s", cp, sys_delim(), fn);
X# if	defined(VMS)
X	{char *vms_filename_canon();
X	return vms_filename_canon(buf);
X	}
X# else
X	/*-----------------------------------------
X	 *   Map dir/./file to dir/file, and
X	 *   dir1/dir2/../file to dir1/file.
X	 *-----------------------------------------*/
Xagain:
X	for (cp = buf; *cp; cp++) {
X		if (*cp == '/' && cp[1] == '.' && cp[2] == '/') {
X			strcpy(cp, cp+2);
X			goto again;
X			}
X		if (*cp == '/' && cp[1] == '.' && cp[2] == '.' && cp[3] == '/') {
X			char *cp1;
X			if (cp == buf) {
X				strcpy(buf, cp+3);
X				goto again;
X				}
X			for (cp1 = cp - 1; cp1 >= buf; cp1--)
X				if (*cp1 == '/')
X					break;
X			strcpy(cp1, cp+3);
X			goto again;
X			}
X		}
X	return buf;
X# endif
X}
Xinq_file_buffer()
X{	BUFFER *bp = bfind(get_str(1), FALSE);
X
X	if (bp == NULL)
X		accumulator = 0;
X	else
X		accumulator = bp->b_bufnum;
X}
X/*
X * Search for a buffer, by name.
X * If not found, and the "cflag" is TRUE,
X * create a buffer and put it in the list of
X * all buffers. Return pointer to the BUFFER
X * block for the buffer.
X */
XBUFFER  *
Xbfind(buffer_name, cflag) 
Xregister char *buffer_name; 
X{
X	register BUFFER *bp;
X	register LINE   *lp;
X	register BUFFER	*bp1;
X	u_int16	i;
X	static	u_int16	buffer_number = 0;
X	static	BUFFER	null_buffer = {0};
X
X	for (bp = bheadp; bp; bp = bp->b_bufp)
X		if (strcmp(buffer_name, bp->b_fname) == 0)
X			return bp;
X
X	if (!cflag)
X		return NULL;
X	/*NOSTRICT*/
X	if ((bp= (BUFFER *) chk_alloc(sizeof(BUFFER))) == NULL) {
X		ewprintf("Can't get %d bytes", sizeof(BUFFER));
X		return NULL;
X		}
X	if ((lp=lalloc((RSIZE) 0)) == NULL) {
X		chk_free((char *) bp);
X		return NULL;
X		}
X	*bp = null_buffer;
X	strcpy(bp->b_fname, filename(buffer_name));
X	bp->b_alist = ll_init();
X	bp->b_syms = spinit();
X	bp->b_register = ll_init();
X# ifdef S_IRUSR
X	bp->b_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
X# else
X	bp->b_mode = 0644;
X# endif
X	bp->b_bufnum = ++buffer_number;
X	bp->b_linep = lp;
X	bp->b_numlines = bp->b_line = bp->b_col = 1;
X	for (i = 0; i < NTABS; i++)
X		bp->b_tabs[i] = i*8;	
X	lp->l_fp = lp;
X	lp->l_bp = lp;
X
X	if (bheadp == NULL)
X		bheadp = bp;
X	else {
X		for (bp1 = bheadp; bp1->b_bufp; )
X			bp1 = bp1->b_bufp;
X		bp1->b_bufp = bp;
X		}
X	
X	return (bp);
X}
X
Xbclear(bp) 
Xregister BUFFER *bp; 
X{
X	bp->b_flag  &= ~(BFCHG|BFRO);
X	while (bp->b_numlines > 1)
X		lfree(bp, 1);
X
X	bp->b_line = bp->b_col = 1;
X
X	while (ll_pop(bp->b_alist))
X		;
X	return TRUE;
X}
X
X/*
X * Display the given buffer in the given window. 
X */
Xshowbuffer(bp, wp)
Xregister BUFFER *bp; 
Xregister WINDOW *wp; 
X{
X	register WINDOW *owp;
X
X	if (wp->w_bufp == bp) {                 /* Easy case!   */
X		wp->w_flag |= WFHARD;
X		return;
X		}
X
X	detach_buffer(wp);
X	wp->w_bufp = bp;
X	wp->w_old_line = 1;
X
X	w_title(wp, bname(bp->b_fname), "");
X
X	if (bp->b_nwnd++ == 0) {                /* First use.           */
X		set_window_parms(wp, bp);
X		return;
X		}
X
X	wp->w_flag |= WFHARD;
X	/* already on screen, steal values from other window */
X	for (owp = wheadp; owp; owp = owp->w_wndp)
X		if (owp->w_bufp == bp && owp != wp) {
X			wp->w_top_line = owp->w_top_line; /* PDF */
X			wp->w_line  = owp->w_line;
X			wp->w_col  = owp->w_col;
X			wp->w_old_line = owp->w_old_line;
X			break;
X			}
X}
Xset_window_parms(wp, bp)
Xregister WINDOW *wp;
Xregister BUFFER *bp;
X{
X	wp->w_flag |= WFHARD;
X	wp->w_top_line = bp->b_top;
X	wp->w_line = bp->b_line;
X	wp->w_col  = bp->b_col;
X	if (wp->w_line - wp->w_top_line >= wp->w_h)
X		wp->w_top_line = wp->w_line;
X}
Xset_buffer_parms(wp, bp)
Xregister WINDOW *wp;
Xregister BUFFER *bp;
X{
X	bp->b_line = wp->w_line;
X	bp->b_col = wp->w_col;
X	bp->b_top = wp->w_top_line;
X}
Xinq_buffer_flags()
X{
X	BUFFER	*bp = argv[1].l_flags == F_INT ? 
X		numberb(argv[1].l_int) : curbp;
X
X	if (bp == NULL)
X		accumulator = -1;
X	else {
X		accumulator = bp->b_flag & 0xff;
X		if (bp->b_display)
X			accumulator |= BFPROC;
X		accumulator &= ~BFCHG;
X		if (curbp->b_nummod)
X			accumulator |= BFCHG;
X		}
X}
SHAR_EOF
chmod 0444 ./buffer.c || echo "restore of ./buffer.c fails"
mkdir . >/dev/null 2>&1
echo "x - extracting ./builtin.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > ./builtin.c &&
X/**************************************************************
X *
X *	CRISP - Custom Reduced Instruction Set Programmers Editor
X *
X *	(C) Paul Fox, 1989
X *	43, Jerome Close	      Tel: +44 6284 4222
X *	    Marlow
X *	     Bucks.
X *		England SL7 1TX
X *
X *
X *    Please See COPYRIGHT notice.
X *
X **************************************************************/
X# include	"list.h"
XSCCSID("@(#) builtin.c 1.8, (C) P. Fox");
X
X# define	ERROR	-1
X# define	EXECUTE	-2
Xint	action;
X
Xstatic LIST f_halt = F_HALT;
XLISTV	*argv;
Xint	argc;
Xint	hooked;
Xint	*cur_line;
Xint	*cur_col;
Xextern	int	break_flag;
Xchar	*command_name;		/* Name of macro primitive currently being */
X				/* executed.				  */
Xint	autoloading = FALSE;	/* TRUE if autoloading a macro - avoids the */
X				/* 'macro successfully loaded' message	*/
X				/* being printed.			*/
Xint	doing_return = FALSE;	/* Set to TRUE when a 'return' is executed.*/
X
Xvoid	set_hooked();
Xextern	int	ctrl_c;
X
Xvoid
Xeval_expr(lp)
XLISTV	*lp;
X{
X	if (lp->l_flags == F_INT)
X		accumulator = lp->l_int;
X	else if (lp->l_flags == F_LIST)
X		(void) execute_macro(lp->l_list);
X	else
X		ewprintf("Internal evaluation error");
X}
Xstr_exec(str)
Xchar	*str;
X{
X	register char *cp = str;
X	char	buf[256];
X	char	*dp = buf;
X	extern char *strtok();
X	int	i;
X# define	LIST_BUF_SIZE	128
X	LIST	lp[LIST_BUF_SIZE];
X	LIST	*lp1;
X
X	while (isspace(*cp))
X		cp++;
X	lp[0] = F_STR;
X	LPUT32(lp, (long) dp);
X	lp1 = lp + 5;
X	while (*cp && !isspace(*cp))
X		*dp++ = *cp++;
X	*dp++ = NULL;
X	while (*cp) {
X		while (isspace(*cp))
X			cp++;
X		if (*cp == NULL)
X			break;
X		if (lp1 >= &lp[LIST_BUF_SIZE-10]) {
X			ewprintf("Out of space in str_exec");
X			return 0;
X			}
X		if (*cp == '-' || (*cp >= '0' && *cp <= '9')) {
X			*lp1 = F_INT;
X			LPUT32(lp1, (long) atoi(cp));
X			while (*cp && *cp != ' ' && *cp != '\t')
X				cp++;
X			}
X		else {
X			register char *cp1;
X			char	ch_term = ' ';
X
X			if (*cp == '"')
X				ch_term = '"', cp++;
X			cp1 = cp;
X
X			while (*cp) {
X				if (*cp == '\\')
X					 cp++;
X				else if (*cp == ch_term)
X					break;
X				cp++;
X				}
X
X			*lp1 = F_LIT;
X			LPUT32(lp1, (long) dp);
X			for (cp = cp1; *cp && *cp != ch_term; ) {
X/*				if (*cp == '\\')
X					++cp;*/
X				*dp++ = *cp++;
X				} 
X
X			*dp++ = NULL;
X			if (*cp)
X				cp++;
X			}
X		lp1 += 5;
X		}
X	*lp1 = F_HALT;
X	i = nexecute_macro(lp);
X	return i;
X}
Xnexecute_macro(lp)
XLIST	*lp;
X{	
X	if (++nest_level >= MAX_NESTING)
X		panic("Macro nesting overflow.");
X	execute_macro(lp);
X	delete_local_symbols();
X}
Xexecute_macro(lp)
Xregister LIST	*lp;
X{	static	int handling_ctrlc = FALSE;
X	u_int16	i;
X
X	while (*lp == F_LIST) {
X		if (ctrl_c && !handling_ctrlc) {
X			handling_ctrlc = TRUE;
X			trigger(REG_CTRLC);
X			ctrl_c = FALSE;
X			handling_ctrlc = FALSE;
X			}
X		execute_macro(lp + sizeof_atoms[*lp]);
X		if (break_flag || doing_return)
X			return;
X		if ((i = LGET16(lp)) == 0)
X			return;
X		lp += i;
X		}
X	if (*lp == F_HALT)
X		return;
X	trace_list(lp);
X	exec1(lp, lp + sizeof_atoms[*lp]);
X}
Xexec1(lp_0, lp_argv)
Xregister LIST	*lp_0;
XLIST	*lp_argv;
X{
X	register BUILTIN *bp;
X	char	*macro_name;
X	register MACRO *mptr;
X	int	saved_msg_level;
X	int	loop_count;
X	MACRO	*saved_macro;
X	int	opc = *lp_0;
X
X	if (opc == F_ID)
X		bp = &builtin[LGET16(lp_0)];
X	else if (opc == F_INT) {
X		acc_type = F_INT;
X		accumulator = LGET32(lp_0);
X		return;
X		}
X	else if (opc == F_LIT) {
X		strl_acc_assign((char *) LGET32(lp_0));
X		return;
X		}
X	else {
X		char	*str = opc == F_RSTR ? ((r_str *) LGET32(lp_0))->r_str 
X				: (char *) LGET32(lp_0);
X		bp = lookup_builtin(str);
X		}
X
X
X	if (bp) {
X		if (bp->flags & B_REDEFINE) {
X			if (bp->macro == NULL) {
X				bp->macro = bp->first_macro;
X				goto hell;
X				}
X			if (bp->macro == bp->first_macro)
X				bp->argv = lp_argv;
X			mptr = saved_macro = bp->macro;
X			bp->macro = bp->macro->m_next;
X			macro_name = bp->name;
X			goto exec_macro;
X			}
X		else {
Xhell:			if (bp->func == NULL) {
X				trace_log("*** Not yet implemented - %s ***\n", 
X					bp->name);
X				return;
X				}
X	 		eval_args(bp, lp_argv);
X			bp->argv = &f_halt;
X			return;
X			}
X		}
X	/*-------------------------------------------------*/
X	/*   Lookup-defined macros.                        */
X	/*-------------------------------------------------*/
X	macro_name = opc == F_ID ? builtin[LGET16(lp_0)].name : 
X				     (char *) LGET32(lp_0);
X	for (loop_count = 0; loop_count < 2; loop_count++) {
X		if (bp)
X			mptr = saved_macro;
X		else
X			mptr = lookup_macro(macro_name);
X		if (mptr)
X			break;
X		if (ld_macro(macro_name)) {
X			extern int m_flag;
Xundefined_macro:
X			if (m_flag == FALSE)
X				errorf("%s undefined.", macro_name);
X			return;
X			}
X		}
X	if (mptr == NULL)
X		goto undefined_macro;
X	/*-------------------------------------------------*/
X	/*   Check to see whether we need to autoload the  */
X	/*   macro.                                        */
X	/*-------------------------------------------------*/
Xexec_macro:
X	if (mptr->m_flags & M_AUTOLOAD) {
X		int saved_auto = autoloading;
X		autoloading = TRUE;
X		if (ld_macro((char *) mptr->m_list)) {
X			autoloading = saved_auto;
X			return;
X			}
X		autoloading = saved_auto;
X		mptr = lookup_macro(macro_name);
X		if (mptr->m_flags & M_AUTOLOAD)
X			return;
X		}
X	lp_0 = mptr->m_list;
X	if (*lp_0 == F_HALT)
X		return;
X	mac_stack[ms_cnt].name = macro_name;
X	mac_stack[ms_cnt].argv = lp_argv;
X	if (ms_cnt++ == 0) {
X		saved_msg_level = msg_level;
X		msg_level = 1;
X		}
X	trace_log("Execute macro: %s\n", macro_name);
X	nexecute_macro(lp_0);
X	if (bp)
X		bp->macro = saved_macro;
X	mptr->m_ftime = FALSE;
X	if (--ms_cnt == 0)
X		msg_level = saved_msg_level;
X}
X
Xstruct saved {
X	OPCODE		save_type;
X	char		*save_str;
X	};
Xeval_args(bp, lp)
Xregister BUILTIN *bp;
Xregister LIST	*lp;
X{
X	extern LIST *copy_list();
X	LISTV	local_argv[MAX_ARGC];
X	register LISTV	*lap = &local_argv[1];
X	register char	*as = bp->args;
X	int	optional;
X	LIST	*bpargv = bp->argv;
X	LIST	*optarg = &f_halt;
X	LIST	*argp;
X	register int	largc = 1;
X	struct saved	saved_str[MAX_ARGC];
X	int	ss_cnt = 0;
X	register int	i;
X	r_str	*rp;
X
X
X	if (*lp == F_HALT) {
X		lp = bpargv;
X		bpargv = &f_halt;
X		}
X# define	RS(x) ((r_str *) (x))
X	while (*as && lp && *lp != F_HALT) {
X		int type;
X		char *str;
X
X		str = *lp == F_STR ? (char *) LGET32(lp) : "";
X		rp = RS(str);
X		if (optional = *as == '*')
X			as++;
X		if (*bpargv != F_HALT) {
X			optarg = bpargv;
X			if (*bpargv == F_LIST)
X				bpargv += LGET16(lp);
X			else 
X				bpargv += sizeof_atoms[*bpargv];
X			}
X		argp = lp;
X		++largc;
X		if (*as != 'R' && str[0] == 'N' && strcmp(str, "NULL") == 0) {
X			if (optarg[0] != F_HALT) {
X				argp = optarg;
X				rp = RS(LGET32(lp));
X				str = *argp == F_STR ? rp->r_str : "";
X				type = eval_expr2(*as, argp, lap, str);
X				}
X			else {
X				if (!optional)
X					return arg_error(bp, TRUE, saved_str, ss_cnt, lap - local_argv);
X				lap->l_int = 0;
X				lap->l_flags = F_NULL;
X				type = F_HALT;
X				}
X			}
X		else
X			type = eval_expr2(*as, argp, lap, str);
X		as++;
X		switch (type) {
X		  case F_INT:
X			lap->l_flags = F_INT;
X			lap->l_int = accumulator;
X			break;
X		  case EXECUTE:
X			goto execute;
X		  case F_HALT:
X			break;
X		  case F_LIT:
X			break;
X		  case F_STR:
X			saved_str[ss_cnt].save_str = lap->l_str = strdup(lap->l_str);
X			saved_str[ss_cnt++].save_type = F_STR;
X			break;
X		  case F_RSTR:
X			saved_str[ss_cnt].save_str = (char *) 
X				(lap->l_rstr = r_inc(lap->l_rstr));
X			saved_str[ss_cnt++].save_type = F_RSTR;
X			lap->l_flags = F_RSTR;
X			break;
X		  case F_LIST:
X			i = length_of_list(lap->l_list);
X			if (i) {
X				saved_str[ss_cnt].save_str = chk_alloc(i);
X				memcpy(saved_str[ss_cnt].save_str, lap->l_list, i);
X				lap->l_list = (LIST *) saved_str[ss_cnt].save_str;
X				saved_str[ss_cnt++].save_type = F_LIST;
X				}
X			break;
X		  case ERROR:
X			return arg_error(bp, TRUE, saved_str, ss_cnt, lap - local_argv);
X		  default:
X			ewprintf("%s: default case", bp->name);
X			panic("default case");
X		  }
X		lap++;
X		if ((i = *lp) == F_LIST) {
X			u_int16 i = LGET16(lp);
X			if (i == 0)
X				goto check_rest_of_arguments;
X			lp += i;
X			}
X		else if (i == F_HALT)
X			lp = bpargv;
X		else
X			lp += sizeof_atoms[i];
X		}
X
X	if (lp && *lp != F_HALT) {
X		ewprintf("%s: Too many arguments", bp->name);
X		return arg_error(bp, FALSE, saved_str, ss_cnt);
X		}
Xcheck_rest_of_arguments:
X	while (*as) {
X		if (*as != '*')
X			return arg_error(bp, TRUE, saved_str, ss_cnt, lap - local_argv);
X		as += 2;
X		lap->l_flags = F_NULL;
X		lap->l_int = 0;
X		lap++;
X		}
X
Xexecute:
X	acc_type = F_INT;
X	argv = local_argv;
X	argc = largc;
X	command_name = bp->name;
X	set_hooked();
X	(*bp->func)(bp->arg);
X# ifndef	PRODUCTION
X	if ((bp->flags & B_NOVALUE) == 0)
X		trace_acc();
X	bp->reference++;
X# endif
X	return free_saved(saved_str, ss_cnt);
X}
Xfree_saved(saved_str, ss_cnt)
Xregister struct saved *saved_str;
Xregister int ss_cnt;
X{
X	while (ss_cnt > 0) {
X		switch (saved_str[--ss_cnt].save_type) {
X		  case F_LIST:
X		  case F_STR:
X			chk_free(saved_str[ss_cnt].save_str);
X			break;
X		  case F_RSTR:
X			r_dec((r_str *) saved_str[ss_cnt].save_str);
X			break;
X		  }
X		}
X}
Xchar state_tbl[][9] = { 
X/*     F_INT, F_STR, F_LIST, NULL, F_ID, F_END, POLY, F_LIT, F_RSTR */
X/*a*/ {   -1, F_STR, F_LIST,   -1, F_ID,    -1,   -1, F_LIT, F_RSTR},
X/*b*/ {F_INT, F_STR,     -1,   -1, F_ID,    -1,   -1, F_LIT, F_RSTR},
X/*c*/ {   -1,    -1,     -1,   -1,   -1,    -1,   -1,    -1,     -1},
X/*d*/ {   -1,    -1,     -1,   -1,   -1,    -1,   -1,    -1,     -1},
X/*e*/ {   -1,    -1,     -1,   -1,   -1,    -1,   -1,    -1,     -1},
X/*f*/ {   -1,    -1,     -1,   -1,   -1,    -1,   -1,    -1,     -1},
X/*g*/ {   -1,    -1,     -1,   -1,   -1,    -1,   -1,    -1,     -1},
X/*h*/ {   -1,    -1,     -1,   -1,   -1,    -1,   -1,    -1,     -1},
X/*i*/ {F_INT,    -1,     -1,   -1,   -1,    -1,   -1,    -1,     -1},
X/*j*/ {   -1,    -1,     -1,   -1,   -1,    -1,   -1,    -1,     -1},
X/*k*/ {   -1,    -1,     -1,   -1,   -1,    -1,   -1,    -1,     -1},
X/*l*/ {   -1,    -1, F_LIST,   -1,   -1,    -1,   -1,    -1,     -1},
X/*m*/ {   -1,    -1,     -1,   -1,   -1,    -1,   -1,    -1,     -1},
X/*n*/ {   -1,    -1,     -1,   -1,   -1,    -1,   -1,    -1,     -1},
X/*o*/ {   -1,    -1,     -1,   -1,   -1,    -1,   -1,    -1,     -1},
X/*p*/ {   -1,    -1,     -1,   -1,   -1,    -1,   -1,    -1,     -1},
X/*q*/ {   -1,    -1,     -1,   -1,   -1,    -1,   -1,    -1,     -1},
X/*r*/ {   -1,    -1,     -1,   -1,   -1,    -1,   -1,    -1,     -1},
X/*s*/ {   -1, F_STR,     -1,   -1, F_ID,    -1,   -1, F_LIT, F_RSTR},
X/*t*/ {F_INT, F_STR, F_LIST,   -1, F_ID,    -1,   -1, F_LIT, F_RSTR},
X	};
Xeval_expr2(ch, argp, lap, str)
XLIST	*argp;
Xregister LISTV *lap;
Xchar	*str;
X{	SYMBOL	*sp;
X	int	type;
X
X	if (isupper(ch)) {
X		if (ch == 'R') {
X			lap->l_list = argp;
X			lap->l_flags = F_LIST;
X			return EXECUTE;
X			}
X		if (ch == 'C') {
X			lap->l_list = argp;
X			lap->l_flags = F_LIST;
X			return F_HALT;
X			}
X		if (!(*argp == F_STR || *argp == F_ID) ||
X		    (sp = lookup(str)) == NULL)
X		    return -1;
X		lap->l_sym = sp;
X		switch (ch) {
X		  case 'S':
X			if (sp->s_type == F_STR) {
X				lap->l_flags = F_STR;
X				return F_HALT;
X				}
X			return ERROR;
X		  case 'I':
X			if (sp->s_type == F_INT) {
X				lap->l_flags = F_INT;
X				return F_HALT;
X				}
X			return ERROR;
X		  case 'L':
X			if (sp->s_type == F_LIST) {
X				lap->l_flags = F_LIST;
X				return F_HALT;
X				}
X			return ERROR;
X		  case 'T':
X			if (sp->s_type == F_LIST) {
X				lap->l_flags = F_LIST;
X				return F_HALT;
X				}
X		  case 'B':
X			if (sp->s_type == F_INT || sp->s_type == F_STR) {
X				lap->l_flags = sp->s_type;
X				return F_HALT;
X				}
X			return ERROR;
X		  }
X		}
X	if (ch == 'm') {
X		if (*argp == F_STR) {
X			lap->l_flags = F_STR;
X			lap->l_str = str;
X			return F_LIT;
X			}
X		if (*argp == F_ID) {
X			eval(argp, lap);
X			return F_STR;
X			}
X		return ERROR;
X		}
X	type = eval(argp, lap);
X	ch -= 'a';
X	if (ch < 0 || ch >= sizeof state_tbl / sizeof state_tbl[0]) {
X		ewprintf("Unknown case string for '%c'", ch + 'a');
X		panic("");
X		}
X	return state_tbl[ch][type - F_INT];
X}
Xarg_error(bp, msg, saved_str, cnt, arg)
Xchar	*saved_str[MAX_ARGC];
XBUILTIN *bp;
X{
X	if (msg)
X		errorf("%s: parameter %d invalid", bp->name, arg);
X	free_saved(saved_str, cnt);
X	acc_type = F_INT;
X	return -1;
X}
Xvoid
Xset_hooked()
X{
X
X	if (hooked = curwp->w_bufp == curbp) {
X		cur_line = &curwp->w_line;
X		cur_col = &curwp->w_col;
X		}
X	else {
X		cur_line = &curbp->b_line;
X		cur_col = &curbp->b_col;
X		}
X}
Xget_iarg1(str, l)
Xchar	*str;
Xlong	*l;
X{
X	char	buf[80];
X
X	if (argv[1].l_flags == F_INT) {
X		*l = argv[1].l_int;
X		return 0;
X		}
X	if (ereply(str, buf, sizeof buf - 1) != TRUE)
X		return -1;
X	(void) sscanf(buf, "%ld", l);
X	return 0;
X}
Xchar *
Xget_arg1(str, buf, bufsiz)
Xchar	*str;
Xchar	*buf;
X{	register char	*cp;
X
X	if (argv[1].l_flags == F_STR)
X		return argv[1].l_str;
X	if (argv[1].l_flags == F_RSTR)
X		return argv[1].l_rstr->r_str;
X
X	if (ereply(str, buf, bufsiz - 1) != TRUE || buf[0] == NULL)
X		return (char *) NULL;
X	for (cp = buf; *cp; cp++)
X		if (*cp != ' ')
X			break;
X	return *cp == NULL ? (char *) NULL : buf;
X}
SHAR_EOF
chmod 0444 ./builtin.c || echo "restore of ./builtin.c fails"
mkdir . >/dev/null 2>&1
echo "x - extracting ./clock.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > ./clock.c &&
X/**************************************************************
X *
X *	CRISP - Custom Reduced Instruction Set Programmers Editor
X *
X *	(C) Paul Fox, 1989
X *	43, Jerome Close	      Tel: +44 6284 4222
X *	    Marlow
X *	     Bucks.
X *		England SL7 1TX
X *
X *
X *    Please See COPYRIGHT notice.
X *
X **************************************************************/
X# include	"list.h"
X# include	"clk.h"
X# include	<signal.h>
XSCCSID("@(#) clock.c 1.7, (C) 1989, P. Fox");
X
X# define	MAX_TIMEOUTS	10
X
Xstruct	callout	{
X		int	(*func)();
X		int	arg;
X		long	id;
X		long	timeout;
X		};
X
X/*# define ALARM(x) (trace_log("alarm(%d)\n", x), alarm(x))*/
X# define ALARM(x) alarm(x)
Xstruct	callout callo[MAX_TIMEOUTS];
Xint	ntmo = 0;
Xstatic	long	clk_id = 0;
Xint	clock_ticked = FALSE;
Xint clock_handler();
X
Xclk_timeout(func, arg, timeout)
Xint (*func)();
Xlong	timeout;
X{	register struct callout *cp = callo;
X	register int i, j;
X
X	clk_remove(func);
X	if (ntmo && clock_ticked == FALSE) {
X		int	secs = ALARM(0);
X		callo[0].timeout = secs;
X		}
X
X	timeout /= 1 SECOND;
X	if (ntmo == 0)
X		goto end_of_function;
X
X	if (ntmo >= MAX_TIMEOUTS-1)
X		return 0;
X	for (i = 0; i < ntmo; i++, cp++) {
X		if (cp->timeout > timeout) {
X			for (j = ntmo; j > i; j--)
X				callo[j] = callo[j-1];
X			cp[1].timeout -= timeout;
X			goto end_of_function;
X			}
X		timeout -= cp->timeout;
X		}
Xend_of_function:
X	cp->func = func;
X	cp->arg = arg;
X	cp->id = ++clk_id;
X	cp->timeout = timeout;
X	ntmo++;
X	if (clock_ticked == FALSE) {
X		if (callo[0].timeout == 0)
X			clock_handler();
X		else {
X			signal(SIGALRM, clock_handler);
X			ALARM(callo[0].timeout);
X			}
X		}
X	return clk_id;
X}
Xclk_remove(func)
Xint (*func)();
X{	register struct callout *cp;
X	register struct callout *cend = &callo[ntmo];
X
X	for (cp = callo; cp < cend; cp++)
X		if (cp->func == func) {
X			cp[1].timeout += cp->timeout;
X			for (; cp < cend; cp++)
X				*cp = cp[1];
X			ntmo--;
X			break;
X			}
X}
Xclock_check()
X{	int	i;
X	int (*func)();
X	int	arg;
X	int	clock_handler();
X
X	if (clock_ticked == FALSE)
X		return 1;
X	callo[0].timeout = 0;
X	while (ntmo && callo[0].timeout == 0) {
X		func = callo[0].func;
X		arg = callo[0].arg;
X		for (i = 0; i < MAX_TIMEOUTS; i++)
X			callo[i] = callo[i+1];
X		ntmo--;
X		if (func)
X			(*func)(arg);
X		}
X	signal(SIGALRM, clock_handler);
X	clock_ticked = FALSE;
X	if (ntmo)
X		ALARM(callo[0].timeout);
X	return 1;
X}
Xclock_handler()
X{
X	signal(SIGALRM, SIG_IGN);
X# if	defined(VMS)
X	sys_cancel_io();
X# endif
X	clock_ticked = TRUE;
X}
Xdump_callo()
X{
X	int	i;
X	trace_log("CALLOUTS = %d\n", ntmo);
X	for (i = 0; i < ntmo; i++) {
X		trace_log("%d: func=", i);
X		trace_log("%08lx ", callo[i].func);
X		trace_log("tmo=%ld.\n", callo[i].timeout);
X		}
X}
SHAR_EOF
chmod 0444 ./clock.c || echo "restore of ./clock.c fails"
mkdir . >/dev/null 2>&1
echo "x - extracting ./cm.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > ./cm.c &&
X/**************************************************************
X *
X *	CRISP - Custom Reduced Instruction Set Programmers Editor
X *
X *	(C) Paul Fox, 1989
X *	43, Jerome Close	      Tel: +44 6284 4222
X *	    Marlow
X *	     Bucks.
X *		England SL7 1TX
X *
X *
X *    Please See COPYRIGHT notice.
X *
X **************************************************************/
X# define	_DECLS
X# include	"list.h"
X# include	"cm.h"
XSCCSID("@(#) cm.c 1.12, (C) 1989 P. Fox");
X
X# define	MAX_ATOMS	32000	/* Max. number of atoms in a macro */
X					/* definition.			   */
X# define	MAX_STRINGS	2048	/* Max. strings in macro file.	   */
X# define	MAX_GLOBALS	256	/* Max. no. of global statements   */
X					/* in program.			   */
X#ifndef TRUE
X# define	TRUE	1
X# define	FALSE	0
X# endif
X
X/* Resolves dummy references *************/
Xchar	*K[1];
XOPCODE	acc_type;
Xlong	accumulator;
Xchar	*saccumulator;
Xexec1() {}
X/**************/
Xvoid	patom();
Xextern	char	*strdup();
Xextern	char	*chk_alloc();
Xextern	char	*get_string();
X
X/*-------------------*/
XBUFFER	*bheadp;
XBUFFER	*curbp;
XWINDOW	*wheadp;
XWINDOW	*curwp;
Xint	hooked;
Xint	*cur_line;
Xint	*cur_col;
Xint	nest_level;
XLISTV	*argv;
Xint	pflag = 0;
Xint	flush_flag = TRUE;
X/*-------------------*/
XMACRO	macro_tbl[MAX_MACROS];
Xu_int32	m_offsets[MAX_MACROS];
Xint	macro_cnt;
Xchar	*bpath;
Xextern	int	cm_running;
Xstruct f fps[MAX_FILES];
Xstruct	f	*fp_ptr;
Xint	a_flag = FALSE;
Xint l_flag = 0;
Xint L_flag = 0;		/* TRUE if we want more disassembly info.	*/
Xint	s_flag = FALSE;	/* TRUE if size info. only.			*/
Xint	nglobals;	/* Number of global statements found so far.	*/
Xu_int32	globals[MAX_GLOBALS]; /* Table of indexes to global statements.	*/
Xlong	nlist;		/* Number of list atoms.		*/
Xlong	nint;		/* Number of int atoms.			*/
Xlong	nstr;		/* Number of F_STR atoms.		*/
Xlong	nid;		/* Number of F_ID atoms.		*/
Xlong	nnull;		/* Number of flags==0 atoms.		*/
Xlong	ndontknow;	/* Number of Don't knows.		*/
Xlong	nhalt;		/* Number of HALT opcodes.		*/
X
Xextern DEFINE	*def_head,
X		*def_ptr;
Xextern int cm_version;
Xextern u_int32 WGET32();
Xextern u_int16 WGET16();
X
XFILE	*fp;			/* File pointer for output file.	*/
X
Xchar	buf[BUFSIZ];		/* Temporary working buffer.		*/
Xchar	*output_file;		/* Name of output file.			*/
XCM	cm_header = {CM_MAGIC};	/* Header for output file.		*/
Xint	string_count;		/* Count of literals in list.		*/
Xchar	**string_table;
Xchar	*str_table;		/* Pointer to string table for disassembly.*/
XLIST	*atom_start;		/* Pointer to base of compiled macro.	*/
Xint	atom_count;		/* Count of atoms in buffer.		*/
X
Xextern	BUILTIN builtin[];
Xextern	int	sizeof_builtin;
Xextern	BUILTIN *lookup_builtin();
X
Xint	do_switches();
Xvoid	usage();
X/*---------------------------------------
X *   Prototype definitions.
X *---------------------------------------*/
Xextern	char	*bsearch();
Xvoid	disassemble();
Xvoid	write_output_file();
Xint	init_fp();
Xint	yyparse();
Xvoid	list_macro();
Xvoid	delete_macro();
Xvoid	yyerror();
Xvoid	execute_macro();
X
Xmain(argc, argv)
Xchar	**argv;
X{	int	arg_index = do_switches(argc, argv);
X	int	len;
X	extern	int	dflag;
X	extern	char	*crisp_log;
X	MACRO	*mp;
X	static char	argv_buf[1024];
X	int	exit_status = 0;
X	int	print_msg;
X
X/*	dflag = 1;
X	crisp_log = "/dev/tty";*/
X
X	cm_running = TRUE;
X	if ((bpath = getenv("BPATH")) == NULL)
X		bpath = "/usr/local/crisp/macros";
X
X
X	fp_ptr = &fps[0]-1;
X	if (arg_index >= argc)
X		usage();
X	malloc_hack();
X	print_msg = arg_index < argc - 1;
X	for ( ; arg_index < argc; arg_index++) {
X		char	*file = argv[arg_index];
X		int	len = strlen(file);
X		atom_count = 0;
X		if (strlen(file) > 3 && strcmp(file + len -3, ".cm") == 0) {
X			disassemble(file);
X			continue;
X			}
X		if (print_msg)
X			printf("Compiling %s...\n", file);
X		if (init_fp(TERMINAL, file) < 0) {
X			perror(file);
X			continue;
X			}
X
X		macro_cnt = 0;
X		nglobals = 0;
X		if (yyparse() != 0) {
X			printf("Compilation of %s unsuccessful.\n", file);
X			exit_status = -1;
X			continue;
X			}
X
X		/*----------------------------------------------
X		 *   Open output file.
X		 *----------------------------------------------*/
X		if (output_file == NULL) {
X			if (len <= 2 || strcmp(file + len -2, ".m") != 0)
X				sprintf(buf, "%s.cm", file);
X			else
X				sprintf(buf, "%.*s.cm", len - 2, file);
X			output_file = buf;
X			}
X
X		write_output_file();
X		if (a_flag)
X			print_perc();
X		/*----------------------------------------------
X		 *   Dump internal form of macro if asked for.
X		 *----------------------------------------------*/
X		for (mp = macro_tbl; mp < &macro_tbl[macro_cnt]; mp++) {
X			if (l_flag) {
X				list_macro(0, mp->m_list);
X				printf("\n");
X				}
X			/*chk_free(mp->m_name);*/
X			/*chk_free(mp->m_list);*/
X			}
X
X		def_head = NULL;
X		def_ptr = NULL;
X		output_file = NULL;
X# ifdef MALLOC
X{		int	i;
X		static int loop_count = 0;
X		if (++loop_count < 10)
X			continue;
X		strcpy(argv_buf, "cm ");
X		if (arg_index + 1 >= argc)
X			continue;
X		for (i = arg_index+1; i < argc; i++) {
X			strcat(argv_buf, " ");
X			strcat(argv_buf, argv[i]);
X			}
X		argv[0] = "/bin/sh", argv[1] = "-c", argv[2] = argv_buf;
X		execv(argv[0], argv);
X		perror("execv");
X}
X# endif
X		}
X	return exit(exit_status);
X}
Xvoid
Xwrite_output_file()
X{
X	int	i;
X	u_int32	base;
X	long	ftell();
X	u_int32	offset;
X	LIST	*lp;
X
X	if ((fp = fopen(output_file, "w")) == NULL) {
X		perror(output_file);
X		exit(1);
X		}
X
X	if ((atom_start = (LIST *) chk_alloc(MAX_ATOMS)) == NULL) {
X		fprintf(stderr, "Not enough room to compile macros\n");
X		exit(1);
X		}
X	if ((string_table = (char **) chk_alloc(sizeof (char *) * MAX_STRINGS)) == NULL) {
X		fprintf(stderr, "Not enough room to allocate string table\n");
X		exit(1);
X		}
X
X	cm_header.cm_num_macros = macro_cnt;
X	cm_header.cm_version = cm_version;
X	if (fwrite((char *) &cm_header, sizeof (CM), 1, fp) != 1) {
Xoutput_error:
X		perror(output_file);
X		exit(1);
X		}
X
X	if (fwrite((char *) m_offsets, sizeof (u_int32), macro_cnt+2, fp) != 
X			macro_cnt+2)
X		goto output_error;
X
X	base = ftell(fp);
X	string_count = 0;
X	for (i = 0; i < macro_cnt; i++) {
X		int n = macro_tbl[i].m_size;
X		LIST	*lpend;
X		if (L_flag)
X			printf("\n*** Macro %d:\n", i);
X		lp = macro_tbl[i].m_list;
X		lpend = lp + n;
X		m_offsets[i] = (ftell(fp) - (long) base) / sizeof (LIST);
X		while (lp < lpend) {
X			char *str = "";
X			if (*lp == F_STR || *lp == F_LIT)
X				str = get_string(lp);
X			else if (*lp == F_ID) {
X				int id = LGET16(lp);
X				if (strcmp(builtin[id].name, "global") == 0) {
X					globals[nglobals++] = m_offsets[i] +
X						(lp - macro_tbl[i].m_list);
X					}
X				}
X			if (L_flag)
X				patom(macro_tbl[i].m_list, lp, str);
X			lp += sizeof_atoms[*lp];
X			}
X		if (fwrite((char *) macro_tbl[i].m_list, sizeof (LIST), n, fp) != n)
X			goto output_error;
X		}
X	if (ftell(fp) & 3)
X		fwrite("PAD", (int) (4 - (ftell(fp) & 3)), 1, fp);
X	m_offsets[macro_cnt] = ftell(fp) - (long) base;
X	m_offsets[macro_cnt+1] = string_count;
X	/*------------------------------------------
X	 *   Now write out table of string offsets from here.
X	 *------------------------------------------*/
X	for (offset = 0, i = 0; i < string_count; i++) {
X		u_int32 o = WGET32(offset);
X		if (fwrite((char *) &o, sizeof o, 1, fp) != 1)
X			goto output_error;
X		offset += strlen(string_table[i]) + 1;
X		}
X	/*------------------------------------------
X	 *   Now write out string table.
X	 *------------------------------------------*/
X	for (i = 0; i < string_count; i++) {
X		int	len = strlen(string_table[i]);
X		if (fwrite(string_table[i], len+1, 1, fp) != 1)
X			goto output_error;
X		}
X	if (ftell(fp) & 3)
X		fwrite("PAD", (int) (4 - (ftell(fp) & 3)), 1, fp);
X	cm_header.cm_globals = ftell(fp);
X	swap_words(globals, nglobals);
X	if (nglobals && fwrite((char *) globals, sizeof globals[0] * nglobals, 1, fp) != 1)
X		goto output_error;
X	rewind(fp);
X	cm_header.cm_num_atoms = atom_count;
X	cm_header.cm_num_globals = nglobals;
X	cm_header.cm_num_strings = string_count;
X	swap_cm_header(&cm_header);
X	if (fwrite((char *) &cm_header, sizeof (CM), 1, fp) != 1)
X		goto output_error;
X	swap_words(m_offsets, macro_cnt+2);
X	if (fwrite((char *) m_offsets, sizeof (u_int32), macro_cnt+2, fp) != 
X			macro_cnt+2)
X		goto output_error;
X	fclose(fp);
X
X	chk_free((char *) string_table);
X	chk_free((char *) atom_start);
X}
Xchar *
Xget_string(lp)
Xregister LIST	*lp;
X{
X	register char **cpp;
X	register char **cpend = &string_table[string_count];
X	char	*str = (char *) LGET32(lp);
X	static char buf[128];
X
X	for (cpp = string_table; cpp < cpend; cpp++)
X		if (**cpp == *str && strcmp(*cpp, str) == 0) {
X			strcpy(buf, str);
X			LPUT32(lp, (long) (cpp - string_table));
X			chk_free(str);
X			return buf;
X			}
X	*cpp = str;
X	LPUT32(lp, (long) string_count++);
X	return str;
X}
Xvoid
Xusage()
X{
X	fprintf(stderr, "Usage: cm [-aLl] [-o output_file] file-name ...\n\n");
X	fprintf(stderr, "	-a	Print atom percentages.\n");
X	fprintf(stderr, "	-l	List macro expansions.\n");
X	fprintf(stderr, "	-L	Print detailed disassembly info.\n");
X	fprintf(stderr, "	-q	Quiet error messages.\n");
X	fprintf(stderr, "	-s	Print size of .cm file only.\n");
X	fprintf(stderr,	"		(Use with .cm file only).\n");
X	fprintf(stderr, "	-o file	Name of compiled output file.\n");
X	exit(1);
X}
X
Xdo_switches(ac, av)
Xchar	**av;
X
X{
X	int	c;
X	extern char *optarg;
X	int	errflag = 0;
X	extern int optind;
X
X	while ((c = getopt(ac, av, "acLqldo:s")) != EOF)
X		switch (c) {
X			case 'a':	a_flag = TRUE; break;
X			case 'l':	l_flag = 1;	break;
X			case 'q': {
X				extern int verbose_errors;
X				verbose_errors = FALSE;
X				break;
X				}
X			case 'L':	L_flag = 1;	break;
X			case 'o':
X				output_file = optarg;
X				break;
X			case 's':	s_flag = TRUE;	break;
X			default:
X				errflag++;
X			}
X	
X	if (errflag)
X		usage();
X	return optind;
X}
Xmac_compare(mac1, mac2)
Xchar	*mac1;
XMACRO	*mac2;
X{
X	return strcmp(mac1, mac2->m_name);
X}
Xenter_macro(list)
XLIST	*list;
X{	register MACRO	*mptr;
X	char	name[64];
X
X	if (*list != F_STR) {
X		printf("Macro name must be an id\n");
X		return -1;
X		}
X	strncpy(name, (char *) LGET32(list), 64);
X	list += sizeof_atoms[F_STR];
X	if (macro_cnt && (mptr = (MACRO *) bsearch(name, macro_tbl, macro_cnt, 
X			sizeof macro_tbl[0], mac_compare)))
X		delete_macro(mptr->m_list);
X	else {
X		MACRO	*mp_end = &macro_tbl[macro_cnt];
X		if (macro_cnt >= MAX_MACROS-1) {
X			printf("Macro table full\n");
X			return -1;
X			}
X		for (mptr = macro_tbl; mptr < mp_end; mptr++)
X			if (strcmp(name, mptr->m_name) < 0) {
X				for ( ; mp_end >= mptr; mp_end--)
X					mp_end[1] = mp_end[0];
X				break;
X				}
X		macro_cnt++;
X		mptr->m_name = strdup(name);
X		}
X	mptr->m_list = list;
X	return 0;
X}
Xvoid
Xdelete_macro(list)
Xregister LIST	*list;
X{
X
X}
Xvoid
Xdisassemble(file)
Xchar	*file;
X{
X	FILE	*fp = fopen(file, "r");
X	int	i;
X	CM	*cm;
X	struct stat stat_buf;
X	u_int32	*vm_offsets;
X	u_int32	num_strings;
X	u_int32	*soffsets;
X	int	nm;
X	LIST	*lp;
X	LIST	*base_list;
X
X	printf("\n*** File: %s\n\n", file);
X	nhalt = nlist = nint = nstr = nid = nnull = ndontknow = 0;
X
X	if (fp == NULL || stat(file, &stat_buf) < 0) {
X		perror(file);
X		exit(1);
X		}
X	cm = (CM *) chk_alloc((unsigned) stat_buf.st_size);
X	if (read(fileno(fp), (char *) cm, (int) stat_buf.st_size) != 
X		(int) stat_buf.st_size) {
X		fprintf(stderr, "Read() error on .cm file");
X		exit(1);
X		}
X	if (cm->cm_version != cm_version) {
X		fprintf(stderr, ".cm file has wrong version number - %d\n",
X			cm->cm_version);
X		fprintf(stderr, "Current version is %d\n", cm_version);
X		exit(1);
X		}
X
X	vm_offsets = (u_int32 *) (cm + 1);
X	base_list = (LIST *) (vm_offsets + cm->cm_num_macros + 2);
X	num_strings = vm_offsets[cm->cm_num_macros + 1];
X	soffsets = (u_int32 *) (((char *) base_list) + 
X			vm_offsets[cm->cm_num_macros]);
X	str_table = (char *) (soffsets + num_strings);
X
X	if (cm->cm_magic != CM_MAGIC) {
X		fprintf(stderr, "%s: invalid magic number\n", file);
X		exit(1);
X		}
X	printf("Version of .cm  :	%d\n", cm->cm_version);
X	printf("Number of macros:	%d\n", cm->cm_num_macros);
X	printf("Number of globals:	%d\n", cm->cm_num_globals);
X	printf("Size		:	  %5ld	Header\n", (u_int32) (sizeof *cm));
X	printf("			  %5ld	Atoms\n",
X			(long) (sizeof (LIST) * cm->cm_num_atoms));
X	printf("			+ %5d	Strings\n", cm->cm_num_strings);
X	printf("			-------\n");
X	printf("			  %5ld\n", (u_int32) stat_buf.st_size);
X	if (s_flag)
X		goto end_of_function;
X
X	for (i = 0; i < cm->cm_num_macros; i++)
X		printf("Macro %d, offset = atom #%ld\n", i, vm_offsets[i]);
X	printf("String table starts at %08lx. No. of strings =%ld\n", 
X		vm_offsets[cm->cm_num_macros], num_strings);
X
X	for (nm = 0, lp = base_list; lp < base_list + cm->cm_num_atoms; ) {
X		char *str = (*lp == F_STR || *lp == F_LIT)
X			? str_table + soffsets[LGET32(lp)] : "";
X		if (strcmp(str, "macro") == 0 && l_flag)
X			printf("\n*** Macro %d:\n", nm++);
X		patom(base_list, lp, str);
X		lp += sizeof_atoms[*lp];
X		}
X
X	if (l_flag == 0)
X		goto end_of_function;
X	printf("String Table:\n");
X	for (i = 0; i < num_strings; i++)
X		printf("\tString %2d: Offset=%04lx '%s'\n", i, 
X			soffsets[i], str_table + soffsets[i]);
X	printf("\n");
Xend_of_function:
X	if (a_flag)
X		print_perc();
X	chk_free((char *) cm);
X}
X# define PC(x)	((x) * 100) / natoms
Xprint_perc()
X{	long	natoms = nlist + nint + nstr + nid + nnull + ndontknow + nhalt;
X	if (natoms == 0)
X		natoms = 1;
X	printf("\n");
X	printf("Number of F_HALT atoms :	  %5ld (%2ld%%)\n", 
X		nhalt, PC(nhalt));
X	printf("Number of F_LIST atoms :	  %5ld (%2ld%%)\n", 
X		nlist, PC(nlist));
X	printf("Number of F_INT atoms :		  %5ld (%2ld%%)\n", 
X		nint, PC(nint));
X	printf(
X"Number of F_STR atoms :		  %5ld (%2ld%%)   INT+STR=%ld (%2ld%%)\n", 
X		nstr, PC(nstr), nstr + nint, PC(nstr + nint));
X	printf("Number of F_ID atoms :		  %5ld (%2ld%%)\n", 
X		nid, PC(nid));
X	printf("Number of F_NULL atoms :	  %5ld (%2ld%%)\n", 
X		nnull, PC(nnull));
X	printf("Number of <DONT KNOW> atoms :	+ %5ld (%2ld%%)\n", 
X		nnull, PC(nnull));
X	printf("      				-------\n", natoms);
X	printf("TOTAL:				  %5ld\n", natoms);
X}
Xvoid
Xexecute_macro(lp)
XLIST	*lp;
X{	char	name[64];
X	char	*macro_keywd;
X	extern char	*strdup();
X	LIST	*lpn;
X	extern int 	sizeof_macro;
X
X	if (macro_cnt >= MAX_MACROS-1) {
X		printf("Macro table full\n");
X		return;
X		}
X	lpn = lp + sizeof_atoms[*lp];
X	if (*lpn != F_STR && *lpn != F_ID) {
X		yyerror("Macro must start with a name\n");
X		exit(1);
X		}
X	strcpy(name, *lpn == F_ID ? 
X			builtin[LGET16(lpn)].name : (char *) LGET32(lpn));
X	macro_keywd = *lp == F_ID ? 
X			builtin[LGET16(lp)].name : (char *) LGET32(lp);
X	if (strcmp(macro_keywd, "macro") != 0 && 
X	    strcmp(macro_keywd, "replacement") != 0)
X		return;
X	if (strcmp(macro_keywd, "macro") == 0 && *lpn == F_ID)
X		printf("Warning: '%s' redefines a builtin.\n", name);
X	macro_tbl[macro_cnt].m_name = strdup(name);
X	macro_tbl[macro_cnt].m_size = sizeof_macro;
X	atom_count += sizeof_macro;
SHAR_EOF
echo "End of part 3"
echo "File ./cm.c is continued in part 4"
echo "4" > s2_seq_.tmp
exit 0
-- 
=====================			Reuters Ltd PLC, 
Tel: +44 628 891313 x. 212		 Westthorpe House,
UUCP:     fox%marlow.uucp@idec.stc.co.uk  Little Marlow,
					   Bucks, England SL7 3RQ