Annotation of coherent/d/bin/diff/diffh.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Half-hearted version of diff (doesn't
                      3:  * use the complicated algorithm).
                      4:  * This algorithm works on arbitrary files
                      5:  * but is only intended where changes are
                      6:  * minimal and well-spaced.  There is another
                      7:  * algorithm which also takes space but is at
                      8:  * least guaranteed to be linear in time and space (unlike
                      9:  * Least Common Subsequence) and sometimes produces
                     10:  * more realistic results (and sometimes it doesn't)
                     11:  * Consult: "A Technique for Isolating Diffeences between
                     12:  * Files", Paul Heckel, CACM, November 1978.
                     13:  * This shares code with the normal
                     14:  * diff though.
                     15:  */
                     16: 
                     17: #include "diff.h"
                     18: 
                     19: #define        NPEND   200             /* Default # pending lines */
                     20: #define        NMATCH  2               /* Minimum lines in a row to have a match */
                     21: 
                     22: /*
                     23:  * Structure for each line 
                     24:  * This is referenced by the
                     25:  * structure for each file
                     26:  * below.
                     27:  */
                     28: typedef        struct  LINE {
                     29:        unsigned        l_num;          /* Line number */
                     30:        struct LINE     *l_next;        /* Pointer for ungetting lines */
                     31:        char    l_text[];               /* Data of line */
                     32: }      LINE;
                     33: 
                     34: /*
                     35:  * Structure of pending lines
                     36:  * and ungot lines stored for
                     37:  * each of the input files.
                     38:  */
                     39: typedef        struct  PENDING {
                     40:        FILE    *p_fp;          /* I/O stream for input */
                     41:        int     p_eof;          /* Reached EOF on this input */
                     42:        char    *p_fn;          /* File name */
                     43:        LINE    *p_master;      /* Master input buffer */
                     44:        LINE    *p_work;        /* Current working line */
                     45:        LINE    *p_ungot;       /* Ungot lines */
                     46:        LINE    *p_lines[NPEND]; /* Pending lines */
                     47: }      PENDING;
                     48: 
                     49: PENDING        p1, p2;
                     50: 
                     51: LINE   *lcopy();
                     52: 
                     53: /*
                     54:  * A NOP routine so that diff()
                     55:  * gets invoked.
                     56:  */
                     57: /* ARGSUSED */
                     58: diffh(args)
                     59: char **args;
                     60: {
                     61: }
                     62: 
                     63: /*
                     64:  * The actual code to produce list
                     65:  * of differences by a stupider
                     66:  * (but cheaper) algorithm.
                     67:  */
                     68: diff(fp1, fp2)
                     69: FILE *fp1;
                     70: FILE *fp2;
                     71: {
                     72:        register int top, bot;
                     73:        register int i;
                     74: 
                     75:        p1.p_master = p1.p_work = (LINE *)alloc(sizeof(LINE) + LSIZE);
                     76:        p2.p_master = p2.p_work = (LINE *)alloc(sizeof(LINE) + LSIZE);
                     77:        p1.p_fp = fp1;
                     78:        p2.p_fp = fp2;
                     79:        p1.p_fn = fn1;
                     80:        p2.p_fn = fn2;
                     81:        while (lget(&p1) | lget(&p2)) {
                     82:                register char *s1, *s2;
                     83: 
                     84:                s1 = p1.p_work->l_text;
                     85:                s2 = p2.p_work->l_text;
                     86:                if (*s1=='\0' && *s2=='\0')
                     87:                        continue;
                     88:                if ((*equal)(s1, s2)) {
                     89:                        text(s1);
                     90:                        continue;
                     91:                }
                     92:                top = 0;
                     93:                lpend(&p1, top);
                     94:                lpend(&p2, top++);
                     95:                do {
                     96:                        if (top >= NPEND)
                     97:                                cerr("Out of memory, lines %d and %d",
                     98:                                    p1.p_lines[0]->l_num, p2.p_lines[0]->l_num);
                     99:                        /*
                    100:                         * Not checked, lget has
                    101:                         * to stop going over EOF
                    102:                         * by itself.
                    103:                         */
                    104:                        lget(&p1);
                    105:                        lget(&p2);
                    106:                        lpend(&p1, top);
                    107:                        lpend(&p2, top++);
                    108:                        bot = top-NMATCH;
                    109:                        for (i=0; i<bot; i++) {
                    110:                                if (lsearch(i, bot)) {
                    111:                                        lunget(&p1, i+NMATCH, top);
                    112:                                        break;
                    113:                                }
                    114:                                if (lsearch(bot, i)) {
                    115:                                        lunget(&p2, i+NMATCH, top);
                    116:                                        break;
                    117:                                }
                    118:                        }
                    119:                } while (i>bot || i==bot && !lsearch(i, i));
                    120:        }
                    121: }
                    122: 
                    123: /*
                    124:  * Get a line and put it into the current
                    125:  * working position.
                    126:  * Return 0 at EOF.
                    127:  */
                    128: lget(pp)
                    129: register PENDING *pp;
                    130: {
                    131:        if (pp->p_master != pp->p_work)
                    132:                free(pp->p_work);
                    133:        if (pp->p_ungot != NULL) {
                    134:                pp->p_work = pp->p_ungot;
                    135:                pp->p_ungot = pp->p_ungot->l_next;
                    136:                return (1);
                    137:        }
                    138:        pp->p_work = pp->p_master;
                    139:        return (lgets(pp));
                    140: }
                    141: 
                    142: /*
                    143:  * Unget pending lines between
                    144:  * `beg' and `end' that are
                    145:  * not already dealt with.
                    146:  */
                    147: lunget(pp, beg, end)
                    148: register PENDING *pp;
                    149: register int beg, end;
                    150: {
                    151:        while (--end >= beg) {
                    152:                pp->p_lines[end]->l_next = pp->p_ungot;
                    153:                pp->p_ungot = pp->p_lines[end];
                    154:                pp->p_lines[end] = NULL;
                    155:        }
                    156: }
                    157: 
                    158: /*
                    159:  * Copy a line to a new (allocated)
                    160:  * line space.
                    161:  */
                    162: LINE *
                    163: lcopy(lp)
                    164: register LINE *lp;
                    165: {
                    166:        register LINE *rlp;
                    167:        register char *cp;
                    168: 
                    169:        for (cp = lp->l_text; *cp != '\0'; cp++)
                    170:                ;
                    171:        rlp = (LINE *)alloc(cp-lp->l_text+1 + sizeof(LINE));
                    172:        rlp->l_num = lp->l_num;
                    173:        rlp->l_next = NULL;
                    174:        strcpy(rlp->l_text, lp->l_text);
                    175:        return (rlp);
                    176: }
                    177: 
                    178: /*
                    179:  * Save line away in a pending line
                    180:  * position, specified by `pos'.
                    181:  */
                    182: lpend(pp, pos)
                    183: register PENDING *pp;
                    184: register int pos;
                    185: {
                    186:        if (pp->p_lines[pos] != NULL)
                    187:                free(pp->p_lines[pos]);
                    188:        if (pp->p_master != pp->p_work) {
                    189:                pp->p_lines[pos] = pp->p_work;
                    190:                pp->p_work = pp->p_master;
                    191:        } else
                    192:                pp->p_lines[pos] = lcopy(pp->p_work);
                    193: }
                    194: 
                    195: /*
                    196:  * Read a string from input (specified
                    197:  * by the PENDING pointer) and throw away
                    198:  * partial lines.
                    199:  */
                    200: lgets(pp)
                    201: register PENDING *pp;
                    202: {
                    203:        register int c;
                    204:        register char *s;
                    205:        register unsigned lim = LSIZE;
                    206: 
                    207:        s = pp->p_master->l_text;
                    208:        if (pp->p_eof) {
                    209:                *s = '\0';
                    210:                return (0);
                    211:        }
                    212:        while (--lim > 0 && (c = getc(pp->p_fp)) != EOF)
                    213:                if ((*s++ = c) == '\n')
                    214:                        break;
                    215:        *s = '\0';
                    216:        if (c == EOF) {
                    217:                if (s != pp->p_master->l_text)
                    218:                        fprintf(stderr, "diff: partial line omitted from %s\n",
                    219:                            pp->p_fn);
                    220:                pp->p_eof++;
                    221:                return (0);
                    222:        }
                    223:        pp->p_master->l_num++;
                    224:        return (1);
                    225: }
                    226: 
                    227: /*
                    228:  * Search for a match in the pending lines.
                    229:  * The two parameters are `pos1' and `pos2'
                    230:  * for the position to start searching in
                    231:  * file1 and file2, respectively.  The
                    232:  * search looks for at least NMATCH lines.
                    233:  */
                    234: lsearch(pos1, pos2)
                    235: int pos1;
                    236: int pos2;
                    237: {
                    238:        register LINE **lpp1, **lpp2;
                    239:        register int i;
                    240:        register char *s1, *s2;
                    241:        register int ln11, ln12, ln21, ln22;
                    242: 
                    243:        lpp1 = &p1.p_lines[pos1];
                    244:        lpp2 = &p2.p_lines[pos2];
                    245:        /*
                    246:         * Empty strings are actually
                    247:         * dummies for after EOF.
                    248:         */
                    249:        for (i=0; i<NMATCH; i++) {
                    250:                s1 = lpp1[i]->l_text;
                    251:                s2 = lpp2[i]->l_text;
                    252:                if (*s1!='\0' || *s2!='\0')
                    253:                        if (!(*equal)(s1, s2))
                    254:                                break;
                    255:        }
                    256:        if (i < NMATCH)
                    257:                return (0);
                    258:        lpp1 = p1.p_lines;
                    259:        lpp2 = p2.p_lines;
                    260:        ln11 = lpp1[0]->l_num;
                    261:        ln12 = lpp1[pos1-1]->l_num;
                    262:        ln21 = lpp2[0]->l_num;
                    263:        ln22 = lpp2[pos2-1]->l_num;
                    264:        if (pos1 == 0)
                    265:                append(ln11, ln21, ln22);
                    266:        else if (pos2 == 0)
                    267:                delete(ln11, ln12, ln21);
                    268:        else
                    269:                change(ln11, ln12, ln21, ln22);
                    270:        for (i = 0; i < pos1; i++)
                    271:                text1(lpp1[i]->l_text);
                    272:        prsep();
                    273:        for (i = 0; i < pos2; i++)
                    274:                text2(lpp2[i]->l_text);
                    275:        prend();
                    276:        for (i=0; i<NMATCH; i++)
                    277:                if (*(s1 = lpp1[i+pos1]->l_text) != '\0')
                    278:                        text(s1);
                    279:        return (1);
                    280: }
                    281: 
                    282: /*
                    283:  * Allocator that also checks for
                    284:  * an prints a message if out of space.
                    285:  */
                    286: char *
                    287: alloc(nb)
                    288: unsigned nb;
                    289: {
                    290:        register char *rp;
                    291: 
                    292:        if ((rp = calloc(nb, 1)) == NULL)
                    293:                cerr("out of memory");
                    294:        return (rp);
                    295: }

unix.superglobalmegacorp.com

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