Annotation of coherent/d/usr/bin/elvis/cmd1.c, revision 1.1.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.