fix.c

Go to the documentation of this file.
00001 /* fix file difflist - update file from difflist     Author: Erik Baalbergen */
00002 
00003 
00004 /* Notes: files old and old.patch are equal after the following commands
00005      diff old new > difflist
00006      patch old difflist > old.patch
00007    * the diff output is assumed to be produced by my diff program.
00008    * the difflist has the following form:
00009      difflist ::= chunk*
00010      chunk ::= append | delete | change ;
00011      append ::= n1 'a' n2 [',' n3]? '\n' ['> ' line '\n'](n3 - n2 + 1)
00012      delete ::= n1 [',' n2]? 'd' n3 '\n' ['< ' line '\n'](n2 - n1 + 1)
00013      change ::= n1 [',' n2]? 'c' n3 [',' n4]? '\n'
00014               ['< ' line '\n'](n2 - n1 + 1)
00015               '---\n'
00016               ['> ' line '\n'](n4 - n3 + 1)
00017      where
00018      - n[1234] is an unsigned integer
00019      - "[pat](expr)" means "(expr) occurences of pat"
00020      - "[pat]?" means "either pat or nothing"
00021    * the information in the diff listing is checked against the file to which
00022      it is applied; an error is printed if there is a conflict
00023 */
00024 
00025 #include <ctype.h>
00026 #include <stdarg.h>
00027 #include <stdlib.h>
00028 #include <string.h>
00029 #include <stdio.h>
00030 
00031 #define IGNORE_WHITE_SPACE      /* This makes it white space insensitive */
00032 
00033 #ifdef IGNORE_WHITE_SPACE
00034 #define strcmp strwcmp
00035 #endif
00036 
00037 #define LINELEN 1024
00038 
00039 char *prog = 0, *processing = 0;
00040 
00041 _PROTOTYPE(int main, (int argc, char **argv));
00042 _PROTOTYPE(char *getline, (FILE *fp, char *b));
00043 _PROTOTYPE(char *range, (char *s, int *p1, int *p2));
00044 _PROTOTYPE(int getcommand, (FILE *fp, int *o1, int *o2, char *pcmd, int *n1, int *n2));
00045 _PROTOTYPE(void fatal, (char *s, ...));
00046 _PROTOTYPE(int strwcmp, (char *s1, char *s2));
00047 _PROTOTYPE(int whitespace, (int ch));
00048 
00049 char *
00050  getline(fp, b)
00051 FILE *fp;
00052 char *b;
00053 {
00054   if (fgets(b, LINELEN, fp) == NULL) fatal("unexpected eof");
00055 
00056   return b;
00057 }
00058 
00059 #define copy(str) printf("%s", str)
00060 
00061 int main(argc, argv)
00062 int argc;
00063 char **argv;
00064 {
00065   char cmd, *fl, *fd, obuf[LINELEN], nbuf[LINELEN];
00066   int o1, o2, n1, n2, here;
00067   FILE *fpf, *fpd;
00068 
00069   prog = argv[0];
00070   processing = argv[1];
00071   if (argc != 3) fatal("use: %s original-file diff-list-file", prog);
00072   if ((fpf = fopen(argv[1], "r")) == NULL) fatal("can't read %s", argv[1]);
00073   if ((fpd = fopen(argv[2], "r")) == NULL) fatal("can't read %s", argv[2]);
00074   here = 0;
00075   while (getcommand(fpd, &o1, &o2, &cmd, &n1, &n2)) {
00076         while (here < o1 - 1) {
00077                 here++;
00078                 copy(getline(fpf, obuf));
00079         }
00080         switch (cmd) {
00081             case 'c':
00082             case 'd':
00083                 if (cmd == 'd' && n1 != n2) fatal("delete count conflict");
00084                 while (o1 <= o2) {
00085                         fl = getline(fpf, obuf);
00086                         here++;
00087                         fd = getline(fpd, nbuf);
00088                         if (strncmp(fd, "<", (size_t)1))
00089                                 fatal("illegal delete line");
00090                         if (strcmp(fl, fd + 2))
00091                                 fatal("delete line conflict");
00092                         o1++;
00093                 }
00094                 if (cmd == 'd') break;
00095                 if (strcmp(getline(fpd, nbuf), "---\n"))
00096                         fatal("illegal separator in chunk");
00097                 /* FALLTHROUGH */
00098             case 'a':
00099                 if (cmd == 'a') {
00100                         if (o1 != o2) fatal("append count conflict");
00101                         copy(getline(fpf, obuf));
00102                         here++;
00103                 }
00104                 while (n1 <= n2) {
00105                         if (strncmp(getline(fpd, nbuf), ">", (size_t)1))
00106                                 fatal("illegal append line");
00107                         copy(nbuf + 2);
00108                         n1++;
00109                 }
00110                 break;
00111         }
00112   }
00113   while (fgets(obuf, LINELEN, fpf) != NULL) copy(obuf);
00114   return(0);
00115 }
00116 
00117 char *
00118  range(s, p1, p2)
00119 char *s;
00120 int *p1, *p2;
00121 {
00122   register int v1 = 0, v2;
00123 
00124   while (isdigit(*s)) v1 = 10 * v1 + *s++ - '0';
00125   v2 = v1;
00126   if (*s == ',') {
00127         s++;
00128         v2 = 0;
00129         while (isdigit(*s)) v2 = 10 * v2 + *s++ - '0';
00130   }
00131   if (v1 > v2) fatal("illegal range");
00132   *p1 = v1;
00133   *p2 = v2;
00134   return s;
00135 }
00136 
00137 int getcommand(fp, o1, o2, pcmd, n1, n2)
00138 FILE *fp;
00139 int *o1, *o2, *n1, *n2;
00140 char *pcmd;
00141 {
00142   char buf[LINELEN];
00143   register char *s;
00144   char cmd;
00145 
00146   if ((s = fgets(buf, LINELEN, fp)) == NULL) return 0;
00147   s = range(s, o1, o2);
00148   if ((cmd = *s++) != 'a' && cmd != 'c' && cmd != 'd')
00149         fatal("illegal command");
00150   s = range(s, n1, n2);
00151   if (*s != '\n' && s[1] != '\0')
00152         fatal("extra characters at end of command: %s", s);
00153   *pcmd = cmd;
00154   return 1;
00155 }
00156 
00157 #ifdef __STDC__
00158 void fatal(char *s, ...)
00159 {
00160   va_list args;
00161 
00162   va_start (args, s);
00163   fprintf(stderr, "%s: processing: %s fatal: ", prog, processing);
00164   vfprintf(stderr, s, args);
00165   fprintf(stderr, "\n");
00166   va_end(args);
00167   exit(1);
00168 }
00169 #else
00170 /* the K&R lib does not have vfprintf */
00171 void fatal(s, a)
00172 char *s, *a;
00173 {
00174   fprintf(stderr, "%s: processing: %s fatal: ", prog, processing);
00175   fprintf(stderr, s, a);
00176   fprintf(stderr, "\n");
00177   exit(1);
00178 }
00179 #endif
00180 
00181 #ifdef IGNORE_WHITE_SPACE
00182 
00183 /* This routine is a white space insensitive version of strcmp.
00184    It is needed for testing things which might have undergone
00185    tab conversion or trailing space removal
00186    Bret Mckee June, 1988 */
00187 
00188 int strwcmp(s1, s2)
00189 char *s1, *s2;
00190 {
00191   char *x1 = s1, *x2 = s2;
00192 
00193   /* Remove leading white space */
00194   while (whitespace(*s1)) s1++;
00195   while (whitespace(*s2)) s2++;
00196   do {
00197         while ((*s1 == *s2) && *s1 && *s2) {
00198                 s1++;
00199                 s2++;
00200         }
00201         ;                       /* consume identical characters */
00202         while (whitespace(*s1)) s1++;
00203         while (whitespace(*s2)) s2++;
00204   } while (*s1 && *s2 && (*s1 == *s2));
00205   if (*s1 - *s2)
00206         fprintf(stderr, "Failing for (%x)[%s]\n            (%x)[%s]\n",
00207                 (int) *s1, x1, (int) *s2, x2);
00208   return(*s1 - *s2);
00209 }
00210 
00211 int whitespace(ch)
00212 char ch;
00213 {
00214   switch (ch) {
00215       case ' ':
00216       case '\n':
00217       case 0x0D:
00218       case '\t':
00219         return(1);
00220       default:  return(0);
00221 }
00222 }
00223 
00224 #endif

Generated on Fri Apr 14 22:57:06 2006 for minix by  doxygen 1.4.6