xref: /csrg-svn/sys/kern/tty_subr.c (revision 47545)
123391Smckusick /*
229110Smckusick  * Copyright (c) 1982, 1986 Regents of the University of California.
323391Smckusick  * All rights reserved.  The Berkeley software License Agreement
423391Smckusick  * specifies the terms and conditions for redistribution.
523391Smckusick  *
6*47545Skarels  *	@(#)tty_subr.c	7.6 (Berkeley) 03/17/91
723391Smckusick  */
81892Swnj 
917097Sbloom #include "param.h"
1017097Sbloom #include "systm.h"
1117097Sbloom #include "buf.h"
1217576Sbloom #include "ioctl.h"
1317097Sbloom #include "tty.h"
1417097Sbloom #include "clist.h"
1532Sbill 
161890Swnj char	cwaiting;
171890Swnj 
1835811Smarc #define setquote(cp) \
1935811Smarc 	setbit(((char *)((int)(cp)&~CROUND)+sizeof(struct cblock *)), \
2035811Smarc 		(int)(cp)&CROUND)
2135811Smarc #define isquote(cp) \
2235811Smarc 	isset(((char *)((int)(cp)&~CROUND)+sizeof(struct cblock *)), \
2335811Smarc 		(int)(cp)&CROUND)
2435811Smarc #define cbptr(x) ((struct cblock *)(x))
2535811Smarc 
2632Sbill /*
27*47545Skarels  * Initialize clist by freeing all character blocks.
28*47545Skarels  */
29*47545Skarels cinit()
30*47545Skarels {
31*47545Skarels 	register int ccp;
32*47545Skarels 	register struct cblock *cp;
33*47545Skarels 
34*47545Skarels 	ccp = (int) cfree;
35*47545Skarels 	ccp = (ccp + CROUND) & ~CROUND;
36*47545Skarels 	for(cp = (struct cblock *) ccp; cp < &cfree[nclist - 1]; cp++) {
37*47545Skarels 		cp->c_next = cfreelist;
38*47545Skarels 		cfreelist = cp;
39*47545Skarels 		cfreecount += CBSIZE;
40*47545Skarels 	}
41*47545Skarels }
42*47545Skarels 
43*47545Skarels /*
4432Sbill  * Character list get/put
4532Sbill  */
4632Sbill getc(p)
4712754Ssam 	register struct clist *p;
4832Sbill {
4932Sbill 	register struct cblock *bp;
5032Sbill 	register int c, s;
5132Sbill 
5217542Skarels 	s = spltty();
5332Sbill 	if (p->c_cc <= 0) {
5432Sbill 		c = -1;
5532Sbill 		p->c_cc = 0;
5632Sbill 		p->c_cf = p->c_cl = NULL;
5732Sbill 	} else {
5835811Smarc 		c = *p->c_cf & 0377;
5935811Smarc 		if (isquote(p->c_cf))
6035811Smarc 			c |= TTY_QUOTE;
6135811Smarc 		p->c_cf++;
6232Sbill 		if (--p->c_cc<=0) {
6335811Smarc 			bp = cbptr(p->c_cf-1);
6435811Smarc 			bp = cbptr((int)bp & ~CROUND);
6532Sbill 			p->c_cf = NULL;
6632Sbill 			p->c_cl = NULL;
6732Sbill 			bp->c_next = cfreelist;
6832Sbill 			cfreelist = bp;
691890Swnj 			cfreecount += CBSIZE;
701890Swnj 			if (cwaiting) {
711890Swnj 				wakeup(&cwaiting);
721890Swnj 				cwaiting = 0;
731890Swnj 			}
7432Sbill 		} else if (((int)p->c_cf & CROUND) == 0){
7535811Smarc 			bp = cbptr(p->c_cf);
7632Sbill 			bp--;
7732Sbill 			p->c_cf = bp->c_next->c_info;
7832Sbill 			bp->c_next = cfreelist;
7932Sbill 			cfreelist = bp;
801890Swnj 			cfreecount += CBSIZE;
811890Swnj 			if (cwaiting) {
821890Swnj 				wakeup(&cwaiting);
831890Swnj 				cwaiting = 0;
841890Swnj 			}
8532Sbill 		}
8632Sbill 	}
8732Sbill 	splx(s);
8826279Skarels 	return (c);
8932Sbill }
9032Sbill 
9132Sbill /*
9232Sbill  * copy clist to buffer.
9332Sbill  * return number of bytes moved.
9432Sbill  */
9532Sbill q_to_b(q, cp, cc)
969761Ssam 	register struct clist *q;
979761Ssam 	register char *cp;
9832Sbill {
9932Sbill 	register struct cblock *bp;
10032Sbill 	register int s;
10117542Skarels 	register nc;
10232Sbill 	char *acp;
10332Sbill 
10432Sbill 	if (cc <= 0)
10526279Skarels 		return (0);
10617542Skarels 	s = spltty();
10732Sbill 	if (q->c_cc <= 0) {
10832Sbill 		q->c_cc = 0;
10932Sbill 		q->c_cf = q->c_cl = NULL;
1101890Swnj 		splx(s);
11126279Skarels 		return (0);
11232Sbill 	}
11332Sbill 	acp = cp;
11432Sbill 
11517542Skarels 	while (cc) {
11626279Skarels 		nc = sizeof (struct cblock) - ((int)q->c_cf & CROUND);
11717542Skarels 		nc = MIN(nc, cc);
11817542Skarels 		nc = MIN(nc, q->c_cc);
11917542Skarels 		(void) bcopy(q->c_cf, cp, (unsigned)nc);
12017542Skarels 		q->c_cf += nc;
12117542Skarels 		q->c_cc -= nc;
12217542Skarels 		cc -= nc;
12317542Skarels 		cp += nc;
12417542Skarels 		if (q->c_cc <= 0) {
12535811Smarc 			bp = cbptr(q->c_cf - 1);
12635811Smarc 			bp = cbptr((int)bp & ~CROUND);
12732Sbill 			q->c_cf = q->c_cl = NULL;
12832Sbill 			bp->c_next = cfreelist;
12932Sbill 			cfreelist = bp;
1301890Swnj 			cfreecount += CBSIZE;
1311890Swnj 			if (cwaiting) {
1321890Swnj 				wakeup(&cwaiting);
1331890Swnj 				cwaiting = 0;
1341890Swnj 			}
13532Sbill 			break;
13632Sbill 		}
13732Sbill 		if (((int)q->c_cf & CROUND) == 0) {
13835811Smarc 			bp = cbptr(q->c_cf);
13932Sbill 			bp--;
14032Sbill 			q->c_cf = bp->c_next->c_info;
14132Sbill 			bp->c_next = cfreelist;
14232Sbill 			cfreelist = bp;
1431890Swnj 			cfreecount += CBSIZE;
1441890Swnj 			if (cwaiting) {
1451890Swnj 				wakeup(&cwaiting);
1461890Swnj 				cwaiting = 0;
1471890Swnj 			}
14832Sbill 		}
14932Sbill 	}
15032Sbill 	splx(s);
15126279Skarels 	return (cp-acp);
15232Sbill }
15332Sbill 
15432Sbill /*
15532Sbill  * Return count of contiguous characters
15632Sbill  * in clist starting at q->c_cf.
15732Sbill  * Stop counting if flag&character is non-null.
15832Sbill  */
15932Sbill ndqb(q, flag)
1609761Ssam 	register struct clist *q;
16132Sbill {
1629761Ssam 	register cc;
1639761Ssam 	int s;
16432Sbill 
16517542Skarels 	s = spltty();
16632Sbill 	if (q->c_cc <= 0) {
16732Sbill 		cc = -q->c_cc;
16832Sbill 		goto out;
16932Sbill 	}
17032Sbill 	cc = ((int)q->c_cf + CBSIZE) & ~CROUND;
17132Sbill 	cc -= (int)q->c_cf;
17232Sbill 	if (q->c_cc < cc)
17332Sbill 		cc = q->c_cc;
17432Sbill 	if (flag) {
17532Sbill 		register char *p, *end;
17632Sbill 
17732Sbill 		p = q->c_cf;
17832Sbill 		end = p;
17932Sbill 		end += cc;
18032Sbill 		while (p < end) {
18132Sbill 			if (*p & flag) {
1821890Swnj 				cc = (int)p;
1831890Swnj 				cc -= (int)q->c_cf;
18432Sbill 				break;
18532Sbill 			}
18632Sbill 			p++;
18732Sbill 		}
18832Sbill 	}
18932Sbill out:
19032Sbill 	splx(s);
19126279Skarels 	return (cc);
19232Sbill }
19332Sbill 
19432Sbill /*
1951890Swnj  * Flush cc bytes from q.
19632Sbill  */
19732Sbill ndflush(q, cc)
19812754Ssam 	register struct clist *q;
19912754Ssam 	register cc;
20032Sbill {
20112754Ssam 	register struct cblock *bp;
20212754Ssam 	char *end;
20312754Ssam 	int rem, s;
20432Sbill 
20517542Skarels 	s = spltty();
20626279Skarels 	if (q->c_cc <= 0)
20732Sbill 		goto out;
2081890Swnj 	while (cc>0 && q->c_cc) {
20935811Smarc 		bp = cbptr((int)q->c_cf & ~CROUND);
2101890Swnj 		if ((int)bp == (((int)q->c_cl-1) & ~CROUND)) {
2111890Swnj 			end = q->c_cl;
2121890Swnj 		} else {
2131890Swnj 			end = (char *)((int)bp + sizeof (struct cblock));
2141890Swnj 		}
2151890Swnj 		rem = end - q->c_cf;
2161890Swnj 		if (cc >= rem) {
2171890Swnj 			cc -= rem;
2181890Swnj 			q->c_cc -= rem;
21932Sbill 			q->c_cf = bp->c_next->c_info;
2201890Swnj 			bp->c_next = cfreelist;
2211890Swnj 			cfreelist = bp;
2221890Swnj 			cfreecount += CBSIZE;
2231890Swnj 			if (cwaiting) {
2241890Swnj 				wakeup(&cwaiting);
2251890Swnj 				cwaiting = 0;
2261890Swnj 			}
22732Sbill 		} else {
2281890Swnj 			q->c_cc -= cc;
2291890Swnj 			q->c_cf += cc;
2301890Swnj 			if (q->c_cc <= 0) {
2311890Swnj 				bp->c_next = cfreelist;
2321890Swnj 				cfreelist = bp;
2331890Swnj 				cfreecount += CBSIZE;
2341890Swnj 				if (cwaiting) {
2351890Swnj 					wakeup(&cwaiting);
2361890Swnj 					cwaiting = 0;
2371890Swnj 				}
2381890Swnj 			}
2391890Swnj 			break;
24032Sbill 		}
2411890Swnj 	}
2421890Swnj 	if (q->c_cc <= 0) {
24332Sbill 		q->c_cf = q->c_cl = NULL;
2441890Swnj 		q->c_cc = 0;
24532Sbill 	}
24632Sbill out:
24732Sbill 	splx(s);
24832Sbill }
249172Sbill 
2501890Swnj 
25132Sbill putc(c, p)
25212754Ssam 	register struct clist *p;
25332Sbill {
25432Sbill 	register struct cblock *bp;
25532Sbill 	register char *cp;
25632Sbill 	register s;
25732Sbill 
25817542Skarels 	s = spltty();
25935811Smarc 	if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) {	/* no cblocks yet */
26032Sbill 		if ((bp = cfreelist) == NULL) {
26132Sbill 			splx(s);
26226279Skarels 			return (-1);
26332Sbill 		}
26432Sbill 		cfreelist = bp->c_next;
2651890Swnj 		cfreecount -= CBSIZE;
26632Sbill 		bp->c_next = NULL;
26735811Smarc 		bzero(bp->c_quote, CBQSIZE);
26832Sbill 		p->c_cf = cp = bp->c_info;
26932Sbill 	} else if (((int)cp & CROUND) == 0) {
27035811Smarc 		bp = cbptr(cp) - 1;	/* pointer arith */
27132Sbill 		if ((bp->c_next = cfreelist) == NULL) {
27232Sbill 			splx(s);
27326279Skarels 			return (-1);
27432Sbill 		}
27532Sbill 		bp = bp->c_next;
27632Sbill 		cfreelist = bp->c_next;
2771890Swnj 		cfreecount -= CBSIZE;
27832Sbill 		bp->c_next = NULL;
27932Sbill 		cp = bp->c_info;
28032Sbill 	}
28135811Smarc 	if (c&TTY_QUOTE)
28235811Smarc 		setquote(cp);
28332Sbill 	*cp++ = c;
28432Sbill 	p->c_cc++;
28532Sbill 	p->c_cl = cp;
28632Sbill 	splx(s);
28726279Skarels 	return (0);
28832Sbill }
28932Sbill 
29032Sbill /*
29132Sbill  * copy buffer to clist.
29232Sbill  * return number of bytes not transfered.
29332Sbill  */
29432Sbill b_to_q(cp, cc, q)
29512754Ssam 	register char *cp;
29612754Ssam 	struct clist *q;
29712754Ssam 	register int cc;
29832Sbill {
29932Sbill 	register char *cq;
30032Sbill 	register struct cblock *bp;
30117542Skarels 	register s, nc;
30217542Skarels 	int acc;
30332Sbill 
30432Sbill 	if (cc <= 0)
30526279Skarels 		return (0);
30617542Skarels 	acc = cc;
30717542Skarels 	s = spltty();
30817542Skarels 	if ((cq = q->c_cl) == NULL || q->c_cc < 0) {
30917542Skarels 		if ((bp = cfreelist) == NULL)
31017542Skarels 			goto out;
31117542Skarels 		cfreelist = bp->c_next;
31217542Skarels 		cfreecount -= CBSIZE;
31335811Smarc 		bzero(bp->c_quote, CBQSIZE);
31417542Skarels 		bp->c_next = NULL;
31517542Skarels 		q->c_cf = cq = bp->c_info;
31617542Skarels 	}
31717542Skarels 
31817542Skarels 	while (cc) {
31932Sbill 		if (((int)cq & CROUND) == 0) {
32035811Smarc 			bp = cbptr(cq) - 1;
32117542Skarels 			if ((bp->c_next = cfreelist) == NULL)
32217542Skarels 				goto out;
32332Sbill 			bp = bp->c_next;
32432Sbill 			cfreelist = bp->c_next;
3251890Swnj 			cfreecount -= CBSIZE;
32635811Smarc 			bzero(bp->c_quote, CBQSIZE);
32732Sbill 			bp->c_next = NULL;
32817542Skarels 			cq = bp->c_info;
32932Sbill 		}
33026279Skarels 		nc = MIN(cc, sizeof (struct cblock) - ((int)cq & CROUND));
33117542Skarels 		(void) bcopy(cp, cq, (unsigned)nc);
33217542Skarels 		cp += nc;
33317542Skarels 		cq += nc;
33417542Skarels 		cc -= nc;
33532Sbill 	}
33617542Skarels out:
33717542Skarels 	q->c_cl = cq;
33817542Skarels 	q->c_cc += acc - cc;
33917542Skarels 	splx(s);
34017368Ssam 	return (cc);
34132Sbill }
34232Sbill 
34332Sbill /*
344172Sbill  * Given a non-NULL pointter into the list (like c_cf which
345172Sbill  * always points to a real character if non-NULL) return the pointer
346172Sbill  * to the next character in the list or return NULL if no more chars.
347172Sbill  *
348172Sbill  * Callers must not allow getc's to happen between nextc's so that the
349172Sbill  * pointer becomes invalid.  Note that interrupts are NOT masked.
350172Sbill  */
351172Sbill char *
35235811Smarc nextc(p, cp, c)
35312754Ssam 	register struct clist *p;
35412754Ssam 	register char *cp;
35535811Smarc 	register int *c;
356172Sbill {
357172Sbill 
358172Sbill 	if (p->c_cc && ++cp != p->c_cl) {
35935811Smarc 		if (((int)cp & CROUND) == 0) {
36035811Smarc 			cp = (cbptr(cp))[-1].c_next->c_info;
36135811Smarc 		}
36235811Smarc 		*c = *cp;
36335811Smarc 		if (isquote(cp))
36435811Smarc 			*c |= TTY_QUOTE;
365172Sbill 		return (cp);
366172Sbill 	}
367172Sbill 	return (0);
368172Sbill }
369172Sbill 
370172Sbill /*
371172Sbill  * Remove the last character in the list and return it.
372172Sbill  */
373172Sbill unputc(p)
37412754Ssam 	register struct clist *p;
375172Sbill {
376172Sbill 	register struct cblock *bp;
377172Sbill 	register int c, s;
378172Sbill 	struct cblock *obp;
379172Sbill 
38017542Skarels 	s = spltty();
381172Sbill 	if (p->c_cc <= 0)
382172Sbill 		c = -1;
383172Sbill 	else {
384172Sbill 		c = *--p->c_cl;
38535811Smarc 		if (isquote(p->c_cl))
38635811Smarc 			c |= TTY_QUOTE;
387172Sbill 		if (--p->c_cc <= 0) {
38835811Smarc 			bp = cbptr(p->c_cl);
38935811Smarc 			bp = cbptr((int)bp & ~CROUND);
390172Sbill 			p->c_cl = p->c_cf = NULL;
391172Sbill 			bp->c_next = cfreelist;
392172Sbill 			cfreelist = bp;
3931890Swnj 			cfreecount += CBSIZE;
39435811Smarc 		} else if (p->c_cl == (cbptr((int)p->c_cl & ~CROUND))->c_info) {
395172Sbill 			p->c_cl = (char *)((int)p->c_cl & ~CROUND);
39635811Smarc 
39735811Smarc 			bp = cbptr(p->c_cf);
39835811Smarc 			bp = cbptr((int)bp & ~CROUND);
39935811Smarc 			while (bp->c_next != cbptr(p->c_cl))
400172Sbill 				bp = bp->c_next;
401172Sbill 			obp = bp;
402172Sbill 			p->c_cl = (char *)(bp + 1);
403172Sbill 			bp = bp->c_next;
404172Sbill 			bp->c_next = cfreelist;
405172Sbill 			cfreelist = bp;
4061890Swnj 			cfreecount += CBSIZE;
407172Sbill 			obp->c_next = NULL;
408172Sbill 		}
409172Sbill 	}
410172Sbill 	splx(s);
411172Sbill 	return (c);
412172Sbill }
413172Sbill 
414172Sbill /*
415172Sbill  * Put the chars in the from que
416172Sbill  * on the end of the to que.
417172Sbill  */
418172Sbill catq(from, to)
41912754Ssam 	struct clist *from, *to;
420172Sbill {
42135811Smarc #ifdef notdef
42217542Skarels 	char bbuf[CBSIZE*4];
42335811Smarc #endif
42417542Skarels 	register s, c;
425172Sbill 
42617542Skarels 	s = spltty();
42717542Skarels 	if (to->c_cc == 0) {
42817542Skarels 		*to = *from;
42917542Skarels 		from->c_cc = 0;
43017542Skarels 		from->c_cf = NULL;
43117542Skarels 		from->c_cl = NULL;
43217542Skarels 		splx(s);
43317542Skarels 		return;
43417542Skarels 	}
43517542Skarels 	splx(s);
43635811Smarc #ifdef notdef
43717542Skarels 	while (from->c_cc > 0) {
43817542Skarels 		c = q_to_b(from, bbuf, sizeof bbuf);
43917542Skarels 		(void) b_to_q(bbuf, c, to);
44017542Skarels 	}
44135811Smarc #endif
44235811Smarc 	/* XXX - FIX */
44335811Smarc 	while ((c = getc(from)) >= 0)
44435811Smarc 		putc(c, to);
445172Sbill }
446172Sbill 
44717542Skarels #ifdef unneeded
448172Sbill /*
44926279Skarels  * Integer (short) get/put using clists.
45032Sbill  */
45117542Skarels typedef	u_short word_t;
4529761Ssam 
45332Sbill getw(p)
4548955Sroot 	register struct clist *p;
45532Sbill {
45617542Skarels 	register int s, c;
45717542Skarels 	register struct cblock *bp;
45832Sbill 
45917542Skarels 	if (p->c_cc <= 1)
46017542Skarels 		return(-1);
46117542Skarels 	if (p->c_cc & 01) {
46217542Skarels 		c = getc(p);
46333398Smckusick #if BYTE_ORDER == LITTLE_ENDIAN
46426279Skarels 		return (c | (getc(p)<<8));
46526279Skarels #else
46626279Skarels 		return (getc(p) | (c<<8));
46726279Skarels #endif
46817542Skarels 	}
46917542Skarels 	s = spltty();
47035811Smarc #if BYTE_ORDER == LITTLE_ENDIAN
47129947Skarels 	c = (((u_char *)p->c_cf)[0] << 8) | ((u_char *)p->c_cf)[1];
47226279Skarels #else
47326279Skarels 	c = (((u_char *)p->c_cf)[1] << 8) | ((u_char *)p->c_cf)[0];
47426279Skarels #endif
47526279Skarels 	p->c_cf += sizeof (word_t);
47626279Skarels 	p->c_cc -= sizeof (word_t);
47717542Skarels 	if (p->c_cc <= 0) {
47835811Smarc 		bp = cbptr(p->c_cf-1);
47935811Smarc 		bp = cbptr((int)bp & ~CROUND);
48017542Skarels 		p->c_cf = NULL;
48117542Skarels 		p->c_cl = NULL;
48217542Skarels 		bp->c_next = cfreelist;
48317542Skarels 		cfreelist = bp;
48417542Skarels 		cfreecount += CBSIZE;
48517542Skarels 		if (cwaiting) {
48617542Skarels 			wakeup(&cwaiting);
48717542Skarels 			cwaiting = 0;
48817542Skarels 		}
48917542Skarels 	} else if (((int)p->c_cf & CROUND) == 0) {
49035811Smarc 		bp = cbptr(p->c_cf);
49117542Skarels 		bp--;
49217542Skarels 		p->c_cf = bp->c_next->c_info;
49317542Skarels 		bp->c_next = cfreelist;
49417542Skarels 		cfreelist = bp;
49517542Skarels 		cfreecount += CBSIZE;
49617542Skarels 		if (cwaiting) {
49717542Skarels 			wakeup(&cwaiting);
49817542Skarels 			cwaiting = 0;
49917542Skarels 		}
50017542Skarels 	}
50117542Skarels 	splx(s);
50217542Skarels 	return (c);
50332Sbill }
50432Sbill 
50532Sbill putw(c, p)
5068955Sroot 	register struct clist *p;
50717542Skarels 	word_t c;
50832Sbill {
50932Sbill 	register s;
51017542Skarels 	register struct cblock *bp;
51117542Skarels 	register char *cp;
51232Sbill 
51317542Skarels 	s = spltty();
51432Sbill 	if (cfreelist==NULL) {
51532Sbill 		splx(s);
51632Sbill 		return(-1);
51732Sbill 	}
51817542Skarels 	if (p->c_cc & 01) {
51933398Smckusick #if BYTE_ORDER == LITTLE_ENDIAN
52017542Skarels 		(void) putc(c, p);
52117542Skarels 		(void) putc(c>>8, p);
52226279Skarels #else
52326279Skarels 		(void) putc(c>>8, p);
52426279Skarels 		(void) putc(c, p);
52526279Skarels #endif
52617542Skarels 	} else {
52717542Skarels 		if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) {
52817542Skarels 			if ((bp = cfreelist) == NULL) {
52917542Skarels 				splx(s);
53017542Skarels 				return (-1);
53117542Skarels 			}
53217542Skarels 			cfreelist = bp->c_next;
53317542Skarels 			cfreecount -= CBSIZE;
53417542Skarels 			bp->c_next = NULL;
53517542Skarels 			p->c_cf = cp = bp->c_info;
53617542Skarels 		} else if (((int)cp & CROUND) == 0) {
53735811Smarc 			bp = cbptr(cp) - 1;
53817542Skarels 			if ((bp->c_next = cfreelist) == NULL) {
53917542Skarels 				splx(s);
54017542Skarels 				return (-1);
54117542Skarels 			}
54217542Skarels 			bp = bp->c_next;
54317542Skarels 			cfreelist = bp->c_next;
54417542Skarels 			cfreecount -= CBSIZE;
54517542Skarels 			bp->c_next = NULL;
54617542Skarels 			cp = bp->c_info;
54717542Skarels 		}
54826279Skarels #if defined(vax)
54917542Skarels 		*(word_t *)cp = c;
55026279Skarels #else
55126279Skarels 		((u_char *)cp)[0] = c>>8;
55226279Skarels 		((u_char *)cp)[1] = c;
55326279Skarels #endif
55426279Skarels 		p->c_cl = cp + sizeof (word_t);
55526279Skarels 		p->c_cc += sizeof (word_t);
55617542Skarels 	}
55732Sbill 	splx(s);
5589761Ssam 	return (0);
55932Sbill }
56017542Skarels #endif unneeded
561