|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /* Copyright (c) 1997 Apple Computer, Inc. All Rights Reserved */
23: /*
24: * Copyright (c) 1993, 1994 Theo de Raadt
25: * All rights reserved.
26: *
27: * Redistribution and use in source and binary forms, with or without
28: * modification, are permitted provided that the following conditions
29: * are met:
30: * 1. Redistributions of source code must retain the above copyright
31: * notice unmodified, this list of conditions, and the following
32: * disclaimer.
33: * 2. Redistributions in binary form must reproduce the above copyright
34: * notice, this list of conditions and the following disclaimer in the
35: * documentation and/or other materials provided with the distribution.
36: *
37: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
38: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
39: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
40: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
41: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
42: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
43: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
45: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
46: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47: * SUCH DAMAGE.
48: *
49: */
50:
51: #ifdef NeXT
52: /*
53: * We use the NetBSD based clist system, it is much more efficient than the
54: * old style clist stuff used by free bsd.
55: */
56:
57: #include <sys/param.h>
58: #include <sys/systm.h>
59: #include <sys/buf.h>
60: #include <sys/ioctl.h>
61: #include <sys/tty.h>
62: #include <sys/malloc.h>
63:
64: #include <machine/spl.h>
65:
66: /*
67: * At compile time, choose:
68: * There are two ways the TTY_QUOTE bit can be stored. If QBITS is
69: * defined we allocate an array of bits -- 1/8th as much memory but
70: * setbit(), clrbit(), and isset() take more cpu. If QBITS is
71: * undefined, we just use an array of bytes.
72: *
73: * If TTY_QUOTE functionality isn't required by a line discipline,
74: * it can free c_cq and set it to NULL. This speeds things up,
75: * and also does not use any extra memory. This is useful for (say)
76: * a SLIP line discipline that wants a 32K ring buffer for data
77: * but doesn't need quoting.
78: */
79: #define QBITS
80:
81: #ifdef QBITS
82: #define QMEM(n) ((((n)-1)/NBBY)+1)
83: #else
84: #define QMEM(n) (n)
85: #endif
86:
87:
88: /*
89: * Initialize clists.
90: */
91: void
92: cinit()
93: {
94: }
95:
96: /*
97: * Initialize a particular clist. Ok, they are really ring buffers,
98: * of the specified length, with/without quoting support.
99: */
100: int
101: clalloc(clp, size, quot)
102: struct clist *clp;
103: int size;
104: int quot;
105: {
106:
107: MALLOC(clp->c_cs, u_char *, size, M_TTYS, M_WAITOK);
108: if (!clp->c_cs)
109: return (-1);
110: bzero(clp->c_cs, size);
111:
112: if(quot) {
113: MALLOC(clp->c_cq, u_char *, QMEM(size), M_TTYS, M_WAITOK);
114: if (!clp->c_cq) {
115: FREE(clp->c_cs, M_TTYS);
116: return (-1);
117: }
118: bzero(clp->c_cs, QMEM(size));
119: } else
120: clp->c_cq = (u_char *)0;
121:
122: clp->c_cf = clp->c_cl = (u_char *)0;
123: clp->c_ce = clp->c_cs + size;
124: clp->c_cn = size;
125: clp->c_cc = 0;
126: return (0);
127: }
128:
129: void
130: clfree(clp)
131: struct clist *clp;
132: {
133: if(clp->c_cs)
134: FREE(clp->c_cs, M_TTYS);
135: if(clp->c_cq)
136: FREE(clp->c_cq, M_TTYS);
137: clp->c_cs = clp->c_cq = (u_char *)0;
138: }
139:
140:
141: /*
142: * Get a character from a clist.
143: */
144: int
145: getc(clp)
146: struct clist *clp;
147: {
148: register int c = -1;
149: int s;
150:
151: s = spltty();
152: if (clp->c_cc == 0)
153: goto out;
154:
155: c = *clp->c_cf & 0xff;
156: if (clp->c_cq) {
157: #ifdef QBITS
158: if (isset(clp->c_cq, clp->c_cf - clp->c_cs) )
159: c |= TTY_QUOTE;
160: #else
161: if (*(clp->c_cf - clp->c_cs + clp->c_cq))
162: c |= TTY_QUOTE;
163: #endif
164: }
165: if (++clp->c_cf == clp->c_ce)
166: clp->c_cf = clp->c_cs;
167: if (--clp->c_cc == 0)
168: clp->c_cf = clp->c_cl = (u_char *)0;
169: out:
170: splx(s);
171: return c;
172: }
173:
174: /*
175: * Copy clist to buffer.
176: * Return number of bytes moved.
177: */
178: int
179: q_to_b(clp, cp, count)
180: struct clist *clp;
181: u_char *cp;
182: int count;
183: {
184: register int cc;
185: u_char *p = cp;
186: int s;
187:
188: s = spltty();
189: /* optimize this while loop */
190: while (count > 0 && clp->c_cc > 0) {
191: cc = clp->c_cl - clp->c_cf;
192: if (clp->c_cf >= clp->c_cl)
193: cc = clp->c_ce - clp->c_cf;
194: if (cc > count)
195: cc = count;
196: bcopy(clp->c_cf, p, cc);
197: count -= cc;
198: p += cc;
199: clp->c_cc -= cc;
200: clp->c_cf += cc;
201: if (clp->c_cf == clp->c_ce)
202: clp->c_cf = clp->c_cs;
203: }
204: if (clp->c_cc == 0)
205: clp->c_cf = clp->c_cl = (u_char *)0;
206: splx(s);
207: return p - cp;
208: }
209:
210: /*
211: * Return count of contiguous characters in clist.
212: * Stop counting if flag&character is non-null.
213: */
214: int
215: ndqb(clp, flag)
216: struct clist *clp;
217: int flag;
218: {
219: int count = 0;
220: register int i;
221: register int cc;
222: int s;
223:
224: s = spltty();
225: if ((cc = clp->c_cc) == 0)
226: goto out;
227:
228: if (flag == 0) {
229: count = clp->c_cl - clp->c_cf;
230: if (count <= 0)
231: count = clp->c_ce - clp->c_cf;
232: goto out;
233: }
234:
235: i = clp->c_cf - clp->c_cs;
236: if (flag & TTY_QUOTE) {
237: while (cc-- > 0 && !(clp->c_cs[i++] & (flag & ~TTY_QUOTE) ||
238: isset(clp->c_cq, i))) {
239: count++;
240: if (i == clp->c_cn)
241: break;
242: }
243: } else {
244: while (cc-- > 0 && !(clp->c_cs[i++] & flag)) {
245: count++;
246: if (i == clp->c_cn)
247: break;
248: }
249: }
250: out:
251: splx(s);
252: return count;
253: }
254:
255: /*
256: * Flush count bytes from clist.
257: */
258: void
259: ndflush(clp, count)
260: struct clist *clp;
261: int count;
262: {
263: register int cc;
264: int s;
265:
266: s = spltty();
267: if (count == clp->c_cc) {
268: clp->c_cc = 0;
269: clp->c_cf = clp->c_cl = (u_char *)0;
270: goto out;
271: }
272: /* optimize this while loop */
273: while (count > 0 && clp->c_cc > 0) {
274: cc = clp->c_cl - clp->c_cf;
275: if (clp->c_cf >= clp->c_cl)
276: cc = clp->c_ce - clp->c_cf;
277: if (cc > count)
278: cc = count;
279: count -= cc;
280: clp->c_cc -= cc;
281: clp->c_cf += cc;
282: if (clp->c_cf == clp->c_ce)
283: clp->c_cf = clp->c_cs;
284: }
285: if (clp->c_cc == 0)
286: clp->c_cf = clp->c_cl = (u_char *)0;
287: out:
288: splx(s);
289: }
290:
291: /*
292: * Put a character into the output queue.
293: */
294: int
295: putc(c, clp)
296: int c;
297: struct clist *clp;
298: {
299: register int i;
300: int s;
301:
302: s = spltty();
303: if (clp->c_cc == 0) {
304: if (!clp->c_cs) {
305: #if DIAGNOSTIC
306: //printf("putc: required clalloc\n");
307: #endif
308: if(clalloc(clp, 1024, 1)) {
309: out:
310: splx(s);
311: return -1;
312: }
313: }
314: clp->c_cf = clp->c_cl = clp->c_cs;
315: }
316:
317: if (clp->c_cc == clp->c_cn)
318: goto out;
319:
320: *clp->c_cl = c & 0xff;
321: i = clp->c_cl - clp->c_cs;
322: if (clp->c_cq) {
323: #ifdef QBITS
324: if (c & TTY_QUOTE)
325: setbit(clp->c_cq, i);
326: else
327: clrbit(clp->c_cq, i);
328: #else
329: q = clp->c_cq + i;
330: *q = (c & TTY_QUOTE) ? 1 : 0;
331: #endif
332: }
333: clp->c_cc++;
334: clp->c_cl++;
335: if (clp->c_cl == clp->c_ce)
336: clp->c_cl = clp->c_cs;
337: splx(s);
338: return 0;
339: }
340:
341: #ifdef QBITS
342: /*
343: * optimized version of
344: *
345: * for (i = 0; i < len; i++)
346: * clrbit(cp, off + len);
347: */
348: void
349: clrbits(cp, off, len)
350: u_char *cp;
351: int off;
352: int len;
353: {
354: int sby, sbi, eby, ebi;
355: register int i;
356: u_char mask;
357:
358: if(len==1) {
359: clrbit(cp, off);
360: return;
361: }
362:
363: sby = off / NBBY;
364: sbi = off % NBBY;
365: eby = (off+len) / NBBY;
366: ebi = (off+len) % NBBY;
367: if (sby == eby) {
368: mask = ((1 << (ebi - sbi)) - 1) << sbi;
369: cp[sby] &= ~mask;
370: } else {
371: mask = (1<<sbi) - 1;
372: cp[sby++] &= mask;
373:
374: mask = (1<<ebi) - 1;
375: cp[eby] &= ~mask;
376:
377: for (i = sby; i < eby; i++)
378: cp[i] = 0x00;
379: }
380: }
381: #endif
382:
383: /*
384: * Copy buffer to clist.
385: * Return number of bytes not transfered.
386: */
387: int
388: b_to_q(cp, count, clp)
389: u_char *cp;
390: int count;
391: struct clist *clp;
392: {
393: register int cc;
394: register u_char *p = cp;
395: int s;
396:
397: if (count <= 0)
398: return 0;
399:
400: s = spltty();
401:
402: if (clp->c_cc == 0) {
403: if (!clp->c_cs) {
404: #if DIAGNOSTIC
405: printf("b_to_q: required clalloc\n");
406: #endif
407: if(clalloc(clp, 1024, 1))
408: goto out;
409: }
410: clp->c_cf = clp->c_cl = clp->c_cs;
411: }
412:
413: if (clp->c_cc == clp->c_cn)
414: goto out;
415:
416: /* optimize this while loop */
417: while (count > 0 && clp->c_cc < clp->c_cn) {
418: cc = clp->c_ce - clp->c_cl;
419: if (clp->c_cf > clp->c_cl)
420: cc = clp->c_cf - clp->c_cl;
421: if (cc > count)
422: cc = count;
423: bcopy(p, clp->c_cl, cc);
424: if (clp->c_cq) {
425: #ifdef QBITS
426: clrbits(clp->c_cq, clp->c_cl - clp->c_cs, cc);
427: #else
428: bzero(clp->c_cl - clp->c_cs + clp->c_cq, cc);
429: #endif
430: }
431: p += cc;
432: count -= cc;
433: clp->c_cc += cc;
434: clp->c_cl += cc;
435: if (clp->c_cl == clp->c_ce)
436: clp->c_cl = clp->c_cs;
437: }
438: out:
439: splx(s);
440: return count;
441: }
442:
443: static int cc;
444:
445: /*
446: * Given a non-NULL pointer into the clist return the pointer
447: * to the next character in the list or return NULL if no more chars.
448: *
449: * Callers must not allow getc's to happen between firstc's and getc's
450: * so that the pointer becomes invalid. Note that interrupts are NOT
451: * masked.
452: */
453: u_char *
454: nextc(clp, cp, c)
455: struct clist *clp;
456: register u_char *cp;
457: int *c;
458: {
459:
460: if (clp->c_cf == cp) {
461: /*
462: * First time initialization.
463: */
464: cc = clp->c_cc;
465: }
466: if (cc == 0 || cp == NULL)
467: return NULL;
468: if (--cc == 0)
469: return NULL;
470: if (++cp == clp->c_ce)
471: cp = clp->c_cs;
472: *c = *cp & 0xff;
473: if (clp->c_cq) {
474: #ifdef QBITS
475: if (isset(clp->c_cq, cp - clp->c_cs))
476: *c |= TTY_QUOTE;
477: #else
478: if (*(clp->c_cf - clp->c_cs + clp->c_cq))
479: *c |= TTY_QUOTE;
480: #endif
481: }
482: return cp;
483: }
484:
485: /*
486: * Given a non-NULL pointer into the clist return the pointer
487: * to the first character in the list or return NULL if no more chars.
488: *
489: * Callers must not allow getc's to happen between firstc's and getc's
490: * so that the pointer becomes invalid. Note that interrupts are NOT
491: * masked.
492: *
493: * *c is set to the NEXT character
494: */
495: u_char *
496: firstc(clp, c)
497: struct clist *clp;
498: int *c;
499: {
500: register u_char *cp;
501:
502: cc = clp->c_cc;
503: if (cc == 0)
504: return NULL;
505: cp = clp->c_cf;
506: *c = *cp & 0xff;
507: if(clp->c_cq) {
508: #ifdef QBITS
509: if (isset(clp->c_cq, cp - clp->c_cs))
510: *c |= TTY_QUOTE;
511: #else
512: if (*(cp - clp->c_cs + clp->c_cq))
513: *c |= TTY_QUOTE;
514: #endif
515: }
516: return clp->c_cf;
517: }
518:
519: /*
520: * Remove the last character in the clist and return it.
521: */
522: int
523: unputc(clp)
524: struct clist *clp;
525: {
526: unsigned int c = -1;
527: int s;
528:
529: s = spltty();
530: if (clp->c_cc == 0)
531: goto out;
532:
533: if (clp->c_cl == clp->c_cs)
534: clp->c_cl = clp->c_ce - 1;
535: else
536: --clp->c_cl;
537: clp->c_cc--;
538:
539: c = *clp->c_cl & 0xff;
540: if (clp->c_cq) {
541: #ifdef QBITS
542: if (isset(clp->c_cq, clp->c_cl - clp->c_cs))
543: c |= TTY_QUOTE;
544: #else
545: if (*(clp->c_cf - clp->c_cs + clp->c_cq))
546: c |= TTY_QUOTE;
547: #endif
548: }
549: if (clp->c_cc == 0)
550: clp->c_cf = clp->c_cl = (u_char *)0;
551: out:
552: splx(s);
553: return c;
554: }
555:
556: /*
557: * Put the chars in the from queue on the end of the to queue.
558: */
559: void
560: catq(from, to)
561: struct clist *from, *to;
562: {
563: int c;
564:
565: while ((c = getc(from)) != -1)
566: putc(c, to);
567: }
568:
569: #endif /* NeXT */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.