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

unix.superglobalmegacorp.com

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