1/*********************************************************************** 2* * 3* This software is part of the ast package * 4* Copyright (c) 1985-2011 AT&T Intellectual Property * 5* and is licensed under the * 6* Common Public License, Version 1.0 * 7* by AT&T Intellectual Property * 8* * 9* A copy of the License is available at * 10* http://www.opensource.org/licenses/cpl1.0.txt * 11* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12* * 13* Information and Software Systems Research * 14* AT&T Research * 15* Florham Park NJ * 16* * 17* Glenn Fowler <gsf@research.att.com> * 18* David Korn <dgk@research.att.com> * 19* Phong Vo <kpv@research.att.com> * 20* * 21***********************************************************************/ 22#include "sfhdr.h" 23 24/* Push back one byte to a given SF_READ stream 25** 26** Written by Kiem-Phong Vo. 27*/ 28#if __STD_C 29static int _uexcept(Sfio_t* f, int type, Void_t* val, Sfdisc_t* disc) 30#else 31static int _uexcept(f,type,val,disc) 32Sfio_t *f; 33int type; 34Void_t* val; 35Sfdisc_t *disc; 36#endif 37{ 38 NOTUSED(val); 39 40 /* hmm! This should never happen */ 41 if(disc != _Sfudisc) 42 return -1; 43 44 /* close the unget stream */ 45 if(type != SF_CLOSING) 46 (void)sfclose((*_Sfstack)(f,NIL(Sfio_t*))); 47 48 return 1; 49} 50 51#if __STD_C 52int sfungetc(Sfio_t* f, int c) 53#else 54int sfungetc(f,c) 55Sfio_t* f; /* push back one byte to this stream */ 56int c; /* the value to be pushed back */ 57#endif 58{ 59 reg Sfio_t* uf; 60 SFMTXDECL(f); 61 62 SFMTXENTER(f, -1) 63 64 if(c < 0 || (f->mode != SF_READ && _sfmode(f,SF_READ,0) < 0)) 65 SFMTXRETURN(f, -1); 66 SFLOCK(f,0); 67 68 /* fast handling of the typical unget */ 69 if(f->next > f->data && f->next[-1] == (uchar)c) 70 { f->next -= 1; 71 goto done; 72 } 73 74 /* make a string stream for unget characters */ 75 if(f->disc != _Sfudisc) 76 { if(!(uf = sfnew(NIL(Sfio_t*),NIL(char*),(size_t)SF_UNBOUND, 77 -1,SF_STRING|SF_READ))) 78 { c = -1; 79 goto done; 80 } 81 _Sfudisc->exceptf = _uexcept; 82 sfdisc(uf,_Sfudisc); 83 SFOPEN(f,0); (void)sfstack(f,uf); SFLOCK(f,0); 84 } 85 86 /* space for data */ 87 if(f->next == f->data) 88 { reg uchar* data; 89 if(f->size < 0) 90 f->size = 0; 91 if(!(data = (uchar*)malloc(f->size+16))) 92 { c = -1; 93 goto done; 94 } 95 f->flags |= SF_MALLOC; 96 if(f->data) 97 memcpy((char*)(data+16),(char*)f->data,f->size); 98 f->size += 16; 99 f->data = data; 100 f->next = data+16; 101 f->endb = data+f->size; 102 } 103 104 *--f->next = (uchar)c; 105done: 106 SFOPEN(f,0); 107 SFMTXRETURN(f, c); 108} 109