]> git.proxmox.com Git - mirror_edk2.git/blame - StdLib/LibC/Stdio/findfp.c
Standard Libraries for EDK II.
[mirror_edk2.git] / StdLib / LibC / Stdio / findfp.c
CommitLineData
2aa62f2b 1/* $NetBSD: findfp.c,v 1.23 2006/10/07 21:40:46 thorpej Exp $ */\r
2\r
3/*-\r
4 * Copyright (c) 1990, 1993\r
5 * The Regents of the University of California. All rights reserved.\r
6 *\r
7 * This code is derived from software contributed to Berkeley by\r
8 * Chris Torek.\r
9 *\r
10 * Redistribution and use in source and binary forms, with or without\r
11 * modification, are permitted provided that the following conditions\r
12 * are met:\r
13 * 1. Redistributions of source code must retain the above copyright\r
14 * notice, this list of conditions and the following disclaimer.\r
15 * 2. Redistributions in binary form must reproduce the above copyright\r
16 * notice, this list of conditions and the following disclaimer in the\r
17 * documentation and/or other materials provided with the distribution.\r
18 * 3. Neither the name of the University nor the names of its contributors\r
19 * may be used to endorse or promote products derived from this software\r
20 * without specific prior written permission.\r
21 *\r
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND\r
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE\r
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\r
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\r
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\r
32 * SUCH DAMAGE.\r
33 */\r
34#include <LibConfig.h>\r
35#include <sys/EfiCdefs.h>\r
36#if defined(LIBC_SCCS) && !defined(lint)\r
37#if 0\r
38static char sccsid[] = "@(#)findfp.c 8.2 (Berkeley) 1/4/94";\r
39#else\r
40__RCSID("$NetBSD: findfp.c,v 1.23 2006/10/07 21:40:46 thorpej Exp $");\r
41#endif\r
42#endif /* LIBC_SCCS and not lint */\r
43\r
44#include "namespace.h"\r
45#include <sys/param.h>\r
46#include <sys/EfiSysCall.h>\r
47#include <stdio.h>\r
48#include <errno.h>\r
49#include <stdlib.h>\r
50#include <string.h>\r
51#include "reentrant.h"\r
52#include "local.h"\r
53#include "glue.h"\r
54#include <MainData.h>\r
55\r
56int __sdidinit;\r
57\r
58#define NDYNAMIC 10 /* add ten more whenever necessary */\r
59\r
60#define std(flags, file) \\r
61/* p r w flags file bf lfbsize cookie close */ \\r
62 { NULL, 0, 0, flags, file, { NULL, 0 }, 0, __sF + file, __sclose, \\r
63/* read seek write ext up */ \\r
64 __sread, __sseek, __swrite, { (void *)(__sFext + file), 0 }, NULL, \\r
65/* ur ubuf, nbuf lb blksize offset */ \\r
66 0, { '\0', '\0', '\0' }, { '\0' }, { NULL, 0 }, 0, (fpos_t)0 }\r
67\r
68 /* the usual - (stdin + stdout + stderr) */\r
69static FILE usual[FOPEN_MAX - 3];\r
70static struct __sfileext usualext[FOPEN_MAX - 3];\r
71static struct glue uglue = { 0, FOPEN_MAX - 3, usual };\r
72\r
73#if defined(_REENTRANT) && !defined(__lint__) /* XXX lint is busted */\r
74#define STDEXT { ._lock = MUTEX_INITIALIZER, ._lockcond = COND_INITIALIZER }\r
75struct __sfileext __sFext[3] = { STDEXT,\r
76 STDEXT,\r
77 STDEXT};\r
78#else\r
79struct __sfileext __sFext[3];\r
80#endif\r
81\r
82FILE __sF[3] = {\r
83 std(__SRD, STDIN_FILENO), /* stdin */\r
84 std(__SWR, STDOUT_FILENO), /* stdout */\r
85 std(__SWR|__SNBF, STDERR_FILENO) /* stderr */\r
86};\r
87struct glue __sglue = { &uglue, 3, __sF };\r
88\r
89static struct glue *moreglue(int);\r
90void f_prealloc(void);\r
91\r
92#ifdef _REENTRANT\r
93rwlock_t __sfp_lock = RWLOCK_INITIALIZER;\r
94#endif\r
95\r
96static struct glue *\r
97moreglue(int n)\r
98{\r
99 struct glue *g;\r
100 FILE *p;\r
101 struct __sfileext *pext;\r
102 static FILE empty;\r
103\r
104 g = (struct glue *)malloc(sizeof(*g) + ALIGNBYTES + n * sizeof(FILE)\r
105 + n * sizeof(struct __sfileext));\r
106 if (g == NULL)\r
107 return (NULL);\r
108 p = (FILE *)ALIGN((g + 1));\r
109 g->next = NULL;\r
110 g->niobs = n;\r
111 g->iobs = p;\r
112 pext = (void *)(p + n);\r
113 while (--n >= 0) {\r
114 *p = empty;\r
115 _FILEEXT_SETUP(p, pext);\r
116 p++;\r
117 pext++;\r
118 }\r
119 return (g);\r
120}\r
121\r
122/*\r
123 * Find a free FILE for fopen et al.\r
124 */\r
125FILE *\r
126__sfp()\r
127{\r
128 FILE *fp;\r
129 int n;\r
130 struct glue *g;\r
131\r
132 if (!__sdidinit)\r
133 __sinit();\r
134\r
135 rwlock_wrlock(&__sfp_lock);\r
136 for (g = &__sglue;; g = g->next) {\r
137 for (fp = g->iobs, n = g->niobs; --n >= 0; fp++)\r
138 if (fp->_flags == 0)\r
139 goto found;\r
140 if (g->next == NULL && (g->next = moreglue(NDYNAMIC)) == NULL)\r
141 break;\r
142 }\r
143 rwlock_unlock(&__sfp_lock);\r
144 return (NULL);\r
145found:\r
146 fp->_flags = 1; /* reserve this slot; caller sets real flags */\r
147 fp->_p = NULL; /* no current pointer */\r
148 fp->_w = 0; /* nothing to read or write */\r
149 fp->_r = 0;\r
150 fp->_bf._base = NULL; /* no buffer */\r
151 fp->_bf._size = 0;\r
152 fp->_lbfsize = 0; /* not line buffered */\r
153 fp->_file = -1; /* no file */\r
154/* fp->_cookie = <any>; */ /* caller sets cookie, _read/_write etc */\r
155 _UB(fp)._base = NULL; /* no ungetc buffer */\r
156 _UB(fp)._size = 0;\r
157 fp->_lb._base = NULL; /* no line buffer */\r
158 fp->_lb._size = 0;\r
159 memset(WCIO_GET(fp), 0, sizeof(struct wchar_io_data));\r
160 rwlock_unlock(&__sfp_lock);\r
161 return (fp);\r
162}\r
163\r
164#if 0\r
165/*\r
166 * XXX. Force immediate allocation of internal memory. Not used by stdio,\r
167 * but documented historically for certain applications. Bad applications.\r
168 */\r
169void\r
170f_prealloc()\r
171{\r
172 struct glue *g;\r
173 int n;\r
174\r
175 n = (int)sysconf(_SC_OPEN_MAX) - FOPEN_MAX + 20; /* 20 for slop. */\r
176 for (g = &__sglue; (n -= g->niobs) > 0 && g->next; g = g->next)\r
177 /* void */;\r
178 if (n > 0)\r
179 g->next = moreglue(n);\r
180}\r
181#endif\r
182\r
183/*\r
184 * exit() calls _cleanup() through *gMD->cleanup, set whenever we\r
185 * open or buffer a file. This chicanery is done so that programs\r
186 * that do not use stdio need not link it all in.\r
187 *\r
188 * The name `_cleanup' is, alas, fairly well known outside stdio.\r
189 */\r
190void\r
191_cleanup( void )\r
192{\r
193 /* (void) _fwalk(fclose); */\r
194 (void) fflush(NULL); /* `cheating' */\r
195}\r
196\r
197/*\r
198 * __sinit() is called whenever stdio's internal variables must be set up.\r
199 */\r
200void\r
201__sinit( void )\r
202{\r
203 int i;\r
204\r
205 for (i = 0; i < FOPEN_MAX - 3; i++)\r
206 _FILEEXT_SETUP(&usual[i], &usualext[i]);\r
207\r
208 /* make sure we clean up on exit */\r
209 gMD->cleanup = _cleanup; /* conservative */\r
210 __sdidinit = 1;\r
211}\r