Update all #include directives to the currently preferred style.
[pspp-builds.git] / src / data / file-handle-def.c
index 872559154469cceebbbf3272aab1702a319b80e8..d411d6917d0ef73d9fc04c1875ebe942f72fa3f8 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
+   Copyright (C) 1997-9, 2000, 2006, 2009, 2010, 2011 Free Software Foundation, Inc.
 
    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
 
    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
 
 #include <config.h>
 
 
 #include <config.h>
 
-#include "file-handle-def.h"
+#include "data/file-handle-def.h"
 
 #include <assert.h>
 #include <errno.h>
 #include <stdlib.h>
 #include <string.h>
 
 
 #include <assert.h>
 #include <errno.h>
 #include <stdlib.h>
 #include <string.h>
 
-#include <libpspp/compiler.h>
-#include <libpspp/hash.h>
-#include <libpspp/ll.h>
-#include <libpspp/message.h>
-#include <libpspp/str.h>
-#include <data/file-name.h>
-#include <data/variable.h>
-#include <data/scratch-handle.h>
+#include "libpspp/compiler.h"
+#include "libpspp/hmap.h"
+#include "libpspp/i18n.h"
+#include "libpspp/ll.h"
+#include "libpspp/message.h"
+#include "libpspp/str.h"
+#include "libpspp/hash-functions.h"
+#include "data/file-name.h"
+#include "data/variable.h"
+#include "data/scratch-handle.h"
 
 
-#include "xalloc.h"
+#include "gl/xalloc.h"
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
@@ -49,6 +51,7 @@ struct file_handle
     /* FH_REF_FILE only. */
     char *file_name;           /* File name as provided by user. */
     enum fh_mode mode;         /* File mode. */
     /* FH_REF_FILE only. */
     char *file_name;           /* File name as provided by user. */
     enum fh_mode mode;         /* File mode. */
+    const char *encoding;       /* File encoding. */
 
     /* FH_REF_FILE and FH_REF_INLINE only. */
     size_t record_width;        /* Length of fixed-format records. */
 
     /* FH_REF_FILE and FH_REF_INLINE only. */
     size_t record_width;        /* Length of fixed-format records. */
@@ -79,6 +82,9 @@ static struct file_handle *create_handle (const char *id,
 static void free_handle (struct file_handle *);
 static void unname_handle (struct file_handle *);
 
 static void free_handle (struct file_handle *);
 static void unname_handle (struct file_handle *);
 
+/* Hash table of all active locks. */
+static struct hmap locks = HMAP_INITIALIZER (locks);
+
 /* File handle initialization routine. */
 void
 fh_init (void)
 /* File handle initialization routine. */
 void
 fh_init (void)
@@ -228,12 +234,13 @@ fh_create_file (const char *id, const char *file_name,
   char *handle_name;
   struct file_handle *handle;
 
   char *handle_name;
   struct file_handle *handle;
 
-  handle_name = id != NULL ? xstrdup (id) : xasprintf ("\"%s\"", file_name);
+  handle_name = id != NULL ? xstrdup (id) : xasprintf ("`%s'", file_name);
   handle = create_handle (id, handle_name, FH_REF_FILE);
   handle->file_name = xstrdup (file_name);
   handle->mode = properties->mode;
   handle->record_width = properties->record_width;
   handle->tab_width = properties->tab_width;
   handle = create_handle (id, handle_name, FH_REF_FILE);
   handle->file_name = xstrdup (file_name);
   handle->mode = properties->mode;
   handle->record_width = properties->record_width;
   handle->tab_width = properties->tab_width;
+  handle->encoding = properties->encoding;
   return handle;
 }
 
   return handle;
 }
 
@@ -254,7 +261,7 @@ const struct fh_properties *
 fh_default_properties (void)
 {
   static const struct fh_properties default_properties
 fh_default_properties (void)
 {
   static const struct fh_properties default_properties
-    = {FH_MODE_TEXT, 1024, 4};
+    = {FH_MODE_TEXT, 1024, 4, C_ENCODING};
   return &default_properties;
 }
 
   return &default_properties;
 }
 
@@ -322,6 +329,14 @@ fh_get_tab_width (const struct file_handle *handle)
   return handle->tab_width;
 }
 
   return handle->tab_width;
 }
 
+/* Returns the encoding of characters read from HANDLE. */
+const char *
+fh_get_legacy_encoding (const struct file_handle *handle)
+{
+  assert (handle->referent & (FH_REF_FILE | FH_REF_INLINE));
+  return (handle->referent == FH_REF_FILE ? handle->encoding : C_ENCODING);
+}
+
 /* Returns the scratch file handle associated with HANDLE.
    Applicable to only FH_REF_SCRATCH files. */
 struct scratch_handle *
 /* Returns the scratch file handle associated with HANDLE.
    Applicable to only FH_REF_SCRATCH files. */
 struct scratch_handle *
@@ -363,6 +378,8 @@ fh_set_default_handle (struct file_handle *new_default_handle)
 /* Information about a file handle's readers or writers. */
 struct fh_lock
   {
 /* Information about a file handle's readers or writers. */
 struct fh_lock
   {
+    struct hmap_node node;      /* hmap_node member. */
+
     /* Hash key. */
     enum fh_referent referent;  /* Type of underlying file. */
     union
     /* Hash key. */
     enum fh_referent referent;  /* Type of underlying file. */
     union
@@ -382,14 +399,12 @@ struct fh_lock
     void *aux;                  /* Owner's auxiliary data. */
   };
 
     void *aux;                  /* Owner's auxiliary data. */
   };
 
-/* Hash table of all active locks. */
-static struct hsh_table *locks;
 
 static void make_key (struct fh_lock *, const struct file_handle *,
                       enum fh_access);
 static void free_key (struct fh_lock *);
 
 static void make_key (struct fh_lock *, const struct file_handle *,
                       enum fh_access);
 static void free_key (struct fh_lock *);
-static int compare_fh_locks (const void *, const void *, const void *);
-static unsigned int hash_fh_lock (const void *, const void *);
+static int compare_fh_locks (const struct fh_lock *a, const struct fh_lock *b);
+static unsigned int hash_fh_lock (const struct fh_lock *lock);
 
 /* Tries to lock handle H for the given kind of ACCESS and TYPE
    of file.  Returns a pointer to a struct fh_lock if successful,
 
 /* Tries to lock handle H for the given kind of ACCESS and TYPE
    of file.  Returns a pointer to a struct fh_lock if successful,
@@ -403,6 +418,10 @@ static unsigned int hash_fh_lock (const void *, const void *);
    and similarly for writing.  If successful, a reference to TYPE
    is retained, so it should probably be a string literal.
 
    and similarly for writing.  If successful, a reference to TYPE
    is retained, so it should probably be a string literal.
 
+   TYPE should be marked with N_() in the caller: that is, the
+   caller should not translate it with gettext, but fh_lock will
+   do so.
+
    ACCESS specifies whether the lock is for reading or writing.
    EXCLUSIVE is true to require exclusive access, false to allow
    sharing with other accessors.  Exclusive read access precludes
    ACCESS specifies whether the lock is for reading or writing.
    EXCLUSIVE is true to require exclusive access, false to allow
    sharing with other accessors.  Exclusive read access precludes
@@ -417,31 +436,36 @@ struct fh_lock *
 fh_lock (struct file_handle *h, enum fh_referent mask UNUSED,
          const char *type, enum fh_access access, bool exclusive)
 {
 fh_lock (struct file_handle *h, enum fh_referent mask UNUSED,
          const char *type, enum fh_access access, bool exclusive)
 {
-  struct fh_lock key, *lock;
-  void **lockp;
+  struct fh_lock *key = NULL;
+  size_t hash ;
+  struct fh_lock *lock = NULL;
+  bool found_lock = false;
 
   assert ((fh_get_referent (h) & mask) != 0);
   assert (access == FH_ACC_READ || access == FH_ACC_WRITE);
 
 
   assert ((fh_get_referent (h) & mask) != 0);
   assert (access == FH_ACC_READ || access == FH_ACC_WRITE);
 
-  if (locks == NULL)
-    locks = hsh_create (0, compare_fh_locks, hash_fh_lock, NULL, NULL);
+  key = xmalloc (sizeof *key);
+
+  make_key (key, h, access);
+
+  key->open_cnt = 1;
+  key->exclusive = exclusive;
+  key->type = type;
+  key->aux = NULL;
 
 
-  make_key (&key, h, access);
-  lockp = hsh_probe (locks, &key);
-  if (*lockp == NULL)
+  hash = hash_fh_lock (key);
+
+  HMAP_FOR_EACH_WITH_HASH (lock, struct fh_lock, node, hash, &locks)
     {
     {
-      lock = *lockp = xmalloc (sizeof *lock);
-      *lock = key;
-      lock->open_cnt = 1;
-      lock->exclusive = exclusive;
-      lock->type = type;
-      lock->aux = NULL;
+      if ( 0 == compare_fh_locks (lock, key))
+       {
+         found_lock = true;
+         break;
+       }
     }
     }
-  else
-    {
-      free_key (&key);
 
 
-      lock = *lockp;
+  if ( found_lock )
+    {
       if (strcmp (lock->type, type))
         {
           if (access == FH_ACC_READ)
       if (strcmp (lock->type, type))
         {
           if (access == FH_ACC_READ)
@@ -461,9 +485,27 @@ fh_lock (struct file_handle *h, enum fh_referent mask UNUSED,
           return NULL;
         }
       lock->open_cnt++;
           return NULL;
         }
       lock->open_cnt++;
+      
+      free_key (key);
+      free (key);
+
+      return lock;
     }
 
     }
 
-  return lock;
+  hmap_insert (&locks, &key->node, hash);
+  found_lock = false;
+  HMAP_FOR_EACH_WITH_HASH (lock, struct fh_lock, node, hash, &locks)
+    {
+      if ( 0 == compare_fh_locks (lock, key))
+       {
+         found_lock = true;
+         break;
+       }
+    }
+
+  assert (found_lock);
+
+  return key;
 }
 
 /* Releases LOCK that was acquired with fh_lock.
 }
 
 /* Releases LOCK that was acquired with fh_lock.
@@ -485,7 +527,7 @@ fh_unlock (struct fh_lock *lock)
       assert (lock->open_cnt > 0);
       if (--lock->open_cnt == 0)
         {
       assert (lock->open_cnt > 0);
       if (--lock->open_cnt == 0)
         {
-          hsh_delete (locks, lock);
+         hmap_delete (&locks, &lock->node);
           free_key (lock);
           free (lock);
           return false;
           free_key (lock);
           free (lock);
           return false;
@@ -518,10 +560,24 @@ bool
 fh_is_locked (const struct file_handle *handle, enum fh_access access)
 {
   struct fh_lock key;
 fh_is_locked (const struct file_handle *handle, enum fh_access access)
 {
   struct fh_lock key;
-  bool is_locked;
+  const struct fh_lock *k = NULL;
+  bool is_locked = false;
+  size_t hash ;
 
   make_key (&key, handle, access);
 
   make_key (&key, handle, access);
-  is_locked = hsh_find (locks, &key) != NULL;
+
+  hash = hash_fh_lock (&key);
+
+
+  HMAP_FOR_EACH_WITH_HASH (k, struct fh_lock, node, hash, &locks)
+    {
+      if ( 0 == compare_fh_locks (k, &key))
+       {
+         is_locked = true;
+         break;
+       }
+    }
+
   free_key (&key);
 
   return is_locked;
   free_key (&key);
 
   return is_locked;
@@ -555,11 +611,8 @@ free_key (struct fh_lock *lock)
 /* Compares the key fields in struct fh_lock objects A and B and
    returns a strcmp()-type result. */
 static int
 /* Compares the key fields in struct fh_lock objects A and B and
    returns a strcmp()-type result. */
 static int
-compare_fh_locks (const void *a_, const void *b_, const void *aux UNUSED)
+compare_fh_locks (const struct fh_lock *a, const struct fh_lock *b)
 {
 {
-  const struct fh_lock *a = a_;
-  const struct fh_lock *b = b_;
-
   if (a->referent != b->referent)
     return a->referent < b->referent ? -1 : 1;
   else if (a->access != b->access)
   if (a->referent != b->referent)
     return a->referent < b->referent ? -1 : 1;
   else if (a->access != b->access)
@@ -575,13 +628,14 @@ compare_fh_locks (const void *a_, const void *b_, const void *aux UNUSED)
 
 /* Returns a hash value for LOCK. */
 static unsigned int
 
 /* Returns a hash value for LOCK. */
 static unsigned int
-hash_fh_lock (const void *lock_, const void *aux UNUSED)
+hash_fh_lock (const struct fh_lock *lock)
 {
 {
-  const struct fh_lock *lock = lock_;
-  unsigned int hash = hsh_hash_int ((lock->referent << 3) | lock->access);
+  unsigned int basis;
   if (lock->referent == FH_REF_FILE)
   if (lock->referent == FH_REF_FILE)
-    hash ^= fn_hash_identity (lock->u.file);
+    basis = fn_hash_identity (lock->u.file);
   else if (lock->referent == FH_REF_SCRATCH)
   else if (lock->referent == FH_REF_SCRATCH)
-    hash ^= hsh_hash_int (lock->u.unique_id);
-  return hash;
+    basis = lock->u.unique_id;
+  else
+    basis = 0;
+  return hash_int ((lock->referent << 3) | lock->access, basis);
 }
 }