1 #ifndef lint 2 static char sccsid[] = "@(#)vcat.c 4.5 (Berkeley) 07/16/83"; 3 #endif 4 5 /* 6 * Cat Simulator for Versatec and Varian 7 */ 8 9 #include <stdio.h> 10 #include <sys/vcmd.h> 11 #include <vfont.h> 12 13 int prtmode[] = {VPRINT}; 14 int pltmode[] = {VPLOT}; 15 16 #define DISPATCHSIZE 256 /* must be a power of two */ 17 #define CHARMASK (DISPATCHSIZE-1) 18 #define NFONTS 25 19 #define SPECIALFONT 3 20 #define DSIZ ((sizeof *dispatch)*DISPATCHSIZE) 21 #define MAXF 4 22 23 #define LOCAL_RAILMAG ".railmag" 24 #define GLOBAL_RAILMAG "/usr/lib/vfont/railmag" 25 26 #define CONVERT(n) (n*(200./432.)) 27 #define RECONVERT(n) (n*(432./200.)) 28 29 #define NLINES 110 30 31 char buffer[NLINES * 880]; /* Big enough for versatec */ 32 char *buf0p = &buffer[0]; /* Zero origin in circular buffer */ 33 34 char *calloc(); 35 char *nalloc(); 36 char *allpanic(); 37 38 struct header header; 39 struct dispatch *dispatch; 40 41 struct fontdes { 42 int fnum; 43 int psize; 44 struct dispatch *disp; 45 char *bits; 46 } fontdes[NFONTS] = { 47 -1, 48 -1 49 }; 50 51 struct point_sizes { 52 int stupid_code; 53 int real_code; 54 } point_sizes[] = { 55 010, 6, 56 0, 7, 57 01, 8, 58 07, 9, 59 02, 10, 60 03, 11, 61 04, 12, 62 05, 14, 63 0211, 16, 64 06, 18, 65 0212, 20, 66 0213, 22, 67 0214, 24, 68 0215, 28, 69 0216, 36, 70 0, 0 71 }; 72 73 int lines; 74 75 int vc = 1; /* varian/versatec output file descriptor */ 76 int varian; /* 0 for versatec, 1 for varian. */ 77 int BYTES_PER_LINE; /* number of bytes per raster line. */ 78 int PAGE_LINES; /* number of raster lines per page. */ 79 int BUFFER_SIZE; /* buffer size. */ 80 int cfnum = -1; 81 int cpsize = 10; 82 int cfont = 1; 83 char *bits; 84 int nfontnum = -1; 85 int fontwanted = 1; 86 int npsize = 10; 87 int last_ssize = 02; 88 int xpos, ypos; 89 int esc, lead, back, verd, mcase, railmag; 90 double row, col; 91 char *fontname[MAXF]; 92 char fnbuf[120]; 93 char *scanline; 94 int linecount; 95 96 char asctab[128] = { 97 '\0', /*blank*/ 98 'h', /*h*/ 99 't', /*t*/ 100 'n', /*n*/ 101 'm', /*m*/ 102 'l', /*l*/ 103 'i', /*i*/ 104 'z', /*z*/ 105 's', /*s*/ 106 'd', /*d*/ 107 'b', /*b*/ 108 'x', /*x*/ 109 'f', /*f*/ 110 'j', /*j*/ 111 'u', /*u*/ 112 'k', /*k*/ 113 '\0', /*blank*/ 114 'p', /*p*/ 115 '\06', /*_ 3/4 em dash*/ 116 ';', /*;*/ 117 '\0', /*blank*/ 118 'a', /*a*/ 119 '\05', /*rule*/ 120 'c', /*c*/ 121 '`', /*` open*/ 122 'e', /*e*/ 123 '\'', /*' close*/ 124 'o', /*o*/ 125 '\021', /*1/4*/ 126 'r', /*r*/ 127 '\022', /*1/2*/ 128 'v', /*v*/ 129 '-', /*- hyphen*/ 130 'w', /*w*/ 131 'q', /*q*/ 132 '/', /*/*/ 133 '.', /*.*/ 134 'g', /*g*/ 135 '\023', /*3/4*/ 136 ',', /*,*/ 137 '&', /*&*/ 138 'y', /*y*/ 139 '\0', /*blank*/ 140 '%', /*%*/ 141 '\0', /*blank*/ 142 'Q', /*Q*/ 143 'T', /*T*/ 144 'O', /*O*/ 145 'H', /*H*/ 146 'N', /*N*/ 147 'M', /*M*/ 148 'L', /*L*/ 149 'R', /*R*/ 150 'G', /*G*/ 151 'I', /*I*/ 152 'P', /*P*/ 153 'C', /*C*/ 154 'V', /*V*/ 155 'E', /*E*/ 156 'Z', /*Z*/ 157 'D', /*D*/ 158 'B', /*B*/ 159 'S', /*S*/ 160 'Y', /*Y*/ 161 '\0', /*blank*/ 162 'F', /*F*/ 163 'X', /*X*/ 164 'A', /*A*/ 165 'W', /*W*/ 166 'J', /*J*/ 167 'U', /*U*/ 168 'K', /*K*/ 169 '0', /*0*/ 170 '1', /*1*/ 171 '2', /*2*/ 172 '3', /*3*/ 173 '4', /*4*/ 174 '5', /*5*/ 175 '6', /*6*/ 176 '7', /*7*/ 177 '8', /*8*/ 178 '9', /*9*/ 179 '*', /***/ 180 '\04', /*minus*/ 181 '\01', /*fi*/ 182 '\02', /*fl*/ 183 '\03', /*ff*/ 184 '\020', /* cent sign */ 185 '\012', /*ffl*/ 186 '\011', /*ffi*/ 187 '(', /*(*/ 188 ')', /*)*/ 189 '[', /*[*/ 190 ']', /*]*/ 191 '\013', /* degree */ 192 '\014', /* dagger */ 193 '=', /*=*/ 194 '\017', /* registered */ 195 ':', /*:*/ 196 '+', /*+*/ 197 '\0', /*blank*/ 198 '!', /*!*/ 199 '\07', /* bullet */ 200 '?', /*?*/ 201 '\015', /*foot mark*/ 202 '|', /*|*/ 203 '\0', /*blank*/ 204 '\016', /* copyright */ 205 '\010', /* square */ 206 '$', /*$*/ 207 '\0', 208 '\0', 209 '"', /*"*/ 210 '#', /*#*/ 211 '<', /*<*/ 212 '>', /*>*/ 213 '@', /*@*/ 214 '\\', /*\\*/ 215 '^', /*^*/ 216 '{', /*{*/ 217 '}', /*}*/ 218 '~' /*~*/ 219 }; 220 221 char spectab[128] = { 222 '\0', /*blank*/ 223 'w', /*psi*/ 224 'h', /*theta*/ 225 'm', /*nu*/ 226 'l', /*mu*/ 227 'k', /*lambda*/ 228 'i', /*iota*/ 229 'f', /*zeta*/ 230 'r', /*sigma*/ 231 'd', /*delta*/ 232 'b', /*beta*/ 233 'n', /*xi*/ 234 'g', /*eta*/ 235 'u', /*phi*/ 236 't', /*upsilon*/ 237 'j', /*kappa*/ 238 '\0', /*blank*/ 239 'p', /*pi*/ 240 '@', /*at-sign*/ 241 '7', /*down arrow*/ 242 '\0', /*blank*/ 243 'a', /*alpha*/ 244 '|', /*or*/ 245 'v', /*chi*/ 246 '"', /*"*/ 247 'e', /*epsilon*/ 248 '=', /*=*/ 249 'o', /*omicron*/ 250 '4', /*left arrow*/ 251 'q', /*rho*/ 252 '6', /*up arrow*/ 253 's', /*tau*/ 254 '_', /*underrule*/ 255 '\\', /*\*/ 256 'W', /*Psi*/ 257 '\07', /*bell system sign*/ 258 '\001', /*infinity*/ 259 'c', /*gamma*/ 260 '\002', /*improper superset*/ 261 '\003', /*proportional to*/ 262 '\004', /*right hand*/ 263 'x', /*omega*/ 264 '\0', /*blank*/ 265 '(', /*gradient*/ 266 '\0', /*blank*/ 267 'U', /*Phi*/ 268 'H', /*Theta*/ 269 'X', /*Omega*/ 270 '\005', /*cup (union)*/ 271 '\006', /*root en*/ 272 '\014', /*terminal sigma*/ 273 'K', /*Lambda*/ 274 '-', /*minus*/ 275 'C', /*Gamma*/ 276 '\015', /*integral sign*/ 277 'P', /*Pi*/ 278 '\032', /*subset of*/ 279 '\033', /*superset of*/ 280 '2', /*approximates*/ 281 'y', /*partial derivative*/ 282 'D', /*Delta*/ 283 '\013', /*square root*/ 284 'R', /*Sigma*/ 285 '1', /*approx =*/ 286 '\0', /*blank*/ 287 '>', /*>*/ 288 'N', /*Xi*/ 289 '<', /*<*/ 290 '\016', /*slash (longer)*/ 291 '\034', /*cap (intersection)*/ 292 'T', /*Upsilon*/ 293 '\035', /*not*/ 294 '\023', /*right ceiling (rt of ")*/ 295 '\024', /*left top (of big curly)*/ 296 '\017', /*bold vertical*/ 297 '\030', /*left center of big curly bracket*/ 298 '\025', /*left bottom*/ 299 '\026', /*right top*/ 300 '\031', /*right center of big curly bracket*/ 301 '\027', /*right bot*/ 302 '\021', /*right floor (rb of ")*/ 303 '\020', /*left floor (left bot of big sq bract)*/ 304 '\022', /*left ceiling (lt of ")*/ 305 '*', /*multiply*/ 306 '/', /*divide*/ 307 '\010', /*plus-minus*/ 308 '\011', /*<=*/ 309 '\012', /*>=*/ 310 '0', /*identically equal*/ 311 '3', /*not equal*/ 312 '{', /*{*/ 313 '}', /*}*/ 314 '\'', /*' acute accent*/ 315 '\`', /*` grave accent*/ 316 '^', /*^*/ 317 '#', /*sharp*/ 318 '\036', /*left hand*/ 319 '\037', /*member of*/ 320 '~', /*~*/ 321 'z', /*empty set*/ 322 '\0', /*blank*/ 323 'Y', /*dbl dagger*/ 324 'Z', /*box rule*/ 325 '9', /*asterisk*/ 326 '[', /*improper subset*/ 327 ']', /*circle*/ 328 '\0', /*blank*/ 329 '+', /*eqn plus*/ 330 '5', /*right arrow*/ 331 '8' /*section mark*/ 332 }; 333 334 main(argc, argv) 335 int argc; 336 char *argv[]; 337 { 338 char *namearg = NULL; 339 char *hostarg = NULL; 340 char *acctfile = NULL; 341 342 while (--argc) { 343 if (*(*++argv) == '-') 344 switch (argv[0][1]) { 345 case 'x': 346 BYTES_PER_LINE = atoi(&argv[0][2]) / 8; 347 BUFFER_SIZE = NLINES * BYTES_PER_LINE; 348 varian = BYTES_PER_LINE == 264; 349 break; 350 351 case 'y': 352 PAGE_LINES = atoi(&argv[0][2]); 353 break; 354 355 case 'n': 356 if (argc > 1) { 357 argc--; 358 namearg = *++argv; 359 } 360 break; 361 362 case 'h': 363 if (argc > 1) { 364 argc--; 365 hostarg = *++argv; 366 } 367 break; 368 } 369 else 370 acctfile = *argv; 371 } 372 ioctl(vc, VSETSTATE, pltmode); 373 readrm(); 374 ofile(); 375 ioctl(vc, VSETSTATE, prtmode); 376 if (varian) 377 write(vc, "\f", 2); 378 else 379 write(vc, "\n\n\n\n\n", 6); 380 account(namearg, hostarg, acctfile); 381 exit(0); 382 } 383 384 readrm() 385 { 386 register int i; 387 register char *cp; 388 register int rmfd; 389 char c; 390 391 if ((rmfd = open(LOCAL_RAILMAG, 0)) < 0) 392 if ((rmfd = open(GLOBAL_RAILMAG, 0)) < 0) { 393 fprintf(stderr, "vcat: No railmag file\n"); 394 exit(2); 395 } 396 cp = fnbuf; 397 for (i = 0; i < MAXF; i++) { 398 fontname[i] = cp; 399 while (read(rmfd, &c, 1) == 1 && c != '\n') 400 *cp++ = c; 401 *cp++ = '\0'; 402 } 403 close(rmfd); 404 } 405 406 ofile() 407 { 408 register int c; 409 double scol; 410 static int initialized; 411 412 lines = 0; 413 while ((c = getchar()) != EOF) { 414 if (!c) 415 continue; 416 if (c & 0200) { 417 esc += (~c) & 0177; 418 continue; 419 } 420 if (esc) { 421 if (back) 422 esc = -esc; 423 col += esc; 424 ypos = CONVERT(col); 425 esc = 0; 426 } 427 if ((c & 0377) < 0100) /* Purely for efficiency */ 428 goto normal_char; 429 switch (c) { 430 431 case 0100: 432 if (initialized) 433 goto out; 434 initialized = 1; 435 row = 25; 436 xpos = CONVERT(row); 437 for (c = 0; c < BUFFER_SIZE; c++) 438 buffer[c] = 0; 439 col = 0; 440 esc = 0; 441 lead = 0; 442 ypos = 0; 443 linecount = 0; 444 verd = 0; 445 back = 0; 446 mcase = 0; 447 railmag = 0; 448 if (loadfont(railmag, cpsize) < 0) 449 fprintf(stderr, "vcat: Can't load inital font\n"); 450 break; 451 452 case 0101: /* lower rail */ 453 crail(railmag &= ~01); 454 break; 455 456 case 0102: /* upper rail */ 457 crail(railmag |= 01); 458 break; 459 460 case 0103: /* upper mag */ 461 crail(railmag |= 02); 462 break; 463 464 case 0104: /* lower mag */ 465 crail(railmag &= ~02); 466 break; 467 468 case 0105: /* lower case */ 469 mcase = 0; 470 break; 471 472 case 0106: /* upper case */ 473 mcase = 0100; 474 break; 475 476 case 0107: /* escape forward */ 477 back = 0; 478 break; 479 480 case 0110: /* escape backwards */ 481 back = 1; 482 break; 483 484 case 0111: /* stop */ 485 break; 486 487 case 0112: /* lead forward */ 488 verd = 0; 489 break; 490 491 case 0113: /* undefined */ 492 break; 493 494 case 0114: /* lead backward */ 495 verd = 1; 496 break; 497 498 case 0115: /* undefined */ 499 case 0116: 500 case 0117: 501 break; 502 503 default: 504 if ((c & 0340) == 0140) /* leading */ { 505 lead = (~c) & 037; 506 if (verd) 507 lead = -lead; 508 row += lead*3; /* Lead is 3 units */ 509 c = CONVERT(row); 510 while (c >= NLINES) { 511 slop_lines(15); 512 c = CONVERT(row); 513 } 514 xpos = c; 515 continue; 516 } 517 if ((c & 0360) == 0120) /* size change */ { 518 loadfont(railmag, findsize(c & 017)); 519 continue; 520 } 521 if (c & 0300) 522 continue; 523 524 normal_char: 525 c = (c & 077) | mcase; 526 outc(c); 527 } 528 } 529 out: 530 slop_lines(NLINES); 531 } 532 533 findsize(code) 534 register int code; 535 { 536 register struct point_sizes *psp; 537 538 psp = point_sizes; 539 while (psp->real_code != 0) { 540 if ((psp->stupid_code & 017) == code) 541 break; 542 psp++; 543 } 544 code = 0; 545 if (!(last_ssize & 0200) && (psp->stupid_code & 0200)) 546 code = -55; 547 else if ((last_ssize & 0200) && !(psp->stupid_code & 0200)) 548 code = 55; 549 if (back) 550 code = -code; 551 esc += code; 552 last_ssize = psp->stupid_code; 553 return(psp->real_code); 554 } 555 556 account(who, from, acctfile) 557 char *who, *from, *acctfile; 558 { 559 register FILE *a; 560 561 if (who == NULL || acctfile == NULL) 562 return; 563 if (access(acctfile, 02) || (a = fopen(acctfile, "a")) == NULL) 564 return; 565 /* 566 * Varian accounting is done by 8.5 inch pages; 567 * Versatec accounting is by the (12 inch) foot. 568 */ 569 fprintf(a, "t%6.2f\t", (lines / 200.0) / PAGE_LINES); 570 if (from != NULL) 571 fprintf(a, "%s:", from); 572 fprintf(a, "%s\n", who); 573 fclose(a); 574 } 575 576 crail(nrail) 577 register int nrail; 578 { 579 register int psize; 580 581 psize = cpsize; 582 if (fontwanted && psize != npsize) 583 psize = npsize; 584 loadfont(nrail, psize); 585 } 586 587 588 loadfont(fnum, size) 589 register int fnum; 590 register int size; 591 { 592 register int i; 593 char cbuf[80]; 594 595 fontwanted = 0; 596 if (fnum == cfnum && size == cpsize) 597 return(0); 598 for (i = 0; i < NFONTS; i++) 599 if (fontdes[i].fnum == fnum && fontdes[i].psize == size) { 600 cfnum = fontdes[i].fnum; 601 cpsize = fontdes[i].psize; 602 dispatch = &fontdes[i].disp[0]; 603 bits = fontdes[i].bits; 604 cfont = i; 605 return(0); 606 } 607 if (fnum < 0 || fnum >= MAXF) { 608 fprintf(stderr, "vcat: Internal error: illegal font\n"); 609 return(-1); 610 } 611 nfontnum = fnum; 612 npsize = size; 613 fontwanted++; 614 return(0); 615 } 616 617 618 getfont() 619 { 620 register int fnum, size, font; 621 int d; 622 char cbuf[BUFSIZ]; 623 624 if (!fontwanted) 625 return(0); 626 fnum = nfontnum; 627 size = npsize; 628 sprintf(cbuf, "%s.%d", fontname[fnum], size); 629 font = open(cbuf, 0); 630 if (font == -1) { 631 fprintf(stderr, "vcat: "); 632 perror(cbuf); 633 fontwanted = 0; 634 return(-1); 635 } 636 if (read(font, &header, sizeof header)!=sizeof header || header.magic!=0436) 637 fprintf(stderr, "vcat: %s: Bad font file", cbuf); 638 else { 639 cfont = relfont(); 640 if (((bits=nalloc(header.size+DSIZ+1,1))== NULL) 641 && ((bits=allpanic(header.size+DSIZ+1))== NULL)) { 642 fprintf(stderr, "vcat: %s: ran out of memory\n", cbuf); 643 exit(2); 644 } else { 645 /* 646 * have allocated one chunk of mem for font, dispatch. 647 * get the dispatch addr, align to word boundary. 648 */ 649 d = (int) bits+header.size; 650 d += 1; 651 d &= ~1; 652 if (read(font, d, DSIZ)!=DSIZ 653 || read(font, bits, header.size)!=header.size) 654 fprintf(stderr, "vcat: bad font header"); 655 else { 656 close(font); 657 cfnum = fontdes[cfont].fnum = fnum; 658 cpsize = fontdes[cfont].psize = size; 659 fontdes[cfont].bits = bits; 660 fontdes[cfont].disp = (struct dispatch *) d; 661 dispatch = &fontdes[cfont].disp[0]; 662 fontwanted = 0; 663 return(0); 664 } 665 } 666 } 667 close(font); 668 fontwanted = 0; 669 return(-1); 670 } 671 672 int lastloaded = -1; 673 674 relfont() 675 { 676 register int newfont; 677 678 newfont = lastloaded; 679 /* 680 * optimization for special font. since we think that usually 681 * there is only one character at a time from any special math 682 * font, make it the candidate for removal. 683 */ 684 if (fontdes[cfont].fnum != SPECIALFONT || fontdes[cfont].bits==0) 685 if (++newfont>=NFONTS) 686 newfont = 0; 687 lastloaded = newfont; 688 if ((int)fontdes[newfont].bits != -1 && fontdes[newfont].bits != 0) 689 nfree(fontdes[newfont].bits); 690 fontdes[newfont].bits = 0; 691 return(newfont); 692 } 693 694 char * 695 allpanic(nbytes) 696 int nbytes; 697 { 698 register int i; 699 700 for (i = 0; i <= NFONTS; i++) 701 if (fontdes[i].bits != (char *)-1 && fontdes[i].bits != (char *)0) 702 nfree(fontdes[i].bits); 703 lastloaded = cfont; 704 for (i = 0; i <= NFONTS; i++) { 705 fontdes[i].fnum = fontdes[i].psize = -1; 706 fontdes[i].bits = 0; 707 cfnum = cpsize = -1; 708 } 709 return(nalloc(nbytes,1)); 710 } 711 712 int M[] = { 0xffffffff, 0xfefefefe, 0xfcfcfcfc, 0xf8f8f8f8, 713 0xf0f0f0f0, 0xe0e0e0e0, 0xc0c0c0c0, 0x80808080, 0x0 }; 714 int N[] = { 0x00000000, 0x01010101, 0x03030303, 0x07070707, 715 0x0f0f0f0f, 0x1f1f1f1f, 0x3f3f3f3f, 0x7f7f7f7f, 0xffffffff }; 716 int strim[] = { 0xffffffff, 0xffffff00, 0xffff0000, 0xff000000, 0 }; 717 718 outc(code) 719 int code; 720 { 721 char c; /* character to print */ 722 register struct dispatch *d; /* ptr to character font record */ 723 register char *addr; /* addr of font data */ 724 int llen; /* length of each font line */ 725 int nlines; /* number of font lines */ 726 register char *scanp; /* ptr to output buffer */ 727 int scanp_inc; /* increment to start of next buffer */ 728 int offset; /* bit offset to start of font data */ 729 int i; /* loop counter */ 730 register int count; /* font data ptr */ 731 register unsigned fontdata; /* font data temporary */ 732 register int off8; /* offset + 8 */ 733 734 if (fontwanted) 735 getfont(); 736 if (railmag == SPECIALFONT) { 737 if ((c = spectab[code]) < 0) 738 return(0); 739 } else if ((c = asctab[code]) < 0) 740 return(0); 741 d = dispatch+c; 742 if (d->nbytes) { 743 addr = bits+d->addr; 744 llen = (d->left+d->right+7)/8; 745 nlines = d->up+d->down; 746 if (xpos+d->down >= NLINES) 747 slop_lines(xpos+d->down-NLINES+1); 748 scanp = ((xpos-d->up-1)*BYTES_PER_LINE+(ypos-d->left)/8)+buf0p; 749 if (scanp < &buffer[0]) 750 scanp += BUFFER_SIZE; 751 scanp_inc = BYTES_PER_LINE-llen; 752 offset = -((ypos-d->left)&07); 753 off8 = offset+8; 754 for (i = 0; i < nlines; i++) { 755 if (scanp >= &buffer[BUFFER_SIZE]) 756 scanp -= BUFFER_SIZE; 757 count = llen; 758 if (scanp + count <= &buffer[BUFFER_SIZE]) 759 do { 760 fontdata = *(unsigned *)addr; 761 addr += 4; 762 if (count < 4) 763 fontdata &= ~strim[count]; 764 *(unsigned *)scanp |= (fontdata << offset) &~ M[off8]; 765 scanp++; 766 *(unsigned *)scanp |= (fontdata << off8) &~ N[off8]; 767 scanp += 3; 768 count -= 4; 769 } while (count > 0); 770 scanp += scanp_inc+count; 771 addr += count; 772 } 773 return(1); 774 } 775 return(0); 776 } 777 778 slop_lines(nlines) 779 int nlines; 780 { 781 register int i, rlines; 782 783 lines += nlines; 784 rlines = (&buffer[BUFFER_SIZE] - buf0p) / BYTES_PER_LINE; 785 if (rlines < nlines) { 786 if (write(vc, buf0p, BYTES_PER_LINE * rlines) < 0) 787 exit(1); 788 clear(buf0p, rlines * BYTES_PER_LINE); 789 buf0p = buffer; 790 nlines -= rlines; 791 xpos -= rlines; 792 row -= RECONVERT(rlines); 793 } 794 if (write(vc, buf0p, BYTES_PER_LINE * nlines) < 0) 795 exit(1); 796 clear(buf0p, BYTES_PER_LINE * nlines); 797 buf0p += BYTES_PER_LINE * nlines; 798 if (buf0p >= &buffer[BUFFER_SIZE]) 799 buf0p -= BUFFER_SIZE; 800 xpos -= nlines; 801 row -= RECONVERT(nlines); 802 /* ioctl(vc, VSETSTATE, pltmode); WHY? */ 803 } 804 805 /*ARGSUSED*/ 806 clear(lp, nbytes) 807 int *lp; 808 int nbytes; 809 { 810 asm("movc5 $0,(sp),$0,8(ap),*4(ap)"); 811 } 812 813 char * 814 nalloc(i, j) 815 int i, j; 816 { 817 register char *cp; 818 819 cp = calloc(i, j); 820 return(cp); 821 } 822 823 nfree(cp) 824 char *cp; 825 { 826 free(cp); 827 } 828