⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ps_impl.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
#ifndef lint#ifdef sccsstatic char  sccsid[] = "@(#)ps_impl.c 1.1 92/07/30";#endif#endif/* *  Copyright (c) 1986, 1987 by Sun Microsystems Inc. *//* * Entity stream implementation for manager of two other streams. * * Conceptually, suppose we want the piece source to contain: *	AB0CD12E345FGH67I8JK9LMN * and the original source contains: *	ABCDEFGHIJKLMN * then the operation sequence: *	replace start:2 stop_plus_one:2 with:"0" *	replace start:5 stop_plus_one:5 with:"12" *	etc * will generate a scratch source that looks like: *	xx0xx12xx345xx67xx8xx9 * and the piece table will alternate with: *	virtual pos:0, length:2, source:original, source_pos:0 *	virtual pos:2, length:1, source:scratch, source_pos:sizeof(xx) *	virtual pos:3, length:2, source:original, source_pos:2 *	virtual pos:5, length:2, source:scratch, source_pos:2*sizeof(xx)+1 *	etc * * It is important that a piece in the piece table represent a contiguous *   run of entities in the original or scratch stream.  Thus, if a break is *   detected during the first read of a piece, a new piece must be created. * * 87Mar23: A major new feature is support for a maximum size that the *	scratch stream is allowed to grow to.  The basic design: * Most of the piece_stream code believes that the scratch stream grows *   without bound.  However, in reality, if the client sets a maximum size on *   the scratch stream, the ops vector for the scratch stream is modified *   so that the logical index space of [0..private->scratch_length) is *   mapped to the physical index space of [0..private->scratch_max_len), *   essentially by making all accesses to the logical indices be modulo *   private->scratch_max_len. * Some special care must be taken with UNDO and secondary piece streams, *   as these both can use logical indices to reference entities that are no *   longer physically available. */#include <suntool/primal.h>#include <suntool/textsw_impl.h>#include <stdio.h>#include <varargs.h>#include <suntool/ps_impl.h>#include <suntool/alert.h>#include <suntool/frame.h>#include "sunwindow/sv_malloc.h"extern char	*calloc();extern char	*malloc();static Es_status ps_commit();static Es_handle ps_destroy(), ps_scratch_destroy();static caddr_t	 ps_get();static Es_index  ps_get_length(), ps_scratch_get_length();static Es_index  ps_get_position(), ps_scratch_get_position();static Es_index  ps_set_position(), ps_scratch_set_position();static Es_index  ps_read(), ps_scratch_read();static Es_index  ps_replace(), ps_scratch_replace();static int	 ps_set();static void	 make_current_valid();static Es_index	 write_header_etc();static struct es_ops ps_ops = {	ps_commit,	ps_destroy,	ps_get,	ps_get_length,	ps_get_position,	ps_set_position,	ps_read,	ps_replace,	ps_set};static  int	max_transcript_alert_displayed; /* default = 0 */#define	INVALIDATE_CURRENT(private)			\	(private)->current = CURRENT_NULL#define	SET_POSITION(private, to)			\	INVALIDATE_CURRENT(private); (private)->position = (to)#define	VALID_PIECE_INDEX(private, index)		\	((index < (private)->pieces.last_plus_one) &&	\	(PIECES_IN_TABLE(private)[index].pos != ES_INFINITY))static char	*wrap_msg = "\n\*** Text is lost because the maximum edit log size has been exceeded. ***\n\n\n";#ifdef DEBUG#define	MAX_PIECE_LENGTH	 100000#define	MAX_LENGTH		4000000#endifstatic Es_handleps_NEW(piece_count)	int			piece_count;{	extern ft_object	ft_create();	Es_handle		esh = NEW(Es_object);	register Piece_table	private = NEW(struct piece_table_object);	if (esh == NULL || private == NULL)	    goto AllocFailed;	private->magic = PS_MAGIC;	if (piece_count > 0) {	    private->pieces = FT_CLIENT_CREATE(piece_count, Piece_object);	    if (private->pieces.seq == NULL)		goto AllocFailed;	    FT_CLEAR_ALL(private->pieces);	} else	    private->pieces.last_plus_one = 0;	esh->data = (caddr_t)private;	esh->ops = &ps_ops;	return(esh);AllocFailed:	if (private)	    free((char *)private);	if (esh)	    free((char *)esh);	return((Es_handle)NULL);}extern Es_handleps_create(client_data, original, scratch)	caddr_t			 client_data;	Es_handle		 original, scratch;{	extern ft_object	 ft_create();	extern int		 ft_set();	Es_handle		 esh = ps_NEW(100);	register Piece_table	 private;	register Piece		 pieces;	if (es_set_position(scratch, 0) != 0) {	    (void) fprintf(stderr,			   "ps_create: cannot reset scratch stream.\n");	    return(NULL);	}	if (esh == NULL)	    goto AllocFailed;	private = ABS_TO_REP(esh);	SET_POSITION(private, 0);	private->length = (original != ES_NULL) ? es_get_length(original) : 0;	pieces = PIECES_IN_TABLE(private);	if (private->length > 0) {	    pieces[0].pos = es_set_position(original, 0);	    PS_SET_ORIGINAL_SANDP(pieces[0], pieces[0].pos);#ifdef notdefThe following fails because it does not match the state after a replace ofeverything by nothing.  However, it is probably correct should theend_of_stream condition change to an empty piece at the end.	} else {	    pieces[0].pos = 0;	    PS_SET_SCRATCH_SANDP(pieces[0], pieces[0].pos);#endif	}	pieces[0].length = private->length;	private->original = original;	private->scratch = scratch;	private->last_write_plus_one = ES_INFINITY;	private->rec_start = ES_INFINITY;	private->rec_insert = ES_INFINITY;	private->oldest_not_undone_mark = ES_INFINITY;	private->rec_insert_len = 0;	private->client_data = client_data;	private->scratch_max_len = ES_INFINITY;	/* scratch_length need not be valid, but must be < scratch_max_len */	private->scratch_length = 0;	private->scratch_ops = (Es_ops)0;	private->status = ES_SUCCESS;	return(esh);AllocFailed:	(void) fprintf(stderr, "ps_create: alloc failure.\n");	return(NULL);}/* ARGSUSED */static Es_statusps_commit(esh)	Es_handle esh;{	return(ES_SUCCESS);}static Es_handleps_destroy(esh)	Es_handle esh;{	register Piece_table private = ABS_TO_REP(esh);	free((char *)esh);	ft_destroy(&private->pieces);	free((char *)private);	return NULL;}static Es_handleps_scratch_destroy(esh)	Es_handle esh;{	register Piece_table private = SCRATCH_TO_REP(esh);	free((char *)esh->ops);	esh->ops = private->scratch_ops;	return(es_destroy(esh));}static Es_indexps_get_length(esh)	Es_handle esh;{	register Piece_table private = ABS_TO_REP(esh);	return (private->length);}static Es_indexps_scratch_get_length(esh)	Es_handle esh;{	register Piece_table private = SCRATCH_TO_REP(esh);	return (private->scratch_length);}static Es_indexps_get_position(esh)	Es_handle esh;{	register Piece_table private = ABS_TO_REP(esh);	return(private->position);}static Es_indexps_scratch_get_position(esh)	Es_handle esh;{	register Piece_table private = SCRATCH_TO_REP(esh);	return(private->scratch_position);}static Es_indexps_set_position(esh, pos)	Es_handle		esh;	register Es_index	pos;{	register Piece_table	private = ABS_TO_REP(esh);	register Piece		pieces = PIECES_IN_TABLE(private);	if (pos > private->length) {	    ASSUME(pos == ES_INFINITY || private->parent);	    pos = private->length;	} else if (pos < pieces[0].pos) {	    pos = pieces[0].pos;	    if (pos == ES_INFINITY)	/* Checks for empty source. */		pos = 0;	}	ASSUME(0 <= pos && pos <= MAX_LENGTH);	/* Client's often lose track of the position, so check if setting to	 * current position to avoid invalidating caches unnecessarily.	 */	if (pos != private->position) {	    /* Try to maintain private->current */	    if (private->current != CURRENT_NULL) {		if ((pos < pieces[private->current].pos) ||		    (pos >= pieces[private->current].pos +			    pieces[private->current].length))		    INVALIDATE_CURRENT(private);	    }	    private->position = pos;	}	return (private->position);}static Es_indexps_scratch_set_position(esh, pos)	Es_handle		esh;	register Es_index	pos;{	register Piece_table private = SCRATCH_TO_REP(esh);	if (pos > private->scratch_length)	    pos = private->scratch_length;	private->scratch_position = pos;	pos = pos % private->scratch_max_len;	pos = private->scratch_ops->set_position(esh, pos);	ASSUME(pos == (private->scratch_position % private->scratch_max_len));	return(private->scratch_position);}#ifdef DEBUGstatic intps_pieces_are_consistent(private)	register Piece_table	private;{	register Piece		pieces = PIECES_IN_TABLE(private);	register Es_index	pos = pieces[0].pos;	register int		current;	ASSUME(pos == 0 || pos == ES_INFINITY || private->parent);	for (current = 0; VALID_PIECE_INDEX(private, current); current++) {	    ASSUME(pos == pieces[current].pos);	    ASSUME(0 < pieces[current].length || (current == 0 && pos == 0));	    ASSUME(pieces[current].length < MAX_PIECE_LENGTH);	    pos += pieces[current].length;	    ASSUME(pos <= private->length);	    ASSUME(PS_SANDP_POS(pieces[current]) < MAX_LENGTH);	}	return(!0);}#endifstatic Es_indexps_scratch_read(esh, len, bufp, resultp)	Es_handle		 esh;	u_int			 len,				*resultp;	register char		*bufp;{	register Piece_table	 private = SCRATCH_TO_REP(esh);	register Es_index	 first_valid, last_plus_one;	Es_index		 remainder;	long int		 count_read;	if (!SCRATCH_HAS_WRAPPED(private)) {	    private->scratch_position =		private->scratch_ops->read(esh, len, bufp, resultp);	} else {	    first_valid = SCRATCH_FIRST_VALID(private);	    last_plus_one = private->scratch_position + len;	    /*	     * scratch stream has wrapped around, so valid "logical" scratch	     *   indices are [first_valid..scratch_length).	     * Watch for:	     *   a) read of characters that no longer exist, and	     *   b) read that is "split" around physical scratch end.	     * First, look to see if read begins at valid position.	     */	    if (private->scratch_position < first_valid) {		/* Invalid start, but may extend into valid positions.		 * However, caller does not know that start is invalid; only		 *   way to communicate this is to read nothing this time.		 * Move position to start of valid range (which changes		 *   private->scratch_position as a side-effect).		 */		(void) es_set_position(esh, first_valid);		*resultp = 0;		goto Return;	    }	    /* Second, look for "split" read. */	    if ((private->scratch_position / private->scratch_max_len) !=		((last_plus_one-1) / private->scratch_max_len)) {		/* Split => read at end of scratch, then at start. */		remainder = private->scratch_max_len -			    private->scratch_ops->get_position(esh);		(void) private->scratch_ops->read(esh, remainder, bufp,						  &count_read);		(void) private->scratch_ops->set_position(esh, 0);		(void) private->scratch_ops->read(esh, len-count_read,						  bufp+count_read, resultp);		*resultp += count_read;	    } else {		(void) private->scratch_ops->read(esh, len, bufp, resultp);	    }	    /* Update the scratch_position, and watch out for read that	     * ends exactly at multiple of scratch_max_len, because this	     * requires repositioning of physical scratch stream to make	     * succeeding calls work properly.	     */	    private->scratch_position += *resultp;	    if ((private->scratch_position % private->scratch_max_len) ==		0) {		(void) private->scratch_ops->set_position(esh, 0);	    }	}Return:	ASSUME(private->scratch_ops->get_position(esh) ==		(private->scratch_position % private->scratch_max_len));	ASSUME(ps_pieces_are_consistent(private));	return(private->scratch_position);}static Es_indexps_scratch_replace(esh, last_plus_one, count, buf, count_used)	Es_handle		 esh;	Es_index		 last_plus_one;	long int		 count, *count_used;	char			*buf;{	register Piece_table	 private = SCRATCH_TO_REP(esh);	register Es_index	 first_valid, max_lpo;	Es_index		 remainder;	long int		 count_replaced;	if (last_plus_one > private->scratch_length) {	    last_plus_one = private->scratch_length;	}	max_lpo = private->scratch_position + count;	if (last_plus_one > max_lpo) {	    max_lpo = last_plus_one;	}	ASSUME(last_plus_one >= private->scratch_position);	if (!SCRATCH_HAS_WRAPPED(private) &&	    (max_lpo <= private->scratch_max_len) ) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -