[BACK]Return to quickfix.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / vim

Annotation of src/usr.bin/vim/quickfix.c, Revision 1.1

1.1     ! downsj      1: /* $OpenBSD$   */
        !             2: /* vi:set ts=4 sw=4:
        !             3:  *
        !             4:  * VIM - Vi IMproved       by Bram Moolenaar
        !             5:  *
        !             6:  * Do ":help uganda"  in Vim to read copying and usage conditions.
        !             7:  * Do ":help credits" in Vim to see a list of people who contributed.
        !             8:  */
        !             9:
        !            10: /*
        !            11:  * quickfix.c: functions for quickfix mode, using a file with error messages
        !            12:  */
        !            13:
        !            14: #include "vim.h"
        !            15: #include "globals.h"
        !            16: #include "proto.h"
        !            17: #include "option.h"
        !            18:
        !            19: static void qf_free __ARGS((void));
        !            20: static char_u *qf_types __ARGS((int, int));
        !            21:
        !            22: /*
        !            23:  * for each error the next struct is allocated and linked in a list
        !            24:  */
        !            25: struct qf_line
        !            26: {
        !            27:    struct qf_line  *qf_next;   /* pointer to next error in the list */
        !            28:    struct qf_line  *qf_prev;   /* pointer to previous error in the list */
        !            29:    linenr_t         qf_lnum;   /* line number where the error occurred */
        !            30:    int              qf_fnum;   /* file number for the line */
        !            31:    int              qf_col;    /* column where the error occurred */
        !            32:    int              qf_nr;     /* error number */
        !            33:    char_u          *qf_text;   /* description of the error */
        !            34:    char_u           qf_cleared;/* set to TRUE if line has been deleted */
        !            35:    char_u           qf_type;   /* type of the error (mostly 'E') */
        !            36:    char_u           qf_valid;  /* valid error message detected */
        !            37: };
        !            38:
        !            39: static struct qf_line *qf_start;       /* pointer to the first error */
        !            40: static struct qf_line *qf_ptr;         /* pointer to the current error */
        !            41:
        !            42: static int qf_count = 0;       /* number of errors (0 means no error list) */
        !            43: static int qf_index;           /* current index in the error list */
        !            44: static int qf_nonevalid;       /* set to TRUE if not a single valid entry found */
        !            45:
        !            46: #define MAX_ADDR   7           /* maximum number of % recognized, also adjust
        !            47:                                    sscanf() below */
        !            48:
        !            49: /*
        !            50:  * Structure used to hold the info of one part of 'errorformat'
        !            51:  */
        !            52: struct eformat
        !            53: {
        !            54:    char_u          *fmtstr;        /* pre-formatted part of 'errorformat' */
        !            55: #ifdef UTS2
        !            56:    char_u          *(adr[MAX_ADDR]);   /* addresses used */
        !            57: #else
        !            58:    void            *(adr[MAX_ADDR]);
        !            59: #endif
        !            60:    int             adr_cnt;        /* number of addresses used */
        !            61:    struct eformat  *next;          /* pointer to next (NULL if last) */
        !            62: };
        !            63:
        !            64: /*
        !            65:  * Read the errorfile into memory, line by line, building the error list.
        !            66:  * Return FAIL for error, OK for success.
        !            67:  */
        !            68:    int
        !            69: qf_init()
        !            70: {
        !            71:    char_u          *namebuf;
        !            72:    char_u          *errmsg;
        !            73:    int             col;
        !            74:    int             type;
        !            75:    int             valid;
        !            76:    long            lnum;
        !            77:    int             enr;
        !            78:    FILE            *fd;
        !            79:    struct qf_line  *qfp = NULL;
        !            80:    struct qf_line  *qfprev = NULL;     /* init to make SASC shut up */
        !            81:    char_u          *efmp;
        !            82:    struct eformat  *fmt_first = NULL;
        !            83:    struct eformat  *fmt_last = NULL;
        !            84:    struct eformat  *fmt_ptr;
        !            85:    char_u          *efm;
        !            86:    int             maxlen;
        !            87:    int             len;
        !            88:    int             i, j;
        !            89:    int             retval = FAIL;
        !            90:
        !            91:    if (*p_ef == NUL)
        !            92:    {
        !            93:        emsg(e_errorf);
        !            94:        return FAIL;
        !            95:    }
        !            96:
        !            97:    namebuf = alloc(CMDBUFFSIZE + 1);
        !            98:    errmsg = alloc(CMDBUFFSIZE + 1);
        !            99:    if (namebuf == NULL || errmsg == NULL)
        !           100:        goto qf_init_end;
        !           101:
        !           102:    if ((fd = fopen((char *)p_ef, "r")) == NULL)
        !           103:    {
        !           104:        emsg2(e_openerrf, p_ef);
        !           105:        goto qf_init_end;
        !           106:    }
        !           107:    qf_free();
        !           108:    qf_index = 0;
        !           109:
        !           110: /*
        !           111:  * Each part of the format string is copied and modified from p_efm to fmtstr.
        !           112:  * Only a few % characters are allowed.
        !           113:  */
        !           114:    efm = p_efm;
        !           115:    while (efm[0])
        !           116:    {
        !           117:        /*
        !           118:         * Allocate a new eformat structure and put it at the end of the list
        !           119:         */
        !           120:        fmt_ptr = (struct eformat *)alloc((unsigned)sizeof(struct eformat));
        !           121:        if (fmt_ptr == NULL)
        !           122:            goto error2;
        !           123:        if (fmt_first == NULL)      /* first one */
        !           124:            fmt_first = fmt_ptr;
        !           125:        else
        !           126:            fmt_last->next = fmt_ptr;
        !           127:        fmt_last = fmt_ptr;
        !           128:        fmt_ptr->next = NULL;
        !           129:        fmt_ptr->adr_cnt = 0;
        !           130:
        !           131:        /*
        !           132:         * Isolate one part in the 'errorformat' option
        !           133:         */
        !           134:        for (len = 0; efm[len] != NUL && efm[len] != ','; ++len)
        !           135:            if (efm[len] == '\\' && efm[len + 1] != NUL)
        !           136:                ++len;
        !           137:
        !           138:        /*
        !           139:         * Get some space to modify the format string into.
        !           140:         * Must be able to do the largest expansion (x3) MAX_ADDR times.
        !           141:         */
        !           142:        maxlen = len + MAX_ADDR * 3 + 4;
        !           143:        if ((fmt_ptr->fmtstr = alloc(maxlen)) == NULL)
        !           144:            goto error2;
        !           145:
        !           146:        for (i = 0; i < MAX_ADDR; ++i)
        !           147:            fmt_ptr->adr[i] = NULL;
        !           148:
        !           149:        for (efmp = efm, i = 0; efmp < efm + len; ++efmp, ++i)
        !           150:        {
        !           151:            if (efmp[0] != '%')             /* copy normal character */
        !           152:            {
        !           153:                if (efmp[0] == '\\' && efmp + 1 < efm + len)
        !           154:                    ++efmp;
        !           155:                fmt_ptr->fmtstr[i] = efmp[0];
        !           156:            }
        !           157:            else
        !           158:            {
        !           159:                fmt_ptr->fmtstr[i++] = '%';
        !           160:                switch (efmp[1])
        !           161:                {
        !           162:                case 'f':       /* filename */
        !           163:                        fmt_ptr->adr[fmt_ptr->adr_cnt++] = namebuf;
        !           164:                        /* FALLTHROUGH */
        !           165:
        !           166:                case 'm':       /* message */
        !           167:                        if (efmp[1] == 'm')
        !           168:                            fmt_ptr->adr[fmt_ptr->adr_cnt++] = errmsg;
        !           169:                        fmt_ptr->fmtstr[i++] = '[';
        !           170:                        fmt_ptr->fmtstr[i++] = '^';
        !           171: #ifdef __EMX__
        !           172:                        /* don't allow spaces in filename. This fixes
        !           173:                         * the broken sscanf() where an empty message
        !           174:                         * is accepted as a valid conversion.
        !           175:                         */
        !           176:                        if (efmp[1] == 'f')
        !           177:                            fmt_ptr->fmtstr[i++] = ' ';
        !           178: #endif
        !           179:                        if (efmp[2] == '\\')        /* could be "%m\," */
        !           180:                            j = 3;
        !           181:                        else
        !           182:                            j = 2;
        !           183:                        if (efmp + j < efm + len)
        !           184:                            fmt_ptr->fmtstr[i++] = efmp[j];
        !           185:                        else
        !           186:                        {
        !           187:                            /*
        !           188:                             * The %f or %m is the last one in the format,
        !           189:                             * stop at the CR of NL at the end of the line.
        !           190:                             */
        !           191: #ifdef USE_CRNL
        !           192:                            fmt_ptr->fmtstr[i++] = '\r';
        !           193: #endif
        !           194:                            fmt_ptr->fmtstr[i++] = '\n';
        !           195:                        }
        !           196:                        fmt_ptr->fmtstr[i] = ']';
        !           197:                        break;
        !           198:                case 'c':       /* column */
        !           199:                        fmt_ptr->adr[fmt_ptr->adr_cnt++] = &col;
        !           200:                        fmt_ptr->fmtstr[i] = 'd';
        !           201:                        break;
        !           202:                case 'l':       /* line */
        !           203:                        fmt_ptr->adr[fmt_ptr->adr_cnt++] = &lnum;
        !           204:                        fmt_ptr->fmtstr[i++] = 'l';
        !           205:                        fmt_ptr->fmtstr[i] = 'd';
        !           206:                        break;
        !           207:                case 'n':       /* error number */
        !           208:                        fmt_ptr->adr[fmt_ptr->adr_cnt++] = &enr;
        !           209:                        fmt_ptr->fmtstr[i] = 'd';
        !           210:                        break;
        !           211:                case 't':       /* error type */
        !           212:                        fmt_ptr->adr[fmt_ptr->adr_cnt++] = &type;
        !           213:                        fmt_ptr->fmtstr[i] = 'c';
        !           214:                        break;
        !           215:                case '%':       /* %% */
        !           216:                case '*':       /* %*: no assignment */
        !           217:                        fmt_ptr->fmtstr[i] = efmp[1];
        !           218:                        break;
        !           219:                default:
        !           220:                        EMSG("invalid % in format string");
        !           221:                        goto error2;
        !           222:                }
        !           223:                if (fmt_ptr->adr_cnt == MAX_ADDR)
        !           224:                {
        !           225:                    EMSG("too many % in format string");
        !           226:                    goto error2;
        !           227:                }
        !           228:                ++efmp;
        !           229:            }
        !           230:            if (i >= maxlen - 6)
        !           231:            {
        !           232:                EMSG("invalid format string");
        !           233:                goto error2;
        !           234:            }
        !           235:        }
        !           236:        fmt_ptr->fmtstr[i] = NUL;
        !           237:
        !           238:        /*
        !           239:         * Advance to next part
        !           240:         */
        !           241:        efm = skip_to_option_part(efm + len);   /* skip comma and spaces */
        !           242:    }
        !           243:    if (fmt_first == NULL)      /* nothing found */
        !           244:    {
        !           245:        EMSG("'errorformat' contains no pattern");
        !           246:        goto error2;
        !           247:    }
        !           248:
        !           249:    /*
        !           250:     * Read the lines in the error file one by one.
        !           251:     * Try to recognize one of the error formats in each line.
        !           252:     */
        !           253:    while (fgets((char *)IObuff, CMDBUFFSIZE, fd) != NULL && !got_int)
        !           254:    {
        !           255:        if ((qfp = (struct qf_line *)alloc((unsigned)sizeof(struct qf_line)))
        !           256:                                                                      == NULL)
        !           257:            goto error2;
        !           258:
        !           259:        IObuff[CMDBUFFSIZE] = NUL;  /* for very long lines */
        !           260:
        !           261:        /*
        !           262:         * Try to match each part of 'errorformat' until we find a complete
        !           263:         * match or none matches.
        !           264:         */
        !           265:        valid = TRUE;
        !           266:        for (fmt_ptr = fmt_first; fmt_ptr != NULL; fmt_ptr = fmt_ptr->next)
        !           267:        {
        !           268:            namebuf[0] = NUL;
        !           269:            errmsg[0] = NUL;
        !           270:            lnum = 0;
        !           271:            col = 0;
        !           272:            enr = -1;
        !           273:            type = 0;
        !           274:
        !           275:            /*
        !           276:             * If first char of the format and message don't match, there is
        !           277:             * no need to try sscanf() on it... Somehow I believe there are
        !           278:             * very slow implementations of sscanf().
        !           279:             * -- Paul Slootman
        !           280:             */
        !           281:            if (fmt_ptr->fmtstr[0] != '%' && fmt_ptr->fmtstr[0] != IObuff[0])
        !           282:                continue;
        !           283:
        !           284:            if (sscanf((char *)IObuff, (char *)fmt_ptr->fmtstr,
        !           285:                        fmt_ptr->adr[0], fmt_ptr->adr[1], fmt_ptr->adr[2],
        !           286:                        fmt_ptr->adr[3], fmt_ptr->adr[4], fmt_ptr->adr[5],
        !           287:                        fmt_ptr->adr[6]) == fmt_ptr->adr_cnt)
        !           288:                break;
        !           289:        }
        !           290:        if (fmt_ptr == NULL)
        !           291:        {
        !           292:            namebuf[0] = NUL;           /* no match found, remove file name */
        !           293:            lnum = 0;                   /* don't jump to this line */
        !           294:            valid = FALSE;
        !           295:            STRCPY(errmsg, IObuff);     /* copy whole line to error message */
        !           296:            if ((efmp = vim_strrchr(errmsg, '\n')) != NULL)
        !           297:                *efmp = NUL;
        !           298: #ifdef USE_CRNL
        !           299:            if ((efmp = vim_strrchr(errmsg, '\r')) != NULL)
        !           300:                *efmp = NUL;
        !           301: #endif
        !           302:        }
        !           303:
        !           304:        if (namebuf[0] == NUL)          /* no file name */
        !           305:            qfp->qf_fnum = 0;
        !           306:        else
        !           307:            qfp->qf_fnum = buflist_add(namebuf);
        !           308:        if ((qfp->qf_text = strsave(errmsg)) == NULL)
        !           309:            goto error1;
        !           310:        qfp->qf_lnum = lnum;
        !           311:        qfp->qf_col = col;
        !           312:        qfp->qf_nr = enr;
        !           313:        qfp->qf_type = type;
        !           314:        qfp->qf_valid = valid;
        !           315:
        !           316:        if (qf_count == 0)      /* first element in the list */
        !           317:        {
        !           318:            qf_start = qfp;
        !           319:            qfp->qf_prev = qfp; /* first element points to itself */
        !           320:        }
        !           321:        else
        !           322:        {
        !           323:            qfp->qf_prev = qfprev;
        !           324:            qfprev->qf_next = qfp;
        !           325:        }
        !           326:        qfp->qf_next = qfp;     /* last element points to itself */
        !           327:        qfp->qf_cleared = FALSE;
        !           328:        qfprev = qfp;
        !           329:        ++qf_count;
        !           330:        if (qf_index == 0 && qfp->qf_valid)     /* first valid entry */
        !           331:        {
        !           332:            qf_index = qf_count;
        !           333:            qf_ptr = qfp;
        !           334:        }
        !           335:        line_breakcheck();
        !           336:    }
        !           337:    if (!ferror(fd))
        !           338:    {
        !           339:        if (qf_index == 0)      /* no valid entry found */
        !           340:        {
        !           341:            qf_ptr = qf_start;
        !           342:            qf_index = 1;
        !           343:            qf_nonevalid = TRUE;
        !           344:        }
        !           345:        else
        !           346:            qf_nonevalid = FALSE;
        !           347:        retval = OK;
        !           348:        goto qf_init_ok;
        !           349:    }
        !           350:    emsg(e_readerrf);
        !           351: error1:
        !           352:    vim_free(qfp);
        !           353: error2:
        !           354:    qf_free();
        !           355: qf_init_ok:
        !           356:    fclose(fd);
        !           357:    for (fmt_ptr = fmt_first; fmt_ptr != NULL; fmt_ptr = fmt_first)
        !           358:    {
        !           359:        fmt_first = fmt_ptr->next;
        !           360:        vim_free(fmt_ptr->fmtstr);
        !           361:        vim_free(fmt_ptr);
        !           362:    }
        !           363: qf_init_end:
        !           364:    vim_free(namebuf);
        !           365:    vim_free(errmsg);
        !           366:    return retval;
        !           367: }
        !           368:
        !           369: /*
        !           370:  * jump to a quickfix line
        !           371:  * if dir == FORWARD go "errornr" valid entries forward
        !           372:  * if dir == BACKWARD go "errornr" valid entries backward
        !           373:  * else if "errornr" is zero, redisplay the same line
        !           374:  * else go to entry "errornr"
        !           375:  */
        !           376:    void
        !           377: qf_jump(dir, errornr)
        !           378:    int     dir;
        !           379:    int     errornr;
        !           380: {
        !           381:    struct qf_line  *old_qf_ptr;
        !           382:    int             old_qf_index;
        !           383:    static char_u   *e_no_more_errors = (char_u *)"No more errors";
        !           384:    char_u          *err = e_no_more_errors;
        !           385:    linenr_t        i;
        !           386:
        !           387:    if (qf_count == 0)
        !           388:    {
        !           389:        emsg(e_quickfix);
        !           390:        return;
        !           391:    }
        !           392:
        !           393:    old_qf_ptr = qf_ptr;
        !           394:    old_qf_index = qf_index;
        !           395:    if (dir == FORWARD)     /* next valid entry */
        !           396:    {
        !           397:        while (errornr--)
        !           398:        {
        !           399:            old_qf_ptr = qf_ptr;
        !           400:            old_qf_index = qf_index;
        !           401:            do
        !           402:            {
        !           403:                if (qf_index == qf_count || qf_ptr->qf_next == NULL)
        !           404:                {
        !           405:                    qf_ptr = old_qf_ptr;
        !           406:                    qf_index = old_qf_index;
        !           407:                    if (err != NULL)
        !           408:                    {
        !           409:                        emsg(err);
        !           410:                        return;
        !           411:                    }
        !           412:                    errornr = 0;
        !           413:                    break;
        !           414:                }
        !           415:                ++qf_index;
        !           416:                qf_ptr = qf_ptr->qf_next;
        !           417:            } while (!qf_nonevalid && !qf_ptr->qf_valid);
        !           418:            err = NULL;
        !           419:        }
        !           420:    }
        !           421:    else if (dir == BACKWARD)       /* previous valid entry */
        !           422:    {
        !           423:        while (errornr--)
        !           424:        {
        !           425:            old_qf_ptr = qf_ptr;
        !           426:            old_qf_index = qf_index;
        !           427:            do
        !           428:            {
        !           429:                if (qf_index == 1 || qf_ptr->qf_prev == NULL)
        !           430:                {
        !           431:                    qf_ptr = old_qf_ptr;
        !           432:                    qf_index = old_qf_index;
        !           433:                    if (err != NULL)
        !           434:                    {
        !           435:                        emsg(err);
        !           436:                        return;
        !           437:                    }
        !           438:                    errornr = 0;
        !           439:                    break;
        !           440:                }
        !           441:                --qf_index;
        !           442:                qf_ptr = qf_ptr->qf_prev;
        !           443:            } while (!qf_nonevalid && !qf_ptr->qf_valid);
        !           444:            err = NULL;
        !           445:        }
        !           446:    }
        !           447:    else if (errornr != 0)      /* go to specified number */
        !           448:    {
        !           449:        while (errornr < qf_index && qf_index > 1 && qf_ptr->qf_prev != NULL)
        !           450:        {
        !           451:            --qf_index;
        !           452:            qf_ptr = qf_ptr->qf_prev;
        !           453:        }
        !           454:        while (errornr > qf_index && qf_index < qf_count && qf_ptr->qf_next != NULL)
        !           455:        {
        !           456:            ++qf_index;
        !           457:            qf_ptr = qf_ptr->qf_next;
        !           458:        }
        !           459:    }
        !           460:
        !           461:    /*
        !           462:     * If there is a file name,
        !           463:     * read the wanted file if needed, and check autowrite etc.
        !           464:     */
        !           465:    if (qf_ptr->qf_fnum == 0 || buflist_getfile(qf_ptr->qf_fnum,
        !           466:                                             (linenr_t)1, GETF_SETMARK) == OK)
        !           467:    {
        !           468:        /*
        !           469:         * Go to line with error, unless qf_lnum is 0.
        !           470:         */
        !           471:        i = qf_ptr->qf_lnum;
        !           472:        if (i > 0)
        !           473:        {
        !           474:            if (i > curbuf->b_ml.ml_line_count)
        !           475:                i = curbuf->b_ml.ml_line_count;
        !           476:            curwin->w_cursor.lnum = i;
        !           477:        }
        !           478:        if (qf_ptr->qf_col > 0)
        !           479:        {
        !           480:            curwin->w_cursor.col = qf_ptr->qf_col - 1;
        !           481:            adjust_cursor();
        !           482:        }
        !           483:        else
        !           484:            beginline(TRUE);
        !           485:        cursupdate();
        !           486:        smsg((char_u *)"(%d of %d)%s%s: %s", qf_index, qf_count,
        !           487:                    qf_ptr->qf_cleared ? (char_u *)" (line deleted)" : (char_u *)"",
        !           488:                    qf_types(qf_ptr->qf_type, qf_ptr->qf_nr), qf_ptr->qf_text);
        !           489:        /*
        !           490:         * if the message is short, redisplay after redrawing the screen
        !           491:         */
        !           492:        if (linetabsize(IObuff) < ((int)p_ch - 1) * Columns + sc_col)
        !           493:            keep_msg = IObuff;
        !           494:    }
        !           495:    else if (qf_ptr->qf_fnum != 0)
        !           496:    {
        !           497:        /*
        !           498:         * Couldn't open file, so put index back where it was.  This could
        !           499:         * happen if the file was readonly and we changed something - webb
        !           500:         */
        !           501:        qf_ptr = old_qf_ptr;
        !           502:        qf_index = old_qf_index;
        !           503:    }
        !           504: }
        !           505:
        !           506: /*
        !           507:  * list all errors
        !           508:  */
        !           509:    void
        !           510: qf_list(all)
        !           511:    int all;        /* If not :cl!, only show recognised errors */
        !           512: {
        !           513:    BUF             *buf;
        !           514:    char_u          *fname;
        !           515:    struct qf_line  *qfp;
        !           516:    int             i;
        !           517:
        !           518:    if (qf_count == 0)
        !           519:    {
        !           520:        emsg(e_quickfix);
        !           521:        return;
        !           522:    }
        !           523:
        !           524:    if (qf_nonevalid)
        !           525:        all = TRUE;
        !           526:    qfp = qf_start;
        !           527:    set_highlight('d');     /* Same as for directories */
        !           528:    for (i = 1; !got_int && i <= qf_count; ++i)
        !           529:    {
        !           530:        if (qfp->qf_valid || all)
        !           531:        {
        !           532:            msg_outchar('\n');
        !           533:            start_highlight();
        !           534:            fname = NULL;
        !           535:            if (qfp->qf_fnum != 0 &&
        !           536:                                 (buf = buflist_findnr(qfp->qf_fnum)) != NULL)
        !           537:                fname = buf->b_xfilename;
        !           538:            if (fname == NULL)
        !           539:                sprintf((char *)IObuff, "%2d", i);
        !           540:            else
        !           541:                sprintf((char *)IObuff, "%2d %s", i, fname);
        !           542:            msg_outtrans(IObuff);
        !           543:            stop_highlight();
        !           544:            if (qfp->qf_lnum == 0)
        !           545:                IObuff[0] = NUL;
        !           546:            else if (qfp->qf_col == 0)
        !           547:                sprintf((char *)IObuff, ":%ld", qfp->qf_lnum);
        !           548:            else
        !           549:                sprintf((char *)IObuff, ":%ld, col %d",
        !           550:                                                   qfp->qf_lnum, qfp->qf_col);
        !           551:            sprintf((char *)IObuff + STRLEN(IObuff), "%s: ",
        !           552:                                        qf_types(qfp->qf_type, qfp->qf_nr));
        !           553:            msg_outstr(IObuff);
        !           554:            msg_prt_line(qfp->qf_text);
        !           555:            flushbuf();                 /* show one line at a time */
        !           556:        }
        !           557:        qfp = qfp->qf_next;
        !           558:        mch_breakcheck();
        !           559:    }
        !           560: }
        !           561:
        !           562: /*
        !           563:  * free the error list
        !           564:  */
        !           565:    static void
        !           566: qf_free()
        !           567: {
        !           568:    struct qf_line *qfp;
        !           569:
        !           570:    while (qf_count)
        !           571:    {
        !           572:        qfp = qf_start->qf_next;
        !           573:        vim_free(qf_start->qf_text);
        !           574:        vim_free(qf_start);
        !           575:        qf_start = qfp;
        !           576:        --qf_count;
        !           577:    }
        !           578: }
        !           579:
        !           580: /*
        !           581:  * qf_mark_adjust: adjust marks
        !           582:  */
        !           583:    void
        !           584: qf_mark_adjust(line1, line2, amount, amount_after)
        !           585:    linenr_t    line1;
        !           586:    linenr_t    line2;
        !           587:    long        amount;
        !           588:    long        amount_after;
        !           589: {
        !           590:    register int i;
        !           591:    struct qf_line *qfp;
        !           592:
        !           593:    if (qf_count)
        !           594:        for (i = 0, qfp = qf_start; i < qf_count; ++i, qfp = qfp->qf_next)
        !           595:            if (qfp->qf_fnum == curbuf->b_fnum)
        !           596:            {
        !           597:                if (qfp->qf_lnum >= line1 && qfp->qf_lnum <= line2)
        !           598:                {
        !           599:                    if (amount == MAXLNUM)
        !           600:                        qfp->qf_cleared = TRUE;
        !           601:                    else
        !           602:                        qfp->qf_lnum += amount;
        !           603:                }
        !           604:                if (amount_after && qfp->qf_lnum > line2)
        !           605:                    qfp->qf_lnum += amount_after;
        !           606:            }
        !           607: }
        !           608:
        !           609: /*
        !           610:  * Make a nice message out of the error character and the error number:
        !           611:  * char    number      message
        !           612:  *  e or E    0            "   error"
        !           613:  *  w or W    0            " warning"
        !           614:  *  other     0            ""
        !           615:  *  w or W    n            " warning n"
        !           616:  *  other     n            "   error n"
        !           617:  */
        !           618:    static char_u *
        !           619: qf_types(c, nr)
        !           620:    int c, nr;
        !           621: {
        !           622:    static char_u   buf[20];
        !           623:    char_u      *p1;
        !           624:
        !           625:    p1 = (char_u *)"   error";
        !           626:    if (c == 'W' || c == 'w')
        !           627:        p1 =  (char_u *)" warning";
        !           628:    else if (nr <= 0 && c != 'E' && c != 'e')
        !           629:        p1 = (char_u *)"";
        !           630:
        !           631:    if (nr <= 0)
        !           632:        return p1;
        !           633:
        !           634:    sprintf((char *)buf, "%s %3d", p1, nr);
        !           635:    return buf;
        !           636: }