14887Schin /***********************************************************************
24887Schin * *
34887Schin * This software is part of the ast package *
4*12068SRoger.Faulkner@Oracle.COM * Copyright (c) 1985-2010 AT&T Intellectual Property *
54887Schin * and is licensed under the *
64887Schin * Common Public License, Version 1.0 *
78462SApril.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
_uexcept(Sfio_t * f,int type,Void_t * val,Sfdisc_t * disc)298462SApril.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)
328462SApril.Chin@Sun.COM Sfio_t *f;
338462SApril.Chin@Sun.COM int type;
344887Schin Void_t* val;
358462SApril.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
sfungetc(Sfio_t * f,int c)528462SApril.Chin@Sun.COM int sfungetc(Sfio_t* f, int c)
534887Schin #else
544887Schin int sfungetc(f,c)
558462SApril.Chin@Sun.COM Sfio_t* f; /* push back one byte to this stream */
568462SApril.Chin@Sun.COM int c; /* the value to be pushed back */
574887Schin #endif
584887Schin {
594887Schin reg Sfio_t* uf;
608462SApril.Chin@Sun.COM SFMTXDECL(f);
614887Schin
628462SApril.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