1 | /* |
2 | * This Source Code Form is subject to the terms of the Mozilla Public |
3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
5 | * |
6 | * Copyright 1997 - July 2008 CWI, August 2008 - 2019 MonetDB B.V. |
7 | */ |
8 | |
9 | #include "monetdb_config.h" |
10 | #include "helpers.h" |
11 | #include "difflib.h" |
12 | |
13 | #include <string.h> |
14 | #include <sys/types.h> |
15 | #include <sys/stat.h> |
16 | #include <fcntl.h> |
17 | #include <ctype.h> |
18 | #ifdef HAVE_UNISTD_H |
19 | # include <unistd.h> |
20 | #endif |
21 | #ifdef HAVE_IO_H |
22 | # include <io.h> |
23 | #endif |
24 | #include <time.h> |
25 | |
26 | #ifdef NATIVE_WIN32 |
27 | #include <windows.h> |
28 | #define DIFF "diff" /* --binary */ |
29 | #define COPY "copy /y" /* "cp -f" */ |
30 | #define popen _popen |
31 | #define pclose _pclose |
32 | |
33 | #ifndef DIR_SEP |
34 | # define DIR_SEP '\\' |
35 | #endif |
36 | |
37 | #define getpid _getpid |
38 | #else |
39 | #ifndef DIFF |
40 | #define DIFF "diff" |
41 | #endif |
42 | |
43 | #ifndef DIR_SEP |
44 | # define DIR_SEP '/' |
45 | #endif |
46 | #endif |
47 | |
48 | #ifdef DEBUG |
49 | #define UNLINK(x) |
50 | #define ERRHNDL(r,s,t,u) ErrXit(s,t,u) |
51 | #else |
52 | #define UNLINK(x) remove(x) |
53 | #define ERRHNDL(r,s,t,u) return r |
54 | #endif |
55 | |
56 | #define SETBLACK(f) if(clr[f]!=0 ) { fprintf(clmn_fp[f],"</span>"); clr[f]=0; } |
57 | #define SETBLUE(f,m) if(clr[f]!=3-m) { if (clr[f]) fprintf(clmn_fp[f], "</span>"); fprintf(clmn_fp[f],"<span class='%sblue'>",(m?"light":"")); clr[f]=3-m; } |
58 | #define SETRED(f,m) if(clr[f]!=5-m) { if (clr[f]) fprintf(clmn_fp[f], "</span>"); fprintf(clmn_fp[f],"<span class='%sred'>",(m?"light":"")); clr[f]=5-m; } |
59 | #define SETPINK(f,m) if(clr[f]!=7-m) { if (clr[f]) fprintf(clmn_fp[f], "</span>"); fprintf(clmn_fp[f],"<span class='%spink'>",(m?"light":"")); clr[f]=7-m; } |
60 | |
61 | #define CMDLEN 8192 |
62 | #define BUFLEN 16384 |
63 | #define BUFLEN2 32768 |
64 | |
65 | static char * |
66 | HTMLsave(char *s) |
67 | { |
68 | static char t[BUFLEN2]; |
69 | char *p = t; |
70 | |
71 | while (*s && p < t + BUFLEN2 - 7) { |
72 | switch (*s) { |
73 | case '<': |
74 | *p++ = '&'; |
75 | *p++ = 'l'; |
76 | *p++ = 't'; |
77 | *p++ = ';'; |
78 | break; |
79 | case '>': |
80 | *p++ = '&'; |
81 | *p++ = 'g'; |
82 | *p++ = 't'; |
83 | *p++ = ';'; |
84 | break; |
85 | case '&': |
86 | *p++ = '&'; |
87 | *p++ = 'a'; |
88 | *p++ = 'm'; |
89 | *p++ = 'p'; |
90 | *p++ = ';'; |
91 | break; |
92 | default: |
93 | *p++ = *s; |
94 | break; |
95 | } |
96 | s++; |
97 | } |
98 | *p++ = 0; |
99 | |
100 | return t; |
101 | } |
102 | |
103 | |
104 | static void |
105 | markNL(FILE *fp, int k) |
106 | { |
107 | int i; |
108 | |
109 | for (i = 0; i < 6; i++) |
110 | fprintf(fp, "@+-%06i\n" , k); |
111 | } |
112 | |
113 | |
114 | FILE * |
115 | oldnew2u_diff(int mindiff, int context, char *ignore, char *function, char *old_fn, char *new_fn) |
116 | { |
117 | char command[CMDLEN]; |
118 | char *_d = mindiff ? "-d" : "" ; |
119 | |
120 | TRACE(fprintf(STDERR, "oldnew2u_diff(%i,%i,%s,%s,%s,%s)\n" , mindiff, context, ignore, function, old_fn, new_fn)); |
121 | |
122 | snprintf(command, sizeof(command), "%s %s %s -a %s -U%d %s %s" , DIFF, ignore, function, _d, context, old_fn, new_fn); |
123 | return popen(command, "r" ); |
124 | } |
125 | |
126 | /* oldnew2u_diff */ |
127 | |
128 | |
129 | int |
130 | u_diff2l_diff(FILE *u_diff_fp, char *l_diff_fn) |
131 | { |
132 | FILE *l_diff_fp; |
133 | char *ok, line[BUFLEN]; |
134 | |
135 | TRACE(fprintf(STDERR, "u_diff2l_diff(%p,%s)\n" , u_diff_fp, l_diff_fn)); |
136 | |
137 | if (!(ok = fgets(line, BUFLEN, u_diff_fp))) { |
138 | pclose(u_diff_fp); |
139 | ERRHNDL(0, "empty file in u_diff2l_diff:" , "pipe" , 1); |
140 | } |
141 | |
142 | l_diff_fp = Wfopen(l_diff_fn); |
143 | while (ok && strncmp(line, "@@ -" , 4)) { |
144 | fprintf(l_diff_fp, "%s" , line); |
145 | ok = fgets(line, BUFLEN, u_diff_fp); |
146 | } |
147 | while (ok) { |
148 | do { |
149 | fprintf(l_diff_fp, "%s" , line); |
150 | } while (line[strlen(line) - 1] != '\n' && (ok = fgets(line, BUFLEN, u_diff_fp))); |
151 | while (ok && (ok = fgets(line, BUFLEN, u_diff_fp)) && strchr(" -+" , line[0])) { |
152 | char l0 = line[0]; |
153 | if (line[1] == '\n') |
154 | snprintf(line + 1, sizeof(line) - 1, "\2\n" ); |
155 | do { |
156 | fprintf(l_diff_fp, "%s" , line); |
157 | } while (line[strlen(line) - 1] != '\n' && (ok = fgets(line, BUFLEN, u_diff_fp))); |
158 | fprintf(l_diff_fp, "%c\1\n" , l0); |
159 | } |
160 | } |
161 | fflush(l_diff_fp); |
162 | fclose(l_diff_fp); |
163 | |
164 | pclose(u_diff_fp); |
165 | return 1; |
166 | } |
167 | |
168 | /* u_diff2l_diff */ |
169 | |
170 | |
171 | static int |
172 | lw_diff2wc_diff(int mindiff, int doChar, char *lw_diff_fn, char *wc_diff_fn) |
173 | { |
174 | FILE *lw_diff_fp, *wc_diff_fp, *fp[2], *pipe_fp; |
175 | char line[BUFLEN], command[CMDLEN], pipe_ln[BUFLEN]; |
176 | char *ok, *fn[2]; |
177 | size_t i; |
178 | int j; |
179 | int space, alpha_, digit, l[2], k[2]; |
180 | char wc_old_fn[CMDLEN], wc_new_fn[CMDLEN]; |
181 | char *_d = mindiff ? "-d" : "" ; |
182 | |
183 | TRACE(fprintf(STDERR, "lw_diff2wc_diff(%i,%i,%s,%s)\n" , mindiff, doChar, lw_diff_fn, wc_diff_fn)); |
184 | |
185 | lw_diff_fp = Rfopen(lw_diff_fn); |
186 | if (!(ok = fgets(line, BUFLEN, lw_diff_fp))) { |
187 | fclose(lw_diff_fp); |
188 | ERRHNDL(0, "empty file in lw_diff2wc_diff:" , lw_diff_fn, 1); |
189 | } |
190 | |
191 | snprintf(wc_old_fn, sizeof(wc_old_fn), "%s%c.difflib-%ld-lw_diff2wc_diff-old" , tmpdir(), DIR_SEP, (long) getpid()); |
192 | fn[0] = wc_old_fn; |
193 | snprintf(wc_new_fn, sizeof(wc_new_fn), "%s%c.difflib-%ld-lw_diff2wc_diff-new" , tmpdir(), DIR_SEP, (long) getpid()); |
194 | fn[1] = wc_new_fn; |
195 | |
196 | wc_diff_fp = Wfopen(wc_diff_fn); |
197 | while (ok && strncmp(line, "@@ -" , 4)) { |
198 | fprintf(wc_diff_fp, "%s" , line); |
199 | ok = fgets(line, BUFLEN, lw_diff_fp); |
200 | } |
201 | fflush(wc_diff_fp); |
202 | fclose(wc_diff_fp); |
203 | |
204 | while (ok) { |
205 | wc_diff_fp = Afopen(wc_diff_fn); |
206 | do { |
207 | fprintf(wc_diff_fp, "%s" , line); |
208 | } while (line[strlen(line) - 1] != '\n' && (ok = fgets(line, BUFLEN, lw_diff_fp))); |
209 | fflush(wc_diff_fp); |
210 | fclose(wc_diff_fp); |
211 | |
212 | l[0] = l[1] = k[0] = k[1] = 0; |
213 | for (j = 0; j < 2; j++) |
214 | fp[j] = Wfopen(fn[j]); |
215 | while (ok && (ok = fgets(line, BUFLEN, lw_diff_fp)) && strchr(" -+" , line[0])) { |
216 | if (line[0] == ' ') { |
217 | char l1 = line[1]; |
218 | while (k[0] < k[1]) { |
219 | markNL(fp[0], k[0]++); |
220 | l[0]++; |
221 | } |
222 | while (k[1] < k[0]) { |
223 | markNL(fp[1], k[1]++); |
224 | l[1]++; |
225 | } |
226 | i = 1; |
227 | do { |
228 | for (j = 0; j < 2; j++) { |
229 | fprintf(fp[j], "%s" , line+i); |
230 | } |
231 | i = 0; |
232 | } while (line[strlen(line) - 1] != '\n' && (ok = fgets(line, BUFLEN, lw_diff_fp))); |
233 | for (j = 0; j < 2; j++) { |
234 | l[j]++; |
235 | } |
236 | if (l1 == '\1') |
237 | for (j = 0; j < 2; j++) { |
238 | markNL(fp[j], k[j]++); |
239 | l[j]++; |
240 | } |
241 | } else { |
242 | if (line[0] == '-') |
243 | j = 0; |
244 | else |
245 | j = 1; |
246 | if (line[1] == '\1') { |
247 | fprintf(fp[j], "\1\n" ); |
248 | markNL(fp[j], k[j]++); |
249 | l[j] += 2; |
250 | } else if (doChar) { |
251 | i = 1; |
252 | do { |
253 | for (; line[i] != '\n' && line[i] != '\0'; i++) { |
254 | fprintf(fp[j], "%c\n" , line[i]); |
255 | l[j]++; |
256 | } |
257 | i = 0; |
258 | } while (line[strlen(line) - 1] != '\n' && (ok = fgets(line, BUFLEN, lw_diff_fp))); |
259 | } else { |
260 | space = isspace((unsigned char) (line[1])); |
261 | alpha_ = isalpha((unsigned char) (line[1])); |
262 | digit = isdigit((unsigned char) (line[1])); |
263 | i = 1; |
264 | do { |
265 | for (; line[i] != '\n' && line[i] != '\0'; i++) { |
266 | if ((space && !isspace((unsigned char) line[i])) || |
267 | (!space && isspace((unsigned char) line[i])) || |
268 | (alpha_ && !isalpha((unsigned char) line[i])) || |
269 | (!alpha_ && isalpha((unsigned char) line[i])) || |
270 | (digit && !isdigit((unsigned char) line[i])) || |
271 | (!digit && isdigit((unsigned char) line[i])) || |
272 | (!isspace((unsigned char) line[i]) && |
273 | !isalpha((unsigned char) line[i]) && |
274 | !isdigit((unsigned char) line[i]))) { |
275 | fprintf(fp[j], "\n" ); |
276 | space = isspace((unsigned char) line[i]); |
277 | alpha_ = isalpha((unsigned char) line[i]); |
278 | digit = isdigit((unsigned char) line[i]); |
279 | l[j]++; |
280 | } |
281 | fprintf(fp[j], "%c" , line[i]); |
282 | } |
283 | i = 0; |
284 | } while (line[strlen(line) - 1] != '\n' && (ok = fgets(line, BUFLEN, lw_diff_fp))); |
285 | fprintf(fp[j], "\n" ); |
286 | l[j]++; |
287 | } |
288 | } |
289 | } |
290 | for (j = 0; j < 2; j++) { |
291 | fflush(fp[j]); |
292 | fclose(fp[j]); |
293 | } |
294 | |
295 | /* |
296 | snprintf(command, sizeof(command), |
297 | "%s -a %s -u%i %s %s | egrep -v '^(@@ \\-|\\+\\+\\+ |\\-\\-\\- |[ \\+\\-]@\\+\\-)' >> %s", |
298 | DIFF,_d,MAX(l[0],l[1]),fn[0],fn[1],wc_diff_fn); |
299 | SYSTEM(command); |
300 | */ |
301 | |
302 | snprintf(command, sizeof(command), "%s -a %s -U%d %s %s" , DIFF, _d, MAX(l[0], l[1]), fn[0], fn[1]); |
303 | |
304 | pipe_fp = popen(command, "r" ); |
305 | |
306 | wc_diff_fp = Afopen(wc_diff_fn); |
307 | while (fgets(pipe_ln, BUFLEN, pipe_fp)) { |
308 | if (strncmp(pipe_ln, "@@ -" , 4) && |
309 | strncmp(pipe_ln, "+++ " , 4) && |
310 | strncmp(pipe_ln, "--- " , 4) && |
311 | strncmp(pipe_ln, " @+-" , 4) && |
312 | strncmp(pipe_ln, "+@+-" , 4) && |
313 | strncmp(pipe_ln, "-@+-" , 4)) { |
314 | fprintf(wc_diff_fp, "%s" , pipe_ln); |
315 | } |
316 | } |
317 | fflush(wc_diff_fp); |
318 | fclose(wc_diff_fp); |
319 | pclose(pipe_fp); |
320 | } |
321 | UNLINK(wc_old_fn); |
322 | UNLINK(wc_new_fn); |
323 | |
324 | fclose(lw_diff_fp); |
325 | return 1; |
326 | } |
327 | |
328 | /* lw_diff2wc_diff */ |
329 | |
330 | |
331 | int |
332 | l_diff2w_diff(int mindiff, char *l_diff_fn, char *w_diff_fn) |
333 | { |
334 | TRACE(fprintf(STDERR, "l_diff2w_diff(%i,%s,%s)\n" , mindiff, l_diff_fn, w_diff_fn)); |
335 | |
336 | return lw_diff2wc_diff(mindiff, 0, l_diff_fn, w_diff_fn); |
337 | } |
338 | |
339 | /* l_diff2w_diff */ |
340 | |
341 | |
342 | int |
343 | w_diff2c_diff(int mindiff, char *w_diff_fn, char *c_diff_fn) |
344 | { |
345 | TRACE(fprintf(STDERR, "w_diff2c_diff(%i,%s,%s)\n" , mindiff, w_diff_fn, c_diff_fn)); |
346 | |
347 | return lw_diff2wc_diff(mindiff, 1, w_diff_fn, c_diff_fn); |
348 | } |
349 | |
350 | /* w_diff2c_diff */ |
351 | |
352 | |
353 | |
354 | int |
355 | oldnew2l_diff(int mindiff, int context, char *ignore, char *function, char *old_fn, char *new_fn, char *l_diff_fn) |
356 | { |
357 | FILE *u_diff_fp; |
358 | int rtrn = 0; |
359 | |
360 | TRACE(fprintf(STDERR, "oldnew2l_diff(%i,%i,%s,%s,%s,%s,%s)\n" , mindiff, context, ignore, function, old_fn, new_fn, l_diff_fn)); |
361 | |
362 | if ((u_diff_fp = oldnew2u_diff(mindiff, context, ignore, function, old_fn, new_fn)) == NULL) { |
363 | ERRHNDL(0, "oldnew2u_diff returns 0 in oldnew2l_diff" , "" , 1); |
364 | } |
365 | |
366 | rtrn = u_diff2l_diff(u_diff_fp, l_diff_fn); |
367 | |
368 | return rtrn; |
369 | } |
370 | |
371 | /* oldnew2l_diff */ |
372 | |
373 | |
374 | int |
375 | oldnew2w_diff(int mindiff, int context, char *ignore, char *function, char *old_fn, char *new_fn, char *w_diff_fn) |
376 | { |
377 | char l_diff_fn[CMDLEN]; |
378 | int rtrn = 0; |
379 | |
380 | TRACE(fprintf(STDERR, "oldnew2w_diff(%i,%i,%s,%s,%s,%s,%s)\n" , mindiff, context, ignore, function, old_fn, new_fn, w_diff_fn)); |
381 | |
382 | snprintf(l_diff_fn, sizeof(l_diff_fn), "%s%c.difflib-%ld-oldnew2w_diff-l_diff" , tmpdir(), DIR_SEP, (long) getpid()); |
383 | |
384 | if (!oldnew2l_diff(mindiff, context, ignore, function, old_fn, new_fn, l_diff_fn)) { |
385 | UNLINK(l_diff_fn); |
386 | ERRHNDL(0, "oldnew2l_diff returns 0 in oldnew2w_diff" , "" , 1); |
387 | } |
388 | |
389 | rtrn = l_diff2w_diff(mindiff, l_diff_fn, w_diff_fn); |
390 | |
391 | UNLINK(l_diff_fn); |
392 | return rtrn; |
393 | } |
394 | |
395 | /* oldnew2w_diff */ |
396 | |
397 | |
398 | int |
399 | oldnew2c_diff(int mindiff, int context, char *ignore, char *function, char *old_fn, char *new_fn, char *c_diff_fn) |
400 | { |
401 | char w_diff_fn[CMDLEN]; |
402 | int rtrn = 0; |
403 | |
404 | TRACE(fprintf(STDERR, "oldnew2c_diff(%i,%i,%s,%s,%s,%s,%s)\n" , mindiff, context, ignore, function, old_fn, new_fn, c_diff_fn)); |
405 | |
406 | snprintf(w_diff_fn, sizeof(w_diff_fn), "%s%c.difflib-%ld-oldnew2c_diff-w_diff" , tmpdir(), DIR_SEP, (long) getpid()); |
407 | |
408 | if (!oldnew2w_diff(mindiff, context, ignore, function, old_fn, new_fn, w_diff_fn)) { |
409 | UNLINK(w_diff_fn); |
410 | ERRHNDL(0, "oldnew2w_diff returns 0 in oldnew2c_diff" , "" , 1); |
411 | } |
412 | |
413 | rtrn = w_diff2c_diff(mindiff, w_diff_fn, c_diff_fn); |
414 | |
415 | UNLINK(w_diff_fn); |
416 | return rtrn; |
417 | } |
418 | |
419 | /* oldnew2c_diff */ |
420 | |
421 | |
422 | int |
423 | oldnew2lwc_diff(int mindiff, int LWC, int context, char *ignore, char *function, char *old_fn, char *new_fn, char *lwc_diff_fn) |
424 | { |
425 | TRACE(fprintf(STDERR, "oldnew2lwc_diff(%i,%i,%i,%s,%s,%s,%s,%s)\n" , mindiff, LWC, context, ignore, function, old_fn, new_fn, lwc_diff_fn)); |
426 | |
427 | switch (LWC) { |
428 | case 0: |
429 | return oldnew2l_diff(mindiff, context, ignore, function, old_fn, new_fn, lwc_diff_fn); |
430 | case 1: |
431 | return oldnew2w_diff(mindiff, context, ignore, function, old_fn, new_fn, lwc_diff_fn); |
432 | case 2: |
433 | return oldnew2c_diff(mindiff, context, ignore, function, old_fn, new_fn, lwc_diff_fn); |
434 | default: |
435 | ErrXit("oldnew2lwc_diff called with wrong LWC" , "" , 1); |
436 | } |
437 | return 0; |
438 | } |
439 | |
440 | /* oldnew2lwc_diff */ |
441 | |
442 | |
443 | static char *doctype = "\ |
444 | <!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN'\n\ |
445 | 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'>\n\ |
446 | " ; |
447 | static char *stylesheet = "\ |
448 | .blue { color: #0000ff; }\n\ |
449 | .lightblue { color: #00aaff; }\n\ |
450 | .red { color: #ff0000; }\n\ |
451 | .lightred { color: #ffaa00; }\n\ |
452 | .pink { color: #ff00ff; }\n\ |
453 | .lightpink { color: #ffaaff; }\n\ |
454 | .colhead { font-family: monospace; color: blue; font-size: medium; }\n\ |
455 | caption { font-weight: bold; font-family: sans-serif; }\n\ |
456 | body { background-color: white; color: black; }\n\ |
457 | a:link { color: green; }\n\ |
458 | a:visited { color: darkgreen; }\n\ |
459 | a:active { color: lime; }\n\ |
460 | td { color: black; font-size: xx-small; font-family: monospace; white-space: pre-wrap; vertical-align: baseline; }\n\ |
461 | " ; |
462 | |
463 | int |
464 | lwc_diff2html(char *old_fn, char *new_fn, char *lwc_diff_fn, char *html_fn, char *caption, char *revision) |
465 | { |
466 | FILE *html_fp, *lwc_diff_fp, *clmn_fp[5]; |
467 | char line[BUFLEN], fn_clmn[CMDLEN], *clmn_fn[5], c[3], *ok; |
468 | char *old = NULL, *new = NULL, *old_time, *new_time, olns[24], nlns[24]; |
469 | int oln, nln, orn, nrn, i, clr[5], newline, newline_, minor = 0, Minor = 0, Major = 0; |
470 | |
471 | TRACE(fprintf(STDERR, "lwc_diff2html(%s,%s,%s,%s)\n" , lwc_diff_fn, html_fn, caption, revision)); |
472 | |
473 | lwc_diff_fp = Rfopen(lwc_diff_fn); |
474 | |
475 | if (!(ok = fgets(line, BUFLEN, lwc_diff_fp))) |
476 | /*{ fclose(lwc_diff_fp); ERRHNDL(0,"empty file in lwc_diff2html:",lwc_diff_fn,1); } */ |
477 | { |
478 | html_fp = Wfopen(html_fn); |
479 | /* |
480 | fprintf(html_fp,"Content-type: text/html\n\n"); |
481 | */ |
482 | fprintf(html_fp, "%s<html>\n<head>\n<style>\n%s</style>\n</head>\n<body>\n<table align='center' border='1' cellspacing='0' cellpadding='1'>\n" , doctype, stylesheet); |
483 | if (*caption) |
484 | fprintf(html_fp, "<caption>%s</caption>\n" , caption); |
485 | fprintf(html_fp, "<tr>" ); |
486 | if (!new_fn) |
487 | fprintf(html_fp, "<th></th>" ); |
488 | fprintf(html_fp, "<th class='colhead'><a href='%s'>%s%s</a></th>" , filename(old_fn), filename(old_fn), revision); |
489 | fprintf(html_fp, "<th></th>" ); |
490 | if (new_fn) |
491 | fprintf(html_fp, "<th class='colhead'><a href='%s'>%s</a></th>" , new_fn, new_fn); |
492 | fprintf(html_fp, "</tr>\n" ); |
493 | fprintf(html_fp, "<tr><th colspan='3' align='center'>No differences.</th></tr>\n" ); |
494 | fprintf(html_fp, "</table>\n" ); |
495 | fprintf(html_fp, "<hr/>\n" ); |
496 | fprintf(html_fp, "</body>\n</html>\n" ); |
497 | fprintf(html_fp, "<!--NoDiffs-->\n" ); |
498 | fflush(html_fp); |
499 | fclose(html_fp); |
500 | return 0; |
501 | } |
502 | |
503 | snprintf(fn_clmn, sizeof(fn_clmn), "%s%c.difflib-%ld-lwc_diff2html-clmn-0-0" , tmpdir(), DIR_SEP, (long) getpid()); |
504 | for (i = 0; i < 5; i++) { |
505 | clmn_fn[i] = strdup(fn_clmn); |
506 | clmn_fn[i][strlen(clmn_fn[i]) - 3] += i; |
507 | } |
508 | |
509 | html_fp = Wfopen(html_fn); |
510 | /* |
511 | fprintf(html_fp,"Content-type: text/html\n\n"); |
512 | */ |
513 | fprintf(html_fp, "%s<html>\n<head>\n<style>\n%s</style>\n</head>\n<body>\n" , doctype, stylesheet); |
514 | fprintf(html_fp, "<table align='center' border='1' cellspacing='0' cellpadding='1' rules='groups'>\n" ); |
515 | if (*caption) |
516 | fprintf(html_fp, "<caption>%s</caption>\n" , caption); |
517 | |
518 | fprintf(html_fp, "<colgroup/><colgroup/><colgroup/><colgroup/><colgroup/><colgroup/><colgroup/>\n" ); |
519 | |
520 | line[strlen(line) - 1] = '\0'; |
521 | while (ok && strncmp(line, "@@ -" , 4)) { |
522 | if (!strncmp(line, "--- " , 4)) |
523 | old = strdup(line + 4); |
524 | else if (!strncmp(line, "+++ " , 4)) |
525 | new = strdup(line + 4); |
526 | else |
527 | fprintf(html_fp, "<tbody><tr><td colspan='7'>%s</td></tr></tbody>\n" , HTMLsave(line)); |
528 | ok = fgets(line, BUFLEN, lwc_diff_fp); |
529 | line[strlen(line) - 1] = '\0'; |
530 | } |
531 | old_time = strchr(old, '\t'); |
532 | *old_time++ = '\0'; |
533 | new_time = strchr(new, '\t'); |
534 | *new_time++ = '\0'; |
535 | fprintf(html_fp, "<thead><tr><th colspan='3' align='center' class='colhead'><a href='%s'>%s%s</a> %s</th>" , filename(old), filename(old_fn), revision, old_time); |
536 | fprintf(html_fp, "<th></th>" ); |
537 | fprintf(html_fp, "<th colspan='3' align='center' class='colhead'><a href='%s'>%s</a> %s</th></tr></thead>\n" , new, new_fn, new_time); |
538 | free(old); |
539 | free(new); |
540 | while (ok) { |
541 | |
542 | for (i = 0; i < 5; i++) |
543 | clmn_fp[i] = Wfopen(clmn_fn[i]); |
544 | sscanf(line, "@@ -%s +%s @@" , olns, nlns); |
545 | oln = atoi(olns); |
546 | nln = atoi(nlns); |
547 | if ((oln > 1) && (nln > 1)) { |
548 | fprintf(html_fp, "<tbody><tr><td align='center'>...</td>" ); |
549 | fprintf(html_fp, "<td align='center'>...</td>" ); |
550 | fprintf(html_fp, "<td align='center'>...</td>" ); |
551 | fprintf(html_fp, "<td></td>" ); |
552 | fprintf(html_fp, "<td align='center'>...</td>" ); |
553 | fprintf(html_fp, "<td align='center'>...</td>" ); |
554 | fprintf(html_fp, "<td align='center'>...</td></tr></tbody>\n" ); |
555 | } |
556 | for (i = 0; i < 3 && ok; i++) |
557 | ok = strchr(ok+1, '@'); |
558 | if (ok && ok[1] == ' ') |
559 | fprintf(html_fp, "<td colspan='7' align='center'>%s</td>\n" , HTMLsave(ok + 2)); |
560 | for (i = 0; i < 5; i++) |
561 | clr[i] = 0; |
562 | orn = nrn = 0; |
563 | newline_ = 1; |
564 | newline = 1; |
565 | snprintf(c, sizeof(c), " " ); |
566 | ok = line; |
567 | while (ok && (ok = fgets(line, BUFLEN, lwc_diff_fp)) && strchr(" -+" , line[0])) { |
568 | if (line[1] != '\3') { |
569 | size_t sl = strlen(line) - 1; |
570 | char nl = line[sl], l0, l1; |
571 | |
572 | if (newline_ || newline) |
573 | Minor |= (minor = (strchr("#=\n\2" , line[1]) != NULL)); |
574 | line[sl] = '\0'; |
575 | if (line[1] == '\2') |
576 | snprintf(line + 1, sizeof(line) - 1, " " ); |
577 | l0 = line[0]; |
578 | l1 = line[1]; |
579 | if (line[0] == ' ') { |
580 | if (newline && (nrn < orn)) { |
581 | while (nrn < orn) { |
582 | SETBLUE(1, minor); |
583 | fprintf(clmn_fp[1], "%i" , oln++); |
584 | SETBLACK(1); |
585 | fprintf(clmn_fp[1], "\n" ); |
586 | SETBLUE(2, minor); |
587 | fprintf(clmn_fp[2], "-" ); |
588 | SETBLACK(2); |
589 | fprintf(clmn_fp[2], "\n" ); |
590 | fprintf(clmn_fp[3], "\n" ); |
591 | fprintf(clmn_fp[4], "\n" ); |
592 | nrn++; |
593 | } |
594 | } |
595 | SETBLACK(0); |
596 | SETBLACK(4); |
597 | } |
598 | if (line[0] == '-') { |
599 | c[0] = '-'; |
600 | SETBLUE(0, minor); |
601 | } |
602 | if (line[0] == '+') { |
603 | c[1] = '+'; |
604 | SETRED(4, minor); |
605 | } |
606 | if (line[1] != '\1') { |
607 | line[sl] = nl; |
608 | line[sl+1] = '\0'; |
609 | i = 1; |
610 | do { |
611 | sl = strlen(line) - 1; |
612 | nl = line[sl]; |
613 | if (nl == '\n') { |
614 | line[sl] = '\0'; |
615 | } |
616 | if (strchr(" -" , l0)) { |
617 | fprintf(clmn_fp[0], "%s" , HTMLsave(line + i)); |
618 | } |
619 | if (strchr(" +" , l0)) { |
620 | fprintf(clmn_fp[4], "%s" , HTMLsave(line + i)); |
621 | } |
622 | i = 0; |
623 | } while (nl != '\n' && (ok = fgets(line, BUFLEN, lwc_diff_fp))); |
624 | if (strchr(" -" , l0)) { |
625 | Major |= (clr[0] & 1); |
626 | } |
627 | if (strchr(" +" , l0)) { |
628 | Major |= (clr[4] & 1); |
629 | } |
630 | } else { |
631 | if (line[0] == '-') { |
632 | SETBLACK(0); |
633 | fprintf(clmn_fp[0], "\n" ); |
634 | orn++; |
635 | } |
636 | if (line[0] == '+') { |
637 | if (orn > nrn) { |
638 | SETPINK(1, minor); |
639 | fprintf(clmn_fp[1], "%i" , oln++); |
640 | SETBLACK(1); |
641 | fprintf(clmn_fp[1], "\n" ); |
642 | SETPINK(2, minor); |
643 | fprintf(clmn_fp[2], "!" ); |
644 | SETBLACK(2); |
645 | fprintf(clmn_fp[2], "\n" ); |
646 | SETPINK(3, minor); |
647 | fprintf(clmn_fp[3], "%i" , nln++); |
648 | SETBLACK(3); |
649 | fprintf(clmn_fp[3], "\n" ); |
650 | } else { |
651 | SETBLACK(0); |
652 | fprintf(clmn_fp[0], "\n" ); |
653 | orn++; |
654 | SETBLACK(1); |
655 | fprintf(clmn_fp[1], "\n" ); |
656 | SETRED(2, minor); |
657 | fprintf(clmn_fp[2], "+" ); |
658 | SETBLACK(2); |
659 | fprintf(clmn_fp[2], "\n" ); |
660 | SETRED(3, minor); |
661 | fprintf(clmn_fp[3], "%i" , nln++); |
662 | SETBLACK(3); |
663 | fprintf(clmn_fp[3], "\n" ); |
664 | } |
665 | SETBLACK(4); |
666 | fprintf(clmn_fp[4], "\n" ); |
667 | nrn++; |
668 | } |
669 | if (line[0] == ' ') { |
670 | if (!strncmp(c, " " , 2)) { |
671 | SETBLACK(1); |
672 | SETBLACK(2); |
673 | SETBLACK(3); |
674 | fprintf(clmn_fp[2], "\n" ); |
675 | } else { |
676 | SETPINK(1, minor); |
677 | SETPINK(3, minor); |
678 | } |
679 | if (!strncmp(c, "-+" , 2)) { |
680 | SETPINK(2, minor); |
681 | fprintf(clmn_fp[2], "!" ); |
682 | SETBLACK(2); |
683 | fprintf(clmn_fp[2], "\n" ); |
684 | } |
685 | if (!strncmp(c, "- " , 2)) { |
686 | SETBLUE(2, minor); |
687 | fprintf(clmn_fp[2], "-" ); |
688 | SETBLACK(2); |
689 | fprintf(clmn_fp[2], "\n" ); |
690 | } |
691 | if (!strncmp(c, " +" , 2)) { |
692 | SETRED(2, minor); |
693 | fprintf(clmn_fp[2], "+" ); |
694 | SETBLACK(2); |
695 | fprintf(clmn_fp[2], "\n" ); |
696 | } |
697 | fprintf(clmn_fp[1], "%i" , oln++); |
698 | SETBLACK(1); |
699 | fprintf(clmn_fp[1], "\n" ); |
700 | fprintf(clmn_fp[3], "%i" , nln++); |
701 | SETBLACK(3); |
702 | fprintf(clmn_fp[3], "\n" ); |
703 | SETBLACK(0); |
704 | fprintf(clmn_fp[0], "\n" ); |
705 | SETBLACK(4); |
706 | fprintf(clmn_fp[4], "\n" ); |
707 | } |
708 | snprintf(c, sizeof(c), " " ); |
709 | } |
710 | newline_ = newline; |
711 | newline = (l1 == '\1'); |
712 | } |
713 | } |
714 | |
715 | if (nrn < orn) { |
716 | SETBLACK(3); |
717 | SETBLACK(4); |
718 | while (nrn < orn) { |
719 | SETBLUE(1, minor); |
720 | fprintf(clmn_fp[1], "%i" , oln++); |
721 | SETBLACK(1); |
722 | fprintf(clmn_fp[1], "\n" ); |
723 | SETBLUE(2, minor); |
724 | fprintf(clmn_fp[2], "-" ); |
725 | SETBLACK(2); |
726 | fprintf(clmn_fp[2], "\n" ); |
727 | fprintf(clmn_fp[3], "\n" ); |
728 | fprintf(clmn_fp[4], "\n" ); |
729 | nrn++; |
730 | } |
731 | } |
732 | if (orn < nrn) { |
733 | SETBLACK(0); |
734 | SETBLACK(1); |
735 | while (orn < nrn) { |
736 | fprintf(clmn_fp[0], "\n" ); |
737 | orn++; |
738 | fprintf(clmn_fp[1], "\n" ); |
739 | SETRED(2, minor); |
740 | fprintf(clmn_fp[2], "+" ); |
741 | SETBLACK(2); |
742 | fprintf(clmn_fp[2], "\n" ); |
743 | SETRED(3, minor); |
744 | fprintf(clmn_fp[3], "%i" , nln++); |
745 | SETBLACK(3); |
746 | fprintf(clmn_fp[3], "\n" ); |
747 | } |
748 | } |
749 | |
750 | for (i = 0; i < 5; i++) { |
751 | fclose(clmn_fp[i]); |
752 | clmn_fp[i] = Rfopen(clmn_fn[i]); |
753 | } |
754 | |
755 | fprintf(html_fp, "<tbody>\n" ); |
756 | for (;;) { |
757 | char ln[BUFLEN], buf1[128], buf2[128], buf3[128]; |
758 | |
759 | if (fgets(ln, sizeof(ln), clmn_fp[0]) == NULL) |
760 | break; |
761 | if (fgets(buf1, sizeof(buf1), clmn_fp[1]) == NULL) |
762 | break; /* shouldn't happen */ |
763 | buf1[strlen(buf1) - 1] = 0; |
764 | if (fgets(buf2, sizeof(buf2), clmn_fp[2]) == NULL) |
765 | break; /* shouldn't happen */ |
766 | buf2[strlen(buf2) - 1] = 0; |
767 | if (fgets(buf3, sizeof(buf3), clmn_fp[3]) == NULL) |
768 | break; /* shouldn't happen */ |
769 | buf3[strlen(buf3) - 1] = 0; |
770 | |
771 | fprintf(html_fp, "<tr>" ); |
772 | fprintf(html_fp, "<td align='center'>%s</td>\n" , buf1); |
773 | fprintf(html_fp, "<td>" ); |
774 | while (ln[strlen(ln) - 1] != '\n') { |
775 | fprintf(html_fp, "%s" , ln); |
776 | if (!fgets(ln, sizeof(ln), clmn_fp[0])) { |
777 | ln[0] = '\n'; |
778 | ln[1] = 0; |
779 | break; |
780 | } |
781 | } |
782 | ln[strlen(ln) - 1] = 0; |
783 | fprintf(html_fp, "%s</td>\n" , ln); |
784 | fprintf(html_fp, "<td align='center'>%s</td>\n" , buf1); |
785 | fprintf(html_fp, "<td align='center'>%s</td>\n" , buf2); |
786 | fprintf(html_fp, "<td align='center'>%s</td>\n" , buf3); |
787 | if (fgets(ln, sizeof(ln), clmn_fp[4]) == NULL) |
788 | break; /* shouldn't happen */ |
789 | fprintf(html_fp, "<td>" ); |
790 | while (ln[strlen(ln) - 1] != '\n') { |
791 | fprintf(html_fp, "%s" , ln); |
792 | if (!fgets(ln, sizeof(ln), clmn_fp[4])) { |
793 | ln[0] = '\n'; |
794 | ln[1] = 0; |
795 | break; |
796 | } |
797 | } |
798 | ln[strlen(ln) - 1] = 0; |
799 | fprintf(html_fp, "%s</td>\n" , ln); |
800 | fprintf(html_fp, "<td align='center'>%s</td>\n" , buf3); |
801 | fprintf(html_fp, "</tr>\n" ); |
802 | } |
803 | fprintf(html_fp, "</tbody>\n" ); |
804 | for (i = 0; i < 5; i++) |
805 | fclose(clmn_fp[i]); |
806 | |
807 | TRACE(for (i = 0; i < 5; i++) clmn_fn[i][strlen(clmn_fn[i]) - 1]++) ; |
808 | } |
809 | |
810 | fprintf(html_fp, "</table>\n" ); |
811 | fprintf(html_fp, "<hr/>\n" ); |
812 | fprintf(html_fp, "</body>\n</html>\n" ); |
813 | fprintf(html_fp, "<!--%sDiffs-->\n" , Major ? "Major" : (Minor ? "Minor" : "No" )); |
814 | fflush(html_fp); |
815 | fclose(html_fp); |
816 | |
817 | for (i = 0; i < 5; i++) { |
818 | UNLINK(clmn_fn[i]); |
819 | free(clmn_fn[i]); |
820 | } |
821 | |
822 | fclose(lwc_diff_fp); |
823 | return (Major ? 2 : (Minor != 0)); |
824 | } |
825 | |
826 | /* lwc_diff2html */ |
827 | |
828 | |
829 | int |
830 | oldnew2html(int mindiff, int LWC, int context, char *ignore, char *function, char *old_fn, char *new_fn, char *html_fn, char *caption, char *revision) |
831 | { |
832 | char lwc_diff_fn[CMDLEN]; |
833 | int rtrn; |
834 | |
835 | TRACE(fprintf(STDERR, "oldnew2html(%i,%i,%i,%s,%s,%s,%s,%s,%s,%s)\n" , mindiff, LWC, context, ignore, function, old_fn, new_fn, html_fn, caption, revision)); |
836 | |
837 | snprintf(lwc_diff_fn, sizeof(lwc_diff_fn), "%s%c.difflib-%ld-oldnew2html-lwc_diff" , tmpdir(), DIR_SEP, (long) getpid()); |
838 | |
839 | if (!oldnew2lwc_diff(mindiff, LWC, context, ignore, function, old_fn, new_fn, lwc_diff_fn)) |
840 | /* { UNLINK(lwc_diff_fn); ERRHNDL(0,"oldnew2lwc_diff returns 0 in oldnew2html","",1); } */ |
841 | fclose(Wfopen(lwc_diff_fn)); |
842 | |
843 | rtrn = lwc_diff2html(old_fn, new_fn, lwc_diff_fn, html_fn, caption, revision); |
844 | |
845 | UNLINK(lwc_diff_fn); |
846 | return rtrn; |
847 | } |
848 | |
849 | /* oldnew2u_diff */ |
850 | |