|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1986 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: * @(#)tty_subr.c 7.5 (Berkeley) 5/15/90
7: */
8:
9: #include "param.h"
10: #include "systm.h"
11: #include "buf.h"
12: #include "ioctl.h"
13: #include "tty.h"
14: #include "clist.h"
15:
16: char cwaiting;
17:
18: #define setquote(cp) \
19: setbit(((char *)((int)(cp)&~CROUND)+sizeof(struct cblock *)), \
20: (int)(cp)&CROUND)
21: #define isquote(cp) \
22: isset(((char *)((int)(cp)&~CROUND)+sizeof(struct cblock *)), \
23: (int)(cp)&CROUND)
24: #define cbptr(x) ((struct cblock *)(x))
25:
26: /*
27: * Character list get/put
28: */
29: getc(p)
30: register struct clist *p;
31: {
32: register struct cblock *bp;
33: register int c, s;
34:
35: s = spltty();
36: if (p->c_cc <= 0) {
37: c = -1;
38: p->c_cc = 0;
39: p->c_cf = p->c_cl = NULL;
40: } else {
41: c = *p->c_cf & 0377;
42: if (isquote(p->c_cf))
43: c |= TTY_QUOTE;
44: p->c_cf++;
45: if (--p->c_cc<=0) {
46: bp = cbptr(p->c_cf-1);
47: bp = cbptr((int)bp & ~CROUND);
48: p->c_cf = NULL;
49: p->c_cl = NULL;
50: bp->c_next = cfreelist;
51: cfreelist = bp;
52: cfreecount += CBSIZE;
53: if (cwaiting) {
54: wakeup(&cwaiting);
55: cwaiting = 0;
56: }
57: } else if (((int)p->c_cf & CROUND) == 0){
58: bp = cbptr(p->c_cf);
59: bp--;
60: p->c_cf = bp->c_next->c_info;
61: bp->c_next = cfreelist;
62: cfreelist = bp;
63: cfreecount += CBSIZE;
64: if (cwaiting) {
65: wakeup(&cwaiting);
66: cwaiting = 0;
67: }
68: }
69: }
70: splx(s);
71: return (c);
72: }
73:
74: /*
75: * copy clist to buffer.
76: * return number of bytes moved.
77: */
78: q_to_b(q, cp, cc)
79: register struct clist *q;
80: register char *cp;
81: {
82: register struct cblock *bp;
83: register int s;
84: register nc;
85: char *acp;
86:
87: if (cc <= 0)
88: return (0);
89: s = spltty();
90: if (q->c_cc <= 0) {
91: q->c_cc = 0;
92: q->c_cf = q->c_cl = NULL;
93: splx(s);
94: return (0);
95: }
96: acp = cp;
97:
98: while (cc) {
99: nc = sizeof (struct cblock) - ((int)q->c_cf & CROUND);
100: nc = MIN(nc, cc);
101: nc = MIN(nc, q->c_cc);
102: (void) bcopy(q->c_cf, cp, (unsigned)nc);
103: q->c_cf += nc;
104: q->c_cc -= nc;
105: cc -= nc;
106: cp += nc;
107: if (q->c_cc <= 0) {
108: bp = cbptr(q->c_cf - 1);
109: bp = cbptr((int)bp & ~CROUND);
110: q->c_cf = q->c_cl = NULL;
111: bp->c_next = cfreelist;
112: cfreelist = bp;
113: cfreecount += CBSIZE;
114: if (cwaiting) {
115: wakeup(&cwaiting);
116: cwaiting = 0;
117: }
118: break;
119: }
120: if (((int)q->c_cf & CROUND) == 0) {
121: bp = cbptr(q->c_cf);
122: bp--;
123: q->c_cf = bp->c_next->c_info;
124: bp->c_next = cfreelist;
125: cfreelist = bp;
126: cfreecount += CBSIZE;
127: if (cwaiting) {
128: wakeup(&cwaiting);
129: cwaiting = 0;
130: }
131: }
132: }
133: splx(s);
134: return (cp-acp);
135: }
136:
137: /*
138: * Return count of contiguous characters
139: * in clist starting at q->c_cf.
140: * Stop counting if flag&character is non-null.
141: */
142: ndqb(q, flag)
143: register struct clist *q;
144: {
145: register cc;
146: int s;
147:
148: s = spltty();
149: if (q->c_cc <= 0) {
150: cc = -q->c_cc;
151: goto out;
152: }
153: cc = ((int)q->c_cf + CBSIZE) & ~CROUND;
154: cc -= (int)q->c_cf;
155: if (q->c_cc < cc)
156: cc = q->c_cc;
157: if (flag) {
158: register char *p, *end;
159:
160: p = q->c_cf;
161: end = p;
162: end += cc;
163: while (p < end) {
164: if (*p & flag) {
165: cc = (int)p;
166: cc -= (int)q->c_cf;
167: break;
168: }
169: p++;
170: }
171: }
172: out:
173: splx(s);
174: return (cc);
175: }
176:
177: /*
178: * Flush cc bytes from q.
179: */
180: ndflush(q, cc)
181: register struct clist *q;
182: register cc;
183: {
184: register struct cblock *bp;
185: char *end;
186: int rem, s;
187:
188: s = spltty();
189: if (q->c_cc <= 0)
190: goto out;
191: while (cc>0 && q->c_cc) {
192: bp = cbptr((int)q->c_cf & ~CROUND);
193: if ((int)bp == (((int)q->c_cl-1) & ~CROUND)) {
194: end = q->c_cl;
195: } else {
196: end = (char *)((int)bp + sizeof (struct cblock));
197: }
198: rem = end - q->c_cf;
199: if (cc >= rem) {
200: cc -= rem;
201: q->c_cc -= rem;
202: q->c_cf = bp->c_next->c_info;
203: bp->c_next = cfreelist;
204: cfreelist = bp;
205: cfreecount += CBSIZE;
206: if (cwaiting) {
207: wakeup(&cwaiting);
208: cwaiting = 0;
209: }
210: } else {
211: q->c_cc -= cc;
212: q->c_cf += cc;
213: if (q->c_cc <= 0) {
214: bp->c_next = cfreelist;
215: cfreelist = bp;
216: cfreecount += CBSIZE;
217: if (cwaiting) {
218: wakeup(&cwaiting);
219: cwaiting = 0;
220: }
221: }
222: break;
223: }
224: }
225: if (q->c_cc <= 0) {
226: q->c_cf = q->c_cl = NULL;
227: q->c_cc = 0;
228: }
229: out:
230: splx(s);
231: }
232:
233:
234: putc(c, p)
235: register struct clist *p;
236: {
237: register struct cblock *bp;
238: register char *cp;
239: register s;
240:
241: s = spltty();
242: if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) { /* no cblocks yet */
243: if ((bp = cfreelist) == NULL) {
244: splx(s);
245: return (-1);
246: }
247: cfreelist = bp->c_next;
248: cfreecount -= CBSIZE;
249: bp->c_next = NULL;
250: bzero(bp->c_quote, CBQSIZE);
251: p->c_cf = cp = bp->c_info;
252: } else if (((int)cp & CROUND) == 0) {
253: bp = cbptr(cp) - 1; /* pointer arith */
254: if ((bp->c_next = cfreelist) == NULL) {
255: splx(s);
256: return (-1);
257: }
258: bp = bp->c_next;
259: cfreelist = bp->c_next;
260: cfreecount -= CBSIZE;
261: bp->c_next = NULL;
262: cp = bp->c_info;
263: }
264: if (c&TTY_QUOTE)
265: setquote(cp);
266: *cp++ = c;
267: p->c_cc++;
268: p->c_cl = cp;
269: splx(s);
270: return (0);
271: }
272:
273: /*
274: * copy buffer to clist.
275: * return number of bytes not transfered.
276: */
277: b_to_q(cp, cc, q)
278: register char *cp;
279: struct clist *q;
280: register int cc;
281: {
282: register char *cq;
283: register struct cblock *bp;
284: register s, nc;
285: int acc;
286:
287: if (cc <= 0)
288: return (0);
289: acc = cc;
290: s = spltty();
291: if ((cq = q->c_cl) == NULL || q->c_cc < 0) {
292: if ((bp = cfreelist) == NULL)
293: goto out;
294: cfreelist = bp->c_next;
295: cfreecount -= CBSIZE;
296: bzero(bp->c_quote, CBQSIZE);
297: bp->c_next = NULL;
298: q->c_cf = cq = bp->c_info;
299: }
300:
301: while (cc) {
302: if (((int)cq & CROUND) == 0) {
303: bp = cbptr(cq) - 1;
304: if ((bp->c_next = cfreelist) == NULL)
305: goto out;
306: bp = bp->c_next;
307: cfreelist = bp->c_next;
308: cfreecount -= CBSIZE;
309: bzero(bp->c_quote, CBQSIZE);
310: bp->c_next = NULL;
311: cq = bp->c_info;
312: }
313: nc = MIN(cc, sizeof (struct cblock) - ((int)cq & CROUND));
314: (void) bcopy(cp, cq, (unsigned)nc);
315: cp += nc;
316: cq += nc;
317: cc -= nc;
318: }
319: out:
320: q->c_cl = cq;
321: q->c_cc += acc - cc;
322: splx(s);
323: return (cc);
324: }
325:
326: /*
327: * Given a non-NULL pointter into the list (like c_cf which
328: * always points to a real character if non-NULL) return the pointer
329: * to the next character in the list or return NULL if no more chars.
330: *
331: * Callers must not allow getc's to happen between nextc's so that the
332: * pointer becomes invalid. Note that interrupts are NOT masked.
333: */
334: char *
335: nextc(p, cp, c)
336: register struct clist *p;
337: register char *cp;
338: register int *c;
339: {
340:
341: if (p->c_cc && ++cp != p->c_cl) {
342: if (((int)cp & CROUND) == 0) {
343: cp = (cbptr(cp))[-1].c_next->c_info;
344: }
345: *c = *cp;
346: if (isquote(cp))
347: *c |= TTY_QUOTE;
348: return (cp);
349: }
350: return (0);
351: }
352:
353: /*
354: * Remove the last character in the list and return it.
355: */
356: unputc(p)
357: register struct clist *p;
358: {
359: register struct cblock *bp;
360: register int c, s;
361: struct cblock *obp;
362:
363: s = spltty();
364: if (p->c_cc <= 0)
365: c = -1;
366: else {
367: c = *--p->c_cl;
368: if (isquote(p->c_cl))
369: c |= TTY_QUOTE;
370: if (--p->c_cc <= 0) {
371: bp = cbptr(p->c_cl);
372: bp = cbptr((int)bp & ~CROUND);
373: p->c_cl = p->c_cf = NULL;
374: bp->c_next = cfreelist;
375: cfreelist = bp;
376: cfreecount += CBSIZE;
377: } else if (p->c_cl == (cbptr((int)p->c_cl & ~CROUND))->c_info) {
378: p->c_cl = (char *)((int)p->c_cl & ~CROUND);
379:
380: bp = cbptr(p->c_cf);
381: bp = cbptr((int)bp & ~CROUND);
382: while (bp->c_next != cbptr(p->c_cl))
383: bp = bp->c_next;
384: obp = bp;
385: p->c_cl = (char *)(bp + 1);
386: bp = bp->c_next;
387: bp->c_next = cfreelist;
388: cfreelist = bp;
389: cfreecount += CBSIZE;
390: obp->c_next = NULL;
391: }
392: }
393: splx(s);
394: return (c);
395: }
396:
397: /*
398: * Put the chars in the from que
399: * on the end of the to que.
400: */
401: catq(from, to)
402: struct clist *from, *to;
403: {
404: #ifdef notdef
405: char bbuf[CBSIZE*4];
406: #endif
407: register s, c;
408:
409: s = spltty();
410: if (to->c_cc == 0) {
411: *to = *from;
412: from->c_cc = 0;
413: from->c_cf = NULL;
414: from->c_cl = NULL;
415: splx(s);
416: return;
417: }
418: splx(s);
419: #ifdef notdef
420: while (from->c_cc > 0) {
421: c = q_to_b(from, bbuf, sizeof bbuf);
422: (void) b_to_q(bbuf, c, to);
423: }
424: #endif
425: /* XXX - FIX */
426: while ((c = getc(from)) >= 0)
427: putc(c, to);
428: }
429:
430: #ifdef unneeded
431: /*
432: * Integer (short) get/put using clists.
433: */
434: typedef u_short word_t;
435:
436: getw(p)
437: register struct clist *p;
438: {
439: register int s, c;
440: register struct cblock *bp;
441:
442: if (p->c_cc <= 1)
443: return(-1);
444: if (p->c_cc & 01) {
445: c = getc(p);
446: #if BYTE_ORDER == LITTLE_ENDIAN
447: return (c | (getc(p)<<8));
448: #else
449: return (getc(p) | (c<<8));
450: #endif
451: }
452: s = spltty();
453: #if BYTE_ORDER == LITTLE_ENDIAN
454: c = (((u_char *)p->c_cf)[0] << 8) | ((u_char *)p->c_cf)[1];
455: #else
456: c = (((u_char *)p->c_cf)[1] << 8) | ((u_char *)p->c_cf)[0];
457: #endif
458: p->c_cf += sizeof (word_t);
459: p->c_cc -= sizeof (word_t);
460: if (p->c_cc <= 0) {
461: bp = cbptr(p->c_cf-1);
462: bp = cbptr((int)bp & ~CROUND);
463: p->c_cf = NULL;
464: p->c_cl = NULL;
465: bp->c_next = cfreelist;
466: cfreelist = bp;
467: cfreecount += CBSIZE;
468: if (cwaiting) {
469: wakeup(&cwaiting);
470: cwaiting = 0;
471: }
472: } else if (((int)p->c_cf & CROUND) == 0) {
473: bp = cbptr(p->c_cf);
474: bp--;
475: p->c_cf = bp->c_next->c_info;
476: bp->c_next = cfreelist;
477: cfreelist = bp;
478: cfreecount += CBSIZE;
479: if (cwaiting) {
480: wakeup(&cwaiting);
481: cwaiting = 0;
482: }
483: }
484: splx(s);
485: return (c);
486: }
487:
488: putw(c, p)
489: register struct clist *p;
490: word_t c;
491: {
492: register s;
493: register struct cblock *bp;
494: register char *cp;
495:
496: s = spltty();
497: if (cfreelist==NULL) {
498: splx(s);
499: return(-1);
500: }
501: if (p->c_cc & 01) {
502: #if BYTE_ORDER == LITTLE_ENDIAN
503: (void) putc(c, p);
504: (void) putc(c>>8, p);
505: #else
506: (void) putc(c>>8, p);
507: (void) putc(c, p);
508: #endif
509: } else {
510: if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) {
511: if ((bp = cfreelist) == NULL) {
512: splx(s);
513: return (-1);
514: }
515: cfreelist = bp->c_next;
516: cfreecount -= CBSIZE;
517: bp->c_next = NULL;
518: p->c_cf = cp = bp->c_info;
519: } else if (((int)cp & CROUND) == 0) {
520: bp = cbptr(cp) - 1;
521: if ((bp->c_next = cfreelist) == NULL) {
522: splx(s);
523: return (-1);
524: }
525: bp = bp->c_next;
526: cfreelist = bp->c_next;
527: cfreecount -= CBSIZE;
528: bp->c_next = NULL;
529: cp = bp->c_info;
530: }
531: #if defined(vax)
532: *(word_t *)cp = c;
533: #else
534: ((u_char *)cp)[0] = c>>8;
535: ((u_char *)cp)[1] = c;
536: #endif
537: p->c_cl = cp + sizeof (word_t);
538: p->c_cc += sizeof (word_t);
539: }
540: splx(s);
541: return (0);
542: }
543: #endif unneeded
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.