1 /* 2 * Copyright (c) 1989 Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Edward Wang at The University of California, Berkeley. 7 * 8 * %sccs.include.redist.c% 9 */ 10 11 #ifndef lint 12 static char sccsid[] = "@(#)compress.c 3.7 (Berkeley) 08/24/92"; 13 #endif /* not lint */ 14 15 #include "ww.h" 16 #include "tt.h" 17 18 /* special */ 19 #include <stdio.h> 20 #include <fcntl.h> 21 int cc_trace = 0; 22 FILE *cc_trace_fp; 23 24 /* tunable parameters */ 25 26 int cc_reverse = 1; 27 int cc_sort = 0; 28 int cc_chop = 0; 29 30 int cc_token_max = 8; /* <= TOKEN_MAX */ 31 int cc_token_min = 2; /* > tt.tt_put_token_cost */ 32 int cc_npass0 = 1; 33 int cc_npass1 = 1; 34 35 int cc_bufsize = 1024 * 3; /* XXX, or 80 * 24 * 2 */ 36 37 int cc_ntoken = 8192; 38 39 #define cc_weight XXX 40 #ifndef cc_weight 41 int cc_weight = 0; 42 #endif 43 44 #define TOKEN_MAX 16 45 46 struct cc { 47 char string[TOKEN_MAX]; 48 char length; 49 char flag; 50 #ifndef cc_weight 51 short weight; 52 #endif 53 long time; /* time last seen */ 54 short bcount; /* count in this buffer */ 55 short ccount; /* count in compression */ 56 short places; /* places in the buffer */ 57 short code; /* token code */ 58 struct cc *qforw, *qback; 59 struct cc *hforw, **hback; 60 }; 61 62 short cc_thresholds[TOKEN_MAX + 1]; 63 #define thresh(length) (cc_thresholds[length]) 64 #define threshp(code, count, length) \ 65 ((code) >= 0 || (short) (count) >= cc_thresholds[length]) 66 67 #ifndef cc_weight 68 short cc_wthresholds[TOKEN_MAX + 1]; 69 #define wthresh(length) (cc_wthresholds[length]) 70 #define wthreshp(weight, length) ((short) (weight) >= cc_wthresholds[length]) 71 #else 72 #define wthreshp(weight, length) (0) 73 #endif 74 75 #ifndef cc_weight 76 short cc_wlimits[TOKEN_MAX + 1]; 77 #define wlimit(length) (cc_wlimits[length]) 78 #endif 79 80 #define put_token_score(length) ((length) - tt.tt_put_token_cost) 81 82 int cc_score_adjustments[TOKEN_MAX + 1][8]; /* XXX, 8 > max of cc_thresholds */ 83 #define score_adjust(score, p) \ 84 do { \ 85 int length = (p)->length; \ 86 int ccount = (p)->ccount; \ 87 if (threshp((p)->code, ccount, length) || \ 88 wthreshp((p)->weight, length)) /* XXX */ \ 89 (score) -= length - tt.tt_put_token_cost; \ 90 else \ 91 (score) += cc_score_adjustments[length][ccount]; \ 92 } while (0) 93 94 int cc_initial_scores[TOKEN_MAX + 1][8]; /* XXX, 8 > max of cc_thresholds */ 95 96 struct cc cc_q0a, cc_q0b, cc_q1a, cc_q1b; 97 98 #define qinsert(p1, p2) \ 99 do { \ 100 register struct cc *forw = (p1)->qforw; \ 101 register struct cc *back = (p1)->qback; \ 102 back->qforw = forw; \ 103 forw->qback = back; \ 104 forw = (p2)->qforw; \ 105 (p1)->qforw = forw; \ 106 forw->qback = (p1); \ 107 (p2)->qforw = (p1); \ 108 (p1)->qback = (p2); \ 109 } while (0) 110 111 #define qinsertq(q, p) \ 112 ((q)->qforw == (q) ? 0 : \ 113 ((q)->qback->qforw = (p)->qforw, \ 114 (p)->qforw->qback = (q)->qback, \ 115 (q)->qforw->qback = (p), \ 116 (p)->qforw = (q)->qforw, \ 117 (q)->qforw = (q), \ 118 (q)->qback = (q))) 119 120 #define H (14) 121 #define HSIZE (1 << H) 122 #define hash(h, c) ((((h) >> H - 8 | (h) << 8) ^ (c)) & HSIZE - 1) 123 124 char *cc_buffer; 125 struct cc **cc_output; /* the output array */ 126 short *cc_places[TOKEN_MAX + 1]; 127 short *cc_hashcodes; /* for computing hashcodes */ 128 struct cc **cc_htab; /* the hash table */ 129 struct cc **cc_tokens; /* holds all the active tokens */ 130 struct cc_undo { 131 struct cc **pos; 132 struct cc *val; 133 } *cc_undo; 134 135 long cc_time, cc_time0; 136 137 char *cc_tt_ob, *cc_tt_obe; 138 139 ccinit() 140 { 141 register i, j; 142 register struct cc *p; 143 144 if (tt.tt_token_max > cc_token_max) 145 tt.tt_token_max = cc_token_max; 146 if (tt.tt_token_min < cc_token_min) 147 tt.tt_token_min = cc_token_min; 148 if (tt.tt_token_min > tt.tt_token_max) { 149 tt.tt_ntoken = 0; 150 return 0; 151 } 152 if (tt.tt_ntoken > cc_ntoken / 2) /* not likely */ 153 tt.tt_ntoken = cc_ntoken / 2; 154 #define C(x) (sizeof (x) / sizeof *(x)) 155 for (i = 0; i < C(cc_thresholds); i++) { 156 int h = i - tt.tt_put_token_cost; 157 if (h > 0) 158 cc_thresholds[i] = 159 (tt.tt_set_token_cost + 1 + h - 1) / h + 1; 160 else 161 cc_thresholds[i] = 0; 162 } 163 for (i = 0; i < C(cc_score_adjustments); i++) { 164 int t = cc_thresholds[i]; 165 for (j = 0; j < C(*cc_score_adjustments); j++) { 166 if (j >= t) 167 cc_score_adjustments[i][j] = 168 - (i - tt.tt_put_token_cost); 169 else if (j < t - 1) 170 cc_score_adjustments[i][j] = 0; 171 else 172 /* 173 * cost now is 174 * length * (ccount + 1) a 175 * cost before was 176 * set-token-cost + length + 177 * ccount * put-token-cost b 178 * the score adjustment is (b - a) 179 */ 180 cc_score_adjustments[i][j] = 181 tt.tt_set_token_cost + i + 182 j * tt.tt_put_token_cost - 183 i * (j + 1); 184 if (j >= t) 185 cc_initial_scores[i][j] = 0; 186 else 187 /* 188 * - (set-token-cost + 189 * (length - put-token-cost) - 190 * (length - put-token-cost) * ccount) 191 */ 192 cc_initial_scores[i][j] = 193 - (tt.tt_set_token_cost + 194 (i - tt.tt_put_token_cost) - 195 (i - tt.tt_put_token_cost) * j); 196 } 197 } 198 #ifndef cc_weight 199 for (i = 1; i < C(cc_wthresholds); i++) { 200 cc_wthresholds[i] = 201 ((tt.tt_set_token_cost + tt.tt_put_token_cost) / i + 202 i / 5 + 1) * 203 cc_weight + 1; 204 cc_wlimits[i] = cc_wthresholds[i] + cc_weight; 205 } 206 #endif 207 #undef C 208 if ((cc_output = (struct cc **) 209 malloc((unsigned) cc_bufsize * sizeof *cc_output)) == 0) 210 goto nomem; 211 if ((cc_hashcodes = (short *) 212 malloc((unsigned) cc_bufsize * sizeof *cc_hashcodes)) == 0) 213 goto nomem; 214 if ((cc_htab = (struct cc **) malloc(HSIZE * sizeof *cc_htab)) == 0) 215 goto nomem; 216 if ((cc_tokens = (struct cc **) 217 malloc((unsigned) 218 (cc_ntoken + tt.tt_token_max - tt.tt_token_min + 1) * 219 sizeof *cc_tokens)) == 0) 220 goto nomem; 221 if ((cc_undo = (struct cc_undo *) 222 malloc((unsigned) cc_bufsize * sizeof *cc_undo)) == 0) 223 goto nomem; 224 for (i = tt.tt_token_min; i <= tt.tt_token_max; i++) 225 if ((cc_places[i] = (short *) 226 malloc((unsigned) cc_bufsize * sizeof **cc_places)) == 0) 227 goto nomem; 228 cc_q0a.qforw = cc_q0a.qback = &cc_q0a; 229 cc_q0b.qforw = cc_q0b.qback = &cc_q0b; 230 cc_q1a.qforw = cc_q1a.qback = &cc_q1a; 231 cc_q1b.qforw = cc_q1b.qback = &cc_q1b; 232 if ((p = (struct cc *) malloc((unsigned) cc_ntoken * sizeof *p)) == 0) 233 goto nomem; 234 for (i = 0; i < tt.tt_ntoken; i++) { 235 p->code = i; 236 p->time = -1; 237 p->qback = cc_q0a.qback; 238 p->qforw = &cc_q0a; 239 p->qback->qforw = p; 240 cc_q0a.qback = p; 241 p++; 242 } 243 for (; i < cc_ntoken; i++) { 244 p->code = -1; 245 p->time = -1; 246 p->qback = cc_q1a.qback; 247 p->qforw = &cc_q1a; 248 p->qback->qforw = p; 249 cc_q1a.qback = p; 250 p++; 251 } 252 cc_tt_ob = tt_ob; 253 cc_tt_obe = tt_obe; 254 if ((cc_buffer = malloc((unsigned) cc_bufsize)) == 0) 255 goto nomem; 256 return 0; 257 nomem: 258 wwerrno = WWE_NOMEM; 259 return -1; 260 } 261 262 ccstart() 263 { 264 register struct cc *p; 265 int ccflush(); 266 267 (*tt.tt_flush)(); 268 tt_obp = tt_ob = cc_buffer; 269 tt_obe = tt_ob + cc_bufsize; 270 tt.tt_flush = ccflush; 271 bzero((char *) cc_htab, HSIZE * sizeof *cc_htab); 272 for (p = cc_q0a.qforw; p != &cc_q0a; p = p->qforw) 273 p->hback = 0; 274 for (p = cc_q1a.qforw; p != &cc_q1a; p = p->qforw) 275 p->hback = 0; 276 if (cc_trace) { 277 cc_trace_fp = fopen("window-trace", "a"); 278 (void) fcntl(fileno(cc_trace_fp), F_SETFD, 1); 279 } 280 } 281 282 ccend() 283 { 284 int ttflush(); 285 286 (*tt.tt_flush)(); 287 tt_obp = tt_ob = cc_tt_ob; 288 tt_obe = cc_tt_obe; 289 tt.tt_flush = ttflush; 290 if (cc_trace_fp != NULL) { 291 (void) fclose(cc_trace_fp); 292 cc_trace_fp = NULL; 293 } 294 } 295 296 ccflush() 297 { 298 int bufsize = tt_obp - tt_ob; 299 int n; 300 int ttflush(); 301 302 if (tt_ob != cc_buffer) 303 abort(); 304 if (cc_trace_fp != NULL) { 305 (void) fwrite(tt_ob, 1, bufsize, cc_trace_fp); 306 putc(-1, cc_trace_fp); 307 } 308 if (bufsize < tt.tt_token_min) { 309 ttflush(); 310 return; 311 } 312 tt_obp = tt_ob = cc_tt_ob; 313 tt_obe = cc_tt_obe; 314 tt.tt_flush = ttflush; 315 cc_time0 = cc_time; 316 cc_time += bufsize; 317 n = cc_sweep_phase(cc_buffer, bufsize, cc_tokens); 318 cc_compress_phase(cc_output, bufsize, cc_tokens, n); 319 cc_output_phase(cc_buffer, cc_output, bufsize); 320 ttflush(); 321 tt_obp = tt_ob = cc_buffer; 322 tt_obe = cc_buffer + cc_bufsize; 323 tt.tt_flush = ccflush; 324 } 325 326 cc_sweep_phase(buffer, bufsize, tokens) 327 char *buffer; 328 struct cc **tokens; 329 { 330 register struct cc **pp = tokens; 331 register i, n; 332 #ifdef STATS 333 int nn, ii; 334 #endif 335 336 #ifdef STATS 337 if (verbose >= 0) 338 time_begin(); 339 if (verbose > 0) 340 printf("Sweep:"); 341 #endif 342 cc_sweep0(buffer, bufsize, tt.tt_token_min - 1); 343 #ifdef STATS 344 ntoken_stat = 0; 345 nn = 0; 346 ii = 0; 347 #endif 348 for (i = tt.tt_token_min; i <= tt.tt_token_max; i++) { 349 #ifdef STATS 350 if (verbose > 0) { 351 if (ii > 7) { 352 printf("\n "); 353 ii = 0; 354 } 355 ii++; 356 printf(" (%d", i); 357 (void) fflush(stdout); 358 } 359 #endif 360 n = cc_sweep(buffer, bufsize, pp, i); 361 pp += n; 362 #ifdef STATS 363 if (verbose > 0) { 364 if (--n > 0) { 365 printf(" %d", n); 366 nn += n; 367 } 368 putchar(')'); 369 } 370 #endif 371 } 372 qinsertq(&cc_q1b, &cc_q1a); 373 #ifdef STATS 374 if (verbose > 0) 375 printf("\n %d tokens, %d candidates\n", 376 ntoken_stat, nn); 377 if (verbose >= 0) 378 time_end(); 379 #endif 380 return pp - tokens; 381 } 382 383 cc_sweep0(buffer, n, length) 384 char *buffer; 385 { 386 register char *p; 387 register short *hc; 388 register i; 389 register short c; 390 register short pc = tt.tt_padc; 391 392 /* n and length are at least 1 */ 393 p = buffer++; 394 hc = cc_hashcodes; 395 i = n; 396 do { 397 if ((*hc++ = *p++) == pc) 398 hc[-1] = -1; 399 } while (--i); 400 while (--length) { 401 p = buffer++; 402 hc = cc_hashcodes; 403 for (i = n--; --i;) { 404 if ((c = *p++) == pc || *hc < 0) 405 c = -1; 406 else 407 c = hash(*hc, c); 408 *hc++ = c; 409 } 410 } 411 } 412 413 cc_sweep(buffer, bufsize, tokens, length) 414 char *buffer; 415 struct cc **tokens; 416 register length; 417 { 418 register struct cc *p; 419 register char *cp; 420 register i; 421 short *hc; 422 short *places = cc_places[length]; 423 struct cc **pp = tokens; 424 short threshold = thresh(length); 425 #ifndef cc_weight 426 short wthreshold = wthresh(length); 427 short limit = wlimit(length); 428 #endif 429 int time; 430 short pc = tt.tt_padc; 431 432 i = length - 1; 433 bufsize -= i; 434 cp = buffer + i; 435 hc = cc_hashcodes; 436 time = cc_time0; 437 for (i = 0; i < bufsize; i++, time++) { 438 struct cc **h; 439 440 { 441 register short *hc1 = hc; 442 register short c = *cp++; 443 register short hh; 444 if ((hh = *hc1) < 0 || c == pc) { 445 *hc1++ = -1; 446 hc = hc1; 447 continue; 448 } 449 h = cc_htab + (*hc1++ = hash(hh, c)); 450 hc = hc1; 451 } 452 for (p = *h; p != 0; p = p->hforw) 453 if (p->length == (char) length) { 454 register char *p1 = p->string; 455 register char *p2 = cp - length; 456 register n = length; 457 do 458 if (*p1++ != *p2++) 459 goto fail; 460 while (--n); 461 break; 462 fail:; 463 } 464 if (p == 0) { 465 p = cc_q1a.qback; 466 if (p == &cc_q1a || 467 p->time >= cc_time0 && p->length == (char) length) 468 continue; 469 if (p->hback != 0) 470 if ((*p->hback = p->hforw) != 0) 471 p->hforw->hback = p->hback; 472 { 473 register char *p1 = p->string; 474 register char *p2 = cp - length; 475 register n = length; 476 do 477 *p1++ = *p2++; 478 while (--n); 479 } 480 p->length = length; 481 #ifndef cc_weight 482 p->weight = cc_weight; 483 #endif 484 p->time = time; 485 p->bcount = 1; 486 p->ccount = 0; 487 p->flag = 0; 488 if ((p->hforw = *h) != 0) 489 p->hforw->hback = &p->hforw; 490 *h = p; 491 p->hback = h; 492 qinsert(p, &cc_q1a); 493 places[i] = -1; 494 p->places = i; 495 #ifdef STATS 496 ntoken_stat++; 497 #endif 498 } else if (p->time < cc_time0) { 499 #ifndef cc_weight 500 if ((p->weight += p->time - time) < 0) 501 p->weight = cc_weight; 502 else if ((p->weight += cc_weight) > limit) 503 p->weight = limit; 504 #endif 505 p->time = time; 506 p->bcount = 1; 507 p->ccount = 0; 508 if (p->code >= 0) { 509 p->flag = 1; 510 *pp++ = p; 511 } else 512 #ifndef cc_weight 513 if (p->weight >= wthreshold) { 514 p->flag = 1; 515 *pp++ = p; 516 qinsert(p, &cc_q1b); 517 } else 518 #endif 519 { 520 p->flag = 0; 521 qinsert(p, &cc_q1a); 522 } 523 places[i] = -1; 524 p->places = i; 525 #ifdef STATS 526 ntoken_stat++; 527 #endif 528 } else if (p->time + length > time) { 529 /* 530 * overlapping token, don't count as two and 531 * don't update time, but do adjust weight to offset 532 * the difference 533 */ 534 #ifndef cc_weight 535 if (cc_weight != 0) { /* XXX */ 536 p->weight += time - p->time; 537 if (!p->flag && p->weight >= wthreshold) { 538 p->flag = 1; 539 *pp++ = p; 540 qinsert(p, &cc_q1b); 541 } 542 } 543 #endif 544 places[i] = p->places; 545 p->places = i; 546 } else { 547 #ifndef cc_weight 548 if ((p->weight += p->time - time) < 0) 549 p->weight = cc_weight; 550 else if ((p->weight += cc_weight) > limit) 551 p->weight = limit; 552 #endif 553 p->time = time; 554 p->bcount++; 555 if (!p->flag && 556 /* code must be < 0 if flag false here */ 557 (p->bcount >= threshold 558 #ifndef cc_weight 559 || p->weight >= wthreshold 560 #endif 561 )) { 562 p->flag = 1; 563 *pp++ = p; 564 qinsert(p, &cc_q1b); 565 } 566 places[i] = p->places; 567 p->places = i; 568 } 569 } 570 if ((i = pp - tokens) > 0) { 571 *pp = 0; 572 if (cc_reverse) 573 cc_sweep_reverse(tokens, places); 574 if (cc_sort && i > 1) { 575 int cc_token_compare(); 576 qsort((char *) tokens, i, sizeof *tokens, 577 cc_token_compare); 578 } 579 if (cc_chop) { 580 if ((i = i * cc_chop / 100) == 0) 581 i = 1; 582 tokens[i] = 0; 583 } 584 i++; 585 } 586 return i; 587 } 588 589 cc_sweep_reverse(pp, places) 590 register struct cc **pp; 591 register short *places; 592 { 593 register struct cc *p; 594 register short front, back, t; 595 596 while ((p = *pp++) != 0) { 597 back = -1; 598 t = p->places; 599 /* the list is never empty */ 600 do { 601 front = places[t]; 602 places[t] = back; 603 back = t; 604 } while ((t = front) >= 0); 605 p->places = back; 606 } 607 } 608 609 cc_compress_phase(output, bufsize, tokens, ntoken) 610 struct cc **output; 611 struct cc **tokens; 612 { 613 register i; 614 615 bzero((char *) output, bufsize * sizeof *output); 616 for (i = 0; i < cc_npass0; i++) 617 cc_compress_phase1(output, tokens, ntoken, 0); 618 for (i = 0; i < cc_npass1; i++) 619 cc_compress_phase1(output, tokens, ntoken, 1); 620 cc_compress_cleanup(output, bufsize); 621 } 622 623 cc_compress_phase1(output, tokens, ntoken, flag) 624 register struct cc **output; 625 struct cc **tokens; 626 { 627 register struct cc **pp; 628 #ifdef STATS 629 register int i = 0; 630 int nt = 0, cc = 0, nc = 0; 631 #endif 632 633 #ifdef STATS 634 if (verbose >= 0) 635 time_begin(); 636 if (verbose > 0) 637 printf("Compress:"); 638 #endif 639 pp = tokens; 640 while (pp < tokens + ntoken) { 641 #ifdef STATS 642 if (verbose > 0) { 643 ntoken_stat = 0; 644 ccount_stat = 0; 645 ncover_stat = 0; 646 if (i > 2) { 647 printf("\n "); 648 i = 0; 649 } 650 i++; 651 printf(" (%d", (*pp)->length); 652 (void) fflush(stdout); 653 } 654 #endif 655 pp += cc_compress(output, pp, flag); 656 #ifdef STATS 657 if (verbose > 0) { 658 printf(" %dt %du %dc)", ntoken_stat, ccount_stat, 659 ncover_stat); 660 nt += ntoken_stat; 661 cc += ccount_stat; 662 nc += ncover_stat; 663 } 664 #endif 665 } 666 #ifdef STATS 667 if (verbose > 0) 668 printf("\n total: (%dt %du %dc)\n", nt, cc, nc); 669 if (verbose >= 0) 670 time_end(); 671 #endif 672 } 673 674 cc_compress_cleanup(output, bufsize) 675 register struct cc **output; 676 { 677 register struct cc **end; 678 679 /* the previous output phase may have been interrupted */ 680 qinsertq(&cc_q0b, &cc_q0a); 681 for (end = output + bufsize; output < end;) { 682 register struct cc *p; 683 register length; 684 if ((p = *output) == 0) { 685 output++; 686 continue; 687 } 688 length = p->length; 689 if (!p->flag) { 690 } else if (p->code >= 0) { 691 qinsert(p, &cc_q0b); 692 p->flag = 0; 693 } else if (p->ccount == 0) { 694 *output = 0; 695 } else if (p->ccount >= thresh(length) 696 #ifndef cc_weight 697 || wthreshp(p->weight, length) 698 #endif 699 ) { 700 p->flag = 0; 701 } else { 702 p->ccount = 0; 703 *output = 0; 704 } 705 output += length; 706 } 707 } 708 709 cc_compress(output, tokens, flag) 710 struct cc **output; 711 struct cc **tokens; 712 char flag; 713 { 714 struct cc **pp = tokens; 715 register struct cc *p = *pp++; 716 int length = p->length; 717 int threshold = thresh(length); 718 #ifndef cc_weight 719 short wthreshold = wthresh(length); 720 #endif 721 short *places = cc_places[length]; 722 int *initial_scores = cc_initial_scores[length]; 723 int initial_score0 = put_token_score(length); 724 725 do { 726 int score; 727 register struct cc_undo *undop; 728 int ccount; 729 #ifdef STATS 730 int ncover; 731 #endif 732 int i; 733 734 ccount = p->ccount; 735 if ((short) ccount >= p->bcount) 736 continue; 737 if (p->code >= 0 || ccount >= threshold) 738 score = 0; 739 #ifndef cc_weight 740 else if (p->weight >= wthreshold) 741 /* allow one fewer match than normal */ 742 /* XXX, should adjust for ccount */ 743 score = - tt.tt_set_token_cost; 744 #endif 745 else 746 score = initial_scores[ccount]; 747 undop = cc_undo; 748 #ifdef STATS 749 ncover = 0; 750 #endif 751 for (i = p->places; i >= 0; i = places[i]) { 752 register struct cc **jp; 753 register struct cc *x; 754 register struct cc **ip = output + i; 755 register score0 = initial_score0; 756 struct cc **iip = ip + length; 757 struct cc_undo *undop1 = undop; 758 759 if ((x = *(jp = ip)) != 0) 760 goto z; 761 while (--jp >= output) 762 if ((x = *jp) != 0) { 763 if (jp + x->length > ip) 764 goto z; 765 break; 766 } 767 jp = ip + 1; 768 while (jp < iip) { 769 if ((x = *jp) == 0) { 770 jp++; 771 continue; 772 } 773 z: 774 if (x == p) 775 goto undo; 776 #ifdef STATS 777 ncover++; 778 #endif 779 undop->pos = jp; 780 undop->val = x; 781 undop++; 782 *jp = 0; 783 x->ccount--; 784 score_adjust(score0, x); 785 if (score0 < 0 && flag) 786 goto undo; 787 jp += x->length; 788 } 789 undop->pos = ip; 790 undop->val = 0; 791 undop++; 792 *ip = p; 793 ccount++; 794 score += score0; 795 continue; 796 undo: 797 while (--undop >= undop1) 798 if (*undop->pos = x = undop->val) 799 x->ccount++; 800 undop++; 801 } 802 if (score > 0) { 803 #ifdef STATS 804 ccount_stat += ccount - p->ccount; 805 ntoken_stat++; 806 ncover_stat += ncover; 807 #endif 808 p->ccount = ccount; 809 } else { 810 register struct cc_undo *u = cc_undo; 811 while (--undop >= u) { 812 register struct cc *x; 813 if (*undop->pos = x = undop->val) 814 x->ccount++; 815 } 816 } 817 } while ((p = *pp++) != 0); 818 return pp - tokens; 819 } 820 821 cc_output_phase(buffer, output, bufsize) 822 register char *buffer; 823 register struct cc **output; 824 register bufsize; 825 { 826 register i; 827 register struct cc *p, *p1; 828 829 for (i = 0; i < bufsize;) { 830 if ((p = output[i]) == 0) { 831 ttputc(buffer[i]); 832 i++; 833 } else if (p->code >= 0) { 834 if (--p->ccount == 0) 835 qinsert(p, &cc_q0a); 836 (*tt.tt_put_token)(p->code, p->string, p->length); 837 wwntokuse++; 838 wwntoksave += put_token_score(p->length); 839 i += p->length; 840 } else if ((p1 = cc_q0a.qback) != &cc_q0a) { 841 p->code = p1->code; 842 p1->code = -1; 843 qinsert(p1, &cc_q1a); 844 if (--p->ccount == 0) 845 qinsert(p, &cc_q0a); 846 else 847 qinsert(p, &cc_q0b); 848 (*tt.tt_set_token)(p->code, p->string, p->length); 849 wwntokdef++; 850 wwntoksave -= tt.tt_set_token_cost; 851 i += p->length; 852 } else { 853 p->ccount--; 854 ttwrite(p->string, p->length); 855 wwntokbad++; 856 i += p->length; 857 } 858 } 859 wwntokc += bufsize; 860 } 861 862 cc_token_compare(p1, p2) 863 struct cc **p1, **p2; 864 { 865 return (*p2)->bcount - (*p1)->bcount; 866 } 867