1 /***********************************************************************
2 *                                                                      *
3 *               This software is part of the ast package               *
4 *          Copyright (c) 1985-2011 AT&T Intellectual Property          *
5 *                      and is licensed under the                       *
6 *                 Eclipse Public License, Version 1.0                  *
7 *                    by AT&T Intellectual Property                     *
8 *                                                                      *
9 *                A copy of the License is available at                 *
10 *          http://www.eclipse.org/org/documents/epl-v10.html           *
11 *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
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 /*	Fundamental function to create a new stream.
25 **	The argument flags defines the type of stream and the scheme
26 **	of buffering.
27 **
28 **	Written by Kiem-Phong Vo.
29 */
30 
31 #if __STD_C
sfnew(Sfio_t * oldf,Void_t * buf,size_t size,int file,int flags)32 Sfio_t* sfnew(Sfio_t* oldf, Void_t* buf, size_t size, int file, int flags)
33 #else
34 Sfio_t* sfnew(oldf,buf,size,file,flags)
35 Sfio_t* oldf;	/* old stream to be reused */
36 Void_t*	buf;	/* a buffer to read/write, if NULL, will be allocated */
37 size_t	size;	/* buffer size if buf is given or desired buffer size */
38 int	file;	/* file descriptor to read/write from */
39 int	flags;	/* type of file stream */
40 #endif
41 {
42 	reg Sfio_t*	f;
43 	reg int		sflags;
44 
45 	SFONCE();	/* initialize mutexes */
46 
47 	if(!(flags&SF_RDWR))
48 		return NIL(Sfio_t*);
49 
50 	sflags = 0;
51 	if((f = oldf) )
52 	{	if(flags&SF_EOF)
53 		{	if(f != sfstdin && f != sfstdout && f != sfstderr)
54 				f->mutex = NIL(Vtmutex_t*);
55 			SFCLEAR(f, f->mutex);
56 			oldf = NIL(Sfio_t*);
57 		}
58 		else if(f->mode&SF_AVAIL)
59 		{	/* only allow SF_STATIC to be already closed */
60 			if(!(f->flags&SF_STATIC) )
61 				return NIL(Sfio_t*);
62 			sflags = f->flags;
63 			oldf = NIL(Sfio_t*);
64 		}
65 		else
66 		{	/* reopening an open stream, close it first */
67 			sflags = f->flags;
68 
69 			if(((f->mode&SF_RDWR) != f->mode && _sfmode(f,0,0) < 0) ||
70 			   SFCLOSE(f) < 0 )
71 				return NIL(Sfio_t*);
72 
73 			if(f->data && ((flags&SF_STRING) || size != (size_t)SF_UNBOUND) )
74 			{	if(sflags&SF_MALLOC)
75 					free((Void_t*)f->data);
76 				f->data = NIL(uchar*);
77 			}
78 			if(!f->data)
79 				sflags &= ~SF_MALLOC;
80 		}
81 	}
82 
83 	if(!f)
84 	{	/* reuse a standard stream structure if possible */
85 		if(!(flags&SF_STRING) && file >= 0 && file <= 2)
86 		{	f = file == 0 ? sfstdin : file == 1 ? sfstdout : sfstderr;
87 			if(f)
88 			{	if(f->mode&SF_AVAIL)
89 				{	sflags = f->flags;
90 					SFCLEAR(f, f->mutex);
91 				}
92 				else	f = NIL(Sfio_t*);
93 			}
94 		}
95 
96 		if(!f)
97 		{	if(!(f = (Sfio_t*)malloc(sizeof(Sfio_t))) )
98 				return NIL(Sfio_t*);
99 			SFCLEAR(f, NIL(Vtmutex_t*));
100 		}
101 	}
102 
103 	/* create a mutex */
104 	if(!f->mutex)
105 		f->mutex = vtmtxopen(NIL(Vtmutex_t*), VT_INIT);
106 
107 	/* stream type */
108 	f->mode = (flags&SF_READ) ? SF_READ : SF_WRITE;
109 	f->flags = (flags&SF_FLAGS) | (sflags&(SF_MALLOC|SF_STATIC));
110 	f->bits = (flags&SF_RDWR) == SF_RDWR ? SF_BOTH : 0;
111 	f->file = file;
112 	f->here = f->extent = 0;
113 	f->getr = f->tiny[0] = 0;
114 
115 	f->mode |= SF_INIT;
116 	if(size != (size_t)SF_UNBOUND)
117 	{	f->size = size;
118 		f->data = size <= 0 ? NIL(uchar*) : (uchar*)buf;
119 	}
120 	f->endb = f->endr = f->endw = f->next = f->data;
121 
122 	if(_Sfnotify)
123 		(*_Sfnotify)(f, SF_NEW, (void*)((long)f->file));
124 
125 	if(f->flags&SF_STRING)
126 		(void)_sfmode(f,f->mode&SF_RDWR,0);
127 
128 	return f;
129 }
130