xref: /minix/minix/commands/fix/fix.c (revision 83133719)
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