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
65static char *
66HTMLsave(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
104static void
105markNL(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
114FILE *
115oldnew2u_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
129int
130u_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
171static int
172lw_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
331int
332l_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
342int
343w_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
354int
355oldnew2l_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
374int
375oldnew2w_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
398int
399oldnew2c_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
422int
423oldnew2lwc_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
443static 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";
447static 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\
455caption { font-weight: bold; font-family: sans-serif; }\n\
456body { background-color: white; color: black; }\n\
457a:link { color: green; }\n\
458a:visited { color: darkgreen; }\n\
459a:active { color: lime; }\n\
460td { color: black; font-size: xx-small; font-family: monospace; white-space: pre-wrap; vertical-align: baseline; }\n\
461";
462
463int
464lwc_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
829int
830oldnew2html(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