| 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 | |