📄 sbstr.c
字号:
/* SB_GETC(sb) - Get next char from sbstring. * Returns char at current location and advances I/O ptr. * Returns EOF on error or end-of-string. */intsb_sgetc(sb)register SBBUF *sb;{ if(--(sb->sbrleft) >= 0) return sb_uchartoint(*sb->sbiop++); /* Must do hard stuff -- check ptrs, get next blk */ sb->sbrleft = 0; /* Reset cnt to zero */ if(sb->sbcur == 0 /* Make sure sbbuffer there */ || (int)sbx_ready(sb,SK_READF,0,SB_BUFSIZ) <= 0) /* Normalize & gobble */ return(EOF); return(sb_sgetc(sb)); /* Try again */} /* Loop wd be faster, but PDL OV will catch infinite-loop bugs *//* SB_PUTC(sb,ch) - Put char into sbstring. * Inserts char at current location. * Returns EOF on error, else the char value. */intsb_sputc(sb,ch)register SBBUF *sb;int ch;{ register struct sdblk *sd; if(--(sb->sbwleft) >= 0) return(*sb->sbiop++ = ch); sb->sbwleft = 0; /* Reset cnt to avoid overflow */ if((sd = sb->sbcur) == 0) /* Verify string is there */ return(EOF); /* Could perhaps create it?? */ if(sb->sbflags&SB_OVW) /* If overwriting, handle std case */ { if(sb->sbiop && --sb->sbrleft >= 0) /* Use this for real count */ { sd->sdflags |= SD_MOD; /* Win, munging... */ return(*sb->sbiop++ = ch); } /* Overwriting and hit end of this block. */ if((int)sbx_ready(sb,SK_READF,0,SB_BUFSIZ) > 0) /* Re-normalize */ return(sb_sputc(sb,ch)); /* No blks left, fall through to insert stuff at end */ } /* Do canonical setup with heavy artillery */ if((int)sbx_ready(sb,SK_WRITEF,SB_SLOP,SB_BUFSIZ) <= 0) /* Get room */ return(EOF); /* Should never happen, but... */ sb->sbflags |= SB_WRIT; sb->sbcur->sdflags |= SD_MOD; return(sb_sputc(sb,ch)); /* Try again */} /* Loop wd be faster, but PDL OV will catch infinite-loop bugs *//* SB_PEEKC(sb) - Peek at next char from sbstring. * Returns char that sb_getc would next return, but without * changing I/O ptr. * Returns EOF on error or end-of-string. */intsb_speekc(sb)register SBBUF *sb;{ if (sb->sbrleft <= 0) /* See if OK to read */ { if (sb_sgetc(sb) == EOF) /* No, try hard to get next */ return EOF; /* Failed, return EOF */ sb_backc(sb); /* Won, back up */ } return sb_uchartoint(*sb->sbiop);}/* SB_RGETC(sb) - Get previous char from sbstring. * Returns char prior to current location and backs up I/O ptr. * Returns EOF on error or beginning-of-string. */intsb_rgetc(sb)register SBBUF *sb;{ register struct smblk *sm; register struct sdblk *sd; if((sd=sb->sbcur) && (sm = sd->sdmem) && sb->sbiop > sm->smaddr) { if(sb->sbflags&SB_WRIT) { sm->smuse = sb->sbiop - sm->smaddr; sb->sbwleft = 0; sb->sbflags &= ~SB_WRIT; } sb->sbrleft++; return sb_uchartoint(*--sb->sbiop); /* Return char */ } if((int)sbx_ready(sb,SK_READB,SB_BUFSIZ,0) <= 0) return(EOF); return(sb_rgetc(sb));}/* SB_RDELC(sb) - Delete backwards one char. * Returns nothing. */sb_rdelc(sbp)SBBUF *sbp;{ register SBBUF *sb; register struct sdblk *sd; if(((sb=sbp)->sbflags&SB_WRIT) /* Handle simple case fast */ && sb->sbiop > (sd = sb->sbcur)->sdmem->smaddr) { sb->sbwleft++; sb->sbiop--; sd->sdflags |= SD_MOD; return; } else sb_deln(sb,(chroff) -1); /* Else punt... */}/* SB_DELC(sb) - Delete one char forward? *//* SB_INSC(sb,ch) - Insert char? (instead of or in addition to PUTC) *//* SBBUF string or N-char operations *//* SB_DELN(sb,chroff) - delete N chars. Negative N means backwards. * Differs from sb_killn in that it flushes the text forever, * and doesn't return anything. */sb_deln(sbp, num)SBBUF *sbp;chroff num;{ register struct sdblk *sd; if(sd = sb_killn(sbp,num)) sbs_del(sd); /* Punt */}/* SB_KILLN(sb,chroff) - delete N chars, saving. Negative N means backwards. * Returns SD pointer to beginning of saved sbstring. */struct sdblk *sb_killn(sbp, num)SBBUF *sbp;chroff num;{ register SBBUF *sb; register struct sdblk *sd, *sd2; struct sdblk *sdr, *sdx; chroff savdot; if((sd = sbx_xcis((sb=sbp),num,&sdr,&savdot)) == 0) return((struct sdblk *)0); sb->sbcur->sdflags &= ~SD_LOCK; /* Now can flush sbcur lock */ /* SD and SD2 now delimit bounds of stuff to excise. * First do direction dependent fixups */ if(num >= 0) /* If deleting forward, */ sb->sbdot = savdot; /* must reset dot to initial loc */ /* SD and SD2 now in first/last order. Complete SBCUR fixup. */ sd2 = sdr; /* sdr has ptr to end of stuff */ if(sd2 = sd2->slforw) /* More stuff after killed list? */ { sb->sbcur = sd2; /* Yes, point at it */ sb->sboff = 0; /* Dot already set right */ } else if(sdx = sd->slback) /* See if any prior to killed list */ { sb->sbcur = sdx; /* Yes, point at it */ sb->sboff = (sdx->sdmem ? /* Get len of prev blk */ sdx->sdmem->smuse : sdx->sdlen); sb->sbdot -= sb->sboff; } else sb_open(sb,(SBSTR *)0); /* No stuff left! Create null sbstring */ /* Fix up logical links. Note SD2 points to succ of killed stuff */ if(sd->slback) /* If previous exists */ { if(sd->slback->slforw = sd2) /* Point it to succ, and */ sd2->slback = sd->slback; /* thence to self */ sd->slback = 0; /* Now init killed list */ } else if(sd2) sd2->slback = 0; /* No prev, clean rest */ (sd2 = sdr)->slforw = 0; /* Finish killed list */ sb->sbcur->sdflags |= SD_LOCK; /* Ensure current SD now locked */ sd->sdflags &= ~SD_LCK2; /* And unlock killed list */ sd2->sdflags &= ~SD_LCK2; return(sd);}/* SB_CPYN(sbp,num) - Copy num characters, returns SD to sbstring. * Like SB_KILLN but doesn't take chars out of original sbstring. */SBSTR *sb_cpyn(sbp,num)SBBUF *sbp;chroff num;{ register SBBUF *sb; register struct sdblk *sd, *sd2; struct sdblk *sdr; chroff savloc; sb = sbp; if((sd = sbx_xcis(sb,num,&sdr,&savloc)) == 0) return((SBSTR *)0); sd2 = sbx_scpy(sd,sdr); sb_seek(sb,-num,1); /* Return to original loc */ return(sd2); /* Return val is ptr to head of copy. * It needn't be locked, because GC will * never move list heads! */}/* SB_SINS(sb,sd) - Insert sbstring at current location * */sb_sins(sbp,sdp)SBBUF *sbp;struct sdblk *sdp;{ register SBBUF *sb; register struct sdblk *sd, *sdx; chroff inslen; if((sb = sbp)==0 || (sd = sdp) == 0) return(0); if(sd->slback) /* Perhaps normalize to beg? */ return(0); if((sdx = (struct sdblk *)sbx_ready(sb,SK_DELB)) == 0) /* Get cur pos ready */ return(0); inslen = sbs_len(sd); /* Save length of inserted stuff */ sd->slback = sdx; /* Fix up links */ if(sdx->slforw) { while(sd->slforw) /* Hunt for end of inserted sbstring */ sd = sd->slforw; sd->slforw = sdx->slforw; sd->slforw->slback = sd; } sdx->slforw = sdp; sb->sboff += inslen; /* Set IO ptr to end of new stuff */ return(1);}/* SBSTRING routines - operate on "bare" sbstrings. *//* SBS_CPY(sd) - Copies given sbstring, returns ptr to new sbstring. */SBSTR *sbs_cpy(sdp)SBSTR *sdp;{ return(sbx_scpy(sdp,(struct sdblk *)0));}/* SBS_DEL(sd) - Flush a sbstring. */sbs_del(sdp)SBSTR *sdp;{ register struct sdblk *sd; if(sd = sdp) while(sd = sbx_ndel(sd));}/* SBS_APP(sd1,sd2) - Appends sbstring sd2 at end of sbstring sd1. * Returns sd1 (pointer to new sbstring). */SBSTR *sbs_app(sdp,sdp2)struct sdblk *sdp,*sdp2;{ register struct sdblk *sd, *sdx; if(sd = sdp) { while(sdx = sd->slforw) sd = sdx; if(sd->slforw = sdx = sdp2) sdx->slback = sd; } return(sdp);}/* SBS_LEN(sd) - Find length of sbstring. */chroffsbs_len(sdp)SBSTR *sdp;{ register struct sdblk *sd; register struct smblk *sm; chroff len; if((sd = sdp)==0) return((chroff)0); len = 0; for(; sd ; sd = sd->slforw) { if(sm = sd->sdmem) len += (chroff)sm->smuse; else len += sd->sdlen; } return(len);}/* SBBUF I/O pointer ("dot") routines *//* SB_SEEK(sb,chroff,flag) - Like FSEEK. Changes I/O ptr value as * indicated by "flag": * 0 - offset from beg * 1 - offset from current pos * 2 - offset from EOF * Returns -1 on errors. * Seeking beyond beginning or end of sbbuf will leave pointer * at the beginning or end respectively. * Returns 0 unless error (then returns -1). */sb_seek(sbp, coff, flg)SBBUF *sbp;chroff coff;int flg;{ register SBBUF *sb; register struct smblk *sm; register struct sdblk *sd; SBMO moff; sb = sbp; if((sd = sb->sbcur) == 0) return(-1); if(sb->sbiop == 0) { switch(flg) { case 0: if(coff == 0) /* Optimize common case */ return(sb_rewind(sb)); sb->sboff = coff - sb->sbdot; /* Abs */ break; case 1: sb->sboff += coff; /* Rel */ break; case 2: sb->sboff += sb_ztell(sb) + coff; break; default: return(-1); } sbx_norm(sb,0); return(0); } if((sm = sd->sdmem) == 0) return(sbx_err(-1,"SDMEM 0")); moff = sb->sbiop - sm->smaddr; /* Get cur smblk offset */ if(sb->sbflags&SB_WRIT) /* Update since moving out */ { sm->smuse = moff; sb->sbflags &= ~SB_WRIT; } sb->sbwleft = 0; /* Always gets zapped */ switch(flg) { case 0: /* Offset from beginning */ coff -= sb->sbdot + (chroff)moff; /* Make rel */ case 1: /* Offset from current loc */ break; case 2: /* Offset from end */ coff += sb_ztell(sb); break; default: return(-1); } /* COFF now has relative offset from current location */ if (-(chroff)moff <= coff && coff <= sb->sbrleft) { /* Win! Handle repos-within-smblk */ sb->sbiop += coff; sb->sbrleft -= coff; /* Set r; wleft already 0 */ return(0); } /* Come here when moving to a different sdblk. */ sb->sbrleft = 0; sb->sbiop = 0; sb->sboff = coff + (chroff)moff; sbx_norm(sb,0); return(0);}/* SB_REWIND(sb) - Go to beginning of sbbuffer. * Much faster than using sb_seek. Note that this leaves the sbbuffer * in an open/idle state which is maximally easy to compact. */sb_rewind(sbp)SBBUF *sbp;{ register SBBUF *sb; register struct sdblk *sd; if((sb = sbp)==0) return; sbx_smdisc(sb); /* Ensure I/O disconnected */ (sd = sb->sbcur)->sdflags &= ~SD_LOCK; /* Unlock current blk */ sd = sbx_beg(sd); /* Move to beg of sbstring */ /* Need not lock - see sb_open comments, also sb_close */ /* sd->sdflags |= SD_LOCK; */ /* Lock onto this one */ sb->sbcur = sd; sb->sbdot = 0; sb->sboff = 0;}/* SB_TELL(sb) - Get I/O ptr value for SBBUF. * Returns -1 on errors. */chroffsb_tell(sbp)SBBUF *sbp;{ register SBBUF *sb; register struct smblk *sm; register struct sdblk *sd; if((sd = (sb=sbp)->sbcur) == 0) return((chroff)-1); if(sb->sbiop == 0) return(sb->sbdot + sb->sboff); if((sm = sd->sdmem) == 0) return(sbx_err(0,"SDMEM 0")); return(sb->sbdot + (unsigned)(sb->sbiop - sm->smaddr));}/* SB_ZTELL(sb) - Get I/O ptr relative to "Z" (EOF). * Returns # chars from current location to EOF; 0 if any errors. */chroffsb_ztell(sbp)SBBUF *sbp;{ register SBBUF *sb; register struct smblk *sm; register struct sdblk *sd; if((sd = (sb=sbp)->sbcur) == 0) return((chroff)0); if(sb->sbiop && (sm = sd->sdmem)) { if(sb->sbflags&SB_WRIT) /* If actively writing, */ return(sbs_len(sd->slforw)); /* ignore this blk. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -