home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / pc / source / fix.c < prev    next >
C/C++ Source or Header  |  1989-05-02  |  4KB  |  167 lines

  1.  
  2.  
  3. /* fix - combine file and diff listing Author: Erik Baalbergen */
  4.  
  5. /* Notes:
  6.    * files old and old.fix are equal after the following commands
  7.       diff old new > difflist
  8.       fix old difflist > old.fix
  9.    * the diff output is assumed to be produced by my diff program.
  10.    * the difflist has the following form:
  11.       difflist ::= chunk*
  12.       chunk ::= append | delete | change ;
  13.       append ::= n1 'a' n2 [',' n3]? '\n' ['> ' line '\n'](n3 - n2 + 1)
  14.       delete ::= n1 [',' n2]? 'd' n3 '\n' ['< ' line '\n'](n2 - n1 + 1)
  15.       change ::= n1 [',' n2]? 'c' n3 [',' n4]? '\n'
  16.              ['< ' line '\n'](n2 - n1 + 1)
  17.              '---\n'
  18.              ['> ' line '\n'](n4 - n3 + 1)
  19.       where
  20.       - n[1234] is an unsigned integer
  21.       - "[pat](expr)" means "(expr) occurences of pat"
  22.       - "[pat]?" means "either pat or nothing"
  23.    * the information in the diff listing is checked against the file to which
  24.      it is applied; an error is printed if there is a conflict
  25. */
  26.  
  27. #include <stdio.h>
  28.  
  29. extern char *fgets();
  30. extern FILE *fopen();
  31. #define LINELEN        1024
  32.  
  33. char *prog = 0;
  34.  
  35. char *
  36. getline(fp, b)
  37.        FILE *fp;
  38.        char *b;
  39. {
  40.        if (fgets(b, LINELEN, fp) == NULL)
  41.            fatal("unexpected eof");
  42.        return b;
  43. }
  44.  
  45. #define copy(str) printf("%s", str)
  46.  
  47. main(argc, argv)
  48.        char **argv;
  49. {
  50.        char cmd, *fl, *fd, obuf[LINELEN], nbuf[LINELEN];
  51.        int o1, o2, n1, n2, here;
  52.        FILE *fpf, *fpd;
  53.  
  54.        prog = argv[0];
  55.        if (argc != 3)
  56.            fatal("use: %s original-file diff-list-file", prog);
  57.        if ((fpf = fopen(argv[1], "r")) == NULL)
  58.            fatal("can't read %s", argv[1]);
  59.        if ((fpd = fopen(argv[2], "r")) == NULL)
  60.            fatal("can't read %s", argv[2]);
  61.        here = 0;
  62.        while (getcommand(fpd, &o1, &o2, &cmd, &n1, &n2)) {
  63.            while (here < o1 - 1) {
  64.                here++;
  65.                copy(getline(fpf, obuf));
  66.            }
  67.            switch (cmd) {
  68.            case 'c':
  69.            case 'd':
  70.                if (cmd == 'd' && n1 != n2)
  71.                    fatal("delete count conflict");
  72.                while (o1 <= o2) {
  73.                    fl = getline(fpf, obuf);
  74.                    here++;
  75.                    fd = getline(fpd, nbuf);
  76.                    if (strncmp(fd, "< ", 2))
  77.                        fatal("illegal delete line");
  78.                    if (strcmp(fl, fd + 2))
  79.                        fatal("delete line conflict");
  80.                    o1++;
  81.                }
  82.                if (cmd == 'd')
  83.                    break;
  84.                if (strcmp(getline(fpd, nbuf), "---\n"))
  85.                    fatal("illegal separator in chunk");
  86.                /*FALLTHROUGH*/
  87.            case 'a':
  88.                if (cmd == 'a') {
  89.                    if (o1 != o2)
  90.                        fatal("append count conflict");
  91.                    copy(getline(fpf, obuf));
  92.                    here++;
  93.                }
  94.                while (n1 <= n2) {
  95.                    if (strncmp(getline(fpd, nbuf), "> ", 2))
  96.                        fatal("illegal append line");
  97.                    copy(nbuf + 2);
  98.                    n1++;
  99.                }
  100.                break;
  101.            }
  102.        }
  103.        while (fgets(obuf, LINELEN, fpf) != NULL)
  104.            copy(obuf);
  105.        exit(0);
  106. }
  107.  
  108. isdigit(c)
  109.        char c;
  110. {
  111.        return c >= '0' && c <= '9';
  112. }
  113.  
  114. char *
  115. range(s, p1, p2)
  116.        char *s;
  117.        int *p1, *p2;
  118. {
  119.        register int v1 = 0, v2;
  120.  
  121.        while (isdigit(*s))
  122.            v1 = 10 * v1 + *s++ - '0';
  123.        v2 = v1;
  124.        if (*s == ',') {
  125.            s++;
  126.            v2 = 0;
  127.            while (isdigit(*s))
  128.                v2 = 10 * v2 + *s++ - '0';
  129.        }
  130.        if (v1 == 0 || v2 == 0 || v1 > v2)
  131.            fatal("illegal range");
  132.        *p1 = v1;
  133.        *p2 = v2;
  134.        return s;
  135. }
  136.  
  137. getcommand(fp, o1, o2, pcmd, n1, n2)
  138.        FILE *fp;
  139.        int *o1, *o2, *n1, *n2;
  140.        char *pcmd;
  141. {
  142.        char buf[LINELEN];
  143.        register char *s;
  144.        char cmd;
  145.  
  146.        if ((s = fgets(buf, LINELEN, fp)) == NULL)
  147.            return 0;
  148.        s = range(s, o1, o2);
  149.        if ((cmd = *s++) != 'a' && cmd != 'c' && cmd != 'd')
  150.            fatal("illegal command");
  151.        s = range(s, n1, n2);
  152.        if (*s != '\n' && s[1] != '\0')
  153.            fatal("extra characters at end of command: %s", s);
  154.        *pcmd = cmd;
  155.        return 1;
  156. }
  157.  
  158. fatal(s, a)
  159.        char *s, *a;
  160. {
  161.        fprintf(stderr, "%s: fatal: ", prog);
  162.        fprintf(stderr, s, a);
  163.        fprintf(stderr, "\n");
  164.        exit(1);
  165. }
  166.  
  167.