v07i049: CRISP release 1.9 part 28/32

Brandon S. Allbery - comp.sources.misc allbery at uunet.UU.NET
Thu Jun 22 13:56:44 AEST 1989


Posting-number: Volume 7, Issue 49
Submitted-by: fox at marlow.UUCP (Paul Fox)
Archive-name: crisp1.9/part29



#!/bin/sh
# this is part 8 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file ./map.c continued
#
CurArch=8
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 ./map.c"
sed 's/^X//' << 'SHAR_EOF' >> ./map.c
X
Xcurrent_col(offset)
Xint	offset;
X{	int	col = 1;
X	LINE	*lp;
X	unsigned char	*cp;
X
X	lp = vm_lock_line(*cur_line);
X	cp = ltext(lp);
X	while (offset > 0) {
X		col += char_width(col, &offset, &cp);
X		}
X	vm_unlock(*cur_line);
X	return col;
X}
X
X
X/************************************************************************
X *                                                                      *
X *				current_offset                          *
X *				--------------                          *
X *                                                                      *
X *  Purpose:                                                            *
X *                                                                      *
X *     Convert current column position into an offset from the start    *
X *     of the line. If the fill is set and cursor is not on a valid     *
X *     character, fill the line with tabs/spaces so that it becomes     *
X *     valid.                                                           *
X *----------------------------------------------------------------------*
X *  Input Parameters:                                                   *
X *----------------------------------------------------------------------*
X *  Output:                                                             *
X *----------------------------------------------------------------------*
X *  Global variables modified:                                          *
X ************************************************************************/
X
Xcurrent_offset(col, fill)
Xregister int col;
X{	register int	pos = 1;
X	int	last_pos = 1;
X	int	i;
X	int	width = 0;
X	u_char *cp;
X	int len;
X
X	global_lp = vm_lock_line(*cur_line);
X	cp = ltext(global_lp);
X	i = len = llength(global_lp);
X	
X	while (pos <= col && len > 0) {
X/*		if (pos == col && *cp == '\t')*/
X		if (pos == col && *cp != 0x1b)
X			break;
X		width = char_width(pos, &len, &cp);
X		pos += width;
X		}
X	last_pos = pos - width;
X	i -= len;
X
X	virtual_space = pos != col;
X	if (!virtual_space || fill == FALSE) {
X		i = cp - ltext(global_lp);
X		if (fill == FALSE && pos > col)
X			i--;
X		vm_unlock(*cur_line);
X		return i;
X		}
X	/*-------------------------------------
X	 *   The following condition is true if cursor
X	 *   is past the end of the line. We can then 
X	 *   tab and space fill.
X	 *-------------------------------------*/
X	if (pos < col)
X		i = space_fill(global_lp, col - pos, i, pos);
X	else /*if (width == 1)*/ {
X		/*-------------------------------------
X	 	*   The following condition is true if cursor
X	 	*   is NOT past the end of the line. In
X	 	*   this case we can only space fill.
X	 	*-------------------------------------*/
X		if (len)
X			i = space_fill(global_lp, col - last_pos, i - 1, last_pos);
X		else
X			i = space_fill(global_lp, pos - col, i-1, col);
X		}
X	vm_unlock(*cur_line);
X	return i;
X}
Xtab_replace()
X{	int offset = current_offset(*cur_col, FALSE);
X	LINE	*lp = vm_lock_line(*cur_line);
X	int	result = FALSE;
X	if (lp->l_flags & L_FILE)
X		lnormal(lp, 0);
X	if (lp->l_text[offset] == '\t') {
X		int	col = *cur_col;
X		int	ntab = next_tab_stop(*cur_col);
X		current_offset(ntab - 1, TRUE);
X		*cur_col = ntab - 1;
X		ldelete((RSIZE) 1);
X		l_insert(' ');
X		*cur_col = col;
X		result = TRUE;
X		}
X	vm_unlock(*cur_line);
X	return result;
X}
Xnext_tab_stop(col)
Xint	col;
X{
X	register u_int16 *tp = curbp->b_tabs;
X	u_int16	tabstop;
X	u_int16	c;
X
X	while (*tp && *tp < col)
X		tp++;
X	if (*tp) 
X		return *tp;
X
X	if (tp > &curbp->b_tabs[1])
X		c = tp[-1], tabstop = tp[-1] - tp[-2];
X	else if (tp == &curbp->b_tabs[1])
X		c = tp[-1], tabstop = tp[-1];
X	else
X		c = 0, tabstop = 8;
X	while (c < col)
X		c += tabstop;
X	return c;
X}
SHAR_EOF
echo "File ./map.c is complete"
chmod 0444 ./map.c || echo "restore of ./map.c fails"
mkdir . >/dev/null 2>&1
echo "x - extracting ./math.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > ./math.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("@(#) math.c 1.10, (C) 1989 P. Fox");
X
XOPCODE	acc_type;
Xlong	accumulator;
X
X
Xcom_equ(op)
X{
X	com_equ1(op, (SYMBOL *) argv[1].l_sym);
X}
Xcom_equ1(op, sp)
Xregister SYMBOL *sp;
X{	long	rvalue;
X	LIST	*lp;
X	OPCODE type = argv[2].l_flags;
X
X	if (sp->s_type != F_LIST && type == F_NULL && (sp->s_flag & SF_POLY) == 0) {
X		ewprintf("Missing assignment value.");
X		return;
X		}
X	if (sp->s_type != type) {
X		if (sp->s_type == F_STR && type == F_RSTR)
X			goto ok_check;
X		if (type == F_NULL)
X			;
X		else if (op == NOOP && sp->s_flag & SF_POLY) {
X			if (sp->s_type == F_STR || sp->s_type == F_LIST)
X				r_dec(sp->s_str);
X			sp->s_str = NULL;
X			sp->s_type = type;
X			if (type == F_STR || type == F_LIST)
X				sp->s_str = r_init("");
X			}
X		else {
X			ewprintf("Mixed types in assignment: %s", sp->s_name);
X			return;
X			}
X		}
Xok_check:
X	if (type == F_INT)
X		rvalue = argv[2].l_int;
X	else if (type == F_LIST)
X		lp = (LIST *) get_str(2);
X	switch (op) {
X	  case NOOP:	
X			if (type == F_INT)
X				sp->s_int = rvalue; 
X			else if (type == F_RSTR) {
X				str_rassign(sp, argv[2].l_rstr);
X				str_acc_assign(argv[2].l_rstr->r_str, argv[2].l_rstr->r_used);
X				sp->s_type = F_STR;
X				}
X			else if (type == F_STR) {
X				char *cp = get_str(2);
X				str_assign(sp, cp);
X				strl_acc_assign(cp);
X				}
X			else if (type == F_NULL) {
X				if (sp->s_list) {
X					chk_free(sp->s_list);
X					sp->s_list = NULL;
X					}
X				}
X			else
X				list_assign(sp, lp);
X			break;
X	  case PLUS:	
X			if (type == F_STR) {
X				sp->s_str = r_cat(sp->s_str, get_str(2));
X				str_acc_assign(sp->s_str->r_str, sp->s_str->r_used);
X				}
X			else if (type == F_RSTR) {
X				sp->s_str = r_cat(sp->s_str, argv[2].l_rstr->r_str);
X				str_acc_assign(sp->s_str->r_str, sp->s_str->r_used);
X				}
X			else
X				sp->s_int += rvalue; 
X			break;
X	  case MINUS:	sp->s_int -= rvalue; break;
X	  case MULTIPLY:	sp->s_int *= rvalue; break;
X	  case DIVIDE:	
X			if (rvalue == 0)
X				rvalue = 1;
X			sp->s_int /= rvalue; 
X			break;
X	  case MODULO:	
X			if (rvalue == 0)
X				rvalue = 1;
X			sp->s_int %= rvalue; 
X			break;
X	  case BAND:	sp->s_int &= rvalue; break;
X	  case BOR:	sp->s_int |= rvalue; break;
X	  case BXOR:	sp->s_int ^= rvalue; break;
X	  }
X	accumulator = sp->s_int;
X	trace_sym(sp);
X	return;
X}
X
Xminusminus()
X{
X	accumulator = --argv[1].l_sym->s_int;
X	return 0;
X}
Xplusplus()
X{
X	accumulator = ++argv[1].l_sym->s_int;
X	return 0;
X}
Xlnot()
X{	
X	accumulator = !argv[1].l_int;
X	return 0;
X}
Xcom_op(op)
X{	long	op1 = argv[1].l_int,
X		op2 = argv[2].l_int;
X	OPCODE	type;
X	extern char *command_name;
X
X	if (argv[1].l_flags == F_INT && argv[2].l_flags == F_INT)
X		type = F_INT;
X	else if ((argv[1].l_flags == F_STR || argv[1].l_flags == F_RSTR) 
X		 && (argv[2].l_flags == F_STR || argv[2].l_flags == F_RSTR))
X		type = F_STR;
X	else if (op != BNOT) {
X		ewprintf("%s: invalid parameters.", command_name);
X		return -1;
X		}
X
X	switch (op) {
X	case	PLUS:	
X			if (type == F_INT)
X				accumulator = op1 + op2; 
X			else {
X				char *str1 = get_str(1);
X				char *str2 = get_str(2);
X				int len_1 = get_len(1);
X				int len_2 = get_len(2);
X				str_acc_assign(str1, len_1 + len_2);
X				memcpy(saccumulator+len_1, str2, len_2);
X				}
X			break;
X	case	MINUS:	
X			accumulator = op1 - op2; 
X			break;
X	case	MULTIPLY:	
X			accumulator = op1 * op2; 
X			break;
X	case	DIVIDE:	
X			accumulator = op1 / (op2 ? op2 : 1); 
X			break;
X	case	MODULO:	
X			accumulator = op1 % (op2 ? op2 : 1); 
X			break;
X	case	EQ:	
X			if (type == F_INT)
X				accumulator = op1 == op2; 
X			else
X				accumulator = strcmp(get_str(1), get_str(2)) == 0;
X			break;
X	case	NE:	
X			if (type == F_INT)
X				accumulator = op1 != op2; 
X			else
X				accumulator = strcmp(get_str(1), get_str(2)) != 0;
X			break;
X	case	LT:	
X			if (type == F_INT)
X				accumulator = op1 < op2; 
X			else
X				accumulator = strcmp(get_str(1), get_str(2)) < 0;
X			break;
X	case	LE:	
X			if (type == F_INT)
X				accumulator = op1 <= op2; 
X			else
X				accumulator = strcmp(get_str(1), get_str(2)) <= 0;
X			break;
X	case	GT:	
X			if (type == F_INT)
X				accumulator = op1 > op2; 
X			else
X				accumulator = strcmp(get_str(1), get_str(2)) > 0;
X			break;
X	case	GE:
X			if (type == F_INT)
X				accumulator = op1 >= op2; 
X			else
X				accumulator = strcmp(get_str(1), get_str(2)) >= 0;
X			break;
X	case	ABOVE:
X			if (type == F_INT)
X				accumulator = (unsigned long) op1 > 
X					(unsigned long) op2; 
X			else
X				accumulator = strcmp(get_str(1), get_str(2)) > 0;
X			break;
X	case	ABOVE_EQ:
X			if (type == F_INT)
X				accumulator = (unsigned long) op1 >= 
X					(unsigned long) op2; 
X			else
X				accumulator = strcmp(get_str(1), get_str(2)) >= 0;
X			break;
X	case	BELOW:
X			if (type == F_INT)
X				accumulator = (unsigned long) op1 < 
X					(unsigned long) op2; 
X			else
X				accumulator = strcmp(get_str(1), get_str(2)) < 0;
X			break;
X	case	BELOW_EQ:
X			if (type == F_INT)
X				accumulator = (unsigned long) op1 <= 
X					(unsigned long) op2; 
X			else
X				accumulator = strcmp(get_str(1), get_str(2)) <= 0;
X			break;
X	case	BAND:
X			accumulator = argv[1].l_int & argv[2].l_int;
X			break;
X	case	BOR:
X			accumulator = argv[1].l_int | argv[2].l_int;
X			break;
X	case	BXOR:
X			accumulator = argv[1].l_int ^ argv[2].l_int;
X			break;
X	case	BNOT:
X			accumulator = ~argv[1].l_int;
X			break;
X
X
X	  }
X	return 0;
X}
Xdo_strlen()
X{
X	accumulator = get_len(1);
X	return 0;
X}
Xdo_atoi()
X{	char *cp = get_str(1);
X	if (argv[2].l_flags == F_NULL || argv[2].l_int)
X		accumulator = (int) atoi(cp);
X	else
X		accumulator = *cp;
X	return 0;
X}
Xstring_count()
X{	register char	*str1 = get_str(1);
X	register char	*str2 = get_str(2);
X	char *strchr();
X
X	accumulator = 0;
X	while (*str1) {
X		if (strchr(str2, *str1++))
X			accumulator++;
X		}
X}
Xvoid
Xdo_index()
X{
X	extern	char	*instr();
X	char	*cp;
X	char	*cp2 = get_str(2);
X	char	*str1 = get_str(1);
X
X	accumulator = 0;
X	if (*cp2 == NULL)
X		accumulator = strlen(str1) + 1;
X	else if (cp = instr(str1, cp2))
X		accumulator = cp - str1 + 1;
X}
Xdo_rindex()
X{
X	extern	char	*instr();
X	char	*cp;
X	char	*str1 = get_str(1);
X	char	*str2 = get_str(2);
X	int	len = get_len(2);
X
X	accumulator = 0;
X	for (cp = str1+strlen(str1)-1; cp >= str1; cp--)
X		if (strncmp(cp, str2, len) == 0) {
X			accumulator = cp - str1 + 1;
X			break;
X			}
X	return 0;
X}
Xsubstr()
X{	char *str1 = get_str(1);
X	int	len1 = get_len(1);
X	int	offset = argv[2].l_flags == F_INT ? argv[2].l_int - 1 : 0;
X	char	*cp;
X
X	if (offset < 0)
X		offset = 0;
X	else if (offset > len1)
X		offset = len1;
X	cp = str1 + offset;
X	len1 = argv[3].l_flags == F_NULL ? strlen(cp) : (int) argv[3].l_int;
X	str_acc_assign(cp, argv[2].l_int ? len1 : 0);
X	return 0;
X}
Xcompress()
X{	register char	*cp;
X	register char	*cp1;
X	strl_acc_assign(get_str(1));
X	cp = saccumulator;
X	while (*cp) {
X		for (cp1 = cp; isspace(*cp1) || *cp1 == '\n'; )
X			cp1++;
X		if (*cp1 != *cp) {
X			strcpy(cp+1, cp1);
X			*cp = ' ';
X			}
X		cp++;
X		}
X	return 0;
X}
Xtrim()
X{	register char *cp;
X	int len = get_len(1);
X
X	str_acc_assign(get_str(1), len);
X	cp = saccumulator + len - 1;
X	while (cp >= saccumulator && (*cp == ' ' || *cp == '\t' || *cp == '\n'))
X		*cp-- = NULL;
X	return 0;
X}
Xltrim()
X{	register char *cp = get_str(1);
X
X	while (*cp == ' ' || *cp == '\t' || *cp == '\n')
X		cp++;
X	strl_acc_assign(cp);
X	return 0;
X}
Xandand()
X{	LISTV	result;
X
X	accumulator = 0;
X	if (argv[1].l_int == 0)
X		return 0;
X	if (eval(argv[2].l_list, &result) != F_INT)
X		return -1;
X	accumulator = result.l_int;
X	return 0;
X}
Xoror()
X{	LISTV	result;
X
X	accumulator = 1;
X	if (argv[1].l_int)
X		return 0;
X	if (eval(argv[2].l_list, &result) != F_INT)
X		return -1;
X	accumulator = result.l_int;
X	return 0;
X}
SHAR_EOF
chmod 0444 ./math.c || echo "restore of ./math.c fails"
mkdir . >/dev/null 2>&1
echo "x - extracting ./phys_term.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > ./phys_term.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 *	24 Jan 89 [PDF]		Added support for ESC [ n C
X **************************************************************/
X
X# include	"list.h"
X# include	<ctype.h>
X# include	"alt.h"
X
XSCCSID("@(#) phys_term.c 1.12, (C) P. Fox");
X
Xextern char	*K[NFKEYS];
XPHYS_TERM	pt;
Xextern LIST	*next_atom();
Xstatic st_key();
X
Xstruct pt_map {
X	int	isbool;
X	char	*ptr;
X	};
X	
Xstruct pt_map pt_chars[] = {
X	FALSE,		pt.pt_top_left,
X	FALSE,		pt.pt_top_right,
X	FALSE,		pt.pt_bot_left,
X	FALSE,		pt.pt_bot_right,
X	FALSE,		pt.pt_vertical,
X	FALSE,		pt.pt_horizontal,
X	FALSE,		pt.pt_top_join,
X	FALSE,		pt.pt_bot_join,
X	FALSE,		pt.pt_cross,
X	FALSE,		pt.pt_left_join,
X	FALSE,		pt.pt_right_join,
X	NULL,		NULL
X	};
Xstruct pt_map pt_features[] = {
X	FALSE,		pt.pt_space,
X	FALSE,		pt.pt_character,
X	FALSE,		pt.pt_icursor,
X	FALSE,		pt.pt_ocursor,
X	FALSE,		pt.pt_vicursor,
X	FALSE,		pt.pt_vocursor,
X	FALSE,		pt.pt_escape,
X	FALSE,		pt.pt_repeat,
X	TRUE,		&pt.pt_0m,
X	TRUE,		&pt.pt_color,
X	FALSE,		pt.pt_escC,
X	NULL,		NULL
X	};
Xset_display_chars()
X{	LISTV	result;
X	register LIST	*lp = argv[1].l_list;
X	int	type;
X	int	i = 0;
X	extern char *ctrl_chars[];
X	char	*strdup();
X	
X	for ( ; lp && *lp != F_HALT; lp = next_atom(lp)) {
X		type = eval(lp, &result);
X		if (type != F_STR && type != F_LIT)
X			continue;
X		if (i > 31)
X			break;
X		ctrl_chars[i++] = strdup(result.l_str);
X		}
X	char_width_init();
X}
Xst_characters()
X{
X	return st_common(pt_chars);
X}
Xst_features()
X{
X	return st_common(pt_features);
X}
Xst_common(p)
Xregister struct pt_map *p;
X{	LISTV	result;
X	register LIST	*lp = argv[1].l_list;
X	int	type;
X
X	for ( ; lp && *lp != F_HALT && p->ptr; p++, lp = next_atom(lp)) {
X		char	*cp = "";
X		type = eval(lp, &result);
X		if (p->isbool) {
X			*p->ptr = (char) result.l_int;
X			continue;
X			}
X		if (type == F_INT) {
X			p->ptr[0] = (char) result.l_int;
X			p->ptr[1] = NULL;
X			continue;
X			}
X		if (type == F_NULL)
X			continue;
X		if (type == F_STR || type == F_LIT)
X			cp = result.l_str;
X		else if (type == F_RSTR)
X 			cp = result.l_rstr->r_str;
X		tcopy_string(p->ptr, cp, NULL);
X		}
X
X}
Xst_keyboard()
X{	LISTV	result;
X	int	key_no;
X	LIST	*lp = argv[1].l_list;
X	LIST	*lp1;
X	int	type;
X
X	for (; lp && *lp != F_HALT; lp = next_atom(lp)) {
X		type = eval(lp, &result);
X		if (type != F_INT)
X			break;
X		key_no = result.l_int;
X		lp += sizeof_atoms[*lp];
X		type = eval(lp, &result);
X		if (type != F_LIST) {
X			st_key(key_no, &result);
X			continue;
X			}
X		lp1 = result.l_list;
X		while (lp1 && *lp1 != F_HALT) {
X			char *cp;
X			long l;
X			r_str *rp;
X
X 			result.l_flags = (OPCODE) *lp1;
X			switch (*lp1) {
X			  case F_INT:
X				cp = chk_alloc(2);
X				l = LGET32(lp1);
X				cp[0] = l;
X				cp[1] = NULL;
X				K[key_no - KFIRST] = cp;
X				break;
X			  case F_STR: case F_LIT:
X				K[key_no - KFIRST] = strdup((char *) LGET32(lp1));
X				break;
X			  case F_RSTR:
X				rp = (r_str *) LGET32(lp1);
X				K[key_no - KFIRST] = strdup(rp->r_str);
X				break;
X			  }
X			lp1 = next_atom(lp1);
X			key_no++;
X			}
X		}
X}
Xstatic
Xst_key(key_no, result)
XLISTV	*result;
X{	char	*cp;
X
X	switch (result->l_flags) {
X	  case F_INT:
X		cp = chk_alloc(2);
X		cp[0] = result->l_int;
X		cp[1] = NULL;
X		K[key_no - KFIRST] = cp;
X		break;
X	  case F_STR: case F_LIT:
X		K[key_no - KFIRST] = strdup(result->l_str);
X		break;
X	  case F_RSTR:
X		K[key_no - KFIRST] = strdup(result->l_rstr->r_str);
X		break;
X	  }
X}
Xgt_characters()
X{
X	gt_common(pt_chars);
X}
Xgt_common(pt)
Xregister struct	pt_map	*pt;
X{	register int	i;
X	for (i = 0; pt[i].ptr; i++)
X		if (argv[i+1].l_flags != F_NULL) {
X			if (pt[i].isbool)
X				int_assign(argv[i+1].l_sym, pt_chars[i].ptr);
X			else
X				str_assign(argv[i+1].l_sym, pt_chars[i].ptr);
X			}
X}
Xgt_keyboard()
X{
X}
Xgt_features()
X{
X	gt_common(pt_features);
X}
SHAR_EOF
chmod 0444 ./phys_term.c || echo "restore of ./phys_term.c fails"
mkdir . >/dev/null 2>&1
echo "x - extracting ./playback.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > ./playback.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("@(#) playback.c 1.7, (C) 1989, P. Fox");
X# define	MAX_STORAGE	512
X# define	MAX_KMACROS	20
X
Xstatic struct playback {
X	int	buffer_id;
X	r_str		*macro;
X	unsigned char	*ip;
X	unsigned char	*op;
X	} kmacs[MAX_KMACROS];
Xstatic	struct playback *ptr_info = NULL;
Xint	last_rem_index = 0;
Xint	defining_macro = FALSE;
Xint	playing_back = FALSE;
Xint	rem_nest_level = -1;
Xint	rem_doing_self_insert;
Xchar	*rem_string = "  ";
Xint	rem_size = MAX_STORAGE;
X
Xvoid
Xdo_pause()
X{
X	if (defining_macro)
X		rem_string = *rem_string == 'P' ? "RE" : "PA";
X	else if (playing_back)
X		rem_string = *rem_string == 'P' ? "  " : "PA";
X	else
X		return;
X	line_col(TRUE);
X}
Xvoid
Xremember()
X{
X	char ch = argv[1].l_flags == F_NULL ? 0 : get_str(1)[0];
X	int	mac_no = argv[2].l_int;
X	r_str *r_alloc();
X	
X	if (playing_back)
X		return;
X	if (!defining_macro && argv[2].l_flags == F_NULL) {
X		if (last_rem_index >= MAX_KMACROS)
X			last_rem_index = 0;
X		mac_no = last_rem_index++;
X		}
X		
X	if (mac_no < 0 || mac_no >= MAX_KMACROS)
X		return;
X	ptr_info = &kmacs[mac_no];
X	
X	if (ptr_info->buffer_id == 0) {
X		char	buf[20];
X		BUFFER	*bp;
X		char	*filename();
X		sprintf(buf, "KBD-MACRO-%d", mac_no);
X		bp = bfind(filename(buf), TRUE);
X		bp->b_flag |= BFREAD;
X		ptr_info->buffer_id = bp->b_bufnum;
X		}
X	
X	if (!defining_macro) {
X 		if (ptr_info->macro == NULL) {
X			ptr_info->macro = r_alloc(rem_size);
X			if (ch == 'n' || ch == 'N')
X				return;
X			ewprintf("Defining keystroke macro.");
X			rem_string = "RE";
X			}
X		else {
X			if (ch == 'y' || ch == 'Y' ||
X		       eyorn("Overwrite existing keystroke macro")) {
X				ewprintf("Defining keystroke macro.");
X				rem_string = "RE";
X				}
X			else
X				return;
X			}
X		defining_macro = TRUE;
X		ptr_info->macro->r_used = 0;
X		bclear(numberb(ptr_info->buffer_id));
X		rem_nest_level = -1;
X		rem_doing_self_insert = FALSE;
X		}
X	else {
X		defining_macro = FALSE;
X		ewprintf("Keystroke macro defined.");
X		rem_string = "  ";
X		}
X
X	ptr_info->ip = (unsigned char *) ptr_info->macro->r_str;
X	line_col(TRUE);
X}
Xvoid
Xplayback()
X{	int mac_no = argv[1].l_int;
X
X	if (argv[1].l_flags == F_NULL)
X		mac_no = last_rem_index - 1;
X	if (playing_back || mac_no < 0 || mac_no >= MAX_KMACROS || 
X	   kmacs[mac_no].buffer_id == 0)
X		return;
X	if (defining_macro) {
X		infof("Can't play back while remembering.");
X		accumulator = -1;
X		return;
X		}
X	infof("Playing back keystroke macro.");
X	playing_back = TRUE;
X	ptr_info = &kmacs[mac_no];
X	ptr_info->op = (unsigned char *) ptr_info->macro->r_str;
X}
Xvoid
Xremember_macro(cp, list_flag)
Xchar *cp;
X{
X	BUFFER *saved_bp = curbp;
X	
X	if (!defining_macro || rem_string[0] == 'P')
X		return;
X	if (rem_nest_level == -1)
X		rem_nest_level = nest_level;
X	else if (rem_nest_level != nest_level)
X		return;
X		
X	curbp = numberb(ptr_info->buffer_id);
X	set_hooked();
X	curbp->b_system = 1;
X	if (list_flag) {
X		char *msg = "/* LIST -- not implemented feature */";
X		llinsert(msg, strlen(msg), TRUE);
X		}
X	else {
X		if (*cp == 's' && strcmp(cp, "self_insert") == 0) {
X			char buf[5];
X			char *bp = buf;
X			extern char character;
X			if (rem_doing_self_insert) {
X				switch (character) {
X				  case '\\':
X				  case '"':
X					*bp++ = '\\';
X					break;
X				  }
X				*bp++ = character;
X				llinsert(buf, bp - buf, FALSE);
X				}
X			else {
X				llinsert("(insert", 7, FALSE);
X				*bp++ = ' ';
X				*bp++ = '"';
X				switch (character) {
X				  case '\\':
X				  case '"':
X					*bp++ = '\\';
X					break;
X				  }
X				*bp++ = character;
X				llinsert(buf, bp - buf, FALSE);
X				rem_doing_self_insert = TRUE;
X				}
X			}
X		else {
X			if (rem_doing_self_insert)
X				llinsert("\")", 2, TRUE);
X			if (*cp == 'r' && strcmp(cp, "remember") == 0) {
X				char *msg = "/* End of macro */";
X				llinsert(msg, strlen(msg), TRUE);
X				}
X			else {
X				llinsert("(", 1, FALSE);
X				llinsert(cp, strlen(cp), FALSE);
X				llinsert(")", 1, TRUE);
X				}
X			rem_doing_self_insert = FALSE;
X			}
X		}
X		
X	curbp->b_system = 0;
X	curbp = saved_bp;
X	set_hooked();
X}
Xvoid
Xstore_char(ch)
X{
X	if (defining_macro && rem_string[0] != 'P') {
X		if (ptr_info->ip < (unsigned char *)
X			&ptr_info->macro->r_str[rem_size]) {
X			ptr_info->macro->r_used++;
X			*ptr_info->ip++ = ch;
X			}
X		else {
X			ewprintf("Maximum keystroke length reached.");
X			defining_macro = FALSE;
X			ptr_info->ip = NULL;
X			}
X		}
X}
Xgrab_char()
X{
X	if (playing_back) {
X		if (*rem_string == 'P')
X			return 0;
X		if (ptr_info->op >= (unsigned char *) 
X				&ptr_info->macro->r_str[ptr_info->macro->r_used]) {
X			playing_back = FALSE;
X			u_chain();
X			infof("Playback successful.");
X			return 0;
X			}
X		return *ptr_info->op++;
X		}
X	return 0;
X}
X
X
SHAR_EOF
chmod 0444 ./playback.c || echo "restore of ./playback.c fails"
mkdir . >/dev/null 2>&1
echo "x - extracting ./pty.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > ./pty.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	"alt.h"
X# include	<signal.h>
X# if	!defined(VMS)
X# 	include	<termio.h>
X# endif
X# include	"clk.h"
XSCCSID("@(#) pty.c 1.15, (C) P. Fox");
Xextern	BYTE	*blanks;
X
X# define	BOLD	0x01
X# define	REVERSE	0x02
X
X# define	POLL_TIME	1	/* Seconds between polls.	*/
X# define	BIT(x)	(1 << (x))
X
Xstatic int entry = 0;
Xextern long	sel_bits;
Xstatic char *flush_pty_buf();
Xstatic void p_update();
Xvoid	p_clear_screen();
Xvoid	p_escape();
Xvoid	p_newline();
Xvoid	p_scroll();
Xvoid	p_tab();
Xvoid	p_poll();
Xstatic	dup2();
Xint	pty = TRUE;
Xint	num_pty = 0;
Xint	mapped = FALSE;
X
Xinq_process_position()
X{
X	if (curbp->b_display == NULL) {
X		accumulator = -1;
X		return;
X		}
X	accumulator = 0;
X	if (argv[1].l_flags != F_NULL)
X		int_assign(argv[1].l_sym, curbp->b_display->d_line_marker);
X	if (argv[2].l_flags != F_NULL)
X		int_assign(argv[2].l_sym, curbp->b_display->d_col_marker);
X}
Xset_process_position()
X{	int	line = argv[1].l_int > curbp->b_numlines
X			? curbp->b_numlines
X			: argv[1].l_int;
X
X	if (curbp->b_display == NULL) {
X		accumulator = -1;
X		return;
X		}
X	accumulator = 0;
X	if (argv[1].l_flags != F_NULL) {
X		curbp->b_display->d_line_marker = line;
X		curbp->b_display->d_col_marker = 1;
X		}
X	if (argv[2].l_flags != F_NULL)
X		curbp->b_display->d_col_marker = argv[2].l_int;
X}
XDISPLAY *
Xp_create(x, y)
X{
X	DISPLAY	*dp = (DISPLAY *)  chk_alloc(sizeof (DISPLAY));
X	int	i;
X
X	if (dp == NULL)
X		return (DISPLAY *) NULL;
X	dp->d_display = (BYTE *) chk_alloc(sizeof (BYTE) * nrow * ncol);
X	if (dp->d_display == NULL) {
X		chk_free((char *) dp);
X		return (DISPLAY *) NULL;
X		}
X	dp->d_line = (BYTE **) chk_alloc(sizeof (BYTE *) * nrow);
X	if (dp->d_line == NULL) {
X		chk_free((char *) dp->d_display);
X		chk_free((char *) dp);
X		return (DISPLAY *) NULL;
X		}
X	dp->d_escptr = NULL;
X	dp->d_flags = 0;
X	dp->d_x = dp->d_y = 0;
X	dp->d_rows = (short) y;
X	dp->d_cols = (short) x;
X	dp->d_color = FG(WHITE);
X	dp->d_attr = 0;
X	dp->d_wlen = 0;
X	dp->d_waitfor = (char *) NULL;
X	dp->d_line_marker = 1;
X	dp->d_col_marker = 1;
X
X	dp->d_line[0] = dp->d_display;
X	for (i = 1; i < nrow; i++)
X		dp->d_line[i] = dp->d_line[i-1] + ncol;
X
X	p_clear_screen(dp);
X
X	return dp;
X}
Xp_enter()
X{
X	if (entry == 0) {
X		entry++;
X		return TRUE;
X		}
X	return FALSE;
X
X}
Xp_leave()
X{
X	entry--;
X
X}
Xvoid
Xp_destroy(bp)
XBUFFER	*bp;
X{
X	if (bp->b_display) {
X		chk_free((char *) bp->b_display->d_line);
X		chk_free((char *) bp->b_display->d_display);
X		chk_free((char *) bp->b_display);
X		if (bp->b_display->d_waitfor)
X			chk_free(bp->b_display->d_waitfor);
X		bp->b_display = NULL;
X		}
X}
Xstatic int tmo_wait_for;
Xp_wait_for_tmo()
X{
X	tmo_wait_for = TRUE;
X}
Xp_wait()
X{
X	p_wait_common(0L, F_LIT, "", TRUE);
X	if (argv[1].l_flags != F_NULL)
X		int_assign(argv[1].l_sym, curbp->b_wstat);
X	
X}
Xp_wait_for()
X{				      
X 	p_wait_common(argv[1].l_flags == F_NULL ? 0l : argv[1].l_int,
X			argv[2].l_flags,
X			(LIST *) get_str(2), FALSE);
X}
Xp_wait_common(tmo, type, lp, waiting)
Xlong	tmo;
XLIST	*lp;
X{
X# if	defined(VMS)
X	return;
X# else
X	char	buf[2];
X	extern long accumulator;
X# define	QUEUE_SIZE 32
X	char	queue[QUEUE_SIZE+1];
X	int	i;
X	int	len;
X	char	*str_arg = NULL;
X	int	fd = curbp->b_display->d_pipe_in;
X	int	flags = fcntl(fd, F_GETFL, 0);
X	extern int case_flag;
X	extern int magic;
X	extern REGEXP *prog;
X	extern int child_sig;
X	char	*qp;
X
X	accumulator = -1;
X	if (curbp->b_display == NULL) {
X		if (!waiting)
X			ewprintf("cannot wait on a normal buffer.");
X		return;
X		}
X
X	if (type != F_LIST)
X		str_arg = (char *) lp;
X	tmo_wait_for = FALSE;
X	curbp->b_display->d_flags |= P_WAIT;
X	buf[1] = NULL;
X	queue[QUEUE_SIZE] = NULL;
X	qp = &queue[QUEUE_SIZE];
X	if (tmo)
X		clk_timeout(p_wait_for_tmo, 0, tmo SECONDS);
X	len = QUEUE_SIZE;
X	if (str_arg && (prog = regcomp(str_arg)) == NULL)
X		goto end_of_function;
X
X	while (clock_check()) {
X		int	n;
X		LIST	*lp1;
X
X		if (tmo_wait_for || curbp->b_display == NULL) {
X			accumulator = -1;
X			break;
X			}
X		if (typeahead()) {
X			break;
X			}
X		/*----------------------------------------
X		/*   There is a race condition in the code
X		/*   below and I dont know how to solve it
X		/*   portably. Hopefully the window is too
X		/*   small to cause a problem.
X		/*----------------------------------------*/
X		if (child_sig)
X			i = -1;
X		else {
X			fcntl(fd, F_SETFL, flags & ~O_NDELAY);
X			if (child_sig)
X				i = -1;
X			i = read(fd, buf, 1);
X			fcntl(fd, F_SETFL, flags);
X			}
X		if (i != 1) {
X			update();
X			if (check_if_died(curbp)) {
X				break;
X				}
X			i = read(fd, buf, 1);
X			}
X		if (i != 1)
X			continue;
X		p_update(curbp, buf);
X		if (waiting)
X			continue;
X
X		memcpy(queue, queue+1, QUEUE_SIZE - 1);
X		queue[QUEUE_SIZE - 1] = buf[0];
X		if (qp > queue)
X			qp--;
X		if (len > 0)
X			len--;
X		if (str_arg) {
X			if (regexec(prog, qp, strlen(qp)) == TRUE) {
X				accumulator = 1;
X				break;
X				}
X			continue;
X			}
X		for (n = 0, lp1 = lp; *lp1 != F_HALT; n++, lp1 += sizeof_atoms[*lp1]) {
X			char *str;
X			if (*lp1 == F_STR || *lp1 == F_LIT)
X				str = (char *) LGET32(lp1);
X			else if (*lp1 == F_RSTR)
X				str = ((r_str *) LGET32(lp1))->r_str;
X			else
X				continue;
X			if ((prog = regcomp(str)) == NULL)
X				goto end_of_function;
X
X			qp = queue + QUEUE_SIZE - strlen(str);
X			if (regexec(prog, qp, strlen(qp)) == TRUE) {
X				accumulator = n;
X				goto end_of_function;
X				}
X			}
X		}
Xend_of_function:
X	update();
X	if (curbp->b_display)
X		curbp->b_display->d_flags &= ~P_WAIT;
X	clk_remove(p_wait_for_tmo);
X# endif
X}
Xstatic void
Xp_update(bp, buf)
XBUFFER	*bp;
Xchar	*buf;
X{	WINDOW	*wp;
X
X	p_addstr(bp, buf);
X	for (wp = wheadp; wp; wp = wp->w_wndp)
X		if (wp->w_bufp == bp) {
X			wp->w_flag |= WFHARD;
X			wp->w_line = bp->b_display->d_line_marker;
X			}
X}
Xvoid
Xp_addstr(bp, str)
XBUFFER	*bp;
Xchar	*str;
X{	register DISPLAY *dp = bp->b_display;
X	BUFFER *saved_bp = curbp;
X	int	pos;
X	int	cursor_moved = FALSE;
X	int	orig_line;
X	int	saved_system = bp->b_system;
X	char	*start_ptr = NULL;
X	
X	curbp = bp;
X	curbp->b_system = TRUE;
X
X	set_hooked();
X	pos = current_col(llength(linep(*cur_line))) - *cur_col;
X	orig_line = *cur_line;
X	*cur_line = dp->d_line_marker;
X	if (*cur_line > curbp->b_numlines)
X		*cur_line = curbp->b_numlines;
X	*cur_col = dp->d_col_marker;
X
X	for ( ; *str; str++) {
X		if (dp->d_escptr) {
X			*dp->d_escptr++ = *str;
X			if (isalpha(*str) || dp->d_escape[0] != '[') {
X				*dp->d_escptr = NULL;
X				cursor_moved = TRUE;
X				p_escape(dp, TRUE);
X				}
X			continue;
X			}
X		switch (*str) {
X		  case ESC:
X		  	start_ptr = flush_pty_buf(start_ptr, str);
X			dp->d_escptr = dp->d_escape;
X			break;
X		  case 0x07:
X		  	start_ptr = flush_pty_buf(start_ptr, str);
X		  	ttbeep();
X			break;
X		  case '\r':
X		  	start_ptr = flush_pty_buf(start_ptr, str);
X		  	break;
X		  case '\n':
X		  	start_ptr = flush_pty_buf(start_ptr, str);
X		  	if (*cur_line < curbp->b_numlines) {
X				(*cur_line)++;
X				*cur_col = 1;
X				break;
X				}
X		  	linsert(str, 1);
X			break;
X		  case '\b':
X		  	start_ptr = flush_pty_buf(start_ptr, str);
X		  	if (*cur_col > 1)
X				(*cur_col)--;
X			break;
X		  case '\f':
X		  	start_ptr = flush_pty_buf(start_ptr, str);
X			p_clear_screen(dp);
X			break;
X		  default:
X		  	if (start_ptr == NULL)
X				start_ptr = str;
X			break;
X		  }
X		}
X  	start_ptr = flush_pty_buf(start_ptr, str);
X	dp->d_line_marker = *cur_line;
X	dp->d_col_marker = *cur_col;
X	if (!cursor_moved) {
X		if (*cur_line != orig_line)
X			pos = 0;
X		*cur_col = current_col(llength(linep(*cur_line))) - pos;
X		if (hooked)
X			set_buffer_parms(curwp, bp);
X		}
X	curbp->b_system = saved_system;
X	curbp = saved_bp;
X	set_hooked();
X}
Xstatic char *
Xflush_pty_buf(start, end)
Xchar	*start;
Xchar *end;
X{	LINE *lp = linep(*cur_line);
X	int	coff;
X	RSIZE 	diff;
X	int	len;
X	
X	if (start == NULL)
X		return NULL;
X		
X	coff = current_offset(*cur_col);
X	len = end - start;
X	diff = lp->l_used - coff;
X	if (diff > len)
X		diff = len;
X	if (diff)
X		ldelete(diff);
X	llinsert(start, len, FALSE);
X	return NULL;
X}
Xvoid
Xp_newline(dp)
Xregister DISPLAY	*dp;
X{
X	if (++dp->d_y >= dp->d_rows) {
X		p_scroll(dp);
X		dp->d_y = dp->d_rows - 1;
X		}
X}
Xvoid
Xp_scroll(dp)
Xregister DISPLAY	*dp;
X{	register int i;
X	BYTE	*vp = dp->d_line[0];
X
X	for (i = 0; i < dp->d_rows; i++)
X		dp->d_line[i] = dp->d_line[i+1];
X	dp->d_line[i] = vp;
X	for (i = 0; i < ncol; i++)
X		vp[i] = ' ';
X	
X}
Xvoid
Xp_clear_screen(dp)
Xregister DISPLAY	*dp;
X{
X	register int	i, j;
X	BYTE	*bp;
X
X	for (i = 0; i < nrow; i++) {
X		bp = dp->d_line[i];
X		for (j = 0; j < ncol; )
X			bp[j++] = ' ';
X		}
X}
Xvoid
Xp_tab(dp)
Xregister DISPLAY	*dp;
X{
X	dp->d_x = (dp->d_x | 7) + 1;
X}
Xvoid
Xp_escape(dp, modify)
Xregister DISPLAY	*dp;
X{
X	register char *cp = dp->d_escape;
X	u_int16	args[MAX_ESCAPE];
X	u_int16	arg_no = 0;
X	u_int16	one_base;
X	u_int16	two_base;
X	u_int16	i;
X	LISTV	local_argv[MAX_ARGC];
X
X	argv = local_argv;
X	for(arg_no = 0; arg_no < MAX_ESCAPE; )
X		args[arg_no++] = 0;
X	arg_no = 0;
X
X	dp->d_escptr = NULL;
X	if (*cp++ != '[')
X		return;
X	while (*cp) {
X		if (isalpha(*cp))
X			break;
X		if (*cp == ';') {
X			cp++;
X			args[arg_no++] = 0;
X			continue;
X			}
X		if (!isdigit(*cp))
X			return;
X		args[arg_no++] = (u_int16) atoi(cp);
X		while (isdigit(*cp))
X			cp++;
X		if (*cp == ';')
X			cp++;
X		}
X
X	one_base = (u_int16) (args[0] == 0 ? 1 : args[0]);
X	two_base = (u_int16) (args[1] == 0 ? 1 : args[1]);
X	switch (*cp) {
X	  case '@':
X	  case 'A':
X		dp->d_y -= one_base;
X		break;
X	  case 'B':
X		dp->d_y += one_base;
X		break;
X	  case 'C':
X		*cur_col += one_base;
X		break;
X	  case 'D':
X	  	*cur_col -= one_base;
X		break;
X	  case 'f':
X	  case 'H': {
X	  	int lines_to_insert = one_base - curbp->b_numlines;
X	  	*cur_line = one_base;
X		*cur_col = two_base; 
X		dp->d_y = curwp->w_top_line + one_base;
X		dp->d_x = two_base;
X		while (lines_to_insert-- > 0) {
X			*cur_line = curbp->b_numlines;
X			lnewline(TRUE);
X			}
X	  	*cur_line = one_base;
X		break;
X		}
X	  case 'J': {
X		if (args[0] == 2)
X	  		*cur_line = curwp->w_top_line;
X		argv[1].l_int = MK_LINE;
X		argv[1].l_flags = F_INT;
X		while (*cur_line < curbp->b_numlines)
X			lfree(curbp, *cur_line);
X		break;
X		}
X	  case 'K':
X	  	del_to_eol();
X		break;
X	  case 'M':
X	  case 'X':
X		break;
X	  case 'm':
X		for (i = 0; i < arg_no; i++) {
X			int j = args[i];
X			extern int ab_color_map[];
X			switch (j) {
X			  case 0:
X				dp->d_attr &= ~(BOLD | REVERSE);
X				break;
X			  case 1:
X				dp->d_attr |= BOLD;
X				break;
X			  case 7:
X				dp->d_attr |= REVERSE;
X				break;
X			  case 30: case 31: case 32: case 33: case 34:
X			  case 35: case 36: case 37:
X			  	j = ab_color_map[j - 30];
X				dp->d_color = (dp->d_color & ~FG_COLOR) | 
X						FG(j);
X				j += 30;
X				break;
X			  case 40: case 41: case 42: case 43: case 44:
X			  case 45: case 46: case 47:
X			  	j = ab_color_map[j - 40];
X				dp->d_color = (dp->d_color & ~BG_COLOR) | 
X						BG(j);
X				j += 40;
X				break;
X			  }
X			if (modify) {
X				sprintf(dp->d_escape, "\033[%dm", args[i]);
X				linsert(dp->d_escape, strlen(dp->d_escape));
X				dp->d_x = *cur_col;
X				dp->d_y = *cur_line;
X				}
X			}
X		break;
X	  }
X
X	if (*cur_col < 1)
X		*cur_col = 1;
X	if (dp->d_x < 0)
X		dp->d_x = 0;
X	else if (dp->d_x >= dp->d_cols)
X		dp->d_x = dp->d_cols - 1;
X	if (dp->d_y < 0)
X		dp->d_y = 0;
X	else if (dp->d_y >= dp->d_rows)
X		dp->d_y = dp->d_rows - 1;
X
X}
Xcreate_ipc(send, recv)
Xint	*send;
Xint	*recv;
X{	int	pid;
X
X# if	!defined(HAVE_PTY)
X	int	pipe1[2], pipe2[2];
X	
X	if (pipe(pipe1) < 0)
X		return -1;
X	if (pipe(pipe2) < 0) {
X		close(pipe1[0]);
X		close(pipe1[1]);
X		return -1;
X		}
X	if ((pid = fork()) < 0) {
X		close(pipe1[0]);
X		close(pipe1[1]);
X		close(pipe2[0]);
X		close(pipe2[1]);
X		return -1;
X		}
X	if (pid == 0) {
X		dup2(pipe1[0], 0);
X		dup2(pipe2[1], 1);
X		dup2(pipe2[1], 2);
X		close(pipe1[0]);
X		close(pipe1[1]);
X		close(pipe2[0]);
X		close(pipe2[1]);
X		}
X	else {
X		close(pipe2[1]);
X		close(pipe1[0]);
X		*send = pipe1[1];
X		*recv = pipe2[0];
X		}
X# else
X# define	PTY_NAME	"/dev/ptyXX"
X# define	TTY_NAME	"/dev/ttyXX"
X# define	TTY_MODE	0622
X	char	pty_name[20];
X	char	tty_name[20];
X	int	xx;
X	int	c1, c2;
X	strcpy(pty_name, PTY_NAME);
X	strcpy(tty_name, TTY_NAME);
X	for (xx = 0; pty_name[xx] != 'X'; )
X		xx++;
X	for (c1 = 'q'; c1 != 'z'; c1++) {
X		for (c2 = 0; c2 < 0x10; c2++) {
X			tty_name[xx] = pty_name[xx] = c1;
X			tty_name[xx+1] = pty_name[xx+1] = 
X				c2 >= 0x0a ? (c2 + 'a' - 0x0a) 
X					   : (c2 + '0');
X			if ((*send = open(pty_name, O_RDWR)) >= 0) {
X				if ((*recv = open(tty_name, O_RDWR)) >= 0) {
X					chown(tty_name, getuid(), getgid());
X					chmod(tty_name, TTY_MODE);
X					goto ipc_created;
X					}
X				close(*send);
X				}
X			}
X		}
X	if (c1 >= 'z')
X		return -1;
X
Xipc_created:
X	if ((pid = fork()) < 0)	{
X		close(*send);
X		close(*recv);
X		return -1;
X		}
X	if (pid == 0) {
X		int	mypid = getpid();
X		dup2(*recv, 0);
X		dup2(*recv, 1);
X		dup2(*recv, 2);
X		close(*recv);
X		close(*send);
X		signal(SIGTTIN, SIG_DFL);
X		signal(SIGTTOU, SIG_DFL);
X		setpgrp(0, mypid);
X		ioctl(0, TIOCSPGRP, &mypid);
X		}
X	else {
X		*recv = *send;
X		signal(SIGTTIN, SIG_IGN);
X		signal(SIGTTOU, SIG_IGN);
X		}
X# endif
X
X	/*----------------------------------------
X	/*   At this point we have created the
X	/*   IPC mechanism, and we are running
X	/*   in both the parent and child, via fork().
X	/*----------------------------------------*/
X# if	defined(SIGTTIN)
X	if (pid == 0) {
X		signal(SIGTTIN, SIG_DFL);
X		signal(SIGTTOU, SIG_DFL);
X		}
X# endif
X	return pid;
X}
Xdo_connect()
X{	register DISPLAY *dp;
X	int	flags = argv[1].l_flags == F_NULL ? P_ECHO : argv[1].l_int;
X	char	*sh = get_str(2);
X	
X	if (curbp->b_display) {
X		accumulator = 0;
X		curbp->b_display->d_flags = (u_int16) flags;
X		return 0;
X		}
X	accumulator = 1;
X	dp = p_create(ncol, nrow-2);
X	if (dp == NULL) {
X		ewprintf("Couldn't allocate memory for connection.");
X		return 0;
X		}
X	dp->d_flags = (u_int16) flags;
X	
X	/*----------------------------------------
X	/*   Create the IPC mechanism (pipe or pty)
X	/*   and fork a child.
X	/*----------------------------------------*/
X	if ((dp->d_pid = create_ipc(&dp->d_pipe_out, &dp->d_pipe_in)) < 0) {
X		chk_free((char *) dp);
X		ewprintf("Couldn't create IPC.");
X		return 0;
X		}
X	proc_add(dp->d_pid, (char *) NULL);
X	/*----------------------------------------
X	/*   Child gets to exec a shell.
X	/*----------------------------------------*/
X	if (dp->d_pid == 0) {
X		extern	char *get_shell();
X		char *shell = (sh && sh[0]) ? sh : get_shell();
X# if	defined(SIGCLD)
X		signal(SIGCLD, SIG_DFL);
X# endif
X		execl(shell, shell, "-i", (char *) NULL);
X		trace_log("exec failed");
X		_exit(1);
X		}
X
X	/*----------------------------------------
X	/*   Parent gets to tidy up.
X	/*----------------------------------------*/
X# if	defined(F_GETFL)
X	flags = fcntl(dp->d_pipe_in, F_GETFL, 0);
X	if (fcntl(dp->d_pipe_in, F_SETFL, flags | O_NDELAY) < 0)
X		errorf("connect: fcntl error.");
X	flags = fcntl(dp->d_pipe_out, F_GETFL, 0);
X	if (fcntl(dp->d_pipe_out, F_SETFL, flags | O_NDELAY) < 0)
X		errorf("connect: fcntl error.");
X# endif
X	accumulator = 0;
X	curbp->b_display = dp;
X	infof("Buffer connected.");
X	num_pty++;
X	sel_bits |= BIT(dp->d_pipe_in);
X	p_poll();
X	return 0;
X}
Xvoid
Xp_cleanup(bp)
XBUFFER	*bp;
X{
X	DISPLAY *dp = bp->b_display;
X	if (dp == NULL)
X		return;
X	sel_bits &= ~BIT(dp->d_pipe_in);
X	close(dp->d_pipe_in);
X	close(dp->d_pipe_out);
X	if (dp->d_pid) {
X		kill(dp->d_pid, SIGTERM);
X		kill(dp->d_pid, SIGKILL);
X		}
X	p_destroy(bp);
X	infof("%s disconnected.", bp->b_fname);
X	num_pty--;
X}
Xdo_disconnect()
X{	register DISPLAY *dp = curbp->b_display;
X
X 	accumulator = 0;
X	if (dp == NULL)
X		return 0;
X	p_cleanup(curbp);
X	p_poll();
X	return 0;
X}
Xvoid
Xp_poll()
X{	register BUFFER	*bp;
X	char	buf[256];
X	BUFFER	*saved_curbp = curbp;
X	int	updated;
X	extern int dflag;
X
X	if (entry || num_pty <= 0) {
X		num_pty = 0;
X		return;
X		}
X
X	entry++;
Xstart_again:
X	do {
X		updated = FALSE;
X		for (bp = bheadp; bp; bp = bp->b_bufp) {
X			int	i;
X			while (1) {
X				if (bp->b_display == NULL || bp->b_display->d_flags & P_WAIT)
X					break;
X				if ((i = read(bp->b_display->d_pipe_in, buf, sizeof buf - 1)) <= 0) {
X					if (i <= 0) {
X						if (check_if_died(bp))
X							goto start_again;
X						}
X					break;
X					}
X				buf[i] = NULL;
Xtrace_log("p_update(buf=%s)", buf);
X				p_update(bp, buf);
X				updated = TRUE;
X				}
X			}
X		curbp = saved_curbp;
X		set_hooked();
X		if (updated)
X			update();
X		}
X	while (updated && !typeahead());
X	entry--;
X# if	!defined(SELECT)
X	clk_timeout(p_poll, 0, (long) (dflag ? 5 : POLL_TIME) SECONDS);
X# endif
X}
Xcheck_if_died(bp)
Xregister BUFFER *bp;
X{	extern int child_sig;
X
X	if (child_sig)
X		proc_wait(-1);
X	if (kill(bp->b_display->d_pid, 0) < 0) {
X		p_cleanup(bp);
X		return TRUE;
X		}
X	return FALSE;
X}
Xp_write(buf, len)
Xchar	*buf;
Xu_int16	len;
X{
X	if (curbp->b_display == NULL)
X		return;
X	write(curbp->b_display->d_pipe_out, buf, (int) len);
X/*     	return curbp->b_display->d_flags & P_ECHO;*/
X}
Xstatic
Xdup2(old, new)
X{
X	close(new);
X	dup(old);
X}
X
SHAR_EOF
chmod 0444 ./pty.c || echo "restore of ./pty.c fails"
mkdir . >/dev/null 2>&1
echo "x - extracting ./ref_string.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > ./ref_string.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
X# include	"list.h"
X
XSCCSID("@(#) ref_string.c 1.4, (C) 1989, P. Fox");
X
Xr_str *
Xnew_rp()
X{
X	return (r_str *) chk_alloc(sizeof (r_str));
X}
Xr_str *
Xr_alloc(size)
X{	register r_str *rp = new_rp();
X
X	rp->r_ref = 1;
X	rp->r_size = size;
X	rp->r_str = chk_alloc(size);
X	return rp;
X}
Xr_str *
Xr_init(new_string)
Xchar	*new_string;
X{	int	len = strlen(new_string) + 1;
X	r_str	*rp = r_alloc(len);
X
X	memcpy(rp->r_str, new_string, rp->r_size);
X	rp->r_used = len - 1;
X	return rp;
X}
Xr_str *
Xr_linit(new_string, len)
Xchar	*new_string;
X{	r_str	*rp = r_alloc(len);
X
X	memcpy(rp->r_str, new_string, len);
X	rp->r_used = len;
X	return rp;
X}
Xr_rinit(rp, new_string)
Xr_str	*rp;
Xchar	*new_string;
X{	int	len = strlen(new_string) + 1;
X	rp->r_ref = 1;
X	rp->r_size = len;
X	rp->r_str = new_string;
X	rp->r_used = len - 1;
X
X}
Xr_str *
Xr_cat(rp, str)
Xregister r_str *rp;
Xchar	*str;
X{	int	len = strlen(str);
X	char	*cp;
X	int	new_used = rp->r_used + len;
X	r_str	*rp1;
X
X	if (rp->r_ref == 1) {
X		if (rp->r_size <= rp->r_used + len) {
X			cp = rp->r_str;
X			rp->r_str = chk_alloc(new_used+1);
X			rp->r_size = new_used + 1;
X			memcpy(rp->r_str, cp, rp->r_used);
X			chk_free(cp);
X			}
X		memcpy(rp->r_str + rp->r_used, str, len+1);
X		rp->r_used += len;
X		return rp;		
X		}
X	rp1 = r_alloc(new_used+1);
X	rp1->r_used = new_used;
X	memcpy(rp1->r_str, rp->r_str, rp->r_used);
X	memcpy(rp1->r_str + rp->r_used, str, len+1);
X	return rp1;
X}
Xr_str *
Xr_inc(rp)
Xr_str *rp;
X{
X	rp->r_ref++;
X	return rp;
X}
Xr_dec(rp)
Xr_str *rp;
X{
X	if (rp && --rp->r_ref <= 0) {
X		chk_free(rp->r_str);
X		chk_free(rp);
X		}
X}
SHAR_EOF
chmod 0444 ./ref_string.c || echo "restore of ./ref_string.c fails"
mkdir . >/dev/null 2>&1
echo "x - extracting ./regexp.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > ./regexp.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("@(#) regexp.c 1.14, (C) 1989, P. Fox");
X
X# define	DEBUG_REGEXP
X# undef	DEBUG_REGEXP
X
X# define	ERROR(x)	{ ewprintf(x); return -1; }
X# define	REGEXP_SIZE	512
X# define	REGEXP_INCR	128
X
X# define	BITMAP_SIZE	(256 / 8)
X# define	FINISH		1	/* End of compiled r.e.		*/
X# define	ZERO_OR_MORE	2	/* ..@				*/
X# define	ONE_OR_MORE	3	/* ..+				*/
X# define	STAR		4	/* *				*/
X# define	QUESTION	5	/* ?				*/
X# define	CLASS		6	/* [xyz] or [~xyz]		*/
X# define	STRING		7	/* xyz...			*/
X# define	END		8	/* End of branch list.		*/
X# define	OR		9	/* '|' alternatives.		*/
X# define	SETPOS		10	/* \c				*/
X# define	BOL		11	/* < or ^			*/
X# define	EOL		12	/* > or $			*/
X# define	LOOP		13	/* Used as end of block terminator*/
X					/* for @ and +.			*/
X# define	OPEN		20	/* '{'				*/
X# define	CLOSE		30	/* '}'				*/
Xint	bittab[] = { 1, 2, 4, 8, 16, 32, 64, 128 };
Xstatic int	match_level;
Xstatic char	*reg_print_bitmap();
Xenum re_syntax {
X	BRIEF_SYNTAX = 0,
X	UNIX_SYNTAX = 1
X	};
Xenum re_syntax	re_syntax = BRIEF_SYNTAX;
X# define	MAGIC_BRIEF	"@+*?[|{}\\$>"
X# define	MAGIC_UNIX	"+*.[|{}\\$>"
Xchar	*re_opcodes[] = {
X		"<0>",
X		"FINISH",
X		"ZERO_OR_MORE",
X		"ONE_OR_MORE",
X		"STAR",
X		"QUESTION",
X		"CLASS",
X		"STRING",
X		"END",
X		"OR",
X		"SETPOS",
X		"BOL",
X		"EOL",
X		"LOOP", "14", "15", "16", "17", "18", "19",
X		"OPEN-0", "OPEN-1", "OPEN-2", "OPEN-3", "OPEN-4", "OPEN-5",
X		"OPEN-6", "OPEN-7", "OPEN-8", "OPEN-9", 
X		"CLOSE-0", "CLOSE-1", "CLOSE-2", "CLOSE-3", "CLOSE-4", "CLOSE-5",
X		"CLOSE-6", "CLOSE-7", "CLOSE-8", "CLOSE-9"
X		};
Xint	bstack[10];
Xint	re_level;
Xint	re_group;	/* Used for {..} in translate patterns. */
Xchar	*re_code = NULL;
Xint	re_code_size = 0;
Xint	end_of_code;
Xint	last_end;
Xchar	*pat_ptr;
Xint	allow_modifier;
Xint	or_just_done = FALSE;
Xextern int dflag;
Xextern	int	case_flag;
Xextern	int	magic;
X
Xvoid
Xre_syntax_fn()
X{
X	accumulator = (int) re_syntax;
X	if (argv[1].l_flags == F_INT && (argv[1].l_int == 0 || argv[1].l_int == 1))
X		re_syntax = (enum re_syntax) argv[1].l_int;
X}
XREGEXP *
Xregcomp(pattern)
Xchar	*pattern;
X{
X	static REGEXP regexp;
X	register char *re;
X	char	*next_block();
X
X	if (re_code == NULL) {
X		re_code = chk_alloc(REGEXP_SIZE);
X		re_code_size = REGEXP_SIZE;
X		}
X	end_of_code = 0;
X	re_group = re_level = 0;
X	pat_ptr = pattern;
X	last_end = -1;
X	allow_modifier = FALSE;
X
X	if (re_comp() < 0)
X		return NULL;
X	if (re_level) {
X		ewprintf("Missing close brace");
X		return NULL;
X		}
X
X	re_code[end_of_code] = FINISH;
X	regexp.program = re_code;
X	if (dflag & DB_REGEXP) {
X		trace_log("Pass 1:\n");
X		re_print(re_code);
X		}
X	/*----------------------------------------
X	/*   Following piece of code walks down the
X	/*   regular expression and sets up the
X	/*   link fields needed by the '|'-OR
X	/*   pattern matching code.
X	/*----------------------------------------*/
X	for (re = re_code; *re != FINISH; ) {
X		register char *re1;
X		register char *re2;
X
X		if (*re == ZERO_OR_MORE || *re == ONE_OR_MORE) {
X			re += 3;
X			continue;
X			}
X		if (*re != OR) {
X			re += *re == END ? 3 : LGET16(re);
X			continue;
X			}
X		re1 = re + 3;
X		re1 = next_block(re1);
X		if (*re1 != END) {
X			ewprintf("Internal inconsistency.");
X			return NULL;
X			}
X		/*--------------------------------
X		 *   Update link field for OR.
X		 *--------------------------------*/
X		LPUT16(re, re1 - re + 3);
X		/*--------------------------------
X		 *   Update END field.
X		 *--------------------------------*/
X		if ((re2 = next_block(re1)) == NULL) {
X			ewprintf("Internal inconsistency (1).");
X			return NULL;
X			}
X		while (1) {
X			if (*re2 != OR) {
X				if ((re2 = next_block(re2)) == NULL) {
X					ewprintf("Internal inconsistency (1).");
X					return NULL;
X					}
X				break;
X				}
X			re2 += 3;
X			while (*re2 != END && *re2 != FINISH)
X				if ((re2 = next_block(re2)) == NULL) {
X					ewprintf("Internal inconsistency (1).");
X					return NULL;
X					}
X			if (*re2 == END)
X				re2 += 3;
X			}
X		LPUT16(re1, re2 - re1);
X		re += 3;
X		}
X	if (dflag & DB_REGEXP) {
X		trace_log("Pass 2:\n");
X		re_print(re_code);
X		}
X	return ®exp;
X}
Xchar *
Xnext_block(re)
Xregister char	*re;
X{	register int	i;
X
X	if (*re >= OPEN && *re <= OPEN + 9) {
X		int close = *re + 10;
X		while (*re != close) {
X			i = (*re == OR || *re == END) ? 3 : LGET16(re);
X			if (i == 0)
X				return NULL;
X			re += i;
X			}
X		}
X	if (*re == OR || *re == END)
X		return re+3;
X	return re + LGET16(re);
X}
Xre_comp()
X{	int	allow_or = FALSE;
X	int	last_end_on_entry = last_end;
X# define	MAX_OR		32
X
X	or_just_done = FALSE;
X	while (*pat_ptr) {
X		if (!magic) {
X			pat_ptr++;
X			goto DEFAULT;
X			}
X		switch (*pat_ptr++) {
X		  case '*':
X		  	if (re_syntax == BRIEF_SYNTAX)
X				goto DEFAULT;
X			/* Fall thru.. */
X		  case '@':
X		  	if (pat_ptr[-1] == '@' && re_syntax == UNIX_SYNTAX)
X				goto DEFAULT;
X			/* Fall thru.. */
X		  case '+':
X			if (allow_modifier == FALSE)
X				goto DEFAULT;
X			shift_up(last_end);
X			re_code[last_end] = pat_ptr[-1] == '+' ? ONE_OR_MORE 
X							    : ZERO_OR_MORE;
X			re_code[end_of_code] = LOOP;		/* NEW */
X			LPUT16(&re_code[end_of_code], 3);		/* NEW */
X			end_of_code += 3;			/* NEW */
X			LPUT16(&re_code[last_end], end_of_code - last_end);
X			allow_modifier = FALSE;
X			break;
X		  case '|':
X			if (allow_or == FALSE)
X				ERROR("Null expression before |");
X			shift_up(last_end);
X			re_code[last_end] = OR;
X			allow_or = FALSE;
X			re_code[end_of_code] = END;
X			LPUT16(&re_code[end_of_code], 0);
X			end_of_code += 3;
X			or_just_done = TRUE;
X			continue;
X		  case '{':
X		  	if (re_syntax == UNIX_SYNTAX)
X				goto DEFAULT;
Xopen_bracket:
X			if (re_level > NSUBEXP)
X				ERROR("Too many '{'");
X			last_end = end_of_code;
X			re_code[end_of_code] = OPEN + re_group;
X			bstack[re_level++] = re_group;
X			if (re_group < 9)
X				re_group++;
X			LPUT16(&re_code[end_of_code], 3);
X			end_of_code += 3;
X			if (re_comp() < 0)
X				return -1;
X			re_level--;
X			allow_or = TRUE;
X			break;
X		  case '}':
X		  	if (re_syntax == UNIX_SYNTAX)
X				goto DEFAULT;
Xclose_bracket:
X			re_code[end_of_code] = CLOSE + bstack[re_level-1];
X			LPUT16(&re_code[end_of_code], 3);
X			end_of_code += 3;
X			allow_modifier = TRUE;
X			last_end = last_end_on_entry;
X			return 0;
X		  case '\\':
X		  	if (re_syntax == UNIX_SYNTAX && *pat_ptr == '(') {
X				pat_ptr++;
X				goto open_bracket;
X				}
X		  	if (re_syntax == UNIX_SYNTAX && *pat_ptr == ')') {
X				pat_ptr++;
X				goto close_bracket;
X				}
X			/* Fall thru .. */
X		  DEFAULT:
X		  default:
X			pat_ptr--;
X			last_end = end_of_code;
X			allow_or = TRUE;
X			allow_modifier = TRUE;
X			if (gen_atom() == FALSE)
X				return -1;
X			LPUT16(&re_code[last_end], end_of_code - last_end);
X			break;
X		  }
X		or_just_done = FALSE;
X		}
X	return	0;
X}
Xgen_atom()
X{	int	len;
X	int	size = 3;
X	int	incr = 1;
X	char *magic_str = re_syntax == BRIEF_SYNTAX ? MAGIC_BRIEF : MAGIC_UNIX;
X	
X	if (!magic)
X		goto DEFAULT;
X	switch (*pat_ptr) {
SHAR_EOF
echo "End of part 8"
echo "File ./regexp.c is continued in part 9"
echo "9" > s2_seq_.tmp
exit 0
-- 
=====================			Reuters Ltd PLC, 
Tel: +44 628 891313 x. 212		 Westthorpe House,
UUCP:     fox%marlow.uucp at idec.stc.co.uk  Little Marlow,
					   Bucks, England SL7 3RQ



More information about the Comp.sources.misc mailing list