]> git.ipfire.org Git - thirdparty/plymouth.git/commitdiff
Add hashtable and bitarray functionality
authorCharlie Brej <cbrej@cs.man.ac.uk>
Sat, 3 Jan 2009 22:18:24 +0000 (22:18 +0000)
committerCharlie Brej <cbrej@cs.man.ac.uk>
Sat, 3 Jan 2009 22:18:24 +0000 (22:18 +0000)
Hashtable uses the bitarray to mark the used/dead places in the hash data array.
The hashtable functions follow the general gist of the glib ones. To create a
hashtable you supply the hashing and comparison functions. Examples of direct
and string based indexing are supplied. Hashtable is a single word because there
is no hash_somethingelse but the name may change soon. Notice the compare
function returns a signed int difference rather than an equal bool. This is
because it may be an idea to later migrate the collision system to a tree
sub-structure (currently it is a linear array search with an incrementing step
size).

src/libply/Makefile.am
src/libply/ply-bitarray.c [new file with mode: 0644]
src/libply/ply-bitarray.h [new file with mode: 0644]
src/libply/ply-hashtable.c [new file with mode: 0644]
src/libply/ply-hashtable.h [new file with mode: 0644]
src/libply/tests/Makefile.am
src/libply/tests/ply-bitarray-test.am [new file with mode: 0644]
src/libply/tests/ply-hashtable-test.am [new file with mode: 0644]

index ca937a5de5c5cc1cb1c00967f7af58e4663a6cb9..6d65ab14de0b4bf2c19c09cfe31e3b948a9311e1 100644 (file)
@@ -17,7 +17,9 @@ libply_HEADERS = \
                    ply-frame-buffer.h                                        \
                    ply-buffer.h                                              \
                    ply-array.h                                               \
+                   ply-bitarray.h                                            \
                    ply-list.h                                                \
+                   ply-hashtable.h                                           \
                    ply-logger.h                                              \
                    ply-progress.h                                            \
                    ply-terminal.h                                            \
@@ -36,7 +38,9 @@ libply_la_SOURCES = ply-event-loop.c                                          \
                    ply-frame-buffer.c                                        \
                    ply-buffer.c                                              \
                    ply-array.c                                               \
+                   ply-bitarray.c                                            \
                    ply-list.c                                                \
+                   ply-hashtable.c                                           \
                    ply-logger.c                                              \
                    ply-progress.c                                            \
                    ply-terminal.c                                            \
diff --git a/src/libply/ply-bitarray.c b/src/libply/ply-bitarray.c
new file mode 100644 (file)
index 0000000..89e2216
--- /dev/null
@@ -0,0 +1,105 @@
+/* ply-bitarray.c - bitarray implementation
+ *
+ * Copyright (C) 2009 Charlie Brej <cbrej@cs.man.ac.uk>
+ *
+ * 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 2, or (at your option)
+ * any later version.
+ *
+ * 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Written by: Charlie Brej <cbrej@cs.man.ac.uk>
+ */
+#include "config.h"
+#include "ply-bitarray.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+
+
+int
+ply_bitarray_count (ply_bitarray_t *bitarray,
+                    int             size)
+{
+  int count = 0;
+  int i;
+  for (i = 0; i < size; i++){
+    count += ply_bitarray_lookup(bitarray, i);
+    }
+  return count;
+}
+
+
+
+
+#ifdef PLY_BITARRAY_ENABLE_TEST
+#include <stdio.h>
+
+int
+main (int    argc,
+      char **argv)
+{
+  ply_bitarray_t *bitarray;
+  int i, i2;
+  printf ("bitarray test start\n");
+  bitarray = ply_bitarray_new (134);
+  
+  for (i=0; i<64; i++)
+    {
+      if (ply_bitarray_lookup (bitarray, i))
+        printf ("1");
+      else
+        printf ("0");
+    }
+  printf ("\n");
+  
+  for (i=0; i<64; i++)
+    if ((6654654654654654654ll >> i) & 1)
+      ply_bitarray_set (bitarray, i);
+  
+  for (i=0; i<64; i++)
+    {
+      if (ply_bitarray_lookup (bitarray, i))
+        printf ("1");
+      else
+        printf ("0");
+    }
+  printf ("\n");
+    
+  for (i = 63; i > 0; i--)
+    {
+      if ((6654654654654654654ll >> i) & 1)
+        {
+          ply_bitarray_clear (bitarray, i);
+          for (i2 = 0; i2 < 64; i2++)
+            {
+              if (ply_bitarray_lookup (bitarray, i2))
+                printf ("1");
+              else
+                printf ("0"); 
+            }
+          printf ("\n");
+        }
+    }
+    
+  ply_bitarray_free (bitarray);
+  
+  printf ("bitarray test end\n");
+  return 0;
+}
+
+#endif
+/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */
diff --git a/src/libply/ply-bitarray.h b/src/libply/ply-bitarray.h
new file mode 100644 (file)
index 0000000..4cdf03a
--- /dev/null
@@ -0,0 +1,45 @@
+/* ply-bitarray.h - bitarray implementation
+ *
+ * Copyright (C) 2009 Charlie Brej <cbrej@cs.man.ac.uk>
+ *
+ * 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 2, or (at your option)
+ * any later version.
+ *
+ * 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Written by: Charlie Brej <cbrej@cs.man.ac.uk>
+ */
+#ifndef PLY_ARRAY_H
+#define PLY_ARRAY_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#define PLY_BITARRAY_BASE_SIZE 32
+#define PLY_BITARRAY_BASE_MASK (PLY_BITARRAY_BASE_SIZE-1)
+
+typedef uint32_t ply_bitarray_t;
+
+#ifndef PLY_HIDE_FUNCTION_DECLARATIONS
+#define ply_bitarray_new(size) calloc ((size + PLY_BITARRAY_BASE_SIZE - 1) / PLY_BITARRAY_BASE_SIZE, sizeof (ply_bitarray_t))
+#define ply_bitarray_free(bitarray) free (bitarray)
+#define ply_bitarray_lookup(bitarray, index) ((bitarray[index / PLY_BITARRAY_BASE_SIZE] >> (index & PLY_BITARRAY_BASE_MASK)) & 1)
+#define ply_bitarray_set(bitarray, index) (bitarray[index / PLY_BITARRAY_BASE_SIZE] |= 1 << (index & PLY_BITARRAY_BASE_MASK))
+#define ply_bitarray_clear(bitarray, index) (bitarray[index / PLY_BITARRAY_BASE_SIZE] &= ~(1 << (index & PLY_BITARRAY_BASE_MASK)))
+#define ply_bitarray_toggle(bitarray, index) (bitarray[index / PLY_BITARRAY_BASE_SIZE] ^= 1 << (index & PLY_BITARRAY_BASE_MASK))
+int ply_bitarray_count (ply_bitarray_t *bitarray,
+                        int             size);
+
+#endif
+
+#endif /* PLY_ARRAY_H */
diff --git a/src/libply/ply-hashtable.c b/src/libply/ply-hashtable.c
new file mode 100644 (file)
index 0000000..1ed6ae5
--- /dev/null
@@ -0,0 +1,334 @@
+/* ply-hashtable.c - hash table implementation
+ *
+ * Copyright (C) 2009 Charlie Brej <cbrej@cs.man.ac.uk>
+ *
+ * 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 2, or (at your option)
+ * any later version.
+ *
+ * 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Written by: Charlie Brej <cbrej@cs.man.ac.uk>
+ */
+#include "config.h"
+#include "ply-hashtable.h"
+#include "ply-utils.h"
+#include "ply-bitarray.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#define MASKGEN(x) {x |= x >> 16; x |= x >> 8; x |= x >> 4; x |= x >> 2;  x |= x >> 1;}
+
+struct _ply_hashtable_node
+{
+  void   *data;
+  void   *key;
+};
+
+struct _ply_hashtable
+{
+  struct _ply_hashtable_node   *nodes;
+  unsigned int                  total_node_count;   /* must be a 2^X */
+  ply_bitarray_t               *dirty_node_bitmap;
+  unsigned int                  dirty_node_count;   /* live + dead nodes */
+  ply_bitarray_t               *live_node_bitmap;
+  unsigned int                  live_node_count;
+  ply_hashtable_compare_func_t *compare_func;
+  ply_hashtable_hash_func_t    *hash_func;
+};
+
+unsigned int
+ply_hashtable_direct_hash (void *element)
+{
+  return (unsigned int) element;
+}
+
+int
+ply_hashtable_direct_compare (void *elementa,
+                              void *elementb)
+{
+  return (unsigned int) elementa - (unsigned int) elementb;
+}
+
+unsigned int
+ply_hashtable_string_hash (void *element)
+{
+  char* strptr;
+  unsigned int hash = 0;
+  for (strptr = element; *strptr; strptr++)
+    {
+      hash ^= *strptr;
+      hash ^= hash << 1;
+    }
+  return hash;
+}
+
+int
+ply_hashtable_string_compare (void *elementa,
+                              void *elementb)
+{
+  return strcmp (elementa, elementb);
+}
+
+ply_hashtable_t *
+ply_hashtable_new (ply_hashtable_hash_func_t    *hash_func,
+                   ply_hashtable_compare_func_t *compare_func)
+{
+  ply_hashtable_t *hashtable;
+
+  hashtable = malloc (sizeof (ply_hashtable_t));
+  hashtable->total_node_count = 0;
+  hashtable->dirty_node_count = 0;
+  hashtable->live_node_count = 0;
+  hashtable->nodes = NULL;
+  hashtable->dirty_node_bitmap = NULL;
+  hashtable->live_node_bitmap = NULL;
+  hashtable->compare_func = compare_func;
+  hashtable->hash_func = hash_func;
+
+  if (hashtable->compare_func == NULL)
+    {
+      hashtable->compare_func = ply_hashtable_direct_compare;
+    }
+  if (hashtable->hash_func == NULL)
+    {
+      hashtable->hash_func = ply_hashtable_direct_hash;
+    }
+  ply_hashtable_resize (hashtable);
+  return hashtable;
+}
+
+void
+ply_hashtable_free (ply_hashtable_t *hashtable)
+{
+  if (hashtable == NULL) return;
+  ply_bitarray_free (hashtable->dirty_node_bitmap);
+  ply_bitarray_free (hashtable->live_node_bitmap);
+  free(hashtable->nodes);
+  free(hashtable);
+}
+
+
+void
+ply_hashtable_insert_internal (ply_hashtable_t *hashtable,
+                               void            *key,
+                               void            *data)
+{
+  unsigned int hash_index;
+  int step = 0;
+  
+#ifdef PLY_HASHTABLE_ENABLE_TEST
+    /* Make sure the counts are synchronised with bitmap */
+  assert (ply_bitarray_count (hashtable->dirty_node_bitmap, hashtable->total_node_count) ==
+          hashtable->dirty_node_count);
+  assert (ply_bitarray_count (hashtable->live_node_bitmap, hashtable->total_node_count) ==
+          hashtable->live_node_count);
+#endif /* PLY_HASHTABLE_ENABLE_TEST */
+
+  hash_index = hashtable->hash_func (key);
+  hash_index &= hashtable->total_node_count - 1;
+
+  while (ply_bitarray_lookup (hashtable->dirty_node_bitmap, hash_index))
+    {
+      step++;
+      hash_index += step;
+      hash_index &= hashtable->total_node_count - 1;
+    }
+  ply_bitarray_set (hashtable->dirty_node_bitmap, hash_index);
+  ply_bitarray_set (hashtable->live_node_bitmap, hash_index);
+  hashtable->nodes[hash_index].key = key;
+  hashtable->nodes[hash_index].data = data;
+
+  hashtable->live_node_count++;
+  hashtable->dirty_node_count++;
+}
+
+
+void
+ply_hashtable_resize (ply_hashtable_t *hashtable)
+{
+  unsigned int newsize, oldsize;
+  int i;
+  struct _ply_hashtable_node *oldnodes;
+  ply_bitarray_t *old_live_node_bitmap;
+
+  newsize = (hashtable->live_node_count + 1) * 4; /* make table 4x to 8x the number of live elements (at least 8) */
+  MASKGEN (newsize);
+  newsize++;
+  oldsize = hashtable->total_node_count;
+  oldnodes = hashtable->nodes;
+
+  hashtable->total_node_count = newsize;
+  hashtable->nodes = malloc (newsize * sizeof (struct _ply_hashtable_node));
+  ply_bitarray_free (hashtable->dirty_node_bitmap);
+  hashtable->dirty_node_bitmap = ply_bitarray_new(newsize);
+  old_live_node_bitmap = hashtable->live_node_bitmap;
+  hashtable->live_node_bitmap = ply_bitarray_new(newsize);
+  hashtable->dirty_node_count = 0;
+  hashtable->live_node_count = 0;
+
+  for (i=0; i<oldsize; i++)
+    {
+      if (ply_bitarray_lookup (old_live_node_bitmap, i))
+        ply_hashtable_insert_internal (hashtable, oldnodes[i].key, oldnodes[i].data);
+    } 
+  ply_bitarray_free (old_live_node_bitmap);
+  free (oldnodes);
+}
+
+inline void
+ply_hashtable_resize_check (ply_hashtable_t *hashtable)
+{
+  if (hashtable->total_node_count < (hashtable->dirty_node_count * 2))
+    ply_hashtable_resize (hashtable);   /* hash tables work best below 50% occupancy */
+}
+
+void
+ply_hashtable_insert (ply_hashtable_t *hashtable,
+                      void            *key,
+                      void            *data)
+{
+  ply_hashtable_resize_check (hashtable);
+  ply_hashtable_insert_internal (hashtable, key, data);
+}
+
+static int
+ply_hashtable_lookup_index (ply_hashtable_t *hashtable,
+                            void            *key)
+{
+  unsigned int hash_index;
+  int step = 0;
+
+  hash_index = hashtable->hash_func (key);
+  while (1)
+    {
+      hash_index &= hashtable->total_node_count - 1;
+      if (!ply_bitarray_lookup (hashtable->dirty_node_bitmap, hash_index))
+        break;
+      if (ply_bitarray_lookup (hashtable->live_node_bitmap, hash_index))
+        if (!hashtable->compare_func (hashtable->nodes[hash_index].key, key))
+          return hash_index;
+      hash_index += step;
+      step++;
+    }
+  return -1;
+}
+
+void *
+ply_hashtable_remove (ply_hashtable_t *hashtable,
+                      void            *key)
+{
+  int index;
+  index = ply_hashtable_lookup_index (hashtable, key);
+  if (index < 0)
+    return NULL;
+    
+  ply_bitarray_clear (hashtable->live_node_bitmap, index);
+  hashtable->live_node_count--;
+  return hashtable->nodes[index].data;
+}
+
+void *
+ply_hashtable_lookup (ply_hashtable_t *hashtable,
+                      void            *key)
+{
+  int index;
+  index = ply_hashtable_lookup_index (hashtable, key);
+  if (index < 0)
+    return NULL;
+  return hashtable->nodes[index].data;
+}
+
+int
+ply_hashtable_lookup_full (ply_hashtable_t *hashtable,
+                           void            *key,
+                           void           **reply_key,
+                           void           **reply_data)
+{
+  int index;
+  index = ply_hashtable_lookup_index (hashtable, key);
+  if (index < 0)
+    return false;
+  *reply_key = hashtable->nodes[index].key;
+  *reply_data = hashtable->nodes[index].data;
+  return true;
+}
+
+void
+ply_hashtable_foreach (ply_hashtable_t              *hashtable,
+                                          ply_hashtable_foreach_func_t  func,
+                                          void                         *user_data)
+{
+  int i;
+  for (i = 0; i < hashtable->total_node_count; i++)
+    {
+      if (ply_bitarray_lookup (hashtable->live_node_bitmap, i))
+        func(hashtable->nodes[i].key, hashtable->nodes[i].data, user_data);
+    }
+}
+
+
+#ifdef PLY_HASHTABLE_ENABLE_TEST
+#include <stdio.h>
+
+void foreach_func (void *key,
+                   void *data,
+                   void *user_data)
+{
+  printf ("foreach key:%s data:%s\n", (char*) key, (char*) data);
+}
+
+
+int
+main (int    argc,
+      char **argv)
+{
+  ply_hashtable_t *hashtable;
+  int i;
+  char* key[10] =  {"k1", "k2", "k3", "k4", "k5", "k6", "k7", "k8", "k9", "k10"};
+  char* data[10] = {"d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10"};
+  char* reply_key = NULL;
+  char* reply_data = NULL;
+  
+  printf ("hashtable test start\n");
+  hashtable = ply_hashtable_new (ply_hashtable_string_hash, ply_hashtable_string_compare);
+  for (i=0; i<10; i++)
+    {
+      ply_hashtable_insert (hashtable, key[i], data[9-i]);
+    }
+  for (i=0; i<10; i++)
+    {
+      reply_data = ply_hashtable_lookup (hashtable, key[i]);
+      printf ("got:%s\n", reply_data);
+    }
+  for (i=0; i<10; i++)
+    {
+      ply_hashtable_remove (hashtable, key[i]);
+      ply_hashtable_insert (hashtable, key[i], data[i]);
+    }
+  for (i=0; i<10; i++)
+    {
+      if (ply_hashtable_lookup_full (hashtable, key[i], (void**) &reply_key, (void**) &reply_data))
+        printf ("got key:%s data:%s\n", reply_key, reply_data);
+    }
+  ply_hashtable_foreach (hashtable, foreach_func, NULL);
+  ply_hashtable_free(hashtable);
+  printf ("hashtable test end\n");
+  return 0;
+}
+
+#endif
+/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */
diff --git a/src/libply/ply-hashtable.h b/src/libply/ply-hashtable.h
new file mode 100644 (file)
index 0000000..016c781
--- /dev/null
@@ -0,0 +1,62 @@
+/* ply-hashtable.h - hash table implementation
+ *
+ * Copyright (C) 2009 Charlie Brej <cbrej@cs.man.ac.uk>
+ *
+ * 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 2, or (at your option)
+ * any later version.
+ *
+ * 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Written by: Charlie Brej <cbrej@cs.man.ac.uk>
+ */
+#ifndef PLY_HASHTABLE_H
+#define PLY_HASHTABLE_H
+
+typedef struct _ply_hashtable ply_hashtable_t;
+
+typedef int (ply_hashtable_compare_func_t) (void *elementa,
+                                            void *elementb);
+typedef unsigned int (ply_hashtable_hash_func_t) (void *element);
+typedef void (ply_hashtable_foreach_func_t) (void *key,
+                                             void *data,
+                                             void *user_data);
+
+
+#ifndef PLY_HIDE_FUNCTION_DECLARATIONS
+int ply_hashtable_direct_compare (void *elementa,
+                                 void *elementb);
+unsigned int ply_hashtable_direct_hash (void *element);
+unsigned int ply_hashtable_string_hash (void *element);
+int ply_hashtable_string_compare (void *elementa,
+                                  void *elementb);
+ply_hashtable_t *ply_hashtable_new (ply_hashtable_hash_func_t    *hash_func,
+                                    ply_hashtable_compare_func_t *compare_func);
+void ply_hashtable_free (ply_hashtable_t *hashtable);
+void ply_hashtable_resize (ply_hashtable_t *hashtable);
+void ply_hashtable_insert (ply_hashtable_t *hashtable,
+                          void            *key,
+                          void            *data);
+void *ply_hashtable_remove (ply_hashtable_t *hashtable,
+                               void            *key);
+void *ply_hashtable_lookup (ply_hashtable_t *hashtable,
+                               void            *key);
+int ply_hashtable_lookup_full (ply_hashtable_t *hashtable,
+                                  void            *key,
+                                  void           **reply_key,
+                                  void           **reply_data);
+void ply_hashtable_foreach (ply_hashtable_t              *hashtable,
+                                                       ply_hashtable_foreach_func_t  func,
+                                                       void                         *user_data);
+#endif
+
+#endif /* PLY_HASHTABLE_H */
index d359e6971bb7b9a68149ea5721ae860b601efd5d..9ef83381c8d4553ac4d1c53509b2125646323acc 100644 (file)
@@ -10,7 +10,9 @@ include $(srcdir)/ply-terminal-test.am
 include $(srcdir)/ply-terminal-session-test.am
 include $(srcdir)/ply-logger-test.am
 include $(srcdir)/ply-array-test.am
+include $(srcdir)/ply-bitarray-test.am
 include $(srcdir)/ply-list-test.am
+include $(srcdir)/ply-hashtable-test.am
 include $(srcdir)/ply-event-loop-test.am
 include $(srcdir)/ply-command-parser-test.am
 include $(srcdir)/ply-progress-test.am
diff --git a/src/libply/tests/ply-bitarray-test.am b/src/libply/tests/ply-bitarray-test.am
new file mode 100644 (file)
index 0000000..85c3608
--- /dev/null
@@ -0,0 +1,8 @@
+TESTS += ply-bitarray-test
+
+ply_bitarray_test_CFLAGS = $(PLYMOUTH_CFLAGS) -DPLY_BITARRAY_ENABLE_TEST
+ply_bitarray_test_LDADD = $(PLYMOUTH_LIBS)
+
+ply_bitarray_test_SOURCES =                                                     \
+                          $(srcdir)/../ply-bitarray.h                           \
+                          $(srcdir)/../ply-bitarray.c
diff --git a/src/libply/tests/ply-hashtable-test.am b/src/libply/tests/ply-hashtable-test.am
new file mode 100644 (file)
index 0000000..d3410fc
--- /dev/null
@@ -0,0 +1,10 @@
+TESTS += ply-hashtable-test
+
+ply_hashtable_test_CFLAGS = $(PLYMOUTH_CFLAGS) -DPLY_HASHTABLE_ENABLE_TEST
+ply_hashtable_test_LDADD = $(PLYMOUTH_LIBS)
+
+ply_hashtable_test_SOURCES =                                                     \
+                          $(srcdir)/../ply-hashtable.h                           \
+                          $(srcdir)/../ply-hashtable.c                           \
+                          $(srcdir)/../ply-bitarray.h                            \
+                          $(srcdir)/../ply-bitarray.c