Annotation of coherent/d/usr/bin/elvis/blk.c, revision 1.1

1.1     ! root        1: /* blk.c */
        !             2: 
        !             3: /* Author:
        !             4:  *     Steve Kirkendall
        !             5:  *     16820 SW Tallac Way
        !             6:  *     Beaverton, OR 97006
        !             7:  *     [email protected], or ...uunet!tektronix!psueea!jove!kirkenda
        !             8:  */
        !             9: 
        !            10: 
        !            11: /* This file contains the functions that get/put blocks from the temp file.
        !            12:  * It also contains the "do" and "undo" functions.
        !            13:  */
        !            14: 
        !            15: #include "config.h"
        !            16: #include "vi.h"
        !            17: 
        !            18: #ifndef NBUFS
        !            19: # define NBUFS 5               /* must be at least 3 -- more is better */
        !            20: #endif
        !            21: 
        !            22: extern long lseek();
        !            23: 
        !            24: /*------------------------------------------------------------------------*/
        !            25: 
        !            26: BLK            hdr;            /* buffer for the header block */
        !            27: 
        !            28: static int     b4cnt;          /* used to count context of beforedo/afterdo */
        !            29: static struct _blkbuf
        !            30: {
        !            31:        BLK             buf;            /* contents of a text block */
        !            32:        unsigned short  logical;        /* logical block number */
        !            33:        int             dirty;          /* must the buffer be rewritten? */
        !            34: }
        !            35:                blk[NBUFS],     /* buffers for text[?] blocks */
        !            36:                *toonew,        /* buffer which shouldn't be recycled yet */
        !            37:                *newtoo,        /* another buffer which should be recycled */
        !            38:                *recycle = blk; /* next block to be recycled */
        !            39: 
        !            40: 
        !            41: 
        !            42: 
        !            43: 
        !            44: /* This function wipes out all buffers */
        !            45: void blkinit()
        !            46: {
        !            47:        int     i;
        !            48: 
        !            49:        for (i = 0; i < NBUFS; i++)
        !            50:        {
        !            51:                blk[i].logical = 0;
        !            52:                blk[i].dirty = FALSE;
        !            53:        }
        !            54:        for (i = 0; i < MAXBLKS; i++)
        !            55:        {
        !            56:                hdr.n[i] = 0;
        !            57:        }
        !            58: }
        !            59: 
        !            60: /* This function allocates a buffer and fills it with a given block's text */
        !            61: BLK *blkget(logical)
        !            62:        int     logical;        /* logical block number to fetch */
        !            63: {
        !            64:        REG struct _blkbuf      *this;  /* used to step through blk[] */
        !            65:        REG int i;
        !            66: 
        !            67:        /* if logical is 0, just return the hdr buffer */
        !            68:        if (logical == 0)
        !            69:        {
        !            70:                return &hdr;
        !            71:        }
        !            72: 
        !            73:        /* see if we have that block in mem already */
        !            74:        for (this = blk; this < &blk[NBUFS]; this++)
        !            75:        {
        !            76:                if (this->logical == logical)
        !            77:                {
        !            78:                        newtoo = toonew;
        !            79:                        toonew = this;
        !            80:                        return &this->buf;
        !            81:                }
        !            82:        }
        !            83: 
        !            84:        /* choose a block to be recycled */
        !            85:        do
        !            86:        {
        !            87:                this = recycle++;
        !            88:                if (recycle == &blk[NBUFS])
        !            89:                {
        !            90:                        recycle = blk;
        !            91:                }
        !            92:        } while (this == toonew || this == newtoo);
        !            93: 
        !            94:        /* if it contains a block, flush that block */
        !            95:        blkflush(this);
        !            96: 
        !            97:        /* fill this buffer with the desired block */
        !            98:        this->logical = logical;
        !            99:        if (hdr.n[logical])
        !           100:        {
        !           101:                /* it has been used before - fill it from tmp file */
        !           102:                lseek(tmpfd, (long)hdr.n[logical] * (long)BLKSIZE, 0);
        !           103:                if (read(tmpfd, this->buf.c, (unsigned)BLKSIZE) != BLKSIZE)
        !           104:                {
        !           105:                        msg("Error reading back from tmp file!");
        !           106:                }
        !           107:        }
        !           108:        else
        !           109:        {
        !           110:                /* it is new - zero it */
        !           111:                for (i = 0; i < BLKSIZE; i++)
        !           112:                {
        !           113:                        this->buf.c[i] = 0;
        !           114:                }
        !           115:        }
        !           116: 
        !           117:        /* This isn't really a change, but it does potentially invalidate
        !           118:         * the kinds of shortcuts that the "changes" variable is supposed
        !           119:         * to protect us from... so count it as a change.
        !           120:         */
        !           121:        changes++;
        !           122: 
        !           123:        /* mark it as being "not dirty" */
        !           124:        this->dirty = 0;
        !           125: 
        !           126:        /* return it */
        !           127:        newtoo = toonew;
        !           128:        toonew = this;
        !           129:        return &this->buf;
        !           130: }
        !           131: 
        !           132: 
        !           133: 
        !           134: /* This function writes a block out to the temporary file */
        !           135: void blkflush(this)
        !           136:        REG struct _blkbuf      *this;  /* the buffer to flush */
        !           137: {
        !           138:        long            seekpos;        /* seek position of the new block */
        !           139:        unsigned short  physical;       /* physical block number */
        !           140: 
        !           141:        /* if its empty (an orphan blkadd() maybe?) then make it dirty */
        !           142:        if (this->logical && !*this->buf.c)
        !           143:        {
        !           144:                blkdirty(&this->buf);
        !           145:        }
        !           146: 
        !           147:        /* if it's an empty buffer or a clean version is on disk, quit */
        !           148:        if (!this->logical || hdr.n[this->logical] && !this->dirty)
        !           149:        {
        !           150:                return;
        !           151:        }
        !           152: 
        !           153:        /* find a free place in the file */
        !           154: #ifndef NO_RECYCLE
        !           155:        seekpos = allocate();
        !           156:        lseek(tmpfd, seekpos, 0);
        !           157: #else
        !           158:        seekpos = lseek(tmpfd, 0L, 2);
        !           159: #endif
        !           160:        physical = seekpos / BLKSIZE;
        !           161: 
        !           162:        /* put the block there */
        !           163:        if (write(tmpfd, this->buf.c, (unsigned)BLKSIZE) != BLKSIZE)
        !           164:        {
        !           165:                msg("Trouble writing to tmp file");
        !           166:        }
        !           167:        this->dirty = FALSE;
        !           168: 
        !           169:        /* update the header so it knows we put it there */
        !           170:        hdr.n[this->logical] = physical;
        !           171: }
        !           172: 
        !           173: 
        !           174: /* This function sets a block's "dirty" flag or deletes empty blocks */
        !           175: void blkdirty(bp)
        !           176:        BLK     *bp;    /* buffer returned by blkget() */
        !           177: {
        !           178:        REG int         i, j;
        !           179:        REG char        *scan;
        !           180:        REG int         k;
        !           181: 
        !           182:        /* find the buffer */
        !           183:        for (i = 0; i < NBUFS && bp != &blk[i].buf; i++)
        !           184:        {
        !           185:        }
        !           186: #ifdef DEBUG
        !           187:        if (i >= NBUFS)
        !           188:        {
        !           189:                msg("blkdirty() called with unknown buffer at 0x%lx", bp);
        !           190:                return;
        !           191:        }
        !           192:        if (blk[i].logical == 0)
        !           193:        {
        !           194:                msg("blkdirty called with freed buffer");
        !           195:                return;
        !           196:        }
        !           197: #endif
        !           198: 
        !           199:        /* if this block ends with line# INFINITY, then it must have been
        !           200:         * allocated unnecessarily during tmpstart().  Forget it.
        !           201:         */
        !           202:        if (lnum[blk[i].logical] == INFINITY)
        !           203:        {
        !           204: #ifdef DEBUG
        !           205:                if (blk[i].buf.c[0])
        !           206:                {
        !           207:                        msg("bkldirty called with non-empty extra BLK");
        !           208:                }
        !           209: #endif
        !           210:                blk[i].logical = 0;
        !           211:                blk[i].dirty = FALSE;
        !           212:                return;
        !           213:        }
        !           214: 
        !           215:        /* count lines in this block */
        !           216:        for (j = 0, scan = bp->c; *scan && scan < bp->c + BLKSIZE; scan++)
        !           217:        {
        !           218:                if (*scan == '\n')
        !           219:                {
        !           220:                        j++;
        !           221:                }
        !           222:        }
        !           223: 
        !           224:        /* adjust lnum, if necessary */
        !           225:        k = blk[i].logical;
        !           226:        j += (lnum[k - 1] - lnum[k]);
        !           227:        if (j != 0)
        !           228:        {
        !           229:                nlines += j;
        !           230:                while (k < MAXBLKS && lnum[k] != INFINITY)
        !           231:                {
        !           232:                        lnum[k++] += j;
        !           233:                }
        !           234:        }
        !           235: 
        !           236:        /* if it still has text, mark it as dirty */
        !           237:        if (*bp->c)
        !           238:        {
        !           239:                blk[i].dirty = TRUE;
        !           240:        }
        !           241:        else /* empty block, so delete it */
        !           242:        {
        !           243:                /* adjust the cache */
        !           244:                k = blk[i].logical;
        !           245:                for (j = 0; j < NBUFS; j++)
        !           246:                {
        !           247:                        if (blk[j].logical >= k)
        !           248:                        {
        !           249:                                blk[j].logical--;
        !           250:                        }
        !           251:                }
        !           252: 
        !           253:                /* delete it from hdr.n[] and lnum[] */
        !           254:                blk[i].logical = 0;
        !           255:                blk[i].dirty = FALSE;
        !           256:                while (k < MAXBLKS - 1)
        !           257:                {
        !           258:                        hdr.n[k] = hdr.n[k + 1];
        !           259:                        lnum[k] = lnum[k + 1];
        !           260:                        k++;
        !           261:                }
        !           262:                hdr.n[MAXBLKS - 1] = 0;
        !           263:                lnum[MAXBLKS - 1] = INFINITY;
        !           264:        }
        !           265: }
        !           266: 
        !           267: 
        !           268: /* insert a new block into hdr, and adjust the cache */
        !           269: BLK *blkadd(logical)
        !           270:        int     logical;        /* where to insert the new block */
        !           271: {
        !           272:        REG int i;
        !           273: 
        !           274:        /* adjust hdr and lnum[] */
        !           275:        for (i = MAXBLKS - 1; i > logical; i--)
        !           276:        {
        !           277:                hdr.n[i] = hdr.n[i - 1];
        !           278:                lnum[i] = lnum[i - 1];
        !           279:        }
        !           280:        hdr.n[logical] = 0;
        !           281:        lnum[logical] = lnum[logical - 1];
        !           282: 
        !           283:        /* adjust the cache */
        !           284:        for (i = 0; i < NBUFS; i++)
        !           285:        {
        !           286:                if (blk[i].logical >= logical)
        !           287:                {
        !           288:                        blk[i].logical++;
        !           289:                }
        !           290:        }
        !           291: 
        !           292:        /* return the new block, via blkget() */
        !           293:        return blkget(logical);
        !           294: }
        !           295: 
        !           296: 
        !           297: /* This function forces all dirty blocks out to disk */
        !           298: void blksync()
        !           299: {
        !           300:        int     i;
        !           301: 
        !           302:        for (i = 0; i < NBUFS; i++)
        !           303:        {
        !           304:                /* blk[i].dirty = TRUE; */
        !           305:                blkflush(&blk[i]);
        !           306:        }
        !           307:        if (*o_sync)
        !           308:        {
        !           309:                sync();
        !           310:        }
        !           311: }
        !           312: 
        !           313: /*------------------------------------------------------------------------*/
        !           314: 
        !           315: static MARK    undocurs;       /* where the cursor should go if undone */
        !           316: static long    oldnlines;
        !           317: static long    oldlnum[MAXBLKS];
        !           318: 
        !           319: 
        !           320: /* This function should be called before each command that changes the text.
        !           321:  * It defines the state that undo() will reset the file to.
        !           322:  */
        !           323: void beforedo(forundo)
        !           324:        int             forundo;        /* boolean: is this for an undo? */
        !           325: {
        !           326:        REG int         i;
        !           327:        REG long        l;
        !           328: 
        !           329:        /* if this is a nested call to beforedo, quit! Use larger context */
        !           330:        if (b4cnt++ > 0)
        !           331:        {
        !           332:                return;
        !           333:        }
        !           334: 
        !           335:        /* force all block buffers to disk */
        !           336:        blksync();
        !           337: 
        !           338: #ifndef NO_RECYCLE
        !           339:        /* perform garbage collection on blocks from tmp file */
        !           340:        garbage();
        !           341: #endif
        !           342: 
        !           343:        /* force the header out to disk */
        !           344:        lseek(tmpfd, 0L, 0);
        !           345:        if (write(tmpfd, hdr.c, (unsigned)BLKSIZE) != BLKSIZE)
        !           346:        {
        !           347:                msg("Trouble writing header to tmp file ");
        !           348:        }
        !           349: 
        !           350:        /* copy or swap oldnlines <--> nlines, oldlnum <--> lnum */
        !           351:        if (forundo)
        !           352:        {
        !           353:                for (i = 0; i < MAXBLKS; i++)
        !           354:                {
        !           355:                        l = lnum[i];
        !           356:                        lnum[i] = oldlnum[i];
        !           357:                        oldlnum[i] = l;
        !           358:                }
        !           359:                l = nlines;
        !           360:                nlines = oldnlines;
        !           361:                oldnlines = l;
        !           362:        }
        !           363:        else
        !           364:        {
        !           365:                for (i = 0; i < MAXBLKS; i++)
        !           366:                {
        !           367:                        oldlnum[i] = lnum[i];
        !           368:                }
        !           369:                oldnlines = nlines;
        !           370:        }
        !           371: 
        !           372:        /* save the cursor position */
        !           373:        undocurs = cursor;
        !           374: 
        !           375:        /* upon return, the calling function continues and makes changes... */
        !           376: }
        !           377: 
        !           378: /* This function marks the end of a (nested?) change to the file */
        !           379: void afterdo()
        !           380: {
        !           381:        if (--b4cnt)
        !           382:        {
        !           383:                return;
        !           384:        }
        !           385: 
        !           386:        /* make sure the cursor wasn't left stranded in deleted text */
        !           387:        if (markline(cursor) > nlines)
        !           388:        {
        !           389:                cursor = MARK_LAST;
        !           390:        }
        !           391:        /* NOTE: it is still possible that markidx(cursor) is after the
        !           392:         * end of a line, so the Vi mode will have to take care of that
        !           393:         * itself */
        !           394: 
        !           395:        /* if a significant change has been made to this file, then set the
        !           396:         * MODIFIED flag.
        !           397:         */
        !           398:        if (significant)
        !           399:        {
        !           400:                setflag(file, MODIFIED);
        !           401:        }       
        !           402: }
        !           403: 
        !           404: /* This function cuts short the current set of changes.  It is called after
        !           405:  * a SIGINT.
        !           406:  */
        !           407: void abortdo()
        !           408: {
        !           409:        /* finish the operation immediately. */
        !           410:        if (b4cnt > 0)
        !           411:        {
        !           412:                b4cnt = 1;
        !           413:                afterdo();
        !           414:        }
        !           415: 
        !           416:        /* in visual mode, the screen is probably screwed up */
        !           417:        if (mode == MODE_COLON)
        !           418:        {
        !           419:                mode = MODE_VI;
        !           420:        }
        !           421:        if (mode == MODE_VI)
        !           422:        {
        !           423:                redraw(MARK_UNSET, FALSE);
        !           424:        }
        !           425: }
        !           426: 
        !           427: /* This function discards all changes made since the last call to beforedo() */
        !           428: int undo()
        !           429: {
        !           430:        BLK             oldhdr;
        !           431: 
        !           432:        /* if beforedo() has never been run, fail */
        !           433:        if (!tstflag(file, MODIFIED))
        !           434:        {
        !           435:                msg("You haven't modified this file yet.");
        !           436:                return FALSE;
        !           437:        }
        !           438: 
        !           439:        /* read the old header form the tmp file */
        !           440:        lseek(tmpfd, 0L, 0);
        !           441:        if (read(tmpfd, oldhdr.c, (unsigned)BLKSIZE) != BLKSIZE)
        !           442:        {
        !           443:                msg("Trouble rereading the old header from tmp file");
        !           444:        }
        !           445: 
        !           446:        /* "do" the changed version, so we can undo the "undo" */
        !           447:        cursor = undocurs;
        !           448:        beforedo(TRUE);
        !           449:        afterdo();
        !           450: 
        !           451:        /* wipe out the block buffers - we can't assume they're correct */
        !           452:        blkinit();
        !           453: 
        !           454:        /* use the old header -- and therefore the old text blocks */
        !           455:        hdr = oldhdr;
        !           456: 
        !           457:        /* This is a change */
        !           458:        changes++;
        !           459: 
        !           460:        return TRUE;
        !           461: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.