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