📄 sbstr.c
字号:
/* 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 + -