1 /* fix file difflist - update file from difflist Author: Erik Baalbergen */ 2 /* Change all K&R-style functions declarations to ANSI-style 3 declarations - Author: Alexandre Beletti (rhiguita@gmail.com) */ 4 5 /* Notes: files old and old.patch are equal after the following commands 6 diff old new > difflist 7 patch old difflist > old.patch 8 * the diff output is assumed to be produced by my diff program. 9 * the difflist has the following form: 10 difflist ::= chunk* 11 chunk ::= append | delete | change ; 12 append ::= n1 'a' n2 [',' n3]? '\n' ['> ' line '\n'](n3 - n2 + 1) 13 delete ::= n1 [',' n2]? 'd' n3 '\n' ['< ' line '\n'](n2 - n1 + 1) 14 change ::= n1 [',' n2]? 'c' n3 [',' n4]? '\n' 15 ['< ' line '\n'](n2 - n1 + 1) 16 '---\n' 17 ['> ' line '\n'](n4 - n3 + 1) 18 where 19 - n[1234] is an unsigned integer 20 - "[pat](expr)" means "(expr) occurences of pat" 21 - "[pat]?" means "either pat or nothing" 22 * the information in the diff listing is checked against the file to which 23 it is applied; an error is printed if there is a conflict 24 */ 25 26 #include <ctype.h> 27 #include <stdarg.h> 28 #include <stdlib.h> 29 #include <string.h> 30 #include <stdio.h> 31 32 #define IGNORE_WHITE_SPACE /* This makes it white space insensitive */ 33 34 #ifdef IGNORE_WHITE_SPACE 35 #define strcmp strwcmp 36 #endif 37 38 #define LINELEN 1024 39 40 char *prog = 0, *processing = 0; 41 42 /* getline() already declared in stdio.h */ 43 #define getline fix_getline 44 char *getline(FILE *fp, char *b); 45 char *range(char *s, int *p1, int *p2); 46 int getcommand(FILE *fp, int *o1, int *o2, char *pcmd, int *n1, int 47 *n2); 48 void fatal(const char *s, ...); 49 int strwcmp(char *s1, char *s2); 50 int whitespace(char ch); 51 52 char * 53 getline(FILE *fp, char *b) 54 { 55 if (fgets(b, LINELEN, fp) == NULL) fatal("unexpected eof"); 56 57 return b; 58 } 59 60 #define copy(str) printf("%s", str) 61 62 int main(int argc, char **argv) 63 { 64 char cmd, *fl, *fd, obuf[LINELEN], nbuf[LINELEN]; 65 int o1, o2, n1, n2, here; 66 FILE *fpf, *fpd; 67 68 prog = argv[0]; 69 processing = argv[1]; 70 if (argc != 3) fatal("use: %s original-file diff-list-file", prog); 71 if ((fpf = fopen(argv[1], "r")) == NULL) fatal("can't read %s", argv[1]); 72 if ((fpd = fopen(argv[2], "r")) == NULL) fatal("can't read %s", argv[2]); 73 here = 0; 74 while (getcommand(fpd, &o1, &o2, &cmd, &n1, &n2)) { 75 while (here < o1 - 1) { 76 here++; 77 copy(getline(fpf, obuf)); 78 } 79 switch (cmd) { 80 case 'c': 81 case 'd': 82 if (cmd == 'd' && n1 != n2) fatal("delete count conflict"); 83 while (o1 <= o2) { 84 fl = getline(fpf, obuf); 85 here++; 86 fd = getline(fpd, nbuf); 87 if (strncmp(fd, "<", (size_t)1)) 88 fatal("illegal delete line"); 89 if (strcmp(fl, fd + 2)) 90 fatal("delete line conflict"); 91 o1++; 92 } 93 if (cmd == 'd') break; 94 if (strcmp(getline(fpd, nbuf), "---\n")) 95 fatal("illegal separator in chunk"); 96 /* FALLTHROUGH */ 97 case 'a': 98 if (cmd == 'a') { 99 if (o1 != o2) fatal("append count conflict"); 100 copy(getline(fpf, obuf)); 101 here++; 102 } 103 while (n1 <= n2) { 104 if (strncmp(getline(fpd, nbuf), ">", (size_t)1)) 105 fatal("illegal append line"); 106 copy(nbuf + 2); 107 n1++; 108 } 109 break; 110 } 111 } 112 while (fgets(obuf, LINELEN, fpf) != NULL) copy(obuf); 113 return(0); 114 } 115 116 char * 117 range(char *s, int *p1, int *p2) 118 { 119 register int v1 = 0, v2; 120 121 while (isdigit(*s)) v1 = 10 * v1 + *s++ - '0'; 122 v2 = v1; 123 if (*s == ',') { 124 s++; 125 v2 = 0; 126 while (isdigit(*s)) v2 = 10 * v2 + *s++ - '0'; 127 } 128 if (v1 > v2) fatal("illegal range"); 129 *p1 = v1; 130 *p2 = v2; 131 return s; 132 } 133 134 int getcommand(FILE *fp, int *o1, int *o2, char *pcmd, int *n1, int *n2) 135 { 136 char buf[LINELEN]; 137 register char *s; 138 char cmd; 139 140 if ((s = fgets(buf, LINELEN, fp)) == NULL) return 0; 141 s = range(s, o1, o2); 142 if ((cmd = *s++) != 'a' && cmd != 'c' && cmd != 'd') 143 fatal("illegal command"); 144 s = range(s, n1, n2); 145 if (*s != '\n' && s[1] != '\0') 146 fatal("extra characters at end of command: %s", s); 147 *pcmd = cmd; 148 return 1; 149 } 150 151 #ifdef __STDC__ 152 void fatal(const char *s, ...) 153 { 154 va_list args; 155 156 va_start (args, s); 157 fprintf(stderr, "%s: processing: %s fatal: ", prog, processing); 158 vfprintf(stderr, s, args); 159 fprintf(stderr, "\n"); 160 va_end(args); 161 exit(1); 162 } 163 #else 164 /* the K&R lib does not have vfprintf */ 165 void fatal(const char *s, const char *a) 166 { 167 fprintf(stderr, "%s: processing: %s fatal: ", prog, processing); 168 fprintf(stderr, s, a); 169 fprintf(stderr, "\n"); 170 exit(1); 171 } 172 #endif 173 174 #ifdef IGNORE_WHITE_SPACE 175 176 /* This routine is a white space insensitive version of strcmp. 177 It is needed for testing things which might have undergone 178 tab conversion or trailing space removal 179 Bret Mckee June, 1988 */ 180 181 int strwcmp(char *s1, char *s2) 182 { 183 char *x1 = s1, *x2 = s2; 184 185 /* Remove leading white space */ 186 while (whitespace(*s1)) s1++; 187 while (whitespace(*s2)) s2++; 188 do { 189 while ((*s1 == *s2) && *s1 && *s2) { 190 s1++; 191 s2++; 192 } 193 ; /* consume identical characters */ 194 while (whitespace(*s1)) s1++; 195 while (whitespace(*s2)) s2++; 196 } while (*s1 && *s2 && (*s1 == *s2)); 197 if (*s1 - *s2) 198 fprintf(stderr, "Failing for (%x)[%s]\n (%x)[%s]\n", 199 (int) *s1, x1, (int) *s2, x2); 200 return(*s1 - *s2); 201 } 202 203 int whitespace(char ch) 204 { 205 switch (ch) { 206 case ' ': 207 case '\n': 208 case 0x0D: 209 case '\t': 210 return(1); 211 default: return(0); 212 } 213 } 214 215 #endif 216