1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1985-2008 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 29 static int _uexcept(Sfio_t* f, int type, Void_t* val, Sfdisc_t* disc) 30 #else 31 static int _uexcept(f,type,val,disc) 32 Sfio_t *f; 33 int type; 34 Void_t* val; 35 Sfdisc_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 52 int sfungetc(Sfio_t* f, int c) 53 #else 54 int sfungetc(f,c) 55 Sfio_t* f; /* push back one byte to this stream */ 56 int 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; 105 done: 106 SFOPEN(f,0); 107 SFMTXRETURN(f, c); 108 } 109