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

📄 ps_impl.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
	    private->scratch_position =		private->scratch_ops->replace(esh, last_plus_one, count,					      buf, count_used);	    private->scratch_length =		private->scratch_ops->get_length(esh);	} else {	    first_valid = (SCRATCH_HAS_WRAPPED(private))			  ? SCRATCH_FIRST_VALID(private) : 0;	    *count_used = count;	    /*	     * Either scratch stream has wrapped around, or it is about to	     *   wrap around.  In either case, the valid "logical"	     *   scratch indices are [first_valid..scratch_length).	     * Bytes that vanish into hole at start of scratch stream are	     *   treated as used.	     * Watch for:	     *   a) range of characters that no longer exist, and	     *   b) "split" around physical scratch end.	     * First, look to see if replace begins at valid position.	     */	    remainder = first_valid - private->scratch_position;	    if (remainder > 0) {		/* Invalid start, but may extend into valid positions.		 * Move position to start of valid range (which changes		 *   private->scratch_position as a side-effect).		 */		(void) es_set_position(esh, first_valid);		if (last_plus_one < first_valid) {		    /* Entire range to replace is invalid. */		    goto Return;		} else if (count > 0) {		    /* Discard any new bytes replacing invalid bytes. */		    if (count > remainder) {			count -= remainder;			buf += remainder;		    } else {			count = 0;		    }		}	    }	    /* Second, look for "split" replace. */	    if ((private->scratch_position / private->scratch_max_len) !=		((max_lpo-1) / private->scratch_max_len) ) {		/* Split => replace at end of scratch, then at start.		 * NOTE: caller guarantees that count > remainder		 */		remainder = private->scratch_max_len -			    private->scratch_ops->get_position(esh);		ASSUME(count > remainder);		(void) private->scratch_ops->replace(			esh,			private->scratch_max_len,			remainder,			buf, &count_replaced);		(void) private->scratch_ops->set_position(esh, 0);		(void) private->scratch_ops->replace(			esh,			count - remainder,			count - remainder,			buf + remainder, &count_replaced);	    } else {		/* If here, then overwrite physical scratch after a wrap. */		(void) private->scratch_ops->replace(			esh,			(private->scratch_position %			 private->scratch_max_len) + count,			count, buf, &count_replaced);	    }	    private->scratch_position += count;	    if (private->scratch_position > private->scratch_length) {		private->scratch_length = private->scratch_position;	    }	}Return:	ASSUME(private->scratch_ops->get_position(esh) ==		(private->scratch_position % private->scratch_max_len));	return(private->scratch_position);}static Piecesplit_piece(pieces, current, delta)	ft_handle		pieces;	register int		current;	register long int	delta;/* Splits the piece_object pieces[current] in two with the second piece, the *   new pieces[current+1], starting at pieces[current].pos+delta. * Returns a properly cast sequence, as old cached version may be invalidated *   by the call to ft_shift_up. */{	register Piece		old, new;	register int		is_scratch;	register Es_index	source_pos;	ft_shift_up(pieces, current+1, current+2, 10);		/* Can invalidate &pieces.seq[i] */	old = ((Piece)(pieces->seq)) + current;	new = old + 1;	is_scratch = PS_SANDP_SOURCE(old[0]);	source_pos = PS_SANDP_POS(old[0]);	new->pos = old->pos + delta;	source_pos += delta;	new->length = old->length - delta;	old->length = delta;	PS_SET_SANDP(new[0], source_pos, is_scratch);	return((Piece)(pieces->seq));}static Es_indexps_read(esh, len, bufp, resultp)	Es_handle	 esh;	u_int		 len,			*resultp;	register char	*bufp;{#ifdef DEBUG_TRACE	Es_index	 next, pos;	char		 temp;	pos = (ABS_TO_REP(esh))->position;	next = ps_debug_read(esh, len, bufp, resultp);	(void) fprintf(stdout,		"ps_read at pos %d of %d chars got %d chars; %s %d ...\n",		pos, len, *resultp, "next read at", next);#ifdef	DEBUG_TRACE_CONTENTS	temp = bufp[*resultp];	bufp[*resultp] = '\0';	(void) fprintf(stdout, "%s\n^^^\n", bufp);	bufp[*resultp] = temp;#endif	return(next);}static Es_indexps_debug_read(esh, len, bufp, resultp)	Es_handle	 esh;	u_int		 len,			*resultp;	register char	*bufp;{#endif/* *   "current" must be signed, because it can become -1 when deciding whether * to combine pieces containing invalid physical scratch indices. */	int			 read_count, save_current;	Es_index		 next_pos, original_len;	register int		 current, to_read;	register long int	 delta;	register Es_index	 current_pos;	register Es_handle	 current_esh;	register Piece		 pieces;	register Piece_table	 private = ABS_TO_REP(esh);	if (private->length - private->position < len)  {	    len = private->length - private->position;	}	pieces = PIECES_IN_TABLE(private);	*resultp = 0;	if (private->current == CURRENT_NULL) {	    current =		ft_bounding_index(&private->pieces, private->position);	} else	    current = private->current;	while (VALID_PIECE_INDEX(private, current) && len > 0) {	    delta = private->position - pieces[current].pos;	    ASSERT(*resultp == 0 || delta == 0);	    current_esh = (PS_SANDP_SOURCE(pieces[current]) ?				private->scratch : 				private->original);	    current_pos = PS_SANDP_POS(pieces[current]) + delta;	    next_pos = es_set_position(current_esh, current_pos);	    ASSERT(next_pos == current_pos);	    to_read = pieces[current].length - delta;	    if (to_read > len)		to_read = len;	    next_pos = es_read(current_esh, to_read, bufp, &read_count);	    /* BUG ALERT!  If we ever support entities that are not bytes,	     * the following addition must have a	     * "* es_get(current_esh, ES_SIZE_OF_ENTITY)"	     */	    bufp += read_count;	    len -= read_count;	    *resultp += read_count;	    private->position += read_count;	/* zaps private->current */	    if (read_count < to_read) {		if (current_esh == private->original) {		    /* The original entity stream has holes in it,		     * and the initialization assumed it was contiguous,		     * so the pieces and length must be corrected.		     */		    pieces = split_piece(			     &private->pieces, current, delta+read_count);		    current++;		    /* Compute the gap size */		    delta = next_pos - (current_pos + read_count);		    ASSERT(pieces[current].length > delta);		    pieces[current].length -= delta;		    private->length -= delta;		    PS_SET_ORIGINAL_SANDP(pieces[current], next_pos);		} else {		    /* The scratch entity stream has wrapped around, making a		     *   hole from [0..scratch_first_valid).		     */		    ASSUME(SCRATCH_HAS_WRAPPED(private) ||			(private->parent &&			 SCRATCH_HAS_WRAPPED(ABS_TO_REP(private->parent)) ));		    /* Caller needs to be told where next successful read		     *   is, so search for piece containing valid scratch		     *   indices (WARNING: there may not be one).		     */		    for (save_current = current,			   current_pos = private->position;			 VALID_PIECE_INDEX(private, current);			 current++) {			ASSERT(PS_SANDP_SOURCE(pieces[current]));			delta = PS_SANDP_POS(pieces[current]);			if (delta >= next_pos) {			    /* next_pos not referenced by pieces => go to start			     * this piece, which is first beyond next_pos			     */			    next_pos = delta;			} else if (next_pos >= delta+pieces[current].length) {			    continue;			}			private->position =			    (next_pos - delta) + pieces[current].pos;			/* Allow uniform handling of current below. */			current++;			break;		    }		    if (current_pos == private->position)			private->position = es_get_length(esh);		    /* Although the pieces are correct it speeds up later		     *   reads if "runs of now invalid scratch references"		     *   are combined; however, only completely invalid		     *   pieces can be combined (else the record headers will		     *   be incorrectly included as part of the visible text).		     * -2 backs over terminating and partially valid pieces.		     */		    current -= 2;		    if (save_current < current) {			delta = PS_LAST_PLUS_ONE(pieces[current]);			pieces[save_current].length =				delta - pieces[save_current].pos;			ft_shift_out(&private->pieces,				     save_current+1, current+1);		    }		    /* A read at the beginning of the scratch stream which		     *   tries to read out of the start of the hole should		     *   give the client (an appropriate part of) wrap_msg.		     * However, don't do this until AFTER finding out where		     *   next valid position is, otherwise can return too		     *   much text.		     */		    for (current = 0, original_len = 0;			 VALID_PIECE_INDEX(private, current);			 current++) {			if (PS_SANDP_SOURCE(pieces[current]))			    break;			original_len = PS_LAST_PLUS_ONE(pieces[current]);		    }		    current = private->pieces.last_plus_one;		    INVALIDATE_CURRENT(private);		    ASSUME(original_len <= current_pos);		    read_count = strlen(wrap_msg);		    if (*resultp == 0 &&			    current_pos < original_len + read_count) {			FILE *	console_fd;   			 			if (private->position < original_len + read_count)			    read_count = private->position - original_len;			read_count -= current_pos - original_len;			if (len < read_count)			    read_count = len;			bcopy(wrap_msg+current_pos, bufp, read_count);			*resultp = read_count;			/* tell user that they are going to wrap */						/*  Use the same flag for console error message */ 			if (max_transcript_alert_displayed != 1) {			     console_fd = fopen("/dev/console", "a");			     fprintf(console_fd, "The text transcript in a Commands window filled up, and the oldest saved text will be erased from the top as more is typed at the bottom.\n");			     fflush(console_fd);			     max_transcript_alert_displayed = 1;			     fclose(console_fd);			 }			#ifdef	notdef			if (max_transcript_alert_displayed != 1) {			    Event	alert_event;			    (void) alert_prompt(				(Frame)0,				&alert_event,				ALERT_MESSAGE_STRINGS,				    "Text has been lost in a cmdtool transcript because",				    "the maximum edit log size has been exceeded.",				    0,				ALERT_BUTTON_YES,	"Continue",		        	ALERT_TRIGGER,		ACTION_STOP,				/* with trigger, yes or no bring it down */		    		0);			    max_transcript_alert_displayed = 1;			}#endif			        				    }		}		/* All of the above code is free and easy with local		 * variables because it expects to exit the loop here, so		 * it will need to be rewritten if this break is removed!		 */		break;	    }	    current++;	}	if (VALID_PIECE_INDEX(private, current)) {	    private->current = current;	    if (pieces[current].pos > private->position)		private->current--;		/* Short read advances current anyway, so undo the advance. */	} else	    INVALIDATE_CURRENT(private);	ASSUME(ps_pieces_are_consistent(private));	return (private->position);}/* The routines ps_replace, ps_insert_pieces, and ps_undo_to_mark all perform *   similar functions and a fix to one needs to be reflected in the others. */static Es_indexps_replace(esh, last_plus_one, count, buf, count_used)	Es_handle	 esh;	Es_index	 last_plus_one;	long int	 count, *count_used;	char		*buf;{#ifdef DEBUG_TRACE	Es_index	 next, pos;	char		 temp;	pos = (ABS_TO_REP(esh))->position;	next = ps_debug_replace(esh, last_plus_one, count, buf, count_used);	(void) fprintf(stdout,		"ps_replace [%d..%d) by %d chars (used %d); next pos %d ...\n",		pos, last_plus_one, count, *count_used, "next read at", next);	if (buf) {	    temp = buf[count];	    buf[count] = '\0';	    (void) fprintf(stdout, "%s\n^^^\n", buf);	    buf[count] = temp;	}	return(next);}static Es_indexps_debug_replace(esh, last_plus_one, count, buf, count_used)	Es_handle	 esh;	Es_index	 last_plus_one;	long int	 count, *count_used;	char		*buf;{#endif	/* Assume that the piece stream looks like:	 *	O1O S1S O2O S2S S3S O3O O4O S4S	 *   where XnX means n-th chunk in stream X, and X2X may actually	 *   occur earlier in stream X than X1X.	 * The possible cases are:	 * 1) Replace an empty region, with subcases:	 * 1a)  Region is at end of previous replace, hence it can be treated	 *      as an extension of the previous replace, and the associated	 *      scratch piece can simply be lengthened. (S4S)	 * 1b)  Otherwise, a new piece must be created, and the piece that	 *      contains the empty region must be split (XnX -> XnX S5S XmX),	 *      unless the empty region is at the beginning of that piece	 *      (XnX -> S5S XnX).	 * 2) Replace a region completely within one piece:	 * 2a)  If within latest scratch region, (1a) applies.	 * 2b)  If the region exactly matches the piece, re-cycle the piece to	 *      point at the new contents.	 * 2c)  Otherwise, (1b) applies.	 * 3) Replace a region spanning multiple pieces.	 * 3a)  For partially enclosed pieces, (1) applies.	 * 3b)  For completely enclosed pieces, delete them all, except	 *      possibly one to use as in (2b) if (3a) does not occur.	 *	 * WARNING!  Changes to the pieces can only be made AFTER calls to	 *   es_replace(scratch, ...) succeed, unless those changes do not	 *   break the assertions about the pieces OR are backed out in case	 *   of es_replace() failing.	 */	Es_index			 scratch_length;	Es_index			 es_temp, new_rec_insert;	long int			 long_temp;	int				 delete_pieces_length, replace_used;	register int			 current, end_index;	register long int		 delta;		/* Has 2 meanings! */	register Es_handle		 scratch;	register Piece			 pieces;	register Piece_table		 private = ABS_TO_REP(esh);	*count_used = 0;	if (buf == NULL && count != 0)  {	    private->status = ES_INVALID_ARGUMENTS;	    return(ES_CANNOT_SET);	}	if (private->parent != NULL)  {	    private->status = ES_INVALID_HANDLE;	    return(ES_CANNOT_SET);	}	scratch = private->scratch;	scratch_length = es_set_position(scratch, ES_INFINITY);	new_rec_insert = ES_INFINITY;		/* => extending current */	if (last_plus_one > private->length) {	    last_plus_one = private->length;	}	ASSUME(last_plus_one >= private->position);

⌨️ 快捷键说明

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