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