The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/tty_subr.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 1994, David Greenman
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice unmodified, this list of conditions, and the following
   10  *    disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  *
   27  * $FreeBSD$
   28  */
   29 
   30 /*
   31  * clist support routines
   32  */
   33 
   34 #include <sys/param.h>
   35 #include <sys/kernel.h>
   36 #include <sys/systm.h>
   37 #include <sys/malloc.h>
   38 #include <sys/tty.h>
   39 #include <sys/clist.h>
   40 
   41 static void clist_init __P((void *));
   42 SYSINIT(clist, SI_SUB_CLIST, SI_ORDER_FIRST, clist_init, NULL)
   43 
   44 static struct cblock *cfreelist = 0;
   45 int cfreecount = 0;
   46 static int cslushcount;
   47 static int ctotcount;
   48 
   49 #ifndef INITIAL_CBLOCKS
   50 #define INITIAL_CBLOCKS 50
   51 #endif
   52 
   53 static struct cblock *cblock_alloc __P((void));
   54 static void cblock_alloc_cblocks __P((int number));
   55 static void cblock_free __P((struct cblock *cblockp));
   56 static void cblock_free_cblocks __P((int number));
   57 
   58 #include "opt_ddb.h"
   59 #ifdef DDB
   60 #include <ddb/ddb.h>
   61 
   62 DB_SHOW_COMMAND(cbstat, cbstat)
   63 {
   64         printf(
   65         "tot = %d (active = %d, free = %d (reserved = %d, slush = %d))\n",
   66                ctotcount * CBSIZE, ctotcount * CBSIZE - cfreecount, cfreecount,
   67                cfreecount - cslushcount * CBSIZE, cslushcount * CBSIZE);
   68 }
   69 #endif /* DDB */
   70 
   71 /*
   72  * Called from init_main.c
   73  */
   74 /* ARGSUSED*/
   75 static void
   76 clist_init(dummy)
   77         void *dummy;
   78 {
   79         /*
   80          * Allocate an initial base set of cblocks as a 'slush'.
   81          * We allocate non-slush cblocks with each initial ttyopen() and
   82          * deallocate them with each ttyclose().
   83          * We should adjust the slush allocation.  This can't be done in
   84          * the i/o routines because they are sometimes called from
   85          * interrupt handlers when it may be unsafe to call malloc().
   86          */
   87         cblock_alloc_cblocks(cslushcount = INITIAL_CBLOCKS);
   88 }
   89 
   90 /*
   91  * Remove a cblock from the cfreelist queue and return a pointer
   92  * to it.
   93  */
   94 static __inline struct cblock *
   95 cblock_alloc()
   96 {
   97         struct cblock *cblockp;
   98 
   99         cblockp = cfreelist;
  100         if (cblockp == NULL)
  101                 panic("clist reservation botch");
  102         cfreelist = cblockp->c_next;
  103         cblockp->c_next = NULL;
  104         cfreecount -= CBSIZE;
  105         return (cblockp);
  106 }
  107 
  108 /*
  109  * Add a cblock to the cfreelist queue.
  110  */
  111 static __inline void
  112 cblock_free(cblockp)
  113         struct cblock *cblockp;
  114 {
  115         if (isset(cblockp->c_quote, CBQSIZE * NBBY - 1))
  116                 bzero(cblockp->c_quote, sizeof cblockp->c_quote);
  117         cblockp->c_next = cfreelist;
  118         cfreelist = cblockp;
  119         cfreecount += CBSIZE;
  120 }
  121 
  122 /*
  123  * Allocate some cblocks for the cfreelist queue.
  124  */
  125 static void
  126 cblock_alloc_cblocks(number)
  127         int number;
  128 {
  129         int i;
  130         struct cblock *cbp;
  131 
  132         for (i = 0; i < number; ++i) {
  133                 cbp = malloc(sizeof *cbp, M_TTYS, M_NOWAIT);
  134                 if (cbp == NULL) {
  135                         printf(
  136 "clist_alloc_cblocks: M_NOWAIT malloc failed, trying M_WAITOK\n");
  137                         cbp = malloc(sizeof *cbp, M_TTYS, M_WAITOK);
  138                 }
  139                 /*
  140                  * Freed cblocks have zero quotes and garbage elsewhere.
  141                  * Set the may-have-quote bit to force zeroing the quotes.
  142                  */
  143                 setbit(cbp->c_quote, CBQSIZE * NBBY - 1);
  144                 cblock_free(cbp);
  145         }
  146         ctotcount += number;
  147 }
  148 
  149 /*
  150  * Set the cblock allocation policy for a a clist.
  151  * Must be called in process context at spltty().
  152  */
  153 void
  154 clist_alloc_cblocks(clistp, ccmax, ccreserved)
  155         struct clist *clistp;
  156         int ccmax;
  157         int ccreserved;
  158 {
  159         int dcbr;
  160 
  161         /*
  162          * Allow for wasted space at the head.
  163          */
  164         if (ccmax != 0)
  165                 ccmax += CBSIZE - 1;
  166         if (ccreserved != 0)
  167                 ccreserved += CBSIZE - 1;
  168 
  169         clistp->c_cbmax = roundup(ccmax, CBSIZE) / CBSIZE;
  170         dcbr = roundup(ccreserved, CBSIZE) / CBSIZE - clistp->c_cbreserved;
  171         if (dcbr >= 0)
  172                 cblock_alloc_cblocks(dcbr);
  173         else {
  174                 if (clistp->c_cbreserved + dcbr < clistp->c_cbcount)
  175                         dcbr = clistp->c_cbcount - clistp->c_cbreserved;
  176                 cblock_free_cblocks(-dcbr);
  177         }
  178         clistp->c_cbreserved += dcbr;
  179 }
  180 
  181 /*
  182  * Free some cblocks from the cfreelist queue back to the
  183  * system malloc pool.
  184  */
  185 static void
  186 cblock_free_cblocks(number)
  187         int number;
  188 {
  189         int i;
  190 
  191         for (i = 0; i < number; ++i)
  192                 free(cblock_alloc(), M_TTYS);
  193         ctotcount -= number;
  194 }
  195 
  196 /*
  197  * Free the cblocks reserved for a clist.
  198  * Must be called at spltty().
  199  */
  200 void
  201 clist_free_cblocks(clistp)
  202         struct clist *clistp;
  203 {
  204         if (clistp->c_cbcount != 0)
  205                 panic("freeing active clist cblocks");
  206         cblock_free_cblocks(clistp->c_cbreserved);
  207         clistp->c_cbmax = 0;
  208         clistp->c_cbreserved = 0;
  209 }
  210 
  211 /*
  212  * Get a character from the head of a clist.
  213  */
  214 int
  215 getc(clistp)
  216         struct clist *clistp;
  217 {
  218         int chr = -1;
  219         int s;
  220         struct cblock *cblockp;
  221 
  222         s = spltty();
  223 
  224         /* If there are characters in the list, get one */
  225         if (clistp->c_cc) {
  226                 cblockp = (struct cblock *)((intptr_t)clistp->c_cf & ~CROUND);
  227                 chr = (u_char)*clistp->c_cf;
  228 
  229                 /*
  230                  * If this char is quoted, set the flag.
  231                  */
  232                 if (isset(cblockp->c_quote, clistp->c_cf - (char *)cblockp->c_info))
  233                         chr |= TTY_QUOTE;
  234 
  235                 /*
  236                  * Advance to next character.
  237                  */
  238                 clistp->c_cf++;
  239                 clistp->c_cc--;
  240                 /*
  241                  * If we have advanced the 'first' character pointer
  242                  * past the end of this cblock, advance to the next one.
  243                  * If there are no more characters, set the first and
  244                  * last pointers to NULL. In either case, free the
  245                  * current cblock.
  246                  */
  247                 if ((clistp->c_cf >= (char *)(cblockp+1)) || (clistp->c_cc == 0)) {
  248                         if (clistp->c_cc > 0) {
  249                                 clistp->c_cf = cblockp->c_next->c_info;
  250                         } else {
  251                                 clistp->c_cf = clistp->c_cl = NULL;
  252                         }
  253                         cblock_free(cblockp);
  254                         if (--clistp->c_cbcount >= clistp->c_cbreserved)
  255                                 ++cslushcount;
  256                 }
  257         }
  258 
  259         splx(s);
  260         return (chr);
  261 }
  262 
  263 /*
  264  * Copy 'amount' of chars, beginning at head of clist 'clistp' to
  265  * destination linear buffer 'dest'. Return number of characters
  266  * actually copied.
  267  */
  268 int
  269 q_to_b(clistp, dest, amount)
  270         struct clist *clistp;
  271         char *dest;
  272         int amount;
  273 {
  274         struct cblock *cblockp;
  275         struct cblock *cblockn;
  276         char *dest_orig = dest;
  277         int numc;
  278         int s;
  279 
  280         s = spltty();
  281 
  282         while (clistp && amount && (clistp->c_cc > 0)) {
  283                 cblockp = (struct cblock *)((intptr_t)clistp->c_cf & ~CROUND);
  284                 cblockn = cblockp + 1; /* pointer arithmetic! */
  285                 numc = min(amount, (char *)cblockn - clistp->c_cf);
  286                 numc = min(numc, clistp->c_cc);
  287                 bcopy(clistp->c_cf, dest, numc);
  288                 amount -= numc;
  289                 clistp->c_cf += numc;
  290                 clistp->c_cc -= numc;
  291                 dest += numc;
  292                 /*
  293                  * If this cblock has been emptied, advance to the next
  294                  * one. If there are no more characters, set the first
  295                  * and last pointer to NULL. In either case, free the
  296                  * current cblock.
  297                  */
  298                 if ((clistp->c_cf >= (char *)cblockn) || (clistp->c_cc == 0)) {
  299                         if (clistp->c_cc > 0) {
  300                                 clistp->c_cf = cblockp->c_next->c_info;
  301                         } else {
  302                                 clistp->c_cf = clistp->c_cl = NULL;
  303                         }
  304                         cblock_free(cblockp);
  305                         if (--clistp->c_cbcount >= clistp->c_cbreserved)
  306                                 ++cslushcount;
  307                 }
  308         }
  309 
  310         splx(s);
  311         return (dest - dest_orig);
  312 }
  313 
  314 /*
  315  * Flush 'amount' of chars, beginning at head of clist 'clistp'.
  316  */
  317 void
  318 ndflush(clistp, amount)
  319         struct clist *clistp;
  320         int amount;
  321 {
  322         struct cblock *cblockp;
  323         struct cblock *cblockn;
  324         int numc;
  325         int s;
  326 
  327         s = spltty();
  328 
  329         while (amount && (clistp->c_cc > 0)) {
  330                 cblockp = (struct cblock *)((intptr_t)clistp->c_cf & ~CROUND);
  331                 cblockn = cblockp + 1; /* pointer arithmetic! */
  332                 numc = min(amount, (char *)cblockn - clistp->c_cf);
  333                 numc = min(numc, clistp->c_cc);
  334                 amount -= numc;
  335                 clistp->c_cf += numc;
  336                 clistp->c_cc -= numc;
  337                 /*
  338                  * If this cblock has been emptied, advance to the next
  339                  * one. If there are no more characters, set the first
  340                  * and last pointer to NULL. In either case, free the
  341                  * current cblock.
  342                  */
  343                 if ((clistp->c_cf >= (char *)cblockn) || (clistp->c_cc == 0)) {
  344                         if (clistp->c_cc > 0) {
  345                                 clistp->c_cf = cblockp->c_next->c_info;
  346                         } else {
  347                                 clistp->c_cf = clistp->c_cl = NULL;
  348                         }
  349                         cblock_free(cblockp);
  350                         if (--clistp->c_cbcount >= clistp->c_cbreserved)
  351                                 ++cslushcount;
  352                 }
  353         }
  354 
  355         splx(s);
  356 }
  357 
  358 /*
  359  * Add a character to the end of a clist. Return -1 is no
  360  * more clists, or 0 for success.
  361  */
  362 int
  363 putc(chr, clistp)
  364         int chr;
  365         struct clist *clistp;
  366 {
  367         struct cblock *cblockp;
  368         int s;
  369 
  370         s = spltty();
  371 
  372         if (clistp->c_cl == NULL) {
  373                 if (clistp->c_cbreserved < 1) {
  374                         splx(s);
  375                         printf("putc to a clist with no reserved cblocks\n");
  376                         return (-1);            /* nothing done */
  377                 }
  378                 cblockp = cblock_alloc();
  379                 clistp->c_cbcount = 1;
  380                 clistp->c_cf = clistp->c_cl = cblockp->c_info;
  381                 clistp->c_cc = 0;
  382         } else {
  383                 cblockp = (struct cblock *)((intptr_t)clistp->c_cl & ~CROUND);
  384                 if (((intptr_t)clistp->c_cl & CROUND) == 0) {
  385                         struct cblock *prev = (cblockp - 1);
  386 
  387                         if (clistp->c_cbcount >= clistp->c_cbreserved) {
  388                                 if (clistp->c_cbcount >= clistp->c_cbmax
  389                                     || cslushcount <= 0) {
  390                                         splx(s);
  391                                         return (-1);
  392                                 }
  393                                 --cslushcount;
  394                         }
  395                         cblockp = cblock_alloc();
  396                         clistp->c_cbcount++;
  397                         prev->c_next = cblockp;
  398                         clistp->c_cl = cblockp->c_info;
  399                 }
  400         }
  401 
  402         /*
  403          * If this character is quoted, set the quote bit, if not, clear it.
  404          */
  405         if (chr & TTY_QUOTE) {
  406                 setbit(cblockp->c_quote, clistp->c_cl - (char *)cblockp->c_info);
  407                 /*
  408                  * Use one of the spare quote bits to record that something
  409                  * may be quoted.
  410                  */
  411                 setbit(cblockp->c_quote, CBQSIZE * NBBY - 1);
  412         } else
  413                 clrbit(cblockp->c_quote, clistp->c_cl - (char *)cblockp->c_info);
  414 
  415         *clistp->c_cl++ = chr;
  416         clistp->c_cc++;
  417 
  418         splx(s);
  419         return (0);
  420 }
  421 
  422 /*
  423  * Copy data from linear buffer to clist chain. Return the
  424  * number of characters not copied.
  425  */
  426 int
  427 b_to_q(src, amount, clistp)
  428         char *src;
  429         int amount;
  430         struct clist *clistp;
  431 {
  432         struct cblock *cblockp;
  433         char *firstbyte, *lastbyte;
  434         u_char startmask, endmask;
  435         int startbit, endbit, num_between, numc;
  436         int s;
  437 
  438         /*
  439          * Avoid allocating an initial cblock and then not using it.
  440          * c_cc == 0 must imply c_cbount == 0.
  441          */
  442         if (amount <= 0)
  443                 return (amount);
  444 
  445         s = spltty();
  446 
  447         /*
  448          * If there are no cblocks assigned to this clist yet,
  449          * then get one.
  450          */
  451         if (clistp->c_cl == NULL) {
  452                 if (clistp->c_cbreserved < 1) {
  453                         splx(s);
  454                         printf("b_to_q to a clist with no reserved cblocks.\n");
  455                         return (amount);        /* nothing done */
  456                 }
  457                 cblockp = cblock_alloc();
  458                 clistp->c_cbcount = 1;
  459                 clistp->c_cf = clistp->c_cl = cblockp->c_info;
  460                 clistp->c_cc = 0;
  461         } else {
  462                 cblockp = (struct cblock *)((intptr_t)clistp->c_cl & ~CROUND);
  463         }
  464 
  465         while (amount) {
  466                 /*
  467                  * Get another cblock if needed.
  468                  */
  469                 if (((intptr_t)clistp->c_cl & CROUND) == 0) {
  470                         struct cblock *prev = cblockp - 1;
  471 
  472                         if (clistp->c_cbcount >= clistp->c_cbreserved) {
  473                                 if (clistp->c_cbcount >= clistp->c_cbmax
  474                                     || cslushcount <= 0) {
  475                                         splx(s);
  476                                         return (amount);
  477                                 }
  478                                 --cslushcount;
  479                         }
  480                         cblockp = cblock_alloc();
  481                         clistp->c_cbcount++;
  482                         prev->c_next = cblockp;
  483                         clistp->c_cl = cblockp->c_info;
  484                 }
  485 
  486                 /*
  487                  * Copy a chunk of the linear buffer up to the end
  488                  * of this cblock.
  489                  */
  490                 numc = min(amount, (char *)(cblockp + 1) - clistp->c_cl);
  491                 bcopy(src, clistp->c_cl, numc);
  492 
  493                 /*
  494                  * Clear quote bits if they aren't known to be clear.
  495                  * The following could probably be made into a seperate
  496                  * "bitzero()" routine, but why bother?
  497                  */
  498                 if (isset(cblockp->c_quote, CBQSIZE * NBBY - 1)) {
  499                         startbit = clistp->c_cl - (char *)cblockp->c_info;
  500                         endbit = startbit + numc - 1;
  501 
  502                         firstbyte = (u_char *)cblockp->c_quote + (startbit / NBBY);
  503                         lastbyte = (u_char *)cblockp->c_quote + (endbit / NBBY);
  504 
  505                         /*
  506                          * Calculate mask of bits to preserve in first and
  507                          * last bytes.
  508                          */
  509                         startmask = NBBY - (startbit % NBBY);
  510                         startmask = 0xff >> startmask;
  511                         endmask = (endbit % NBBY);
  512                         endmask = 0xff << (endmask + 1);
  513 
  514                         if (firstbyte != lastbyte) {
  515                                 *firstbyte &= startmask;
  516                                 *lastbyte &= endmask;
  517 
  518                                 num_between = lastbyte - firstbyte - 1;
  519                                 if (num_between)
  520                                         bzero(firstbyte + 1, num_between);
  521                         } else {
  522                                 *firstbyte &= (startmask | endmask);
  523                         }
  524                 }
  525 
  526                 /*
  527                  * ...and update pointer for the next chunk.
  528                  */
  529                 src += numc;
  530                 clistp->c_cl += numc;
  531                 clistp->c_cc += numc;
  532                 amount -= numc;
  533                 /*
  534                  * If we go through the loop again, it's always
  535                  * for data in the next cblock, so by adding one (cblock),
  536                  * (which makes the pointer 1 beyond the end of this
  537                  * cblock) we prepare for the assignment of 'prev'
  538                  * above.
  539                  */
  540                 cblockp += 1;
  541 
  542         }
  543 
  544         splx(s);
  545         return (amount);
  546 }
  547 
  548 /*
  549  * Get the next character in the clist. Store it at dst. Don't
  550  * advance any clist pointers, but return a pointer to the next
  551  * character position.
  552  */
  553 char *
  554 nextc(clistp, cp, dst)
  555         struct clist *clistp;
  556         char *cp;
  557         int *dst;
  558 {
  559         struct cblock *cblockp;
  560 
  561         ++cp;
  562         /*
  563          * See if the next character is beyond the end of
  564          * the clist.
  565          */
  566         if (clistp->c_cc && (cp != clistp->c_cl)) {
  567                 /*
  568                  * If the next character is beyond the end of this
  569                  * cblock, advance to the next cblock.
  570                  */
  571                 if (((intptr_t)cp & CROUND) == 0)
  572                         cp = ((struct cblock *)cp - 1)->c_next->c_info;
  573                 cblockp = (struct cblock *)((intptr_t)cp & ~CROUND);
  574 
  575                 /*
  576                  * Get the character. Set the quote flag if this character
  577                  * is quoted.
  578                  */
  579                 *dst = (u_char)*cp | (isset(cblockp->c_quote, cp - (char *)cblockp->c_info) ? TTY_QUOTE : 0);
  580 
  581                 return (cp);
  582         }
  583 
  584         return (NULL);
  585 }
  586 
  587 /*
  588  * "Unput" a character from a clist.
  589  */
  590 int
  591 unputc(clistp)
  592         struct clist *clistp;
  593 {
  594         struct cblock *cblockp = 0, *cbp = 0;
  595         int s;
  596         int chr = -1;
  597 
  598 
  599         s = spltty();
  600 
  601         if (clistp->c_cc) {
  602                 --clistp->c_cc;
  603                 --clistp->c_cl;
  604 
  605                 chr = (u_char)*clistp->c_cl;
  606 
  607                 cblockp = (struct cblock *)((intptr_t)clistp->c_cl & ~CROUND);
  608 
  609                 /*
  610                  * Set quote flag if this character was quoted.
  611                  */
  612                 if (isset(cblockp->c_quote, (u_char *)clistp->c_cl - cblockp->c_info))
  613                         chr |= TTY_QUOTE;
  614 
  615                 /*
  616                  * If all of the characters have been unput in this
  617                  * cblock, then find the previous one and free this
  618                  * one.
  619                  */
  620                 if (clistp->c_cc && (clistp->c_cl <= (char *)cblockp->c_info)) {
  621                         cbp = (struct cblock *)((intptr_t)clistp->c_cf & ~CROUND);
  622 
  623                         while (cbp->c_next != cblockp)
  624                                 cbp = cbp->c_next;
  625 
  626                         /*
  627                          * When the previous cblock is at the end, the 'last'
  628                          * pointer always points (invalidly) one past.
  629                          */
  630                         clistp->c_cl = (char *)(cbp+1);
  631                         cblock_free(cblockp);
  632                         if (--clistp->c_cbcount >= clistp->c_cbreserved)
  633                                 ++cslushcount;
  634                         cbp->c_next = NULL;
  635                 }
  636         }
  637 
  638         /*
  639          * If there are no more characters on the list, then
  640          * free the last cblock.
  641          */
  642         if ((clistp->c_cc == 0) && clistp->c_cl) {
  643                 cblockp = (struct cblock *)((intptr_t)clistp->c_cl & ~CROUND);
  644                 cblock_free(cblockp);
  645                 if (--clistp->c_cbcount >= clistp->c_cbreserved)
  646                         ++cslushcount;
  647                 clistp->c_cf = clistp->c_cl = NULL;
  648         }
  649 
  650         splx(s);
  651         return (chr);
  652 }
  653 
  654 /*
  655  * Move characters in source clist to destination clist,
  656  * preserving quote bits.
  657  */
  658 void
  659 catq(src_clistp, dest_clistp)
  660         struct clist *src_clistp, *dest_clistp;
  661 {
  662         int chr, s;
  663 
  664         s = spltty();
  665         /*
  666          * If the destination clist is empty (has no cblocks atttached),
  667          * and there are no possible complications with the resource counters,
  668          * then we simply assign the current clist to the destination.
  669          */
  670         if (!dest_clistp->c_cf
  671             && src_clistp->c_cbcount <= src_clistp->c_cbmax
  672             && src_clistp->c_cbcount <= dest_clistp->c_cbmax) {
  673                 dest_clistp->c_cf = src_clistp->c_cf;
  674                 dest_clistp->c_cl = src_clistp->c_cl;
  675                 src_clistp->c_cf = src_clistp->c_cl = NULL;
  676 
  677                 dest_clistp->c_cc = src_clistp->c_cc;
  678                 src_clistp->c_cc = 0;
  679                 dest_clistp->c_cbcount = src_clistp->c_cbcount;
  680                 src_clistp->c_cbcount = 0;
  681 
  682                 splx(s);
  683                 return;
  684         }
  685 
  686         splx(s);
  687 
  688         /*
  689          * XXX  This should probably be optimized to more than one
  690          * character at a time.
  691          */
  692         while ((chr = getc(src_clistp)) != -1)
  693                 putc(chr, dest_clistp);
  694 }

Cache object: d2b09f25c8c4162bf5a3cad0b6ba86b4


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.