Keep m68klynx.c
[deliverable/binutils-gdb.git] / bfd / cache.c
index 39ffc7ac1734618034105aaeffbe21ca51e924e6..6be253cffb39021e20fa4d180beb199aa1e5676b 100644 (file)
-/*** cache.c -- Allows you to have more bfds open than your system has fds. */
+/* BFD library -- caching of file descriptors.
+   Copyright 1990, 1991, 1992 Free Software Foundation, Inc.
+   Hacked by Steve Chamberlain of Cygnus Support (steve@cygnus.com).
 
-/* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+This file is part of BFD, the Binary File Descriptor library.
 
-This file is part of BFD, the Binary File Diddler.
-
-BFD is free software; you can redistribute it and/or modify
+This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 1, or (at your option)
-any later version.
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
 
-BFD is distributed in the hope that it will be useful,
+This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with BFD; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/*
+SECTION
+       File Caching
+
+       The file caching mechanism is embedded within BFD and allows
+       the application to open as many BFDs as it wants without
+       regard to the underlying operating system's file descriptor
+       limit (often as low as 20 open files).  The module in
+       <<cache.c>> maintains a least recently used list of
+       <<BFD_CACHE_MAX_OPEN>> files, and exports the name
+       <<bfd_cache_lookup>> which runs around and makes sure that
+       the required BFD is open. If not, then it chooses a file to
+       close, closes it and opens the one wanted, returning its file
+       handle. 
+
+*/
 
-/* $Id$ */
-#include "sysdep.h"
 #include "bfd.h"
+#include "sysdep.h"
 #include "libbfd.h"
 
-/* These declarations should not be needed; libbfd.h's inclusion should
-   have handled it.
-   int fclose();
-   int fseek();
-*/
+/*
+INTERNAL_FUNCTION
+       BFD_CACHE_MAX_OPEN macro
+
+DESCRIPTION
+       The maximum number of files which the cache will keep open at
+       one time.
 
+.#define BFD_CACHE_MAX_OPEN 10
+
+*/
 
-/* The maximum number of FDs opened by bfd */
-#define BFD_CACHE_MAX_OPEN 10
 
-/* when this exceeds BFD_CACHE_MAX_OPEN, we get to work */
 static int open_files;
 
-static bfd *cache_sentinel;    /* Chain of bfds with active fds we've
+static bfd *cache_sentinel;    /* Chain of BFDs with active fds we've
                                   opened */
-static void
-bfd_cache_delete();
+
+/*
+INTERNAL_FUNCTION
+       bfd_last_cache
+
+SYNOPSIS
+       extern bfd *bfd_last_cache;
+
+DESCRIPTION
+       Zero, or a pointer to the topmost BFD on the chain.  This is
+       used by the <<bfd_cache_lookup>> macro in @file{libbfd.h} to
+       determine when it can avoid a function call.
+*/
 
 bfd *bfd_last_cache;
-\f
+
+/*
+ * INTERNAL_FUNCTION
+ *     bfd_cache_lookup
+ *
+ * DESCRIPTION
+ *     Checks to see if the required BFD is the same as the last one
+ *     looked up. If so then it can use the iostream in the BFD with
+ *     impunity, since it can't have changed since the last lookup,
+ *     otherwise it has to perform the complicated lookup function 
+ *
+ * .#define bfd_cache_lookup(x) \
+ * .    ((x)==bfd_last_cache? \
+ * .      (FILE*)(bfd_last_cache->iostream): \
+ * .       bfd_cache_lookup_worker(x))
+ *
+ *
+ */
+
+static boolean EXFUN(bfd_cache_delete,(bfd *));
+
 
 static void
-close_one()
+DEFUN_VOID(close_one)
 {
     bfd *kill = cache_sentinel;
     if (kill == 0)             /* Nothing in the cache */
@@ -59,33 +108,43 @@ close_one()
     }
 
     kill->where = ftell((FILE *)(kill->iostream));
-    bfd_cache_delete(kill);
-
+    (void) bfd_cache_delete(kill);
 }
-/* Cuts the bfd abfd out of the chain in the cache */
+
+/* Cuts the BFD abfd out of the chain in the cache */
 static void 
-snip (abfd)
-     bfd *abfd;
+DEFUN(snip,(abfd),
+      bfd *abfd)
 {
   abfd->lru_prev->lru_next = abfd->lru_next;
   abfd->lru_next->lru_prev = abfd->lru_prev; 
   if (cache_sentinel == abfd) cache_sentinel = (bfd *)NULL;
 }
 
-static void
-bfd_cache_delete (abfd)
-     bfd *abfd;
+static boolean
+DEFUN(bfd_cache_delete,(abfd),
+      bfd *abfd)
 {
-  fclose ((FILE *)(abfd->iostream));
+  boolean ret;
+
+  if (fclose ((FILE *)(abfd->iostream)) == 0)
+    ret = true;
+  else
+    {
+      ret = false;
+      bfd_error = system_call_error;
+    }
   snip (abfd);
   abfd->iostream = NULL;
   open_files--;
+  bfd_last_cache = 0;
+  return ret;
 }
   
 static bfd *
-insert(x,y)
-bfd *x;
-bfd *y;
+DEFUN(insert,(x,y),
+      bfd *x AND
+      bfd *y)
 {
   if (y) {
     x->lru_next = y;
@@ -102,99 +161,155 @@ bfd *y;
 }
 \f
 
-/* Initialize a BFD by putting it on the cache LRU.  */
+/*
+INTERNAL_FUNCTION
+       bfd_cache_init
+
+SYNOPSIS
+       void  bfd_cache_init (bfd *);
+
+DESCRIPTION
+       Initialize a BFD by putting it on the cache LRU.
+*/
+
 void
-bfd_cache_init(abfd)
-bfd *abfd;
+DEFUN(bfd_cache_init,(abfd),
+      bfd *abfd)
 {
   cache_sentinel = insert(abfd, cache_sentinel);
 }
 
-void
-bfd_cache_close(abfd)
-bfd *abfd;
+
+/*
+INTERNAL_FUNCTION
+       bfd_cache_close
+
+DESCRIPTION
+       Remove the BFD from the cache. If the attached file is open,
+       then close it too.
+
+SYNOPSIS
+       boolean bfd_cache_close (bfd *);
+
+RETURNS
+       <<false>> is returned if closing the file fails, <<true>> is
+       returned if all is well.
+*/
+boolean
+DEFUN(bfd_cache_close,(abfd),
+      bfd *abfd)
 {
   /* If this file is open then remove from the chain */
   if (abfd->iostream) 
     {
-      bfd_cache_delete(abfd);
+      return bfd_cache_delete(abfd);
+    }
+  else
+    {
+      return true;
     }
 }
-\f
-/* Call the OS to open a file for this BFD.  Returns the FILE *
-   (possibly null) that results from this operation.  Sets up the
-   BFD so that future accesses know the file is open.  */
+
+/*
+INTERNAL_FUNCTION
+       bfd_open_file
+
+DESCRIPTION
+       Call the OS to open a file for this BFD.  Returns the FILE *
+       (possibly null) that results from this operation.  Sets up the
+       BFD so that future accesses know the file is open. If the FILE
+       * returned is null, then there is won't have been put in the
+       cache, so it won't have to be removed from it.
+
+SYNOPSIS
+       FILE* bfd_open_file(bfd *);
+*/
 
 FILE *
-bfd_open_file (abfd)
-     bfd *abfd;
+DEFUN(bfd_open_file, (abfd),
+      bfd *abfd)
 {
-    abfd->cacheable = true;    /* Allow it to be closed later. */
-    if(open_files >= BFD_CACHE_MAX_OPEN) {
-       close_one();
-    }
-    switch (abfd->direction) {
- case read_direction:
- case no_direction:
-       abfd->iostream = (char *) fopen(abfd->filename, "r");
-       break;
- case both_direction:
- case write_direction:
-       if (abfd->opened_once == true) {
-           abfd->iostream = (char *) fopen(abfd->filename, "r+");
-           if (!abfd->iostream) {
-               abfd->iostream = (char *) fopen(abfd->filename, "w+");
-           }
-       } else {
-           /*open for creat */
-           abfd->iostream = (char *) fopen(abfd->filename, "w");
-           abfd->opened_once = true;
-       }
-       break;
-    }
-    if (abfd->iostream) {
-       open_files++;
-       bfd_cache_init (abfd);
+  abfd->cacheable = true;      /* Allow it to be closed later. */
+
+  if(open_files >= BFD_CACHE_MAX_OPEN) {
+    close_one();
+  }
+
+  switch (abfd->direction) {
+  case read_direction:
+  case no_direction:
+    abfd->iostream = (char *) fopen(abfd->filename, FOPEN_RB);
+    break;
+  case both_direction:
+  case write_direction:
+    if (abfd->opened_once == true) {
+      abfd->iostream = (char *) fopen(abfd->filename, FOPEN_RUB);
+      if (!abfd->iostream) {
+       abfd->iostream = (char *) fopen(abfd->filename, FOPEN_WUB);
+      }
+    } else {
+      /*open for creat */
+      abfd->iostream = (char *) fopen(abfd->filename, FOPEN_WB);
+      abfd->opened_once = true;
     }
+    break;
+  }
 
-    return (FILE *)(abfd->iostream);
+  if (abfd->iostream) {
+    open_files++;
+    bfd_cache_init (abfd);
+  }
+
+  return (FILE *)(abfd->iostream);
 }
 
-/* Find a file descriptor for this BFD.  If necessary, open it.
-   If there are already more than BFD_CACHE_MAX_OPEN files open, try to close
-   one first, to avoid running out of file descriptors.  */
+/*
+INTERNAL_FUNCTION
+       bfd_cache_lookup_worker
+
+DESCRIPTION
+       Called when the macro <<bfd_cache_lookup>> fails to find a
+       quick answer. Finds a file descriptor for this BFD.  If
+       necessary, it open it. If there are already more than
+       BFD_CACHE_MAX_OPEN files open, it trys to close one first, to
+       avoid running out of file descriptors.  
+
+SYNOPSIS
+       FILE *bfd_cache_lookup_worker(bfd *);
+
+*/
 
 FILE *
-bfd_cache_lookup_worker (abfd)
-     bfd *abfd;
+DEFUN(bfd_cache_lookup_worker,(abfd),
+      bfd *abfd)
 {
   if (abfd->my_archive) 
-    {
-      abfd = abfd->my_archive;
-    }
+      {
+       abfd = abfd->my_archive;
+      }
   /* Is this file already open .. if so then quick exit */
   if (abfd->iostream) 
-    {
-      if (abfd != cache_sentinel) {
-       /* Place onto head of lru chain */
-       snip (abfd);
-       cache_sentinel = insert(abfd, cache_sentinel);
+      {
+       if (abfd != cache_sentinel) {
+         /* Place onto head of lru chain */
+         snip (abfd);
+         cache_sentinel = insert(abfd, cache_sentinel);
+       }
       }
-    }
-  /* This is a bfd without a stream -
+  /* This is a BFD without a stream -
      so it must have been closed or never opened.
      find an empty cache entry and use it.  */
   else 
-    {
+      {
 
-      if (open_files >= BFD_CACHE_MAX_OPEN) 
-       {
-       close_one();
-    }
+       if (open_files >= BFD_CACHE_MAX_OPEN) 
+           {
+             close_one();
+           }
 
-      BFD_ASSERT(bfd_open_file (abfd) != (FILE *)NULL) ;
-      fseek((FILE *)(abfd->iostream), abfd->where, false);
-    }
-bfd_last_cache = abfd;
+       BFD_ASSERT(bfd_open_file (abfd) != (FILE *)NULL) ;
+       fseek((FILE *)(abfd->iostream), abfd->where, false);
+      }
+  bfd_last_cache = abfd;
   return (FILE *)(abfd->iostream);
 }
This page took 0.027384 seconds and 4 git commands to generate.