]> git.proxmox.com Git - mirror_edk2.git/blobdiff - StdLib/LibC/Stdio/findfp.c
Standard Libraries for EDK II.
[mirror_edk2.git] / StdLib / LibC / Stdio / findfp.c
diff --git a/StdLib/LibC/Stdio/findfp.c b/StdLib/LibC/Stdio/findfp.c
new file mode 100644 (file)
index 0000000..b6495c3
--- /dev/null
@@ -0,0 +1,211 @@
+/*  $NetBSD: findfp.c,v 1.23 2006/10/07 21:40:46 thorpej Exp $  */\r
+\r
+/*-\r
+ * Copyright (c) 1990, 1993\r
+ *  The Regents of the University of California.  All rights reserved.\r
+ *\r
+ * This code is derived from software contributed to Berkeley by\r
+ * Chris Torek.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions\r
+ * are met:\r
+ * 1. Redistributions of source code must retain the above copyright\r
+ *    notice, this list of conditions and the following disclaimer.\r
+ * 2. Redistributions in binary form must reproduce the above copyright\r
+ *    notice, this list of conditions and the following disclaimer in the\r
+ *    documentation and/or other materials provided with the distribution.\r
+ * 3. Neither the name of the University nor the names of its contributors\r
+ *    may be used to endorse or promote products derived from this software\r
+ *    without specific prior written permission.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND\r
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE\r
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\r
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\r
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\r
+ * SUCH DAMAGE.\r
+ */\r
+#include  <LibConfig.h>\r
+#include  <sys/EfiCdefs.h>\r
+#if defined(LIBC_SCCS) && !defined(lint)\r
+#if 0\r
+static char sccsid[] = "@(#)findfp.c  8.2 (Berkeley) 1/4/94";\r
+#else\r
+__RCSID("$NetBSD: findfp.c,v 1.23 2006/10/07 21:40:46 thorpej Exp $");\r
+#endif\r
+#endif /* LIBC_SCCS and not lint */\r
+\r
+#include  "namespace.h"\r
+#include  <sys/param.h>\r
+#include  <sys/EfiSysCall.h>\r
+#include  <stdio.h>\r
+#include  <errno.h>\r
+#include  <stdlib.h>\r
+#include  <string.h>\r
+#include  "reentrant.h"\r
+#include  "local.h"\r
+#include  "glue.h"\r
+#include  <MainData.h>\r
+\r
+int __sdidinit;\r
+\r
+#define NDYNAMIC 10   /* add ten more whenever necessary */\r
+\r
+#define std(flags, file) \\r
+/*    p     r  w  flags  file  bf     lfbsize  cookie       close */ \\r
+  { NULL, 0, 0, flags, file, { NULL, 0 }, 0, __sF + file, __sclose, \\r
+/*    read      seek     write     ext                              up */ \\r
+    __sread,  __sseek, __swrite, { (void *)(__sFext + file), 0 }, NULL, \\r
+/*    ur ubuf,                 nbuf      lb     blksize  offset */ \\r
+    0, { '\0', '\0', '\0' }, { '\0' }, { NULL, 0 }, 0, (fpos_t)0 }\r
+\r
+        /* the usual - (stdin + stdout + stderr) */\r
+static FILE usual[FOPEN_MAX - 3];\r
+static struct __sfileext usualext[FOPEN_MAX - 3];\r
+static struct glue uglue = { 0, FOPEN_MAX - 3, usual };\r
+\r
+#if defined(_REENTRANT) && !defined(__lint__) /* XXX lint is busted */\r
+#define STDEXT { ._lock = MUTEX_INITIALIZER, ._lockcond = COND_INITIALIZER }\r
+struct __sfileext __sFext[3] = { STDEXT,\r
+         STDEXT,\r
+         STDEXT};\r
+#else\r
+struct __sfileext __sFext[3];\r
+#endif\r
+\r
+FILE __sF[3] = {\r
+  std(__SRD, STDIN_FILENO),   /* stdin */\r
+  std(__SWR, STDOUT_FILENO),    /* stdout */\r
+  std(__SWR|__SNBF, STDERR_FILENO)  /* stderr */\r
+};\r
+struct glue __sglue = { &uglue, 3, __sF };\r
+\r
+static struct glue *moreglue(int);\r
+void f_prealloc(void);\r
+\r
+#ifdef _REENTRANT\r
+rwlock_t __sfp_lock = RWLOCK_INITIALIZER;\r
+#endif\r
+\r
+static struct glue *\r
+moreglue(int n)\r
+{\r
+  struct glue *g;\r
+  FILE *p;\r
+  struct __sfileext *pext;\r
+  static FILE empty;\r
+\r
+  g = (struct glue *)malloc(sizeof(*g) + ALIGNBYTES + n * sizeof(FILE)\r
+    + n * sizeof(struct __sfileext));\r
+  if (g == NULL)\r
+    return (NULL);\r
+  p = (FILE *)ALIGN((g + 1));\r
+  g->next = NULL;\r
+  g->niobs = n;\r
+  g->iobs = p;\r
+  pext = (void *)(p + n);\r
+  while (--n >= 0) {\r
+    *p = empty;\r
+    _FILEEXT_SETUP(p, pext);\r
+    p++;\r
+    pext++;\r
+  }\r
+  return (g);\r
+}\r
+\r
+/*\r
+ * Find a free FILE for fopen et al.\r
+ */\r
+FILE *\r
+__sfp()\r
+{\r
+  FILE *fp;\r
+  int n;\r
+  struct glue *g;\r
+\r
+  if (!__sdidinit)\r
+    __sinit();\r
+\r
+  rwlock_wrlock(&__sfp_lock);\r
+  for (g = &__sglue;; g = g->next) {\r
+    for (fp = g->iobs, n = g->niobs; --n >= 0; fp++)\r
+      if (fp->_flags == 0)\r
+        goto found;\r
+    if (g->next == NULL && (g->next = moreglue(NDYNAMIC)) == NULL)\r
+      break;\r
+  }\r
+  rwlock_unlock(&__sfp_lock);\r
+  return (NULL);\r
+found:\r
+  fp->_flags = 1;   /* reserve this slot; caller sets real flags */\r
+  fp->_p = NULL;    /* no current pointer */\r
+  fp->_w = 0;   /* nothing to read or write */\r
+  fp->_r = 0;\r
+  fp->_bf._base = NULL; /* no buffer */\r
+  fp->_bf._size = 0;\r
+  fp->_lbfsize = 0; /* not line buffered */\r
+  fp->_file = -1;   /* no file */\r
+/*  fp->_cookie = <any>; */ /* caller sets cookie, _read/_write etc */\r
+  _UB(fp)._base = NULL; /* no ungetc buffer */\r
+  _UB(fp)._size = 0;\r
+  fp->_lb._base = NULL; /* no line buffer */\r
+  fp->_lb._size = 0;\r
+  memset(WCIO_GET(fp), 0, sizeof(struct wchar_io_data));\r
+  rwlock_unlock(&__sfp_lock);\r
+  return (fp);\r
+}\r
+\r
+#if 0\r
+/*\r
+ * XXX.  Force immediate allocation of internal memory.  Not used by stdio,\r
+ * but documented historically for certain applications.  Bad applications.\r
+ */\r
+void\r
+f_prealloc()\r
+{\r
+  struct glue *g;\r
+  int n;\r
+\r
+  n = (int)sysconf(_SC_OPEN_MAX) - FOPEN_MAX + 20; /* 20 for slop. */\r
+  for (g = &__sglue; (n -= g->niobs) > 0 && g->next; g = g->next)\r
+    /* void */;\r
+  if (n > 0)\r
+    g->next = moreglue(n);\r
+}\r
+#endif\r
+\r
+/*\r
+ * exit() calls _cleanup() through *gMD->cleanup, set whenever we\r
+ * open or buffer a file.  This chicanery is done so that programs\r
+ * that do not use stdio need not link it all in.\r
+ *\r
+ * The name `_cleanup' is, alas, fairly well known outside stdio.\r
+ */\r
+void\r
+_cleanup( void )\r
+{\r
+  /* (void) _fwalk(fclose); */\r
+  (void) fflush(NULL);      /* `cheating' */\r
+}\r
+\r
+/*\r
+ * __sinit() is called whenever stdio's internal variables must be set up.\r
+ */\r
+void\r
+__sinit( void )\r
+{\r
+  int i;\r
+\r
+  for (i = 0; i < FOPEN_MAX - 3; i++)\r
+    _FILEEXT_SETUP(&usual[i], &usualext[i]);\r
+\r
+  /* make sure we clean up on exit */\r
+  gMD->cleanup = _cleanup;   /* conservative */\r
+  __sdidinit = 1;\r
+}\r