1 /***********************************************************************
2 * *
3 * This software is part of the ast package *
4 * Copyright (c) 1985-2010 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
_uexcept(Sfio_t * f,int type,Void_t * val,Sfdisc_t * disc)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
sfungetc(Sfio_t * f,int 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