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

1.1     ! root        1: /* cmd1.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 some of the EX commands - mostly ones that deal with
        !            12:  * files, options, etc. -- anything except text.
        !            13:  */
        !            14: 
        !            15: #include "config.h"
        !            16: #include <ctype.h>
        !            17: #include "vi.h"
        !            18: #include "regexp.h"
        !            19: 
        !            20: #if MSDOS
        !            21: #define        DATE __DATE__
        !            22: #endif
        !            23: 
        !            24: #ifdef DEBUG
        !            25: /* print the selected lines with info on the blocks */
        !            26: /*ARGSUSED*/
        !            27: void cmd_debug(frommark, tomark, cmd, bang, extra)
        !            28:        MARK    frommark;
        !            29:        MARK    tomark;
        !            30:        CMD     cmd;
        !            31:        int     bang;
        !            32:        char    *extra;
        !            33: {
        !            34:        REG char        *scan;
        !            35:        REG long        l;
        !            36:        REG int         i;
        !            37:        int             len;
        !            38: 
        !            39:        /* scan lnum[] to determine which block its in */
        !            40:        l = markline(frommark);
        !            41:        for (i = 1; l > lnum[i]; i++)
        !            42:        {
        !            43:        }
        !            44: 
        !            45:        do
        !            46:        {
        !            47:                /* fetch text of the block containing that line */
        !            48:                scan = blkget(i)->c;
        !            49: 
        !            50:                /* calculate its length */
        !            51:                if (scan[BLKSIZE - 1])
        !            52:                {
        !            53:                        len = BLKSIZE;
        !            54:                }
        !            55:                else
        !            56:                {
        !            57:                        len = strlen(scan);
        !            58:                }
        !            59: 
        !            60:                /* print block stats */
        !            61:                msg("##### hdr[%d]=%d, lnum[%d-1]=%ld, lnum[%d]=%ld (%ld lines)",
        !            62:                        i, hdr.n[i], i, lnum[i-1], i, lnum[i], lnum[i] - lnum[i - 1]);
        !            63:                msg("##### len=%d, buf=0x%lx, %sdirty",
        !            64:                        len, scan, ((int *)scan)[MAXBLKS + 1] ? "" : "not ");
        !            65:                if (bang)
        !            66:                {
        !            67:                        while (--len >= 0)
        !            68:                        {
        !            69:                                addch(*scan);
        !            70:                                scan++;
        !            71:                        }
        !            72:                }
        !            73:                exrefresh();
        !            74: 
        !            75:                /* next block */
        !            76:                i++;
        !            77:        } while (i < MAXBLKS && lnum[i] && lnum[i - 1] < markline(tomark));
        !            78: }
        !            79: 
        !            80: 
        !            81: /* This function checks a lot of conditions to make sure they aren't screwy */
        !            82: /*ARGSUSED*/
        !            83: void cmd_validate(frommark, tomark, cmd, bang, extra)
        !            84:        MARK    frommark;
        !            85:        MARK    tomark;
        !            86:        CMD     cmd;
        !            87:        int     bang;
        !            88:        char    *extra;
        !            89: {
        !            90:        char    *scan;
        !            91:        int     i;
        !            92:        int     nlcnt;  /* used to count newlines */
        !            93:        int     len;    /* counts non-NUL characters */
        !            94: 
        !            95:        /* check lnum[0] */
        !            96:        if (lnum[0] != 0L)
        !            97:        {
        !            98:                msg("lnum[0] = %ld", lnum[0]);
        !            99:        }
        !           100: 
        !           101:        /* check each block */
        !           102:        for (i = 1; lnum[i] <= nlines; i++)
        !           103:        {
        !           104:                scan = blkget(i)->c;
        !           105:                if (scan[BLKSIZE - 1])
        !           106:                {
        !           107:                        msg("block %d has no NUL at the end", i);
        !           108:                }
        !           109:                else
        !           110:                {
        !           111:                        for (nlcnt = len = 0; *scan; scan++, len++)
        !           112:                        {
        !           113:                                if (*scan == '\n')
        !           114:                                {
        !           115:                                        nlcnt++;
        !           116:                                }
        !           117:                        }
        !           118:                        if (scan[-1] != '\n')
        !           119:                        {
        !           120:                                msg("block %d doesn't end with '\\n' (length %d)", i, len);
        !           121:                        }
        !           122:                        if (bang || nlcnt != lnum[i] - lnum[i - 1])
        !           123:                        {
        !           124:                                msg("block %d (line %ld?) has %d lines, but should have %ld",
        !           125:                                        i, lnum[i - 1] + 1L, nlcnt, lnum[i] - lnum[i - 1]);
        !           126:                        }
        !           127:                }
        !           128:                exrefresh();
        !           129:        }
        !           130: 
        !           131:        /* check lnum again */
        !           132:        if (lnum[i] != INFINITY)
        !           133:        {
        !           134:                msg("hdr.n[%d] = %d, but lnum[%d] = %ld",
        !           135:                        i, hdr.n[i], i, lnum[i]);
        !           136:        }
        !           137: 
        !           138:        msg("# = \"%s\", %% = \"%s\"", prevorig, origname);
        !           139: }
        !           140: #endif /* DEBUG */
        !           141: 
        !           142: 
        !           143: /*ARGSUSED*/
        !           144: void cmd_mark(frommark, tomark, cmd, bang, extra)
        !           145:        MARK    frommark;
        !           146:        MARK    tomark;
        !           147:        CMD     cmd;
        !           148:        int     bang;
        !           149:        char    *extra;
        !           150: {
        !           151:        /* validate the name of the mark */
        !           152:        if (!extra || *extra < 'a' || *extra > 'z' || extra[1])
        !           153:        {
        !           154:                msg("Invalid mark name");
        !           155:                return;
        !           156:        }
        !           157: 
        !           158:        mark[*extra - 'a'] = tomark;
        !           159: }
        !           160: 
        !           161: /*ARGSUSED*/
        !           162: void cmd_write(frommark, tomark, cmd, bang, extra)
        !           163:        MARK    frommark;
        !           164:        MARK    tomark;
        !           165:        CMD     cmd;
        !           166:        int     bang;
        !           167:        char    *extra;
        !           168: {
        !           169:        int             fd;
        !           170:        int             append; /* boolean: write in "append" mode? */
        !           171:        REG long        l;
        !           172:        REG char        *scan;
        !           173:        REG int         i;
        !           174: 
        !           175:        /* if all lines are to be written, use tmpsave() */
        !           176:        if (frommark == MARK_FIRST && tomark == MARK_LAST)
        !           177:        {
        !           178:                tmpsave(extra, bang);
        !           179:                return;
        !           180:        }
        !           181: 
        !           182:        /* see if we're going to do this in append mode or not */
        !           183:        append = FALSE;
        !           184:        if (extra[0] == '>' && extra[1] == '>')
        !           185:        {
        !           186:                extra += 2;
        !           187:                append = TRUE;
        !           188:        }
        !           189: 
        !           190:        /* either the file must not exist, or we must have a ! or be appending */
        !           191:        if (access(extra, 0) == 0 && !bang && !append)
        !           192:        {
        !           193:                msg("File already exists - Use :w! to overwrite");
        !           194:                return;
        !           195:        }
        !           196: 
        !           197:        /* else do it line-by-line, like cmd_print() */
        !           198:        if (append)
        !           199:        {
        !           200: #ifdef O_APPEND
        !           201:                fd = open(extra, O_WRONLY|O_APPEND);
        !           202: #else
        !           203:                fd = open(extra, O_WRONLY);
        !           204:                if (fd >= 0)
        !           205:                {
        !           206:                        lseek(fd, 0L, 2);
        !           207:                }
        !           208: #endif
        !           209:        }
        !           210:        else
        !           211:        {
        !           212:                fd = -1; /* so we know the file isn't open yet */
        !           213:        }
        !           214: 
        !           215:        if (fd < 0)
        !           216:        {
        !           217:                fd = creat(extra, FILEPERMS);
        !           218:                if (fd < 0)
        !           219:                {
        !           220:                        msg("Can't write to \"%s\"", extra);
        !           221:                        return;
        !           222:                }
        !           223:        }
        !           224:        for (l = markline(frommark); l <= markline(tomark); l++)
        !           225:        {
        !           226:                /* get the next line */
        !           227:                scan = fetchline(l);
        !           228:                i = strlen(scan);
        !           229:                scan[i++] = '\n';
        !           230: 
        !           231:                /* print the line */
        !           232:                twrite(fd, scan, i);
        !           233:        }
        !           234:        close(fd);
        !           235: }      
        !           236: 
        !           237: 
        !           238: /*ARGSUSED*/
        !           239: void cmd_shell(frommark, tomark, cmd, bang, extra)
        !           240:        MARK    frommark, tomark;
        !           241:        CMD     cmd;
        !           242:        int     bang;
        !           243:        char    *extra;
        !           244: {
        !           245:        static char     prevextra[80];
        !           246: 
        !           247:        /* special case: ":sh" means ":!sh" */
        !           248:        if (cmd == CMD_SHELL)
        !           249:        {
        !           250:                extra = o_shell;
        !           251:                frommark = tomark = 0L;
        !           252:        }
        !           253: 
        !           254:        /* if extra is "!", substute previous command */
        !           255:        if (*extra == '!')
        !           256:        {
        !           257:                if (!*prevextra)
        !           258:                {
        !           259:                        msg("No previous shell command to substitute for '!'");
        !           260:                        return;
        !           261:                }
        !           262:                extra = prevextra;
        !           263:        }
        !           264:        else if (cmd == CMD_BANG && strlen(extra) < sizeof(prevextra) - 1)
        !           265:        {
        !           266:                strcpy(prevextra, extra);
        !           267:        }
        !           268: 
        !           269:        /* if no lines were specified, just run the command */
        !           270:        suspend_curses();
        !           271:        if (frommark == 0L)
        !           272:        {
        !           273:                system(extra);
        !           274:        }
        !           275:        else /* pipe lines from the file through the command */
        !           276:        {
        !           277:                filter(frommark, tomark, extra);
        !           278:        }
        !           279: 
        !           280:        /* resume curses quietly for MODE_EX, but noisily otherwise */
        !           281:        resume_curses(mode == MODE_EX);
        !           282: }
        !           283: 
        !           284: 
        !           285: /*ARGSUSED*/
        !           286: void cmd_global(frommark, tomark, cmd, bang, extra)
        !           287:        MARK    frommark, tomark;
        !           288:        CMD     cmd;
        !           289:        int     bang;
        !           290:        char    *extra; /* rest of the command line */
        !           291: {
        !           292:        char    *cmdptr;        /* the command from the command line */
        !           293:        char    cmdln[100];     /* copy of the command from the command line */
        !           294:        char    *line;          /* a line from the file */
        !           295:        long    l;              /* used as a counter to move through lines */
        !           296:        long    lqty;           /* quantity of lines to be scanned */
        !           297:        long    nchanged;       /* number of lines changed */
        !           298:        regexp  *re;            /* the compiled search expression */
        !           299: 
        !           300:        /* can't nest global commands */
        !           301:        if (doingglobal)
        !           302:        {
        !           303:                msg("Can't nest global commands.");
        !           304:                rptlines = -1L;
        !           305:                return;
        !           306:        }
        !           307: 
        !           308:        /* ":g! ..." is the same as ":v ..." */
        !           309:        if (bang)
        !           310:        {
        !           311:                cmd = CMD_VGLOBAL;
        !           312:        }
        !           313: 
        !           314:        /* make sure we got a search pattern */
        !           315:        if (*extra != '/' && *extra != '?')
        !           316:        {
        !           317:                msg("Usage: %c /regular expression/ command", cmd == CMD_GLOBAL ? 'g' : 'v');
        !           318:                return;
        !           319:        }
        !           320: 
        !           321:        /* parse & compile the search pattern */
        !           322:        cmdptr = parseptrn(extra);
        !           323:        if (!extra[1])
        !           324:        {
        !           325:                msg("Can't use empty regular expression with '%c' command", cmd == CMD_GLOBAL ? 'g' : 'v');
        !           326:                return;
        !           327:        }
        !           328:        re = regcomp(extra + 1);
        !           329:        if (!re)
        !           330:        {
        !           331:                /* regcomp found & described an error */
        !           332:                return;
        !           333:        }
        !           334: 
        !           335:        /* for each line in the range */
        !           336:        doingglobal = TRUE;
        !           337:        ChangeText
        !           338:        {
        !           339:                /* NOTE: we have to go through the lines in a forward order,
        !           340:                 * otherwise "g/re/p" would look funny.  *BUT* for "g/re/d"
        !           341:                 * to work, simply adding 1 to the line# on each loop won't
        !           342:                 * work.  The solution: count lines relative to the end of
        !           343:                 * the file.  Think about it.
        !           344:                 */
        !           345:                for (l = nlines - markline(frommark),
        !           346:                        lqty = markline(tomark) - markline(frommark) + 1L,
        !           347:                        nchanged = 0L;
        !           348:                     lqty > 0 && nlines - l >= 0 && nchanged >= 0L;
        !           349:                     l--, lqty--)
        !           350:                {
        !           351:                        /* fetch the line */
        !           352:                        line = fetchline(nlines - l);
        !           353: 
        !           354:                        /* if it contains the search pattern... */
        !           355:                        if ((!regexec(re, line, 1)) == (cmd != CMD_GLOBAL))
        !           356:                        {
        !           357:                                /* move the cursor to that line */
        !           358:                                cursor = MARK_AT_LINE(nlines - l);
        !           359: 
        !           360:                                /* do the ex command (without mucking up
        !           361:                                 * the original copy of the command line)
        !           362:                                 */
        !           363:                                strcpy(cmdln, cmdptr);
        !           364:                                rptlines = 0L;
        !           365:                                doexcmd(cmdln);
        !           366:                                nchanged += rptlines;
        !           367:                        }
        !           368:                }
        !           369:        }
        !           370:        doingglobal = FALSE;
        !           371: 
        !           372:        /* free the regexp */
        !           373:        free(re);
        !           374: 
        !           375:        /* Reporting...*/
        !           376:        rptlines = nchanged;
        !           377: }
        !           378: 
        !           379: 
        !           380: /*ARGSUSED*/
        !           381: void cmd_file(frommark, tomark, cmd, bang, extra)
        !           382:        MARK    frommark, tomark;
        !           383:        CMD     cmd;
        !           384:        int     bang;
        !           385:        char    *extra;
        !           386: {
        !           387: #ifndef CRUNCH
        !           388:        /* if we're given a new filename, use it as this file's name */
        !           389:        if (extra && *extra)
        !           390:        {
        !           391:                strcpy(origname, extra);
        !           392:        }
        !           393: #endif
        !           394:        if (cmd == CMD_FILE)
        !           395:        {
        !           396:                msg("\"%s\" %s%s %ld lines,  line %ld [%ld%%]",
        !           397:                        *origname ? origname : "[NO FILE]",
        !           398:                        tstflag(file, MODIFIED) ? "[MODIFIED]" : "",
        !           399:                        tstflag(file, READONLY) ? "[READONLY]" : "",
        !           400:                        nlines,
        !           401:                        markline(frommark),
        !           402:                        markline(frommark) * 100 / nlines);
        !           403:        }
        !           404:        else if (markline(frommark) == markline(tomark))
        !           405:        {
        !           406:                msg("%ld", markline(frommark));
        !           407:        }
        !           408:        else
        !           409:        {
        !           410:                msg("range \"%ld,%ld\" contains %ld lines",
        !           411:                        markline(frommark),
        !           412:                        markline(tomark),
        !           413:                        markline(tomark) - markline(frommark) + 1L);
        !           414:        }
        !           415: }
        !           416: 
        !           417: 
        !           418: /*ARGSUSED*/
        !           419: void cmd_edit(frommark, tomark, cmd, bang, extra)
        !           420:        MARK    frommark, tomark;
        !           421:        CMD     cmd;
        !           422:        int     bang;
        !           423:        char    *extra;
        !           424: {
        !           425:        long    line = 1L;      /* might be set to prevline */
        !           426: 
        !           427:        /* Editing previous file?  Then start at previous line */
        !           428:        if (!strcmp(extra, prevorig))
        !           429:        {
        !           430:                line = prevline;
        !           431:        }
        !           432: 
        !           433: #ifndef CRUNCH
        !           434:        /* if we were given an explicit starting line, then start there */
        !           435:        if (*extra == '+')
        !           436:        {
        !           437:                for (extra++, line = 0L; *extra >= '0' && *extra <= '9'; extra++)
        !           438:                {
        !           439:                        line *= 10L;
        !           440:                        line += (*extra - '0');
        !           441:                }
        !           442:                while (isascii(*extra) && isspace(*extra))
        !           443:                {
        !           444:                        extra++;
        !           445:                }
        !           446:        }
        !           447: #endif /* not CRUNCH */
        !           448: 
        !           449:        /* switch files */
        !           450:        if (tmpabort(bang))
        !           451:        {
        !           452:                tmpstart(extra);
        !           453:                if (line <= nlines && line >= 1L)
        !           454:                {
        !           455:                        cursor = MARK_AT_LINE(line);
        !           456:                }
        !           457:        }
        !           458:        else
        !           459:        {
        !           460:                msg("Use edit! to abort changes, or w to save changes");
        !           461: 
        !           462:                /* so we can say ":e!#" next time... */
        !           463:                strcpy(prevorig, extra);
        !           464:                prevline = 1L;
        !           465:        }
        !           466: }
        !           467: 
        !           468: /* This code is also used for rewind -- GB */
        !           469: 
        !           470: /*ARGSUSED*/
        !           471: void cmd_next(frommark, tomark, cmd, bang, extra)
        !           472:        MARK    frommark, tomark;
        !           473:        CMD     cmd;
        !           474:        int     bang;
        !           475:        char    *extra;
        !           476: {
        !           477:        int     i, j;
        !           478:        char    *scan;
        !           479:        char    *build;
        !           480: 
        !           481:        /* if extra stuff given, use ":args" to define a new args list */
        !           482:        if (cmd == CMD_NEXT && extra && *extra)
        !           483:        {
        !           484:                cmd_args(frommark, tomark, cmd, bang, extra);
        !           485:        }
        !           486: 
        !           487:        /* move to the next arg */
        !           488:        if (cmd == CMD_NEXT)
        !           489:        {
        !           490:                i = argno + 1;
        !           491:        }
        !           492:        else if (cmd == CMD_PREVIOUS)
        !           493:        {
        !           494:                i = argno - 1;
        !           495:        }
        !           496:        else /* cmd == CMD_REWIND */
        !           497:        {
        !           498:                i = 0;
        !           499:        }       
        !           500:        if (i < 0 || i >= nargs)
        !           501:        {
        !           502:                msg("No %sfiles to edit", cmd == CMD_REWIND ? "" : "more ");
        !           503:                return;
        !           504:        }
        !           505: 
        !           506:        /* find & isolate the name of the file to edit */
        !           507:        for (j = i, scan = args; j > 0; j--)
        !           508:        {
        !           509:                while(!isascii(*scan) || !isspace(*scan))
        !           510:                {
        !           511:                        scan++;
        !           512:                }
        !           513:                while (isascii(*scan) && isspace(*scan))
        !           514:                {
        !           515:                        scan++;
        !           516:                }
        !           517:        }
        !           518:        for (build = tmpblk.c; *scan && (!isascii(*scan) || !isspace(*scan)); )
        !           519:        {
        !           520:                *build++ = *scan++;
        !           521:        }
        !           522:        *build = '\0';
        !           523: 
        !           524:        /* switch to the next file */
        !           525:        if (tmpabort(bang))
        !           526:        {
        !           527:                tmpstart(tmpblk.c);
        !           528:                argno = i;
        !           529:        }
        !           530:        else
        !           531:        {
        !           532:                msg("Use :%s! to abort changes, or w to save changes",
        !           533:                        cmd == CMD_NEXT ? "next" :
        !           534:                        cmd == CMD_PREVIOUS ? "previous" :
        !           535:                                        "rewind");
        !           536:        }
        !           537: }
        !           538: 
        !           539: /* also called from :wq -- always writes back in this case */
        !           540: 
        !           541: /*ARGSUSED*/
        !           542: void cmd_xit(frommark, tomark, cmd, bang, extra)
        !           543:        MARK    frommark, tomark;
        !           544:        CMD     cmd;
        !           545:        int     bang;
        !           546:        char    *extra;
        !           547: {
        !           548:        static long     whenwarned;     /* when the user was last warned of extra files */
        !           549:        int             oldflag;
        !           550: 
        !           551:        /* if there are more files to edit, then warn user */
        !           552:        if (argno + 1 < nargs && whenwarned != changes && (!bang || cmd != CMD_QUIT))
        !           553:        {
        !           554:                msg("More files to edit -- Use \":n\" to go to next file");
        !           555:                whenwarned = changes;
        !           556:                return;
        !           557:        }
        !           558: 
        !           559:        if (cmd == CMD_QUIT)
        !           560:        {
        !           561:                if (tmpabort(bang))
        !           562:                {
        !           563:                        mode = MODE_QUIT;
        !           564:                }
        !           565:                else
        !           566:                {
        !           567:                        msg("Use q! to abort changes, or wq to save changes");
        !           568:                }
        !           569:        }
        !           570:        else
        !           571:        {
        !           572:                /* else try to save this file */
        !           573:                oldflag = tstflag(file, MODIFIED);
        !           574:                if (cmd == CMD_WQUIT)
        !           575:                        setflag(file, MODIFIED);
        !           576:                if (tmpend(bang))
        !           577:                {
        !           578:                        mode = MODE_QUIT;
        !           579:                }
        !           580:                else
        !           581:                {
        !           582:                        msg("Could not save file -- use quit! to abort changes, or w filename");
        !           583:                }
        !           584:                if (!oldflag)
        !           585:                        clrflag(file, MODIFIED);
        !           586:        }
        !           587: }
        !           588: 
        !           589: 
        !           590: /*ARGSUSED*/
        !           591: void cmd_args(frommark, tomark, cmd, bang, extra)
        !           592:        MARK    frommark, tomark;
        !           593:        CMD     cmd;
        !           594:        int     bang;
        !           595:        char    *extra;
        !           596: {
        !           597:        char    *scan;
        !           598:        char    *eow;
        !           599:        int     col;
        !           600:        int     arg;
        !           601:        int     addcols;
        !           602:        int     scrolled = 0;
        !           603: 
        !           604:        /* if no extra names given, or just current name, then report the args
        !           605:         * we have now.
        !           606:         */
        !           607:        if (!extra || !*extra)
        !           608:        {
        !           609:                for (scan = args, col=arg=0; *scan; )
        !           610:                {
        !           611:                        while (*scan && isascii(*scan) && isspace(*scan))
        !           612:                                scan++;
        !           613:                        eow = scan;
        !           614:                        while (*eow && (!isascii(*++eow) || !isspace(*eow)))
        !           615:                                ;
        !           616:                        if (arg == argno)
        !           617:                                addcols = 2;
        !           618:                        else
        !           619:                                addcols = 0;    
        !           620:                        if (col+addcols+(int)(eow-scan)+1>=COLS)
        !           621:                        {
        !           622:                                addch('\n');
        !           623:                                scrolled=1;
        !           624:                                col=0;
        !           625:                        }
        !           626:                        else if (arg)
        !           627:                        {       qaddch(' ');
        !           628:                                col++;
        !           629:                        }
        !           630:                        if (arg == argno)
        !           631:                                qaddch('[');
        !           632:                        while (scan < eow)
        !           633:                        {       qaddch(*scan++);
        !           634:                                col++;
        !           635:                        }
        !           636:                        if (arg == argno)
        !           637:                                qaddch(']');    
        !           638:                        arg++;  
        !           639:                        col+=addcols;
        !           640:                }
        !           641:                /* write a trailing newline */
        !           642:                if ((mode == MODE_EX || mode == MODE_COLON || scrolled) && col)
        !           643:                        addch('\n');
        !           644:                exrefresh();    
        !           645:        }
        !           646:        else /* new args list given */
        !           647:        {
        !           648:                strcpy(args, extra);
        !           649:                argno = -1; /* before the first, so :next will go to first */
        !           650: 
        !           651:                /* count the names */
        !           652:                for (nargs = 0, scan = args; *scan; nargs++)
        !           653:                {
        !           654:                        while (*scan && (!isascii(*scan) || !isspace(*scan)))
        !           655:                        {
        !           656:                                scan++;
        !           657:                        }
        !           658:                        while (isascii(*scan) && isspace(*scan))
        !           659:                        {
        !           660:                                scan++;
        !           661:                        }
        !           662:                }
        !           663:                msg("%d files to edit", nargs);
        !           664:        }
        !           665: }
        !           666: 
        !           667: 
        !           668: /*ARGSUSED*/
        !           669: void cmd_cd(frommark, tomark, cmd, bang, extra)
        !           670:        MARK    frommark, tomark;
        !           671:        CMD     cmd;
        !           672:        int     bang;
        !           673:        char    *extra;
        !           674: {
        !           675:        char    *getenv();
        !           676: 
        !           677:        /* default directory name is $HOME */
        !           678:        if (!*extra)
        !           679:        {
        !           680:                extra = getenv("HOME");
        !           681:                if (!extra)
        !           682:                {
        !           683:                        msg("environment variable $HOME not set");
        !           684:                        return;
        !           685:                }
        !           686:        }
        !           687: 
        !           688:        /* go to the directory */
        !           689:        if (chdir(extra) < 0)
        !           690:        {
        !           691:                perror(extra);
        !           692:        }
        !           693: }
        !           694: 
        !           695: 
        !           696: /*ARGSUSED*/
        !           697: void cmd_map(frommark, tomark, cmd, bang, extra)
        !           698:        MARK    frommark, tomark;
        !           699:        CMD     cmd;
        !           700:        int     bang;
        !           701:        char    *extra;
        !           702: {
        !           703:        char    *mapto;
        !           704: 
        !           705:        /* "map" with no extra will dump the map table contents */
        !           706:        if (!*extra)
        !           707:        {
        !           708:                dumpkey(bang ? WHEN_VIINP|WHEN_VIREP : WHEN_VICMD);
        !           709:        }
        !           710:        else
        !           711:        {
        !           712:                /* "extra" is key to map, followed my what it maps to */
        !           713:                for (mapto = extra; *mapto && *mapto != ' ' && *mapto!= '\t'; mapto++)
        !           714:                {
        !           715:                }
        !           716:                while (*mapto == ' ' || *mapto == '\t')
        !           717:                {
        !           718:                        *mapto++ = '\0';
        !           719:                }
        !           720: 
        !           721:                mapkey(extra, mapto, bang ? WHEN_VIINP|WHEN_VIREP : WHEN_VICMD, (char *)0);
        !           722:        }
        !           723: }
        !           724: 
        !           725: 
        !           726: /*ARGSUSED*/
        !           727: void cmd_set(frommark, tomark, cmd, bang, extra)
        !           728:        MARK    frommark, tomark;
        !           729:        CMD     cmd;
        !           730:        int     bang;
        !           731:        char    *extra;
        !           732: {
        !           733:        if (!*extra)
        !           734:        {
        !           735:                dumpopts(FALSE);/* "FALSE" means "don't dump all" - only set */
        !           736:        }
        !           737:        else if (!strcmp(extra, "all"))
        !           738:        {
        !           739:                dumpopts(TRUE); /* "TRUE" means "dump all" - even unset vars */
        !           740:        }
        !           741:        else
        !           742:        {
        !           743:                setopts(extra);
        !           744: 
        !           745:                /* That option may have affected the appearence of text */
        !           746:                changes++;
        !           747:        }
        !           748: }
        !           749: 
        !           750: /*ARGSUSED*/
        !           751: void cmd_tag(frommark, tomark, cmd, bang, extra)
        !           752:        MARK    frommark, tomark;
        !           753:        CMD     cmd;
        !           754:        int     bang;
        !           755:        char    *extra;
        !           756: {
        !           757:        char    *scan;  /* used to scan through the tmpblk.c */
        !           758:        char    *cmp;   /* char of tag name we're comparing, or NULL */
        !           759:        char    *end;   /* marks the end of chars in tmpblk.c */
        !           760:        int     fd;     /* file descriptor used to read the file */
        !           761: #ifndef NO_MAGIC
        !           762:        char    wasmagic; /* preserves the original state of o_magic */
        !           763: #endif
        !           764:        static char prevtag[30];
        !           765: 
        !           766:        /* if no tag is given, use the previous tag */
        !           767:        if (!extra || !*extra)
        !           768:        {
        !           769:                if (!*prevtag)
        !           770:                {
        !           771:                        msg("No previous tag");
        !           772:                        return;
        !           773:                }
        !           774:                extra = prevtag;
        !           775:        }
        !           776:        else
        !           777:        {
        !           778:                strncpy(prevtag, extra, sizeof prevtag);
        !           779:        }
        !           780: 
        !           781:        /* open the tags file */
        !           782:        fd = open(TAGS, O_RDONLY);
        !           783:        if (fd < 0)
        !           784:        {
        !           785:                msg("No tags file");
        !           786:                return;
        !           787:        }
        !           788: 
        !           789:        /* Hmmm... this would have been a lot easier with <stdio.h> */
        !           790: 
        !           791:        /* find the line with our tag in it */
        !           792:        for(scan = end = tmpblk.c, cmp = extra; ; scan++)
        !           793:        {
        !           794:                /* read a block, if necessary */
        !           795:                if (scan >= end)
        !           796:                {
        !           797:                        end = tmpblk.c + tread(fd, tmpblk.c, BLKSIZE);
        !           798:                        scan = tmpblk.c;
        !           799:                        if (scan >= end)
        !           800:                        {
        !           801:                                msg("tag \"%s\" not found", extra);
        !           802:                                close(fd);
        !           803:                                return;
        !           804:                        }
        !           805:                }
        !           806: 
        !           807:                /* if we're comparing, compare... */
        !           808:                if (cmp)
        !           809:                {
        !           810:                        /* matched??? wow! */
        !           811:                        if (!*cmp && *scan == '\t')
        !           812:                        {
        !           813:                                break;
        !           814:                        }
        !           815:                        if (*cmp++ != *scan)
        !           816:                        {
        !           817:                                /* failed! skip to newline */
        !           818:                                cmp = (char *)0;
        !           819:                        }
        !           820:                }
        !           821: 
        !           822:                /* if we're skipping to newline, do it fast! */
        !           823:                if (!cmp)
        !           824:                {
        !           825:                        while (scan < end && *scan != '\n')
        !           826:                        {
        !           827:                                scan++;
        !           828:                        }
        !           829:                        if (scan < end)
        !           830:                        {
        !           831:                                cmp = extra;
        !           832:                        }
        !           833:                }
        !           834:        }
        !           835: 
        !           836:        /* found it! get the rest of the line into memory */
        !           837:        for (cmp = tmpblk.c, scan++; scan < end && *scan != '\n'; )
        !           838:        {
        !           839:                *cmp++ = *scan++;
        !           840:        }
        !           841:        if (scan == end)
        !           842:        {
        !           843:                tread(fd, cmp, BLKSIZE - (cmp - tmpblk.c));
        !           844:        }
        !           845: 
        !           846:        /* we can close the tags file now */
        !           847:        close(fd);
        !           848: 
        !           849:        /* extract the filename from the line, and edit the file */
        !           850:        for (cmp = tmpblk.c; *cmp != '\t'; cmp++)
        !           851:        {
        !           852:        }
        !           853:        *cmp++ = '\0';
        !           854:        if (strcmp(origname, tmpblk.c) != 0)
        !           855:        {
        !           856:                if (!tmpabort(bang))
        !           857:                {
        !           858:                        msg("Use :tag! to abort changes, or :w to save changes");
        !           859:                        return;
        !           860:                }
        !           861:                tmpstart(tmpblk.c);
        !           862:        }
        !           863: 
        !           864:        /* move to the desired line (or to line 1 if that fails) */
        !           865: #ifndef NO_MAGIC
        !           866:        wasmagic = *o_magic;
        !           867:        *o_magic = FALSE;
        !           868: #endif
        !           869:        cursor = MARK_FIRST;
        !           870:        linespec(cmp, &cursor);
        !           871:        if (cursor == MARK_UNSET)
        !           872:        {
        !           873:                cursor = MARK_FIRST;
        !           874:        }
        !           875: #ifndef NO_MAGIC
        !           876:        *o_magic = wasmagic;
        !           877: #endif
        !           878: }
        !           879: 
        !           880: 
        !           881: 
        !           882: /*ARGSUSED*/
        !           883: void cmd_visual(frommark, tomark, cmd, bang, extra)
        !           884:        MARK    frommark, tomark;
        !           885:        CMD     cmd;
        !           886:        int     bang;
        !           887:        char    *extra;
        !           888: {
        !           889:        mode = MODE_VI;
        !           890:        msg("");
        !           891: }
        !           892: 
        !           893: 
        !           894: 
        !           895: 
        !           896: 
        !           897: /* describe this version of the program */
        !           898: /*ARGSUSED*/
        !           899: void cmd_version(frommark, tomark, cmd, bang, extra)
        !           900:        MARK    frommark;
        !           901:        MARK    tomark;
        !           902:        CMD     cmd;
        !           903:        int     bang;
        !           904:        char    *extra;
        !           905: {
        !           906: #ifndef DATE
        !           907:        msg("%s", VERSION);
        !           908: #else
        !           909:        msg("%s  (%s)", VERSION, DATE);
        !           910: #endif
        !           911: #ifdef COMPILED_BY
        !           912:        msg("Compiled by %s", COMPILED_BY);
        !           913: #endif
        !           914: #ifdef CREDIT
        !           915:        msg("%s", CREDIT);
        !           916: #endif
        !           917: #ifdef COPYING
        !           918:        msg("%s", COPYING);
        !           919: #endif
        !           920: }
        !           921: 
        !           922: 
        !           923: #ifndef NO_MKEXRC
        !           924: /* make a .exrc file which describes the current configuration */
        !           925: /*ARGSUSED*/
        !           926: void cmd_mkexrc(frommark, tomark, cmd, bang, extra)
        !           927:        MARK    frommark;
        !           928:        MARK    tomark;
        !           929:        CMD     cmd;
        !           930:        int     bang;
        !           931:        char    *extra;
        !           932: {
        !           933:        int     fd;
        !           934: 
        !           935:        /* the default name for the .exrc file EXRC */
        !           936:        if (!*extra)
        !           937:        {
        !           938:                extra = EXRC;
        !           939:        }
        !           940: 
        !           941:        /* create the .exrc file */
        !           942:        fd = creat(extra, FILEPERMS);
        !           943:        if (fd < 0)
        !           944:        {
        !           945:                msg("Couldn't create a new \"%s\" file", extra);
        !           946:                return;
        !           947:        }
        !           948: 
        !           949:        /* save stuff */
        !           950:        savekeys(fd);
        !           951:        saveopts(fd);
        !           952: #ifndef NO_DIGRAPH
        !           953:        savedigs(fd);
        !           954: #endif
        !           955: #ifndef        NO_ABBR
        !           956:        saveabbr(fd);
        !           957: #endif
        !           958: 
        !           959:        /* close the file */
        !           960:        close(fd);
        !           961:        msg("Created a new \"%s\" file", extra);
        !           962: }
        !           963: #endif
        !           964: 
        !           965: #ifndef NO_DIGRAPH
        !           966: /*ARGSUSED*/
        !           967: void cmd_digraph(frommark, tomark, cmd, bang, extra)
        !           968:        MARK    frommark;
        !           969:        MARK    tomark;
        !           970:        CMD     cmd;
        !           971:        int     bang;
        !           972:        char    *extra;
        !           973: {
        !           974:        do_digraph(bang, extra);
        !           975: }
        !           976: #endif
        !           977: 
        !           978: 
        !           979: #ifndef NO_ERRLIST 
        !           980: static char    errfile[256];   /* the name of a file containing an error */
        !           981: static long    errline;        /* the line number for an error */
        !           982: 
        !           983: /* This static function tries to parse an error message.
        !           984:  *
        !           985:  * For most compilers, the first word is taken to be the name of the erroneous
        !           986:  * file, and the first number after that is taken to be the line number where
        !           987:  * the error was detected.  The description of the error follows, possibly
        !           988:  * preceded by an "error ... :" or "warning ... :" label which is skipped.
        !           989:  *
        !           990:  * For Coherent, error messages look like "line#: filename: message".
        !           991:  *
        !           992:  * For non-error lines, or unparsable error lines, this function returns NULL.
        !           993:  * Normally, though, it alters errfile and errline, and returns a pointer to
        !           994:  * the description.
        !           995:  */
        !           996: static char *parse_errmsg(text)
        !           997:        REG char        *text;
        !           998: {
        !           999:        REG char        *cpy;
        !          1000:        long            atol();
        !          1001: # if COHERENT
        !          1002:        /* Get the line number.  If no line number, then ignore this line. */
        !          1003:        errline = atol(text);
        !          1004:        if (errline == 0L)
        !          1005:                return (char *)0;
        !          1006: 
        !          1007:        /* Skip to the start of the filename */
        !          1008:        while (*text && *text++ != ':')
        !          1009:        {
        !          1010:        }
        !          1011:        if (!*text++)
        !          1012:                return (char *)0;
        !          1013: 
        !          1014:        /* copy the filename to errfile */
        !          1015:        for (cpy = errfile; *text && (*cpy++ = *text++) != ':'; )
        !          1016:        {
        !          1017:        }
        !          1018:        if (!*text++)
        !          1019:                return (char *)0;
        !          1020:        cpy[-1] = '\0';
        !          1021: 
        !          1022:        return text;
        !          1023: # else /* not COHERENT */
        !          1024:        char            *errmsg;
        !          1025: 
        !          1026:        /* the error message is the whole line, by default */
        !          1027:        errmsg = text;
        !          1028: 
        !          1029:        /* skip leading garbage */
        !          1030:        while (*text && !(isascii(*text) && isalnum(*text)))
        !          1031:        {
        !          1032:                text++;
        !          1033:        }
        !          1034: 
        !          1035:        /* copy over the filename */
        !          1036:        cpy = errfile;
        !          1037:        while(isascii(*text) && isalnum(*text) || *text == '.')
        !          1038:        {
        !          1039:                *cpy++ = *text++;
        !          1040:        }
        !          1041:        *cpy = '\0';
        !          1042: 
        !          1043:        /* ignore the name "Error" and filenames that contain a '/' */
        !          1044:        if (*text == '/' || !strcmp(errfile + 1, "rror") || access(errfile, 0) < 0)
        !          1045:        {
        !          1046:                return (char *)0;
        !          1047:        }
        !          1048: 
        !          1049:        /* skip garbage between filename and line number */
        !          1050:        while (*text && !(isascii(*text) && isdigit(*text)))
        !          1051:        {
        !          1052:                text++;
        !          1053:        }
        !          1054: 
        !          1055:        /* if the number is part of a larger word, then ignore this line */
        !          1056:        if (*text && isascii(text[-1]) && isalpha(text[-1]))
        !          1057:        {
        !          1058:                return (char *)0;
        !          1059:        }
        !          1060: 
        !          1061:        /* get the error line */
        !          1062:        errline = 0L;
        !          1063:        while (isascii(*text) && isdigit(*text))
        !          1064:        {
        !          1065:                errline *= 10;
        !          1066:                errline += (*text - '0');
        !          1067:                text++;
        !          1068:        }
        !          1069: 
        !          1070:        /* any line which lacks a filename or line number should be ignored */
        !          1071:        if (!errfile[0] || !errline)
        !          1072:        {
        !          1073:                return (char *)0;
        !          1074:        }
        !          1075: 
        !          1076:        /* locate the beginning of the error description */
        !          1077:        while (*text && isascii(*text) && !isspace(*text))
        !          1078:        {
        !          1079:                text++;
        !          1080:        }
        !          1081:        while (*text)
        !          1082:        {
        !          1083: #  ifndef CRUNCH
        !          1084:                /* skip "error #:" and "warning #:" clauses */
        !          1085:                if (!strncmp(text + 1, "rror ", 5)
        !          1086:                 || !strncmp(text + 1, "arning ", 7)
        !          1087:                 || !strncmp(text + 1, "atal error", 10))
        !          1088:                {
        !          1089:                        do
        !          1090:                        {
        !          1091:                                text++;
        !          1092:                        } while (*text && *text != ':');
        !          1093:                        continue;
        !          1094:                }
        !          1095: #  endif
        !          1096: 
        !          1097:                /* anything other than whitespace or a colon is important */
        !          1098:                if (!isascii(*text) || (!isspace(*text) && *text != ':'))
        !          1099:                {
        !          1100:                        errmsg = text;
        !          1101:                        break;
        !          1102:                }
        !          1103: 
        !          1104:                /* else keep looking... */
        !          1105:                text++;
        !          1106:        }
        !          1107: 
        !          1108:        return errmsg;
        !          1109: # endif /* not COHERENT */
        !          1110: }
        !          1111: 
        !          1112: /*ARGSUSED*/
        !          1113: void cmd_errlist(frommark, tomark, cmd, bang, extra)
        !          1114:        MARK    frommark, tomark;
        !          1115:        CMD     cmd;
        !          1116:        int     bang;
        !          1117:        char    *extra;
        !          1118: {
        !          1119:        static long     endline;/* original number of lines in this file */
        !          1120:        static long     offset; /* offset of the next line in the errlist file */
        !          1121:        static int      fd = -2;/* fd of the errlist file */
        !          1122:        int             i;
        !          1123:        char            *errmsg;
        !          1124: 
        !          1125:        /* if a new errlist file is named, open it */
        !          1126:        if (extra && extra[0])
        !          1127:        {
        !          1128:                /* close the old one */
        !          1129:                if (fd >= 0)
        !          1130:                {
        !          1131:                        close(fd);
        !          1132:                }
        !          1133: 
        !          1134:                fd = open(extra, O_RDONLY);
        !          1135:                offset = 0L;
        !          1136:        }
        !          1137:        else if (fd < 0)
        !          1138:        {
        !          1139:                fd = open(ERRLIST, O_RDONLY);
        !          1140:                offset = 0L;
        !          1141:        }
        !          1142: 
        !          1143:        /* do we have an errlist file now? */
        !          1144:        if (fd < 0)
        !          1145:        {
        !          1146:                msg("There is no errlist file");
        !          1147:                beep();
        !          1148:                return;
        !          1149:        }
        !          1150: 
        !          1151:        /* find the next error message in the file */
        !          1152:        do
        !          1153:        {
        !          1154:                /* read the next line from the errlist */
        !          1155:                lseek(fd, offset, 0);
        !          1156:                if (read(fd, tmpblk.c, (unsigned)BLKSIZE) <= 0)
        !          1157:                {
        !          1158:                        msg("No more errors");
        !          1159:                        beep();
        !          1160:                        close(fd);
        !          1161:                        return;
        !          1162:                }
        !          1163:                for (i = 0; tmpblk.c[i] != '\n'; i++)
        !          1164:                {
        !          1165:                }
        !          1166:                tmpblk.c[i++] = 0;
        !          1167: 
        !          1168:                /* look for an error message in the line */
        !          1169:                errmsg = parse_errmsg(tmpblk.c);
        !          1170:                if (!errmsg)
        !          1171:                {
        !          1172:                        offset += i;
        !          1173:                }
        !          1174: 
        !          1175:        } while (!errmsg);
        !          1176: 
        !          1177:        /* switch to the file containing the error, if this isn't it */
        !          1178:        if (strcmp(origname, errfile))
        !          1179:        {
        !          1180:                if (!tmpabort(bang))
        !          1181:                {
        !          1182:                        msg("Use :er! to abort changes, or :w to save changes");
        !          1183:                        beep();
        !          1184:                        return;
        !          1185:                }
        !          1186:                tmpstart(errfile);
        !          1187:                endline = nlines;
        !          1188:        }
        !          1189:        else if (endline == 0L)
        !          1190:        {
        !          1191:                endline = nlines;
        !          1192:        }
        !          1193: 
        !          1194:        /* go to the line where the error was detected */
        !          1195:        cursor = MARK_AT_LINE(errline + (nlines - endline));
        !          1196:        if (cursor > MARK_LAST)
        !          1197:        {
        !          1198:                cursor = MARK_LAST;
        !          1199:        }
        !          1200:        if (mode == MODE_VI)
        !          1201:        {
        !          1202:                redraw(cursor, FALSE);
        !          1203:        }
        !          1204: 
        !          1205:        /* display the error message */
        !          1206:        if (nlines > endline)
        !          1207:        {
        !          1208:                msg("line %ld(+%ld): %.60s", errline, nlines - endline, errmsg);
        !          1209:        }
        !          1210:        else if (nlines < endline)
        !          1211:        {
        !          1212:                msg("line %ld(-%ld): %.60s", errline, endline - nlines, errmsg);
        !          1213:        }
        !          1214:        else
        !          1215:        {
        !          1216:                msg("line %ld: %.65s", errline, errmsg);
        !          1217:        }
        !          1218: 
        !          1219:        /* remember where the NEXT error line will start */
        !          1220:        offset += i;
        !          1221: }
        !          1222: 
        !          1223: 
        !          1224: /*ARGSUSED*/
        !          1225: void cmd_make(frommark, tomark, cmd, bang, extra)
        !          1226:        MARK    frommark, tomark;
        !          1227:        CMD     cmd;
        !          1228:        int     bang;
        !          1229:        char    *extra;
        !          1230: {
        !          1231:        BLK     buf;
        !          1232: 
        !          1233:        /* if the file hasn't been saved, then complain unless ! */
        !          1234:        if (tstflag(file, MODIFIED) && !bang)
        !          1235:        {
        !          1236:                msg("\"%s\" not saved yet", origname);
        !          1237:                return;
        !          1238:        }
        !          1239: 
        !          1240:        /* build the command */
        !          1241:        sprintf(buf.c, "%s %s %s%s", (cmd == CMD_CC ? o_cc : o_make), extra, REDIRECT, ERRLIST);
        !          1242:        qaddstr(buf.c);
        !          1243:        addch('\n');
        !          1244: 
        !          1245:        /* run the command, with curses temporarily disabled */
        !          1246:        suspend_curses();
        !          1247:        system(buf.c);
        !          1248:        resume_curses(mode == MODE_EX);
        !          1249:        if (mode == MODE_COLON)
        !          1250:                mode = MODE_VI;
        !          1251: 
        !          1252:        /* run the "errlist" command */
        !          1253:        cmd_errlist(MARK_UNSET, MARK_UNSET, cmd, bang, ERRLIST);
        !          1254: }
        !          1255: #endif
        !          1256: 
        !          1257: 
        !          1258: #ifndef NO_ABBR
        !          1259: /*ARGSUSED*/
        !          1260: void cmd_abbr(frommark, tomark, cmd, bang, extra)
        !          1261:        MARK    frommark, tomark;
        !          1262:        CMD     cmd;
        !          1263:        int     bang;
        !          1264:        char    *extra;
        !          1265: {
        !          1266:        do_abbr(extra);
        !          1267: }
        !          1268: #endif

unix.superglobalmegacorp.com

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