genericopenlibs/cstdlib/LSTDIO/UNGETC.C
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     1 /* UNGETC.C
       
     2  * 
       
     3  * Portions Copyright (c) 1990-1999 Nokia Corporation and/or its subsidiary(-ies).
       
     4  * All rights reserved.
       
     5  */
       
     6 
       
     7 /*
       
     8  * Copyright (c) 1990 The Regents of the University of California.
       
     9  * All rights reserved.
       
    10  *
       
    11  * Redistribution and use in source and binary forms are permitted
       
    12  * provided that the above copyright notice and this paragraph are
       
    13  * duplicated in all such forms and that any documentation,
       
    14  * advertising materials, and other materials related to such
       
    15  * distribution and use acknowledge that the software was developed
       
    16  * by the University of California, Berkeley.  The name of the
       
    17  * University may not be used to endorse or promote products derived
       
    18  * from this software without specific prior written permission.
       
    19  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
       
    20  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
       
    21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
       
    22  */
       
    23 
       
    24 #include <stdio_r.h>
       
    25 #include <stdlib_r.h>
       
    26 #include <string.h>
       
    27 #include "LOCAL.H"
       
    28 
       
    29 /*
       
    30  * Expand the ungetc buffer `in place'.  That is, adjust fp->_p when
       
    31  * the buffer moves, so that it points the same distance from the end,
       
    32  * and move the bytes in the buffer around as necessary so that they
       
    33  * are all at the end (stack-style).
       
    34  */
       
    35 
       
    36 /*static*/
       
    37 int
       
    38 __submore (register FILE *fp)
       
    39 {
       
    40   register int i;
       
    41   register unsigned char *p;
       
    42 
       
    43   if (fp->_ub._base == fp->_ubuf)
       
    44     {
       
    45       /*
       
    46        * Get a new buffer (rather than expanding the old one).
       
    47        */
       
    48       if ((p = (unsigned char *) _malloc_r (fp->_data, (size_t) BUFSIZ)) == NULL)
       
    49 	return EOF;
       
    50       fp->_ub._base = p;
       
    51       fp->_ub._size = BUFSIZ;
       
    52       p += BUFSIZ - sizeof (fp->_ubuf);
       
    53       for (i = sizeof (fp->_ubuf); --i >= 0;)
       
    54 	p[i] = fp->_ubuf[i];
       
    55       fp->_p = p;
       
    56       return 0;
       
    57     }
       
    58   i = fp->_ub._size;
       
    59   p = (unsigned char *) _realloc_r (fp->_data, (void*) (fp->_ub._base), i << 1);
       
    60   if (p == NULL)
       
    61     return EOF;
       
    62   (void) memcpy ((void *) (p + i), (void *) p, (size_t) i);
       
    63   fp->_p = p + i;
       
    64   fp->_ub._base = p;
       
    65   fp->_ub._size = i << 1;
       
    66   return 0;
       
    67 }
       
    68 
       
    69 /**
       
    70 Push a character back into stream.
       
    71 @return If successful, the character putted is returned.
       
    72 Otherwise EOF is returned and the stream remains unchanged.
       
    73 @param c character to be pushed. 
       
    74 @param fp pointer to an open file.
       
    75 */
       
    76 EXPORT_C int
       
    77 ungetc (int c,register FILE *fp)
       
    78 {
       
    79   if (c == EOF)
       
    80     return (EOF);
       
    81 
       
    82   /* Ensure stdio has been initialized.
       
    83      ??? Might be able to remove this as some other stdio routine should
       
    84      have already been called to get the char we are un-getting.  */
       
    85 
       
    86   CHECK_INIT (fp);
       
    87 
       
    88   /* After ungetc, we won't be at eof anymore */
       
    89   fp->_flags &= ~__SEOF;
       
    90 
       
    91   if ((fp->_flags & __SRD) == 0)
       
    92     {
       
    93       /*
       
    94        * Not already reading: no good unless reading-and-writing.
       
    95        * Otherwise, flush any current write stuff.
       
    96        */
       
    97       if ((fp->_flags & __SRW) == 0)
       
    98 	return EOF;
       
    99       if (fp->_flags & __SWR)
       
   100 	{
       
   101 	  if (fflush (fp))
       
   102 	    return EOF;
       
   103 	  fp->_flags &= ~__SWR;
       
   104 	  fp->_w = 0;
       
   105 	  fp->_lbfsize = 0;
       
   106 	}
       
   107       fp->_flags |= __SRD;
       
   108     }
       
   109   c = (unsigned char) c;
       
   110 
       
   111   /*
       
   112    * If we are in the middle of ungetc'ing, just continue.
       
   113    * This may require expanding the current ungetc buffer.
       
   114    */
       
   115 
       
   116   if (HASUB (fp))
       
   117     {
       
   118       if (fp->_r >= fp->_ub._size && __submore (fp))
       
   119 	return EOF;
       
   120       *--fp->_p = (unsigned char)c;
       
   121       fp->_r++;
       
   122       return c;
       
   123     }
       
   124 
       
   125   /*
       
   126    * If we can handle this by simply backing up, do so,
       
   127    * but never replace the original character.
       
   128    * (This makes sscanf() work when scanning `const' data.)
       
   129    */
       
   130 
       
   131   if (fp->_bf._base != NULL && fp->_p > fp->_bf._base && fp->_p[-1] == c)
       
   132     {
       
   133       fp->_p--;
       
   134       fp->_r++;
       
   135       return c;
       
   136     }
       
   137 
       
   138   /*
       
   139    * Create an ungetc buffer.
       
   140    * Initially, we will use the `reserve' buffer.
       
   141    */
       
   142 
       
   143   fp->_ur = fp->_r;
       
   144   fp->_up = fp->_p;
       
   145   fp->_ub._base = fp->_ubuf;
       
   146   fp->_ub._size = sizeof (fp->_ubuf);
       
   147   fp->_ubuf[sizeof (fp->_ubuf) - 1] = (unsigned char)c;
       
   148   fp->_p = &fp->_ubuf[sizeof (fp->_ubuf) - 1];
       
   149   fp->_r = 1;
       
   150   return c;
       
   151 }