1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1985-2007 AT&T Knowledge Ventures * 5 * and is licensed under the * 6 * Common Public License, Version 1.0 * 7 * by AT&T Knowledge Ventures * 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(reg Sfio_t* f, reg int type, Void_t* val, reg Sfdisc_t* disc) 30 #else 31 static int _uexcept(f,type,val,disc) 32 reg Sfio_t *f; 33 reg int type; 34 Void_t* val; 35 reg 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(reg Sfio_t* f, reg int c) 53 #else 54 int sfungetc(f,c) 55 reg Sfio_t* f; /* push back one byte to this stream */ 56 reg int c; /* the value to be pushed back */ 57 #endif 58 { 59 reg Sfio_t* uf; 60 61 SFMTXSTART(f, -1) 62 63 if(c < 0 || (f->mode != SF_READ && _sfmode(f,SF_READ,0) < 0)) 64 SFMTXRETURN(f, -1); 65 SFLOCK(f,0); 66 67 /* fast handling of the typical unget */ 68 if(f->next > f->data && f->next[-1] == (uchar)c) 69 { f->next -= 1; 70 goto done; 71 } 72 73 /* make a string stream for unget characters */ 74 if(f->disc != _Sfudisc) 75 { if(!(uf = sfnew(NIL(Sfio_t*),NIL(char*),(size_t)SF_UNBOUND, 76 -1,SF_STRING|SF_READ))) 77 { c = -1; 78 goto done; 79 } 80 _Sfudisc->exceptf = _uexcept; 81 sfdisc(uf,_Sfudisc); 82 SFOPEN(f,0); (void)sfstack(f,uf); SFLOCK(f,0); 83 } 84 85 /* space for data */ 86 if(f->next == f->data) 87 { reg uchar* data; 88 if(f->size < 0) 89 f->size = 0; 90 if(!(data = (uchar*)malloc(f->size+16))) 91 { c = -1; 92 goto done; 93 } 94 f->flags |= SF_MALLOC; 95 if(f->data) 96 memcpy((char*)(data+16),(char*)f->data,f->size); 97 f->size += 16; 98 f->data = data; 99 f->next = data+16; 100 f->endb = data+f->size; 101 } 102 103 *--f->next = (uchar)c; 104 done: 105 SFOPEN(f,0); 106 SFMTXRETURN(f, c); 107 } 108