2 * Copyright (c) 1994, David Greenman
4 * Copyright (c) 2003-2011 The DragonFly Project. All rights reserved.
6 * This code is derived from software contributed to The DragonFly Project
7 * by Matthew Dillon <dillon@backplane.com>
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice unmodified, this list of conditions, and the following
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * clist support routines
35 * The clist now contains two linear buffers c_quote and c_info, sized
36 * to c_cbmax. The caller must hold a lock or token specific to the clist
39 #include <sys/param.h>
40 #include <sys/kernel.h>
41 #include <sys/systm.h>
42 #include <sys/malloc.h>
44 #include <sys/thread2.h>
47 * Allocate or reallocate clist buffers.
50 clist_alloc_cblocks(struct clist
*cl
, int ccmax
)
56 if (ccmax
== cl
->c_ccmax
)
59 clist_free_cblocks(cl
);
62 data
= kmalloc(ccmax
* sizeof(*data
), M_TTYS
, M_INTWAIT
|M_ZERO
);
63 /* NOTE: cl fields may now be different due to blocking */
69 n
= cl
->c_ccmax
- cl
->c_cchead
;
72 bcopy(cl
->c_data
+ cl
->c_cchead
, data
, n
* sizeof(*data
));
74 bcopy(cl
->c_data
, data
+ n
,
75 (count
- n
) * sizeof(*data
));
85 * Free the clist's buffer.
88 clist_free_cblocks(struct clist
*cl
)
104 * Get a character from the head of a clist.
107 clist_getc(struct clist
*cl
)
116 if (++i
== cl
->c_ccmax
)
124 * Copy data from the clist to the destination linear buffer.
125 * Return the number of characters actually copied.
128 clist_qtob(struct clist
*cl
, char *dest
, int n
)
141 if (++i
== cl
->c_ccmax
)
153 * Flush characters from the head of the clist, deleting them.
156 ndflush(struct clist
*cl
, int n
)
162 i
= cl
->c_cchead
+ n
;
163 if (i
>= cl
->c_ccmax
)
170 * Append a character to the clist, return 0 on success, -1 if
171 * there is no room. The character can be quoted by setting TTY_QUOTE.
174 clist_putc(int c
, struct clist
*cl
)
178 if (cl
->c_cc
== cl
->c_ccmax
)
180 i
= cl
->c_cchead
+ cl
->c_cc
;
181 if (i
>= cl
->c_ccmax
)
183 cl
->c_data
[i
] = (short)c
& (TTY_QUOTE
| TTY_CHARMASK
);
190 * Copy data from linear buffer to clist chain. Return the
191 * number of characters not copied. The data will be flagged
192 * as not being quoted.
195 clist_btoq(char *src
, int n
, struct clist
*cl
)
201 count
= cl
->c_ccmax
- cl
->c_cc
; /* space available */
203 count
= n
; /* count = bytes to copy */
204 remain
= n
- count
; /* remain = bytes not copied */
206 i
= cl
->c_cchead
+ cl
->c_cc
; /* clist write index */
207 if (i
>= cl
->c_ccmax
)
211 cl
->c_data
[i
] = (short)(uint8_t)*src
;
212 if (++i
== cl
->c_ccmax
)
217 cl
->c_cc
+= n
- remain
; /* bytes actually copied */
219 return remain
; /* return bytes not copied */
223 * Get the next character in the clist relative to cp. If cp is NULL
224 * returns the first character in the clist. The character is stored in
225 * *dst. No clist pointers are advanced or adjusted.
227 * The returned pointer can be used as an iterator but should not be
228 * directly dereferenced.
231 clist_nextc(struct clist
*cl
, void *cp
, int *dst
)
240 cp
= &cl
->c_data
[cl
->c_cchead
];
241 *dst
= (uint16_t)*(short *)cp
; /* can be quoted */
246 * Use i to calculate the next logical index to determine if
247 * there are any characters remaining.
249 i
= (short *)cp
- cl
->c_data
;
250 if (i
< cl
->c_cchead
)
251 i
+= cl
->c_ccmax
- cl
->c_cchead
;
254 if (i
+ 1 == cl
->c_cc
) { /* no more chars */
260 * We can just use cp to iterate the next actual buffer
263 cp
= (short *)cp
+ 1; /* next char (use pointer) */
264 if (cp
== &cl
->c_data
[cl
->c_ccmax
])
266 *dst
= (uint16_t)*(short *)cp
;
272 * "Unput" a character from a clist, returning it.
275 clist_unputc(struct clist
*cl
)
283 i
= cl
->c_cchead
+ cl
->c_cc
;
284 if (i
>= cl
->c_ccmax
)
286 c
= (int)(uint16_t)cl
->c_data
[i
];
292 * Move characters in source clist to destination clist,
293 * preserving quote bits. Non-critical path.
296 clist_catq(struct clist
*cls
, struct clist
*cld
)
300 while ((c
= clist_getc(cls
)) != -1)