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