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

1.1     ! root        1: /*
        !             2:  * This code is common between diff and /usr/lib/diffh.
        !             3:  * It is a restructuring and re-write of the earlier
        !             4:  * Tom Duff code so that reading options, opening files,
        !             5:  * and outputing of the differences is common.
        !             6:  */
        !             7: 
        !             8: #include "diff.h"
        !             9: #ifdef COHERENT
        !            10: #include <sys/stat.h>
        !            11: #include <signal.h>
        !            12: #else
        !            13: #include <sys/types.h>
        !            14: #endif
        !            15: #include <path.h>
        !            16: 
        !            17: int    dflag;                  /* Dynamic decision about -h or not */
        !            18: int    bflag;                  /* Strip trailing blanks, multiple blanks */
        !            19: int    eflag;                  /* Editor script */
        !            20: int    sflag;                  /* Sed script output (used by SCCS) */
        !            21: int    rflag;                  /* Reversed order of printed (usually -e) */
        !            22: int    nflag;                  /* Trailing '.' on edit script */
        !            23: int    incr;                   /* Line number increment for `rflag' diff */
        !            24: char   *csymbol;               /* Symbol for C pre-processor (#ifdef) */
        !            25: int    sepflag;                /* On if text from both files involved */
        !            26: int    caflag;                 /* On for a change or append */
        !            27: unsigned ninsert;              /* Number of lines inserted */
        !            28: unsigned ndelete;              /* Number of lines deleted */
        !            29: unsigned nunchanged;           /* Number of line unchanged */
        !            30: char   *tmpnam1, *tmpnam2;
        !            31: FILE   *fp1;                   /* First input stream */
        !            32: FILE   *fp2;                   /* Second input stream */
        !            33: char   *fn1, *fn2;             /* Filenames */
        !            34: 
        !            35: char   buf1[BUFSIZ];
        !            36: char   buf2[BUFSIZ];
        !            37: 
        !            38: FILE   *openfile();
        !            39: int    rmexit();
        !            40: int    catchsig();
        !            41: int    streq();
        !            42: int    bstreq();
        !            43: 
        !            44: int    (*equal)() = streq;
        !            45: 
        !            46: main(argc, argv)
        !            47: int argc;
        !            48: char *argv[];
        !            49: {
        !            50:        register char *ap;
        !            51:        register char **sargv = argv;
        !            52:        fsize_t size1, size2;
        !            53: 
        !            54:        while (argc>1 && argv[1][0]=='-' && argv[1][1]!='\0') {
        !            55:                for (ap = &argv[1][1]; *ap != '\0'; ap++)
        !            56:                        switch (*ap) {
        !            57:                        case 'b':
        !            58:                                bflag = 1;
        !            59:                                equal = bstreq;
        !            60:                                break;
        !            61: 
        !            62:                        case 'c':
        !            63:                                if (argc < 3)
        !            64:                                        usage();
        !            65:                                csymbol = argv[2];
        !            66:                                argv++;
        !            67:                                argc--;
        !            68:                                break;
        !            69: 
        !            70:                        case 'd':
        !            71:                                dflag = 1;
        !            72:                                break;
        !            73: 
        !            74:                        case 'e':
        !            75:                                eflag = rflag = 1;
        !            76:                                break;
        !            77: 
        !            78:                        case 'f':
        !            79:                                eflag = 1;
        !            80:                                rflag = 0;
        !            81:                                break;
        !            82: 
        !            83:                        case 'n':
        !            84:                                eflag = nflag = 1;
        !            85:                                rflag = 0;
        !            86:                                break;
        !            87: 
        !            88:                        case 's':
        !            89:                                eflag = sflag = 1;
        !            90:                                break;
        !            91: 
        !            92:                        case 'h':
        !            93:                                diffh(sargv);
        !            94:                                break;
        !            95: 
        !            96:                        default:
        !            97:                                usage();
        !            98:                        }
        !            99:                argc--;
        !           100:                argv++;
        !           101:        }
        !           102:        if (argc != 3)
        !           103:                usage();
        !           104:        if (eflag && csymbol!=NULL)
        !           105:                cerr("-e and -c are incompatible options");
        !           106: #ifdef COHERENT
        !           107:        if (signal(SIGINT, SIG_IGN) != SIG_IGN)
        !           108:                signal(SIGINT, catchsig);
        !           109:        if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
        !           110:                signal(SIGHUP, catchsig);
        !           111:        if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
        !           112:                signal(SIGTERM, catchsig);
        !           113: #endif
        !           114:        fp1 = openfile(argv[1], argv[2], &tmpnam1, &size1);
        !           115:        fp2 = openfile(argv[2], argv[1], &tmpnam2, &size2);
        !           116:        if (dflag && (size1>NBIGF || size2>NBIGF))
        !           117:                diffh(argv);
        !           118:        setbuf(fp1, buf1);
        !           119:        setbuf(fp2, buf2);
        !           120:        fn1 = argv[1];
        !           121:        fn2 = argv[2];
        !           122:        diff(fp1, fp2);
        !           123:        if (sflag)
        !           124:                printf(":I%d\n:D%d\n:U%d\n", ninsert, ndelete, nunchanged);
        !           125:        rmexit(ninsert || ndelete);
        !           126: }
        !           127: 
        !           128: /*
        !           129:  * Compare input lines for equality.
        !           130:  */
        !           131: bstreq(s1, s2)
        !           132: register char *s1, *s2;
        !           133: {
        !           134:        for (;;) {
        !           135:                if (*s1==' ' || *s1=='\t') {
        !           136:                        do {
        !           137:                                s1++;
        !           138:                        } while (*s1==' ' || *s1=='\t');
        !           139:                        if (*s1 == '\n') {
        !           140:                                while (*s2==' ' || *s2=='\t')
        !           141:                                        s2++;
        !           142:                                return (*s2 == '\n');
        !           143:                        }
        !           144:                        if (*s2!=' ' && *s2!='\t')
        !           145:                                return (0);
        !           146:                        do {
        !           147:                                s2++;
        !           148:                        } while (*s2==' ' || *s2=='\t');
        !           149:                } else {
        !           150:                        if (*s1 == '\n')
        !           151:                                while (*s2==' ' || *s2=='\t')
        !           152:                                        s2++;
        !           153:                        if (*s1++ != *s2)
        !           154:                                return (0);
        !           155:                        if (*s2++ == '\n')
        !           156:                                return (1);
        !           157:                }
        !           158:        }
        !           159: }
        !           160: 
        !           161: /*
        !           162:  * Open the files, allowing for special standard input
        !           163:  * convention (`-') and directories.  Copy any special
        !           164:  * files or pipes to a tempfile because they cannot be
        !           165:  * rewound.
        !           166:  * `ofn' is the other name, for directory concatenation.
        !           167:  */
        !           168: FILE *
        !           169: openfile(fn, ofn, tfnp, sizep)
        !           170: char *fn;
        !           171: char *ofn;
        !           172: char **tfnp;
        !           173: fsize_t *sizep;
        !           174: {
        !           175:        register FILE *fp;
        !           176: #ifdef COHERENT
        !           177:        register char *cp;
        !           178:        register int c;
        !           179:        register FILE *tfp;
        !           180:        char fname[300];
        !           181:        struct stat sb;
        !           182:        static int dirflag;
        !           183: 
        !           184: again:
        !           185: #endif
        !           186:        if (fn[0]=='-' && fn[1]=='\0')
        !           187:                fp = stdin;
        !           188:        else if ((fp = fopen(fn, "r")) == NULL)
        !           189:                cerr("cannot open `%s'", fn);
        !           190: #ifdef COHERENT
        !           191:        fstat(fileno(fp), &sb);
        !           192:        *sizep = sb.st_size;
        !           193:        switch (sb.st_mode & S_IFMT) {
        !           194:        case S_IFDIR:
        !           195:                if (dirflag)
        !           196:                        break;
        !           197:                dirflag++;
        !           198:                for (cp = ofn; *cp != '\0'; cp++)
        !           199:                        ;
        !           200:                while (cp > ofn)
        !           201:                        if (*--cp == PATHSEP) {
        !           202:                                cp++;
        !           203:                                break;
        !           204:                        }
        !           205:                sprintf(fname, "%s%c%s", fn, PATHSEP, cp);
        !           206:                fn = fname;
        !           207:                goto again;
        !           208: 
        !           209:        case S_IFREG:
        !           210:                break;
        !           211: 
        !           212:        default:
        !           213:                *tfnp = "/tmp/difXXXXXX";
        !           214:                if ((tfp = fopen(mktemp(*tfnp), "w")) == NULL)
        !           215:                        cerr("cannot create tempfile");
        !           216:                setbuf(fp, buf1);
        !           217:                setbuf(tfp, buf2);
        !           218:                while ((c = getc(fp)) != EOF)
        !           219:                        putc(c, tfp);
        !           220:                fflush(tfp);
        !           221:                if (ferror(tfp))
        !           222:                        cerr("write error on tempfile");
        !           223:                fclose(tfp);
        !           224:                if (fp != stdin)
        !           225:                        fclose(fp);
        !           226:                if ((fp = fopen(*tfnp, "r")) == NULL)
        !           227:                        cerr("cannot re-open tempfile");
        !           228:        }
        !           229: #endif
        !           230:        return (fp);
        !           231: }
        !           232: 
        !           233: /*
        !           234:  * Output a text line common to both files.
        !           235:  * This is only used by the `-c' option.
        !           236:  */
        !           237: text(line)
        !           238: char *line;
        !           239: {
        !           240:        ++nunchanged;
        !           241:        if (csymbol != NULL)
        !           242:                fputs(line, stdout);
        !           243: }
        !           244: 
        !           245: /*
        !           246:  * Output a text line from the first file.
        !           247:  */
        !           248: text1(line)
        !           249: register char *line;
        !           250: {
        !           251:        if (csymbol != NULL)
        !           252:                fputs(line, stdout);
        !           253:        else if (!eflag) {
        !           254:                fputs("< ", stdout);
        !           255:                fputs(line, stdout);
        !           256:        }
        !           257:        ++ndelete;
        !           258: }
        !           259: 
        !           260: /*
        !           261:  * Output a line that is only in
        !           262:  * the second file.
        !           263:  */
        !           264: text2(line)
        !           265: register char *line;
        !           266: {
        !           267:        if (sflag) {
        !           268:                putchar('\\');
        !           269:                putchar('\n');
        !           270: #if REALSED
        !           271:                /*
        !           272:                 * Sed is documented to strip
        !           273:                 * leading blanks/tabs in appended
        !           274:                 * text but doesn't.  This appears
        !           275:                 * to be a feature rather than a bug.
        !           276:                 */
        !           277:                if (line[0]==' ' || line[0]=='\t')
        !           278:                        putchar('\\');
        !           279: #endif
        !           280:                while (*line != '\n') {
        !           281:                        if (*line == '\\')
        !           282:                                putchar(*line);
        !           283:                        putchar(*line++);
        !           284:                }
        !           285:        } else if (eflag) {
        !           286:                if (!nflag && line[0]=='.' && line[1]=='\n' && line[2]=='\0')
        !           287:                        fputs("~\n.\ns/~/./\na\n", stdout);
        !           288:                else
        !           289:                        fputs(line, stdout);
        !           290:        } else if (csymbol != NULL)
        !           291:                fputs(line, stdout);
        !           292:        else {
        !           293:                fputs("> ", stdout);
        !           294:                fputs(line, stdout);
        !           295:        }
        !           296:        caflag = 1;
        !           297:        ++ninsert;
        !           298: }
        !           299: 
        !           300: /*
        !           301:  * Output the start of a set of
        !           302:  * changed lines.
        !           303:  * Change is from `f1',`f2' (other file is `t1,t2').
        !           304:  */
        !           305: change(f1, f2, t1, t2)
        !           306: unsigned f1, f2, t1, t2;
        !           307: {
        !           308:        sepflag = 1;
        !           309:        if (csymbol != NULL)
        !           310:                printf("#ifndef %s\n", csymbol);
        !           311:        else if (nflag) {
        !           312:                printf("d%u %u\n", f1+incr, f2-f1+1);
        !           313:                printf("a%u %u\n", f1+incr+f2-f1, t2-t1+1);
        !           314:        } else {
        !           315:                prange(f1, f2);
        !           316:                if (sflag)
        !           317:                        putchar('c');
        !           318:                else if (eflag)
        !           319:                        fputs("c\n", stdout);
        !           320:                else {
        !           321:                        fputs(" c ", stdout);
        !           322:                        prange(t1, t2);
        !           323:                        putchar('\n');
        !           324:                }
        !           325:        }
        !           326:        if (rflag)
        !           327:                incr += t2-t1 + f1-f2;
        !           328: }
        !           329: 
        !           330: /*
        !           331:  * Output a set of appended lines.
        !           332:  * Append after `f' the lines in
        !           333:  * range `t1,t2'.
        !           334:  */
        !           335: append(f, t1, t2)
        !           336: unsigned f, t1, t2;
        !           337: {
        !           338:        f--;
        !           339:        if (csymbol != NULL)
        !           340:                printf("#ifdef %s\n", csymbol);
        !           341:        else if (nflag)
        !           342:                printf("a%u %u\n", f+incr, t2-t1+1);
        !           343:        else {
        !           344:                prange(f, f);
        !           345:                if (sflag)
        !           346:                        putchar('a');
        !           347:                else if (eflag) {
        !           348:                        fputs("a\n", stdout);
        !           349:                } else {
        !           350:                        fputs(" a ", stdout);
        !           351:                        prange(t1, t2);
        !           352:                        putchar('\n');
        !           353:                }
        !           354:        }
        !           355:        if (rflag)
        !           356:                incr += t2-t1+1;
        !           357: }
        !           358: 
        !           359: /*
        !           360:  * Output a set of deleted lines.
        !           361:  * Delete range `f1,f2' (other file
        !           362:  * number is `t'.
        !           363:  */
        !           364: delete(f1, f2, t)
        !           365: unsigned f1, f2, t;
        !           366: {
        !           367:        if (csymbol != NULL)
        !           368:                printf("#ifndef %s\n", csymbol);
        !           369:        else if (nflag)
        !           370:                printf("d%u %u\n", f1+incr, f2-f1+1);
        !           371:        else {
        !           372:                prange(f1, f2);
        !           373:                if (eflag)
        !           374:                        fputs("d\n", stdout);
        !           375:                else
        !           376:                        printf(" d %u\n", t-1);
        !           377:        }
        !           378:        if (rflag)
        !           379:                incr -= f2-f1+1;
        !           380: }
        !           381: 
        !           382: /*
        !           383:  * Output the middle of a set of
        !           384:  * changed lines.
        !           385:  */
        !           386: prsep()
        !           387: {
        !           388:        if (!sepflag)
        !           389:                return;
        !           390:        sepflag = 0;
        !           391:        if (csymbol != NULL)
        !           392:                fputs("#else\n", stdout);
        !           393:        else if (!eflag)
        !           394:                fputs("---\n", stdout);
        !           395: }
        !           396: 
        !           397: /*
        !           398:  * Output the end part of a set
        !           399:  * of changed lines.
        !           400:  */
        !           401: prend()
        !           402: {
        !           403:        if (csymbol != NULL)
        !           404:                fputs("#endif\n", stdout);
        !           405:        else if (caflag) {
        !           406:                if (sflag)
        !           407:                        putchar('\n');
        !           408:                else if (eflag && !nflag)
        !           409:                        fputs(".\n", stdout);
        !           410:        }
        !           411:        caflag = 0;
        !           412: }
        !           413: 
        !           414: /*
        !           415:  * Print a line range either in the form
        !           416:  * `a,b' or `a' (if a==b).
        !           417:  */
        !           418: prange(a, b)
        !           419: register unsigned a, b;
        !           420: {
        !           421:        a += incr;
        !           422:        b += incr;
        !           423:        if (a == b)
        !           424:                printf("%u", a);
        !           425:        else
        !           426:                printf("%u,%u", a, b);
        !           427: }
        !           428: 
        !           429: /*
        !           430:  * Exit, removing any possible temmpfiles.
        !           431:  */
        !           432: rmexit(s)
        !           433: {
        !           434:        if (tmpnam1 != NULL)
        !           435:                unlink(tmpnam1);
        !           436:        if (tmpnam2 != NULL)
        !           437:                unlink(tmpnam2);
        !           438:        exit(s);
        !           439: }
        !           440: 
        !           441: /*
        !           442:  * Catch signal and exit.
        !           443:  */
        !           444: catchsig()
        !           445: {
        !           446:        rmexit(2);
        !           447: }
        !           448: usage()
        !           449: {
        !           450:        fprintf(stderr, "Usage: diff [-bdefhns] [-c symbol] file1 file2\n");
        !           451:        exit(2);
        !           452: }
        !           453: 
        !           454: /* VARARGS */
        !           455: cerr(x)
        !           456: {
        !           457:        fprintf(stderr, "diff: %r\n", &x);
        !           458:        exit(2);
        !           459: }

unix.superglobalmegacorp.com

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