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

📄 sbstr.c

📁 操作系统源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
			/* Note that previous code makes it unnecessary			 * to invoke sbx_smdisc.  (otherwise wrong			 * smuse would confuse sbs_len).			 */		return(sbs_len(sd) - (sb->sbiop - sm->smaddr));	  }	else		return(sbs_len(sd) - sb->sboff);}/* Code past this point should insofar as possible be INTERNAL. *//* SBX_READY(sb,type,cmin,cmax) - Set up SBBUF for reading or writing. * * If no current smblk: *	reading - set up for reading *	writing - set up for splitting? * If current smblk: *	reading - if can read, OK.  Else position at beg of next sdblk *	writing - if can write, OK.  Else position at end of prev sdblk, *		or set up for splitting? * Types: *	0 - Read forward (BOB) *	1 - Read backward (EOB) *	3 - Write (insert forward) (EOB) *	4 - Delete forward (return SD, force BOB-aligned) *	5 - Delete backward (return SD, force EOB-aligned) * Connected SD is always locked. * Returns 0 if error, -1 if EOF-type error, 1 for success. * * For types 0,1: *	CMIN,CMAX represent max # chars to read in to left and right of *		I/O ptr (prev and post).  Actual amount read in may be *		much less, but will never be zero. *	Successful return guarantees that SBIOP etc. are ready. * For type 3: *	If new block is allocated, CMIN and CMAX represent min, max sizes *		of the block. *	Successful return guarantees that SBIOP etc. are ready, but *	NOTE that SB_WRIT and SD_MOD are not set!  If not going to use *	for writing, be sure to clear sbwleft on return! * For types 4,5: *	CMIN, CMAX are ignored. *	SBIOP is always cleared.  SBOFF is guaranteed to be 0 for *	type 4, SMUSE for type 5. *	Return value is a SD ptr; 0 indicates error.  -1 isn't used. */struct sdblk *sbx_ready(sbp,type,cmin,cmax)SBBUF *sbp;int type;SBMO cmin,cmax;{	register SBBUF *sb;	register struct sdblk *sd;	register struct smblk *sm;	int cnt, slop, rem;	SBMO moff;	if((sd = (sb=sbp)->sbcur) == 0)		return(0);	if(sb->sbiop)		/* Canonicalize for given operation */	  {	if((sm = sd->sdmem)==0)			return(0);		moff = sb->sbiop - sm->smaddr;	/* Current block offset */	  switch(type)	  {	case SK_READF:		/* Read Forward */		if(sb->sbrleft > 0)	/* Already set up? */			return(1);	/* Yup, fast return */		sbx_smdisc(sb);		/* None left, disc to get next */		if((sd = sbx_next(sb)) == 0)	/* Try to get next blk */			return(-1);	/* At EOF */		break;	case SK_READB:		/* Read Backward */		if(moff)		/* Stuff there to read? */		  {	if(sb->sbflags&SB_WRIT)	/* Yup, turn writes off */			  {	sm->smuse = moff;				sb->sbflags &= ~SB_WRIT;			  }			sb->sbwleft = 0;			return(1);		  }		sbx_smdisc(sb);		break;	case SK_WRITEF:		/* Writing */		if(sb->sbrleft <= 0)			sb->sbwleft = sm->smlen - moff;		if(sb->sbwleft > 0)			return(1);	/* OK to write now */					/* NOTE: flags not set!!! */		sbx_smdisc(sb);		break;	case SK_DELF:		/* Delete forward - force BOB */		if(sb->sbrleft <= 0)		/* At end of blk? */		  {	sbx_smdisc(sb);		/* Win, unhook */			return(sbx_next(sb));   /* Return next or 0 if EOF */		  }		sbx_smdisc(sb);			/* Not at end, but see if */		if(moff == 0)			/* at beg of blk? */			return(sd);	/* Fast win! */		break;	case SK_DELB:		/* Delete backward - force EOB */		if(sb->sbrleft <= 0)		/* Win if already EOB */		  {	sbx_smdisc(sb);			return(sd);		  }		sbx_smdisc(sb);		break;	default:		return(0);	  }	  }	/* Schnarf in the text, or whatever.	 * SD points to current sdblk (must be SD_LOCKed)	 * SBDOT must have correct value for this SD	 * SBOFF has offset from there to put I/O ptr at.	 *	 * After normalization, SBOFF is guaranteed to point within	 * the SD.  Other guarantees apply to boundary cases, depending	 * on the mode (type) bits.	 */	sd = sbx_norm(sb,type);	/* Normalize I/O pos appropriately */	sm = sd->sdmem;	switch(type)	  {	case SK_READB:		/* Read Backward */		if(sb->sboff == 0)	/* Due to normalize, if 0 seen */			return(-1);	/* then we know it's BOF */		if(sm) goto sekr2;		else goto sekr1;	case SK_READF:		/* Read Forward */		if(sm) goto sekr2;		if(sb->sboff == sd->sdlen)	/* Normalize means if EOB */			return(-1);		/* then at EOF. */	sekr1:	slop = SB_SLOP;	sekr3:	if(sb->sboff > cmin+slop)	/* Too much leading text? */		  {				/* Split off leading txt */			sbx_split(sd,(chroff)(sb->sboff - cmin));			sd = sbx_next(sb);	/* Point to next sdblk */			sb->sboff = cmin;	/* Set correct offset */						/* (sbx_next assumes 0) */		  }		if(sd->sdlen > sb->sboff+cmax+slop) /* Too much trailing txt? */			sbx_split(sd,(chroff)(sb->sboff+cmax));		/* ----- Try to get mem blk to read stuff into ----- */		/* Note alignment hack for extra efficiency.  This ensures		 * that all reads from disk to memory are made with the same		 * source and destination word alignment, so the system kernel		 * only needs byte-moves for the first or last bytes; all		 * others can be word-moves.		 * This works because sbx_mget always returns word-aligned		 * storage, and we use sbx_msplit to trim off the right number		 * of bytes from the start.		 */		cnt = sd->sdlen;		/* Get # bytes we'd like */		if(rem = rndrem(sd->sdaddr))	/* If disk not word-aligned */			cnt += rem;		/* allow extra for aligning.*/		if(sm == 0)			/* Always true 1st time */		  {	sm = sbx_mget(SB_SLOP,cnt); /* Get room (may GC!)*/			if(sm->smlen < cnt)	/* Got what we wanted? */			  {	slop = 0;	/* NO!!	 Impose stricter */				cmin = 0;	/* limits.  Allow for new */				cmax = sm->smlen - (WDSIZE-1); /* rem. */				if(type == SK_READB)				  {	cmin = cmax; cmax = 0; }				goto sekr3;	/* Go try again, sigh. */			  }		  }		else if(sm->smlen < cnt)	/* 2nd time shd always win */		  {	sbx_err(0,"Readin blksiz err");	/* Internal error, */			if((cmax /= 2) > 0) goto sekr3;	/* w/crude recovery */			return(0);		  }		if(rem)		/* If disk not word-aligned, hack stuff */		  {	sm = sbx_msplit(sm, (SBMO)rem);	/* Trim off from beg*/			sbm_mfree(sm->smback);		/* Free the excess */		  }		sd->sdmem = sm;		sm->smuse = sd->sdlen;		if(sd->sdfile == 0)			return(sbx_err(0,"No file"));	/* Gasp? */		if(!sbx_rdf(sd->sdfile->sffd, sm->smaddr, sm->smuse,				1, sd->sdaddr))			return(sbx_err(0,"Readin SD: %o", sd));		/* ------- */	sekr2:	sbx_sbrdy(sb);		/* Make it current, pt to beg */		sb->sbwleft = 0;	/* Ensure not set (esp if READB) */		break;	case SK_WRITEF:		/* Write-type seek */		if(sm == 0)		  {	/* Block is on disk, so always split (avoid readin) */			if(sd->sdlen)			/* May be empty */			  {	sbx_split(sd, sb->sboff); /* Split at IO ptr */				sd = sbx_next(sb);	/* Move to 2nd part */				if(sd->sdlen)		/* If stuff there, */							/* split it again. */					sbx_split(sd, (chroff) 0);			  }			goto sekwget;		  }		/* Block in memory */		moff = sm->smuse;		if(sb->sboff == moff)		/* At end of the block? */		  {	if(sm->smlen > moff)	/* Yes, have room? */				goto sekw;	/* Win, go setup and ret */			if(sm->smforw			/* If next mem blk */			  && (sm->smforw->smflags	/* Can have bytes */				& (SM_USE|SM_NXM))==0	/* stolen from it */			  && (sd->sdflags&SD_MOD)	/* and we ain't pure*/			  && sm->smlen < cmax)		/* and not too big */			  {	/* Then steal some core!!  Note that without				 * the size test, a stream of putc's could				 * create a monster block gobbling all mem.				 */				cmin = cmax - sm->smlen;				if(cmin&01) cmin++;	/* Ensure wd-align */				if(sm->smforw->smlen <= cmin)				  {	sbm_mmrg(sm);					goto sekw;				  }				sm->smforw->smlen -= cmin;				sm->smforw->smaddr += cmin;				sm->smlen += cmin;				goto sekw;			  }			/* Last try... check next logical blk for room */			if(sd->slforw && (sm = sd->slforw->sdmem)			  && sm->smuse == 0			  && sm->smlen)			  {	sd = sbx_next(sb);	/* Yup, go there */				goto sekw;			  }		  }		/* Middle of block, split up to insert */		sbx_split(sd, sb->sboff);	/* Split at IO ptr */		if(sd->sdmem)			/* Unless blk now empty, */		  {	sd = sbx_next(sb);	/* move to next. */			if(sd->sdmem)		/* If not empty either */			  sbx_split(sd, (chroff) 0);	/* Split again */		  }		/* Have empty SD block, get some mem for it */  sekwget:	sd->sdmem = sm = sbx_mget(cmin,cmax);		sm->smuse = 0;   sekw:	sbx_sbrdy(sb);		/* Sets up sbwleft... */		return(1);	case SK_DELF:		/* Delete forward */		if(sb->sboff == 0)	/* At block beg already? */			return(sd);	/* Win, return it */		sbx_split(sd, sb->sboff);	/* No, split up and */		return(sbx_next(sb));	/* return ptr to 2nd part */	case SK_DELB:		/* Delete backward (force EOB align) */		if(sb->sboff !=		/* If not at EOB already, */		  (sm ? (chroff)(sm->smuse) : sd->sdlen))			sbx_split(sd, sb->sboff);	/* Then split */		return(sd);	/* And return ptr to 1st part */		break;	default:		return(0);	  }	/* End of switch */	return(1);}struct sdblk *sbx_next (sbp)SBBUF *sbp;{	register SBBUF *sb;	register struct sdblk *sd, *sdf;	if((sdf = (sd = (sb=sbp)->sbcur)->slforw) == 0)		return((struct sdblk *)0);	sb->sbdot += (sd->sdmem ? (chroff)sd->sdmem->smuse : sd->sdlen);	sb->sboff = 0;	sd->sdflags &= ~SD_LOCK;	/* Unlock current */	sdf->sdflags |= SD_LOCK;	/* Lock next */	sb->sbcur = sdf;	return(sdf);}/* SBX_NORM(sb,mode) - Normalizes I/O position as desired. *	The SBBUF must have I/O disconnected (SBIOP==0). *	Adjusts SBCUR, SBDOT, and SBOFF so that SBOFF is guaranteed *	to point to a location in the current SD block. *	The mode flags determine action when there is more than *	one possible SD that could be pointed to, as is the case *	when the I/O pos falls on a block boundary (possibly with *	adjacent zero-length blocks as well). *	SKM_0BACK - Zero-skip direction. *		  0 = Skip forward over zero-length blocks. *		set = Skip backward over zero-length blocks. *	SKM_EOB	  - Block-end selection (applies after skipping done). *		  0 = Point to BOB (Beginning Of Block). *		set = Point to EOB (End Of Block). * Returns the new current SD as a convenience. * Notes: *	The SKM_0BACK flag value is a special hack to search in *		the right direction when SBOFF is initially 0. *	None of the mode flags have any effect if the I/O pos falls *		within a block. *	Perhaps this routine should flush the zero-length blks it *		finds, if they're not locked?? */struct sdblk *sbx_norm(sbp,mode)SBBUF *sbp;int mode;{	register struct sdblk *sd;	register struct smblk *sm;	register SBBUF *sb;	chroff len;	if((sd = (sb=sbp)->sbcur) == 0)	  {	sb->sbdot = 0;		sb->sboff = 0;		return(sd);	  }	sd->sdflags &= ~SD_LOCK;	/* Unlock current blk */	if(sb->sboff >= (mode&01))	/* Hack hack to get right skip */	  for(;;)			/* Scan forwards */	  {	if(sm = sd->sdmem)		/* Get length of this blk */			len = sm->smuse;		else len = sd->sdlen;		if(sb->sboff <= len)		  if(sb->sboff < len	/* If == and fwd 0-skip, continue */		  || (mode&SKM_0BACK))		    {	if((mode&SKM_EOB)	/* Done, adjust to EOB? */			  && sb->sboff == 0	/* Yes, are we at BOB? */			  && sd->slback)	/* and can do it? */			  {	sd = sd->slback;	/* Move to EOB */				sb->sboff = (sm = sd->sdmem) 					? (chroff)(sm->smuse) : sd->sdlen;				sb->sbdot -= sb->sboff;			  }			break;		    }		if(sd->slforw == 0)	/* At EOF? */		  {	sb->sboff = len;			break;		  }		sd = sd->slforw;		sb->sboff -= len;		sb->sbdot += len;	  }	else				/* Scan backwards */	 for(;;)	  {	if(sd->slback == 0)	/* At BOF? */		  {	sb->sboff = 0;			sb->sbdot = 0;	/* Should already be 0, but... */			break;		  }		sd = sd->slback;		if(sm = sd->sdmem)		/* Get length of this blk */			len = sm->smuse;		else len = sd->sdlen;		sb->sbdot -= len;		if((sb->sboff += len) >= 0)		  if(sb->sboff > 0	/* If == 0 and bkwd 0-skip, continue */		    || !(mode&SKM_0BACK))		    {	if((mode&SKM_EOB) == 0	/* Done, adjust to BOB? */			  && sb->sboff == len	/* Yes, are we at EOB? */			  && sd->slforw)	/* and can do it? */			  {	sd = sd->slforw;	/* Move to BOB */				sb->sboff = 0;				sb->sbdot += len;			  }			break;		    }	  }	sb->sbcur = sd;	sd->sdflags |= SD_LOCK;	return(sd);}struct sdblk *sbx_beg(sdp)struct sdblk *sdp;{	register struct sdblk *sd, *sdx;	if(sd = sdp)		while(sdx = sd->slback)			sd = sdx;	return(sd);}sbx_smdisc(sbp)SBBUF *sbp;{	register SBBUF *sb;	register struct smblk *sm;	register struct sdblk *sd;	sb = sbp;	if((sd = sb->sbcur) == 0	  || (sm = sd->sdmem) == 0)		return;	if(sb->sbflags&SB_WRIT)	  {	sm->smuse = sb->sbiop - sm->smaddr;		sb->sbflags &= ~SB_WRIT;	  }	sb->sboff = sb->sbiop - sm->smaddr;	sb->sbiop = 0;	sb->sbrleft = sb->sbwleft = 0;}sbx_sbrdy(sbp)		/* Sets up SBIOP, SBRLEFT, SBWLEFT */SBBUF *sbp;{	register SBBUF *sb;	register struct sdblk *sd;	register struct smblk *sm;	if((sd = (sb=sbp)->sbcur) == 0	  || (sm = sd->sdmem) == 0)		return;	sd->sdflags |= SD_LOCK;	sb->sbiop = sm->smaddr + sb->sboff;	if(sb->sbrleft = sm->smuse - sb->sboff)		sb->sbwleft = 0;	else sb->sbwleft = sm->smlen - sm->smuse;

⌨️ 快捷键说明

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