Annotation of coherent/d/bin/diff/diff3.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Internal part of diff3.
        !             3:  * This file resides in /usr/lib/diff3.
        !             4:  * It is called as:
        !             5:  * /usr/lib/diff3 [options] generator
        !             6:  * Generator is the generator for the tempfile
        !             7:  * names (as in /tmp/d30239).  `a' and `b' are used.
        !             8:  */
        !             9: 
        !            10: #include <stdio.h>
        !            11: #include <ctype.h>
        !            12: 
        !            13: #define NINF   3               /* Number of input files */
        !            14: 
        !            15: typedef        long    SEEK;           /* May be made long */
        !            16: 
        !            17: /*
        !            18:  * A set of changes between two files.
        !            19:  * This is just pairs of ranges from each file.
        !            20:  */
        !            21: typedef        struct  CHANGES {
        !            22:        SEEK    c_seek;         /* Seek position after header line */
        !            23:        unsigned c_oldbeg;      /* Old (first) file - beginning line number */
        !            24:        unsigned c_oldend;      /* end line number */
        !            25:        unsigned c_newbeg;      /* New (second) file - beginning */
        !            26:        unsigned c_newend;      /* end line number */
        !            27: }      CHANGES;
        !            28: 
        !            29: int    eflag;          /* Type of ed script */
        !            30: int    ndiffs;         /* Number of differences found */
        !            31: unsigned lastchange[NINF];
        !            32: char   line[1000];     /* Input line buffer */
        !            33: 
        !            34: FILE   *fp13;          /* Changes of file 1 versus file 3 */
        !            35: FILE   *fp23;          /* Changes of file 2 versus file 3 */
        !            36: 
        !            37: FILE   *diffopen();
        !            38: CHANGES        *getdiff();
        !            39: 
        !            40: main(argc, argv)
        !            41: int argc;
        !            42: char *argv[];
        !            43: {
        !            44:        register char *ap;
        !            45: 
        !            46:        if (argc>1 && *argv[1]=='-') {
        !            47:                for (ap = &argv[1][1]; *ap!='\0'; ap++)
        !            48:                        switch (*ap) {
        !            49:                        case 'e':
        !            50:                                eflag = 03;
        !            51:                                break;
        !            52: 
        !            53:                        case 'x':
        !            54:                                eflag = 01;
        !            55:                                break;
        !            56: 
        !            57:                        case '3':
        !            58:                                eflag = 02;
        !            59:                                break;
        !            60: 
        !            61:                        default:
        !            62:                                cerr("bad option `%s'", argv[1]);
        !            63:                        }
        !            64:                argv++;
        !            65:                argc--;
        !            66:        }
        !            67:        if (argc != 2)
        !            68:                ierr("main");
        !            69:        fp13 = diffopen(argv[1], 'a');
        !            70:        fp23 = diffopen(argv[1], 'b');
        !            71:        collate();
        !            72:        exit(ndiffs!=0);
        !            73: }
        !            74: 
        !            75: /*
        !            76:  * Open one of the difference files
        !            77:  * (i.e. the output of `diff').
        !            78:  * Arguments are the generator name and
        !            79:  * an identifying letter.
        !            80:  */
        !            81: FILE *
        !            82: diffopen(gener, let)
        !            83: char *gener;
        !            84: int let;
        !            85: {
        !            86:        FILE *fp;
        !            87: 
        !            88:        sprintf(line, "%s%c", gener, let);
        !            89:        if ((fp = fopen(line, "r")) == NULL)
        !            90:                cerr("cannot open intermediate file `%s'", line);
        !            91:        return (fp);
        !            92: }
        !            93: 
        !            94: /*
        !            95:  * Read in one entry from the specified
        !            96:  * file of differences.  The `fp'
        !            97:  * argument is the stream containing one
        !            98:  * of the output files of `diff'.
        !            99:  */
        !           100: CHANGES *
        !           101: getdiff(fp)
        !           102: FILE *fp;
        !           103: {
        !           104:        register CHANGES *cp;
        !           105:        char *linep;
        !           106:        register int type;
        !           107: 
        !           108:        while (fgets(line, sizeof line, fp) != NULL) {
        !           109:                if (!isdigit(line[0]))
        !           110:                        continue;
        !           111:                if ((cp = (CHANGES *)malloc(sizeof (CHANGES))) == NULL)
        !           112:                        cerr("out of memory for changes");
        !           113:                linep = line;
        !           114:                cp->c_oldbeg = cp->c_oldend = readnum(&linep);
        !           115:                if (*linep == ',') {
        !           116:                        linep++;
        !           117:                        cp->c_oldend = readnum(&linep);
        !           118:                }
        !           119:                type = *linep++;
        !           120:                cp->c_newbeg = cp->c_newend = readnum(&linep);
        !           121:                if (*linep == ',') {
        !           122:                        linep++;
        !           123:                        cp->c_newend = readnum(&linep);
        !           124:                }
        !           125:                if (type == 'a')
        !           126:                        cp->c_oldbeg++;
        !           127:                else if (type == 'd')
        !           128:                        cp->c_newbeg++;
        !           129:                cp->c_oldend++;
        !           130:                cp->c_newend++;
        !           131:                cp->c_seek = ftell(fp);
        !           132:                ndiffs++;
        !           133:                return (cp);
        !           134:        }
        !           135:        return (NULL);
        !           136: }
        !           137: 
        !           138: /*
        !           139:  * Read a line number from the line.
        !           140:  * The pointer is given by reference
        !           141:  * so that it can be updated.
        !           142:  * Leading and trailing space is skipped.
        !           143:  */
        !           144: readnum(npp)
        !           145: register char **npp;
        !           146: {
        !           147:        register char *np;
        !           148:        register int n = 0;
        !           149: 
        !           150:        np = *npp;
        !           151:        while (isspace(*np))
        !           152:                np++;
        !           153:        while (isdigit(*np))
        !           154:                n = n*10 + *np++ - '0';
        !           155:        while (isspace(*np))
        !           156:                np++;
        !           157:        *npp = np;
        !           158:        return (n);
        !           159: }
        !           160: 
        !           161: /*
        !           162:  * Read through the two difference
        !           163:  * files, collating changes that we
        !           164:  * encounter to produce one consistent
        !           165:  * view of changes on all three files.
        !           166:  */
        !           167: collate()
        !           168: {
        !           169:        register CHANGES *p13, *p23;
        !           170:        register CHANGES *n13, *n23;
        !           171: 
        !           172:        if ((p13 = getdiff(fp13)) != NULL)
        !           173:                n13 = getdiff(fp13); else
        !           174:                n13 = NULL;
        !           175:        if ((p23 = getdiff(fp23)) != NULL)
        !           176:                n23 = getdiff(fp23); else
        !           177:                n23 = NULL;
        !           178:        while (p13!=NULL || p23!=NULL) {
        !           179:                /*
        !           180:                 * Differences found in the
        !           181:                 * first file.
        !           182:                 */
        !           183:                if (p23==NULL || (p13!=NULL && p13->c_newend<p23->c_newbeg)) {
        !           184:                        prsep(1);
        !           185:                        prchanges(1, p13, fp13);
        !           186:                        prdummy(2, p13);
        !           187:                        prchanges(3, p13, fp13);
        !           188:                        cfree(p13);
        !           189:                        if ((p13 = n13) != NULL)
        !           190:                                n13 = getdiff(fp13);
        !           191:                        continue;
        !           192:                }
        !           193:                /*
        !           194:                 * Differences found in the
        !           195:                 * second file.
        !           196:                 */
        !           197:                if (p13==NULL || (p23!=NULL && p23->c_newend<p13->c_newbeg)) {
        !           198:                        prsep(2);
        !           199:                        prdummy(1, p23);
        !           200:                        prchanges(2, p23, fp23);
        !           201:                        prchanges(3, p23, fp23);
        !           202:                        cfree(p23);
        !           203:                        if ((p23 = n23) != NULL)
        !           204:                                p23 = getdiff(fp23);
        !           205:                        continue;
        !           206:                }
        !           207:                /*
        !           208:                 * Merge changes that overlap
        !           209:                 * with next change in first file.
        !           210:                 * This happens as a result of
        !           211:                 * the extension of a change as below.
        !           212:                 */
        !           213:                if (n13!=NULL && p13->c_newend >= n13->c_newbeg) {
        !           214:                        n13->c_oldbeg = p13->c_oldbeg;
        !           215:                        n13->c_newbeg = p13->c_newbeg;
        !           216:                        cfree(p13);
        !           217:                        p13 = n13;
        !           218:                        n13 = getdiff(fp13);
        !           219:                        continue;
        !           220:                }
        !           221:                /*
        !           222:                 * Do the same merge as above
        !           223:                 * only for the second file of changed.
        !           224:                 */
        !           225:                if (n23!=NULL && p23->c_newend >= n23->c_newbeg) {
        !           226:                        n23->c_oldbeg = p23->c_oldbeg;
        !           227:                        n23->c_newbeg = p23->c_newbeg;
        !           228:                        cfree(p23);
        !           229:                        p23 = n23;
        !           230:                        n23 = getdiff(fp23);
        !           231:                        continue;
        !           232:                }
        !           233:                /*
        !           234:                 * Find lines only in third file or
        !           235:                 * different in all.  The difference
        !           236:                 * between these two cases has to
        !           237:                 * be tested by reading the actual
        !           238:                 * different lines and comparing them.
        !           239:                 */
        !           240:                if (p13->c_newbeg == p23->c_newbeg
        !           241:                 && p13->c_newend == p23->c_newend) {
        !           242:                        register int mat;
        !           243:                        register CHANGES *cp;
        !           244:                        register FILE *fp;
        !           245: 
        !           246:                        mat = match12(p13, p23);
        !           247:                        prsep(mat ? 3 : 0);
        !           248:                        /*
        !           249:                         * This masks out the editing changes
        !           250:                         * desired, i.e. all different and 3 different
        !           251:                         * for -e, and the individual cases for -x and -3.
        !           252:                         */
        !           253:                        if (eflag & (mat+01))
        !           254:                                preditor(p13);
        !           255:                        prchanges(1, p13, mat?NULL:fp13);
        !           256:                        prchanges(2, p23, fp23);
        !           257:                        /*
        !           258:                         * Depends on whether a `c' or
        !           259:                         * an `a' operation.
        !           260:                         */
        !           261:                        if (p13->c_oldend > p13->c_oldbeg) {
        !           262:                                cp = p13;
        !           263:                                fp = fp13;
        !           264:                        } else {
        !           265:                                cp = p23;
        !           266:                                fp = fp23;
        !           267:                        }
        !           268:                        prchanges(3, cp, fp);
        !           269:                        cfree(p13);
        !           270:                        if ((p13 = n13) != NULL)
        !           271:                                n13 = getdiff(fp13);
        !           272:                        cfree(p23);
        !           273:                        if ((p23 = n23) != NULL)
        !           274:                                n23 = getdiff(fp23);
        !           275:                        continue;
        !           276:                }
        !           277:                /*
        !           278:                 * When a range of lines overlaps that
        !           279:                 * of another range in the other change
        !           280:                 * file, the ranges have to be adjusted.
        !           281:                 */
        !           282:                if (p13->c_newbeg < p23->c_newbeg) {
        !           283:                        p23->c_oldbeg -= p23->c_newbeg-p13->c_newbeg;
        !           284:                        p23->c_newbeg = p13->c_newbeg;
        !           285:                } else if (p23->c_newbeg < p13->c_newbeg) {
        !           286:                        p13->c_oldbeg -= p13->c_newbeg-p23->c_newbeg;
        !           287:                        p13->c_newbeg = p23->c_newbeg;
        !           288:                }
        !           289:                if (p13->c_newend > p23->c_newend) {
        !           290:                        p23->c_oldend += p13->c_newend-p23->c_newend;
        !           291:                        p23->c_newend = p13->c_newend;
        !           292:                } else if (p23->c_newend > p13->c_newend) {
        !           293:                        p13->c_oldend += p23->c_newend-p13->c_newend;
        !           294:                        p13->c_newend = p23->c_newend;
        !           295:                }
        !           296:        }
        !           297: }
        !           298: 
        !           299: /*
        !           300:  * Free a CHANGES node, checking first
        !           301:  * to see if it is NULL.
        !           302:  */
        !           303: cfree(cp)
        !           304: register CHANGES *cp;
        !           305: {
        !           306:        if (cp != NULL)
        !           307:                free((char *)cp);
        !           308: }
        !           309: 
        !           310: /*
        !           311:  * Since we have only the output of two diffs,
        !           312:  * we have to cross-check the output for a match
        !           313:  * between files one and two.  This will use the
        !           314:  * line ranges found in the c_before of each
        !           315:  * CHANGES description.
        !           316:  * We have to seek both file descriptors back
        !           317:  * to where they were at entry upon leaving this routine.
        !           318:  */
        !           319: match12(cp13, cp23)
        !           320: register CHANGES *cp13, *cp23;
        !           321: {
        !           322:        register int n;
        !           323:        register char *lp;
        !           324:        register int ret = 1;
        !           325:        long seek13, seek23;
        !           326: 
        !           327:        n = cp13->c_oldend - cp13->c_oldbeg;
        !           328:        if (n != cp23->c_oldend - cp23->c_oldbeg)
        !           329:                return (0);
        !           330:        if (n == 0)
        !           331:                return (1);
        !           332:        seek13 = ftell(fp13);
        !           333:        seek23 = ftell(fp23);
        !           334:        fseek(fp13, (long)cp13->c_seek, 0);
        !           335:        fseek(fp23, (long)cp23->c_seek, 0);
        !           336:        do {
        !           337:                if (fgets(line, sizeof line, fp13) == NULL)
        !           338:                        ierr("match12/1");
        !           339:                for (lp = line; *lp++ != '\0'; )
        !           340:                        ;
        !           341:                if (fgets(lp, sizeof line - (lp-line), fp23) == NULL)
        !           342:                        ierr("match12/2");
        !           343:                if (line[0]!='<' || line[1]!=' ')
        !           344:                        ierr("match12/3");
        !           345:                if (*lp++!='<' || *lp++!=' ')
        !           346:                        ierr("match12/4");
        !           347:                if (strcmp(lp, line+2) != 0) {
        !           348:                        ret = 0;
        !           349:                        break;
        !           350:                }
        !           351:        } while (--n);
        !           352:        fseek(fp13, seek13, 0);
        !           353:        fseek(fp23, seek23, 0);
        !           354:        return (ret);
        !           355: }
        !           356: 
        !           357: /*
        !           358:  * Print out the changes on file numbered `fn' (1-3),
        !           359:  * given the CHANGES structure reference `cp'.
        !           360:  * Since file 3 is always the `new' file, if `fn==3'
        !           361:  * then the new range is used, otherwise the old.
        !           362:  * `prt' is set, if the text needs to be printed.
        !           363:  */
        !           364: prchanges(fn, cp, prtfp)
        !           365: int fn;
        !           366: CHANGES *cp;
        !           367: FILE *prtfp;
        !           368: {
        !           369:        register unsigned beg, end;
        !           370:        register char recog;
        !           371:        register int nl;
        !           372:        long oseek;
        !           373: 
        !           374:        if (eflag)
        !           375:                return;
        !           376:        if (fn == 3) {
        !           377:                recog = '>';
        !           378:                beg = cp->c_newbeg;
        !           379:                end = cp->c_newend;
        !           380:        } else {
        !           381:                recog = '<';
        !           382:                beg = cp->c_oldbeg;
        !           383:                end = cp->c_oldend;
        !           384:        }
        !           385:        lastchange[fn-1] = end;
        !           386:        printf("%d: ", fn);
        !           387:        predcom(beg, end);
        !           388:        if (prtfp == NULL)
        !           389:                return;
        !           390:        oseek = ftell(prtfp);
        !           391:        fseek(prtfp, (long)cp->c_seek, 0);
        !           392:        while (fgets(line, sizeof line, prtfp) != NULL)
        !           393:                if (line[0]==recog && line[1]==' ')
        !           394:                        break;
        !           395:        for (nl = end-beg; nl-- > 0; ) {
        !           396:                if (line[0]!=recog || line[1]!=' ')
        !           397:                        break;
        !           398:                printf("  %s", line+2);
        !           399:                if (fgets(line, sizeof line, prtfp) == NULL)
        !           400:                        break;
        !           401:        }
        !           402:        fseek(prtfp, oseek, 0);
        !           403: }
        !           404: 
        !           405: /*
        !           406:  * Print out dummy changes.
        !           407:  */
        !           408: prdummy(fn, cp)
        !           409: register int fn;
        !           410: register CHANGES *cp;
        !           411: {
        !           412:        register unsigned diff;
        !           413: 
        !           414:        if (eflag)
        !           415:                return;
        !           416:        diff = lastchange[3-1] - lastchange[fn-1];
        !           417:        lastchange[fn-1] = cp->c_newend-diff;
        !           418:        printf("%d: ", fn);
        !           419:        predcom(cp->c_newbeg-diff, cp->c_newend-diff);
        !           420: }
        !           421: 
        !           422: /*
        !           423:  * Print out an entry in the editor
        !           424:  * script given the first difference
        !           425:  * file (between files 1 and 3).
        !           426:  * Line numbers have to be adjusted
        !           427:  * because this script is printed in
        !           428:  * forward order.  Special handling is
        !           429:  * done for a line which is `.'
        !           430:  */
        !           431: preditor(cp)
        !           432: register CHANGES *cp;
        !           433: {
        !           434:        register int nl;
        !           435:        long seek13;
        !           436:        static int lnadjust;
        !           437: 
        !           438:        predcom(cp->c_oldbeg+lnadjust, cp->c_oldend+lnadjust);
        !           439:        if (cp->c_oldend > cp->c_oldbeg)
        !           440:                lnadjust -= cp->c_oldend-cp->c_oldbeg;
        !           441:        seek13 = ftell(fp13);
        !           442:        fseek(fp13, (long)cp->c_seek, 0);
        !           443:        while (fgets(line, sizeof line, fp13) != NULL)
        !           444:                if (line[0]=='>' && line[1]==' ')
        !           445:                        break;
        !           446:        for (nl = cp->c_newend-cp->c_newbeg; nl--  > 0; ) {
        !           447:                if (line[0]!='>' || line[1]!=' ')
        !           448:                        break;
        !           449:                if (line[2]=='.' && line[3]=='\n' && line[4]=='\0')
        !           450:                        fputs("~\n.\ns/~/./\na\n", stdout);
        !           451:                else
        !           452:                        fputs(line+2, stdout);
        !           453:                lnadjust++;
        !           454:                if (fgets(line, sizeof line, fp13) == NULL)
        !           455:                        break;
        !           456:        }
        !           457:        fputs(".\n", stdout);
        !           458:        fseek(fp13, seek13, 0);
        !           459: }
        !           460: 
        !           461: /*
        !           462:  * Print out an editing command based
        !           463:  * upon the range of lines given.
        !           464:  * They have been adjusted in `readdiffs'
        !           465:  * so that an `a' and `c' are differentiable.
        !           466:  */
        !           467: predcom(beg, end)
        !           468: register unsigned beg, end;
        !           469: {
        !           470:        if (end <= beg)
        !           471:                printf("%da\n", beg-1);
        !           472:        else {
        !           473:                printf("%d", beg);
        !           474:                if (end > beg+1)
        !           475:                        printf(",%d", end-1);
        !           476:                printf("c\n");
        !           477:        }
        !           478: }
        !           479: 
        !           480: /*
        !           481:  * Print out a separator.
        !           482:  * The `fn' is which file differs.
        !           483:  * If `fn' is 0, it means all files differ.
        !           484:  */
        !           485: prsep(fn)
        !           486: register int fn;
        !           487: {
        !           488:        if (!eflag)
        !           489:                if (fn != 0)
        !           490:                        printf("====%d\n", fn); else
        !           491:                        printf("====\n");
        !           492: }
        !           493: 
        !           494: /*
        !           495:  * Error routines
        !           496:  */
        !           497: /* VARARGS */
        !           498: cerr(x)
        !           499: {
        !           500:        fprintf(stderr, "diff3: %r\n", &x);
        !           501:        exit(2);
        !           502: }
        !           503: 
        !           504: /*
        !           505:  * Internal error.
        !           506:  */
        !           507: ierr(type)
        !           508: char *type;
        !           509: {
        !           510:        cerr("internal error in %s", type);
        !           511: }

unix.superglobalmegacorp.com

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