Annotation of coherent/d/bin/diff/diff2.c, revision 1.1.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.