From 2469c867a164210ce96143517059f21db7f1fd17 Mon Sep 17 00:00:00 2001 From: rgrimes Date: Wed, 25 May 1994 09:21:21 +0000 Subject: The big 4.4BSD Lite to FreeBSD 2.0.0 (Development) patch. Reviewed by: Rodney W. Grimes Submitted by: John Dyson and David Greenman --- sys/kern/subr_clist.c | 428 ++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 328 insertions(+), 100 deletions(-) (limited to 'sys/kern/subr_clist.c') diff --git a/sys/kern/subr_clist.c b/sys/kern/subr_clist.c index fe8f000..acbb7f1 100644 --- a/sys/kern/subr_clist.c +++ b/sys/kern/subr_clist.c @@ -1,159 +1,387 @@ -/*- - * Copyright (c) 1982, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * (c) UNIX System Laboratories, Inc. - * All or some portions of this file are derived from material licensed - * to the University of California by American Telephone and Telegraph - * Co. or Unix System Laboratories, Inc. and are reproduced herein with - * the permission of UNIX System Laboratories, Inc. +/* + * Copyright (C) 1994, David Greenman. This software may be used, modified, + * copied, distributed, and sold, in both source and binary form provided + * that the above copyright and these terms are retained. Under no + * circumstances is the author responsible for the proper functioning + * of this software, nor does the author assume any responsibility + * for damages incurred with its use. * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * from: @(#)tty_subr.c 8.2 (Berkeley) 9/5/93 */ #include +#include #include #include +#include +#include char cwaiting; -struct cblock *cfree, *cfreelist; -int cfreecount, nclist; +struct cblock *cfreelist = 0; +int cfreecount, nclist = 256; void clist_init() { + int i; + struct cblock *tmp; - /* - * Body deleted. - */ + for (i = 0; i < nclist; ++i) { + tmp = malloc(sizeof(struct cblock), M_TTYS, M_NOWAIT); + if (!tmp) + panic("clist_init: could not allocate cblock"); + bzero((char *)tmp, sizeof(struct cblock)); + tmp->c_next = cfreelist; + cfreelist = tmp; + cfreecount += CBSIZE; + } return; } -getc(a1) - struct clist *a1; +/* + * Get a character from head of clist. + */ +int +getc(clistp) + struct clist *clistp; { + int chr = -1; + int s; + struct cblock *cblockp; - /* - * Body deleted. - */ - return ((char)0); -} + s = spltty(); -q_to_b(a1, a2, a3) - struct clist *a1; - char *a2; - int a3; -{ + /* If there are characters in the list, get one */ + if (clistp->c_cc) { + cblockp = (struct cblock *)((long)clistp->c_cf & ~CROUND); + chr = (u_char)*clistp->c_cf; +#if 0 + /* + * If this char is quoted, set the flag. + */ + if (isset(cblockp->c_quote, clistp->c_cf - (char *)cblockp->c_info)) + chr |= TTY_QUOTE; +#endif + clistp->c_cf++; + clistp->c_cc--; + if ((clistp->c_cf >= (char *)(cblockp+1)) || (clistp->c_cc == 0)) { + if (clistp->c_cc > 0) { + clistp->c_cf = cblockp->c_next->c_info; + } else { + clistp->c_cf = clistp->c_cl = NULL; + } + cblockp->c_next = cfreelist; + cfreelist = cblockp; + cfreecount += CBSIZE; + } + } - /* - * Body deleted. - */ - return (0); + splx(s); + return (chr); } -ndqb(a1, a2) - struct clist *a1; - int a2; +/* + * Copy 'amount' of chars, beginning at head of clist 'clistp' to + * destination linear buffer 'dest'. + */ +int +q_to_b(clistp, dest, amount) + struct clist *clistp; + char *dest; + int amount; { + struct cblock *cblockp; + struct cblock *cblockn; + char *dest_orig = dest; + int numc; + int s; - /* - * Body deleted. - */ - return (0); + s = spltty(); + + while (clistp && amount && (clistp->c_cc > 0)) { + cblockp = (struct cblock *)((long)clistp->c_cf & ~CROUND); + cblockn = cblockp + 1; /* pointer arithmetic! */ + numc = min(amount, (char *)cblockn - clistp->c_cf); + numc = min(numc, clistp->c_cc); + bcopy(clistp->c_cf, dest, numc); + amount -= numc; + clistp->c_cf += numc; + clistp->c_cc -= numc; + dest += numc; + if ((clistp->c_cf >= (char *)cblockn) || (clistp->c_cc == 0)) { + if (clistp->c_cc > 0) { + clistp->c_cf = cblockp->c_next->c_info; + } else { + clistp->c_cf = clistp->c_cl = NULL; + } + cblockp->c_next = cfreelist; + cfreelist = cblockp; + cfreecount += CBSIZE; + } + } + + splx(s); + return (dest - dest_orig); } +/* + * Flush 'amount' of chars, beginning at head of clist 'clistp'. + */ void -ndflush(a1, a2) - struct clist *a1; - int a2; +ndflush(clistp, amount) + struct clist *clistp; + int amount; { + struct cblock *cblockp; + struct cblock *cblockn; + int numc; + int s; - /* - * Body deleted. - */ + s = spltty(); + + while (amount && (clistp->c_cc > 0)) { + cblockp = (struct cblock *)((long)clistp->c_cf & ~CROUND); + cblockn = cblockp + 1; /* pointer arithmetic! */ + numc = min(amount, (char *)cblockn - clistp->c_cf); + numc = min(numc, clistp->c_cc); + amount -= numc; + clistp->c_cf += numc; + clistp->c_cc -= numc; + if ((clistp->c_cf >= (char *)cblockn) || (clistp->c_cc == 0)) { + if (clistp->c_cc > 0) { + clistp->c_cf = cblockp->c_next->c_info; + } else { + clistp->c_cf = clistp->c_cl = NULL; + } + cblockp->c_next = cfreelist; + cfreelist = cblockp; + cfreecount += CBSIZE; + } + } + + splx(s); return; } -putc(a1, a2) - char a1; - struct clist *a2; +int +putc(chr, clistp) + int chr; + struct clist *clistp; { + struct cblock *cblockp; + struct cblock *bclockn; + int s; - /* - * Body deleted. - */ + s = spltty(); + + cblockp = (struct cblock *)((long)clistp->c_cl & ~CROUND); + + if (clistp->c_cl == NULL) { + if (cfreelist) { + cblockp = cfreelist; + cfreelist = cfreelist->c_next; + cfreecount -= CBSIZE; + cblockp->c_next = NULL; + clistp->c_cf = clistp->c_cl = cblockp->c_info; + clistp->c_cc = 0; + } else { + splx(s); + return (-1); + } + } else { + if (((long)clistp->c_cl & CROUND) == 0) { + if (cfreelist) { + cblockp = (cblockp-1)->c_next = cfreelist; + cfreelist = cfreelist->c_next; + cfreecount -= CBSIZE; + cblockp->c_next = NULL; + clistp->c_cl = cblockp->c_info; + } else { + splx(s); + return (-1); + } + } + } + +#if 0 + if (chr & TTY_QUOTE) + setbit(cblockp->c_quote, clistp->c_cl - (char *)cblockp->c_info); +#endif + *clistp->c_cl++ = chr; + clistp->c_cc++; + + splx(s); return (0); } -b_to_q(a1, a2, a3) - char *a1; - int a2; - struct clist *a3; +/* + * Copy data from linear buffer to clist chain. + */ +int +b_to_q(src, amount, clistp) + char *src; + int amount; + struct clist *clistp; { + struct cblock *cblockp; + struct cblock *bclockn; + int s; + int numc; + + s = spltty(); /* - * Body deleted. + * If there are no cblocks assigned to this clist yet, + * then get one. */ - return (0); + if (clistp->c_cl == NULL) { + if (cfreelist) { + cblockp = cfreelist; + cfreelist = cfreelist->c_next; + cfreecount -= CBSIZE; + cblockp->c_next = NULL; + clistp->c_cf = clistp->c_cl = cblockp->c_info; + clistp->c_cc = 0; + } else { + splx(s); + return (amount); + } + } else { + cblockp = (struct cblock *)((long)clistp->c_cl & ~CROUND); + } + + while (amount) { + /* + * Get another cblock if needed. + */ + if (((long)clistp->c_cl & CROUND) == 0) { + if (cfreelist) { + cblockp = (cblockp-1)->c_next = cfreelist; + cfreelist = cfreelist->c_next; + cfreecount -= CBSIZE; + cblockp->c_next = NULL; + clistp->c_cl = cblockp->c_info; + } else { + splx(s); + return (amount); + } + } + + /* + * Copy a chunk of the linear buffer up to the end + * of this cblock. + */ + cblockp += 1; + numc = min(amount, (char *)(cblockp) - clistp->c_cl); + bcopy(src, clistp->c_cl, numc); + + /* + * Clear quote bits. + */ + + /* + * ...and update pointer for the next chunk. + */ + src += numc; + clistp->c_cl += numc; + clistp->c_cc += numc; + amount -= numc; + } + + splx(s); + return (amount); } char * -nextc(a1, a2, a3) - struct clist *a1; - char *a2; - int *a3; +nextc(clistp, cp, dst) + struct clist *clistp; + char *cp; + int *dst; { + struct cblock *cblockp; - /* - * Body deleted. - */ - return ((char *)0); + ++cp; + if (clistp->c_cc && (cp != clistp->c_cl)) { + if (((long)cp & CROUND) == 0) + cp = ((struct cblock *)cp - 1)->c_next->c_info; + cblockp = (struct cblock *)((long)cp & ~CROUND); +#if 0 + *dst = *cp | (isset(cblockp->c_quote, cp - (char *)cblockp->c_info) ? TTY_QUOTE : 0); +#endif + *dst = (u_char)*cp; + return (cp); + } + + return (NULL); } -unputc(a1) - struct clist *a1; +int +unputc(clistp) + struct clist *clistp; { + struct cblock *cblockp = 0, *cbp = 0; + int s; + int chr = -1; + + + s = spltty(); + + if (clistp->c_cc) { + --clistp->c_cc; + chr = (u_char)*--clistp->c_cl; + /* + * Get the quote flag and 'unput' it, too. + */ + + /* XXX write me! */ + + cblockp = (struct cblock *)((long)clistp->c_cl & ~CROUND); + + /* + * If all of the characters have been unput in this + * cblock, the find the previous one and free this + * one. + */ + if (clistp->c_cc && (clistp->c_cl <= (char *)cblockp->c_info)) { + cbp = (struct cblock *)((long)clistp->c_cf & ~CROUND); + + while (cbp->c_next != cblockp) + cbp = cbp->c_next; + + clistp->c_cl = (char *)(cbp+1); + cblockp->c_next = cfreelist; + cfreelist = cblockp; + cfreecount += CBSIZE; + cbp->c_next = NULL; + } + } /* - * Body deleted. + * If there are no more characters on the list, then + * free the last cblock. */ - return ((char)0); + if ((clistp->c_cc == 0) && clistp->c_cl) { + cblockp = (struct cblock *)((long)clistp->c_cl & ~CROUND); + cblockp->c_next = cfreelist; + cfreelist = cblockp; + cfreecount += CBSIZE; + clistp->c_cf = clistp->c_cl = NULL; + } + + splx(s); + return (chr); } void -catq(a1, a2) - struct clist *a1, *a2; +catq(src_clistp, dest_clistp) + struct clist *src_clistp, *dest_clistp; { + char buffer[CBSIZE*2]; + int amount; + + while (src_clistp->c_cc) { + amount = q_to_b(src_clistp, buffer, sizeof(buffer)); + b_to_q(buffer, amount, dest_clistp); + } - /* - * Body deleted. - */ return; } -- cgit v1.1