14887Schin /*********************************************************************** 24887Schin * * 34887Schin * This software is part of the ast package * 4*8462SApril.Chin@Sun.COM * Copyright (c) 1985-2008 AT&T Intellectual Property * 54887Schin * and is licensed under the * 64887Schin * Common Public License, Version 1.0 * 7*8462SApril.Chin@Sun.COM * by AT&T Intellectual Property * 84887Schin * * 94887Schin * A copy of the License is available at * 104887Schin * http://www.opensource.org/licenses/cpl1.0.txt * 114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 124887Schin * * 134887Schin * Information and Software Systems Research * 144887Schin * AT&T Research * 154887Schin * Florham Park NJ * 164887Schin * * 174887Schin * Glenn Fowler <gsf@research.att.com> * 184887Schin * David Korn <dgk@research.att.com> * 194887Schin * Phong Vo <kpv@research.att.com> * 204887Schin * * 214887Schin ***********************************************************************/ 224887Schin #include "sfhdr.h" 234887Schin 244887Schin /* Push back one byte to a given SF_READ stream 254887Schin ** 264887Schin ** Written by Kiem-Phong Vo. 274887Schin */ 284887Schin #if __STD_C 29*8462SApril.Chin@Sun.COM static int _uexcept(Sfio_t* f, int type, Void_t* val, Sfdisc_t* disc) 304887Schin #else 314887Schin static int _uexcept(f,type,val,disc) 32*8462SApril.Chin@Sun.COM Sfio_t *f; 33*8462SApril.Chin@Sun.COM int type; 344887Schin Void_t* val; 35*8462SApril.Chin@Sun.COM Sfdisc_t *disc; 364887Schin #endif 374887Schin { 384887Schin NOTUSED(val); 394887Schin 404887Schin /* hmm! This should never happen */ 414887Schin if(disc != _Sfudisc) 424887Schin return -1; 434887Schin 444887Schin /* close the unget stream */ 454887Schin if(type != SF_CLOSING) 464887Schin (void)sfclose((*_Sfstack)(f,NIL(Sfio_t*))); 474887Schin 484887Schin return 1; 494887Schin } 504887Schin 514887Schin #if __STD_C 52*8462SApril.Chin@Sun.COM int sfungetc(Sfio_t* f, int c) 534887Schin #else 544887Schin int sfungetc(f,c) 55*8462SApril.Chin@Sun.COM Sfio_t* f; /* push back one byte to this stream */ 56*8462SApril.Chin@Sun.COM int c; /* the value to be pushed back */ 574887Schin #endif 584887Schin { 594887Schin reg Sfio_t* uf; 60*8462SApril.Chin@Sun.COM SFMTXDECL(f); 614887Schin 62*8462SApril.Chin@Sun.COM SFMTXENTER(f, -1) 634887Schin 644887Schin if(c < 0 || (f->mode != SF_READ && _sfmode(f,SF_READ,0) < 0)) 654887Schin SFMTXRETURN(f, -1); 664887Schin SFLOCK(f,0); 674887Schin 684887Schin /* fast handling of the typical unget */ 694887Schin if(f->next > f->data && f->next[-1] == (uchar)c) 704887Schin { f->next -= 1; 714887Schin goto done; 724887Schin } 734887Schin 744887Schin /* make a string stream for unget characters */ 754887Schin if(f->disc != _Sfudisc) 764887Schin { if(!(uf = sfnew(NIL(Sfio_t*),NIL(char*),(size_t)SF_UNBOUND, 774887Schin -1,SF_STRING|SF_READ))) 784887Schin { c = -1; 794887Schin goto done; 804887Schin } 814887Schin _Sfudisc->exceptf = _uexcept; 824887Schin sfdisc(uf,_Sfudisc); 834887Schin SFOPEN(f,0); (void)sfstack(f,uf); SFLOCK(f,0); 844887Schin } 854887Schin 864887Schin /* space for data */ 874887Schin if(f->next == f->data) 884887Schin { reg uchar* data; 894887Schin if(f->size < 0) 904887Schin f->size = 0; 914887Schin if(!(data = (uchar*)malloc(f->size+16))) 924887Schin { c = -1; 934887Schin goto done; 944887Schin } 954887Schin f->flags |= SF_MALLOC; 964887Schin if(f->data) 974887Schin memcpy((char*)(data+16),(char*)f->data,f->size); 984887Schin f->size += 16; 994887Schin f->data = data; 1004887Schin f->next = data+16; 1014887Schin f->endb = data+f->size; 1024887Schin } 1034887Schin 1044887Schin *--f->next = (uchar)c; 1054887Schin done: 1064887Schin SFOPEN(f,0); 1074887Schin SFMTXRETURN(f, c); 1084887Schin } 109