aboutsummaryrefslogtreecommitdiff
path: root/dlib
diff options
context:
space:
mode:
authorjcid <devnull@localhost>2007-10-07 00:36:34 +0200
committerjcid <devnull@localhost>2007-10-07 00:36:34 +0200
commit93715c46a99c96d6c866968312691ec9ab0f6a03 (patch)
tree573f19ec6aa740844f53a7c0eb7114f04096bf64 /dlib
Initial revision
Diffstat (limited to 'dlib')
-rw-r--r--dlib/Makefile.am6
-rw-r--r--dlib/dlib.c750
-rw-r--r--dlib/dlib.h158
3 files changed, 914 insertions, 0 deletions
diff --git a/dlib/Makefile.am b/dlib/Makefile.am
new file mode 100644
index 00000000..378cd785
--- /dev/null
+++ b/dlib/Makefile.am
@@ -0,0 +1,6 @@
+noinst_LIBRARIES = libDlib.a
+
+libDlib_a_SOURCES = \
+ dlib.h \
+ dlib.c
+
diff --git a/dlib/dlib.c b/dlib/dlib.c
new file mode 100644
index 00000000..bba1cc5e
--- /dev/null
+++ b/dlib/dlib.c
@@ -0,0 +1,750 @@
+/*
+ * File: dlib.c
+ *
+ * Copyright (C) 2006 Jorge Arellano Cid <jcid@dillo.org>
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ */
+
+/* Memory allocation, Simple dynamic strings, Lists (simple and sorted),
+ * and a few utility functions
+ */
+
+/*
+ * TODO: vsnprintf() is in C99, maybe a simple replacement if necessary.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <ctype.h>
+
+#include "dlib.h"
+
+/*
+ *- Memory --------------------------------------------------------------------
+ */
+
+void *dMalloc (size_t size)
+{
+ void *value = malloc (size);
+ if (value == 0)
+ exit(1);
+ return value;
+}
+
+void *dRealloc (void *mem, size_t size)
+{
+ void *value = realloc (mem, size);
+ if (value == 0)
+ exit(1);
+ return value;
+}
+
+void *dMalloc0 (size_t size)
+{
+ void *value = dMalloc (size);
+ memset (value, 0, size);
+ return value;
+}
+
+void dFree (void *mem)
+{
+ if (mem)
+ free(mem);
+}
+
+/*
+ *- strings (char *) ----------------------------------------------------------
+ */
+
+char *dStrdup(const char *s)
+{
+ if (s) {
+ int len = strlen(s)+1;
+ char *ns = dNew(char, len);
+ memcpy(ns, s, len);
+ return ns;
+ }
+ return NULL;
+}
+
+char *dStrndup(const char *s, size_t sz)
+{
+ if (s) {
+ char *ns = dNew(char, sz+1);
+ memcpy(ns, s, sz);
+ ns[sz] = 0;
+ return ns;
+ }
+ return NULL;
+}
+
+/*
+ * Concatenate a NULL-terminated list of strings
+ */
+char *dStrconcat(const char *s1, ...)
+{
+ va_list args;
+ char *s, *ns = NULL;
+
+ if (s1) {
+ Dstr *dstr = dStr_sized_new(64);
+ va_start(args, s1);
+ for (s = (char*)s1; s; s = va_arg(args, char*))
+ dStr_append(dstr, s);
+ va_end(args);
+ ns = dstr->str;
+ dStr_free(dstr, 0);
+ }
+ return ns;
+}
+
+/*
+ * Remove leading and trailing whitespace
+ */
+char *dStrstrip(char *s)
+{
+ char *p;
+ int len;
+
+ if (s && *s) {
+ for (p = s; isspace(*p); ++p);
+ for (len = strlen(p); len && isspace(p[len-1]); --len);
+ if (p > s)
+ memmove(s, p, len);
+ s[len] = 0;
+ }
+ return s;
+}
+
+/*
+ * Return a new string of length 'len' filled with 'c' characters
+ */
+char *dStrnfill(size_t len, char c)
+{
+ char *ret = dNew(char, len+1);
+ for (ret[len] = 0; len > 0; ret[--len] = c);
+ return ret;
+}
+
+/*
+ * strsep() implementation
+ */
+char *dStrsep(char **orig, const char *delim)
+{
+ char *str, *p;
+
+ if (!(str = *orig))
+ return NULL;
+
+ p = strpbrk(str, delim);
+ if (p) {
+ *p++ = 0;
+ *orig = p;
+ } else {
+ *orig = NULL;
+ }
+ return str;
+}
+
+/*
+ * Case insensitive strstr
+ */
+char *dStristr(const char *haystack, const char *needle)
+{
+ int i, j;
+
+ for (i = 0, j = 0; haystack[i] && needle[j]; ++i)
+ if (tolower(haystack[i]) == tolower(needle[j])) {
+ ++j;
+ } else if (j) {
+ i -= j;
+ j = 0;
+ }
+
+ if (!needle[j]) /* Got all */
+ return (char *)(haystack + i - j);
+ return NULL;
+}
+
+
+/*
+ *- dStr ----------------------------------------------------------------------
+ */
+
+/*
+ * Private allocator
+ */
+static void dStr_resize(Dstr *ds, int n_sz, int keep)
+{
+ if (n_sz >= 0) {
+ if (keep && n_sz > ds->len) {
+ ds->str = (Dstr_char_t*) dRealloc (ds->str, n_sz*sizeof(Dstr_char_t));
+ ds->sz = n_sz;
+ } else {
+ if (ds->str)
+ free(ds->str);
+ ds->str = dNew(Dstr_char_t, n_sz);
+ ds->sz = n_sz;
+ ds->len = 0;
+ ds->str[0] = 0;
+ }
+ }
+}
+
+/*
+ * Create a new string with a given size.
+ * Initialized to ""
+ */
+Dstr *dStr_sized_new (int sz)
+{
+ if (sz < 2)
+ sz = 2;
+
+ Dstr *ds = dNew(Dstr, 1);
+ ds->str = NULL;
+ dStr_resize(ds, sz, 0);
+ return ds;
+}
+
+/*
+ * Return memory if there's too much allocated
+ */
+void dStr_fit (Dstr *ds)
+{
+ dStr_resize(ds, ds->len + 1, 1);
+}
+
+/*
+ * Insert a C string, at a given position, into a Dstr (providing length).
+ * Note: It also works with embedded nil characters.
+ */
+void dStr_insert_l (Dstr *ds, int pos_0, const char *s, int l)
+{
+ int n_sz;
+
+ if (ds && s && l && pos_0 >= 0 && pos_0 <= ds->len) {
+ for (n_sz = ds->sz; ds->len + l >= n_sz; n_sz *= 2);
+ if (n_sz > ds->sz) {
+ dStr_resize(ds, n_sz, (ds->len > 0) ? 1 : 0);
+ }
+ if (pos_0 < ds->len)
+ memmove(ds->str+pos_0+l, ds->str+pos_0, ds->len-pos_0);
+ memcpy(ds->str+pos_0, s, l);
+ ds->len += l;
+ ds->str[ds->len] = 0;
+ }
+}
+
+/*
+ * Insert a C string, at a given position, into a Dstr
+ */
+void dStr_insert (Dstr *ds, int pos_0, const char *s)
+{
+ if (s)
+ dStr_insert_l(ds, pos_0, s, strlen(s));
+}
+
+/*
+ * Append a C string to a Dstr (providing length).
+ * Note: It also works with embedded nil characters.
+ */
+void dStr_append_l (Dstr *ds, const char *s, int l)
+{
+ dStr_insert_l(ds, ds->len, s, l);
+}
+
+/*
+ * Append a C string to a Dstr.
+ */
+void dStr_append (Dstr *ds, const char *s)
+{
+ dStr_append_l(ds, s, strlen(s));
+}
+
+/*
+ * Create a new string.
+ * Initialized to 's' or empty if 's == NULL'
+ */
+Dstr *dStr_new (const char *s)
+{
+ Dstr *ds = dStr_sized_new(0);
+ if (s)
+ dStr_append(ds, s);
+ return ds;
+}
+
+/*
+ * Free a dillo string.
+ * if 'all' free everything, else free the structure only.
+ */
+void dStr_free (Dstr *ds, int all)
+{
+ if (ds) {
+ if (all && ds->str)
+ free(ds->str);
+ free(ds);
+ }
+}
+
+/*
+ * Append one character.
+ */
+void dStr_append_c (Dstr *ds, int c)
+{
+ char cs[2];
+
+ if (ds) {
+ if (ds->sz > ds->len + 1) {
+ ds->str[ds->len++] = (Dstr_char_t)c;
+ ds->str[ds->len] = 0;
+ } else {
+ cs[0] = (Dstr_char_t)c;
+ cs[1] = 0;
+ dStr_append_l (ds, cs, 1);
+ }
+ }
+}
+
+/*
+ * Truncate a Dstr to be 'len' bytes long.
+ */
+void dStr_truncate (Dstr *ds, int len)
+{
+ if (ds && len < ds->len) {
+ ds->str[len] = 0;
+ ds->len = len;
+ }
+}
+
+/*
+ * Erase a substring.
+ */
+void dStr_erase (Dstr *ds, int pos_0, int len)
+{
+ if (ds && pos_0 >= 0 && len > 0 && pos_0 + len <= ds->len) {
+ memmove(ds->str + pos_0, ds->str + pos_0 + len, ds->len - pos_0 - len);
+ ds->len -= len;
+ ds->str[ds->len] = 0;
+ }
+}
+
+/*
+ * vsprintf-like function that appends.
+ * Used by: dStr_vsprintf(), dStr_sprintf() and dStr_sprintfa().
+ */
+void dStr_vsprintfa (Dstr *ds, const char *format, va_list argp)
+{
+ int n, n_sz;
+
+ if (ds && format) {
+ while (1) {
+ n = vsnprintf(ds->str + ds->len, ds->sz - ds->len, format, argp);
+ if (n > -1 && n < ds->sz - ds->len) {
+ ds->len += n; /* Success! */
+ break;
+ } else if (n > -1) { /* glibc >= 2.1 */
+ n_sz = ds->len + n + 1;
+ } else { /* old glibc */
+ n_sz = ds->sz * 2;
+ }
+ dStr_resize(ds, n_sz, (ds->len > 0) ? 1 : 0);
+ }
+ }
+}
+
+/*
+ * vsprintf-like function.
+ */
+void dStr_vsprintf (Dstr *ds, const char *format, va_list argp)
+{
+ if (ds) {
+ dStr_truncate(ds, 0);
+ dStr_vsprintfa(ds, format, argp);
+ }
+}
+
+/*
+ * Printf-like function
+ */
+void dStr_sprintf (Dstr *ds, const char *format, ...)
+{
+ va_list argp;
+
+ if (ds && format) {
+ va_start(argp, format);
+ dStr_vsprintf(ds, format, argp);
+ va_end(argp);
+ }
+}
+
+/*
+ * Printf-like function that appends.
+ */
+void dStr_sprintfa (Dstr *ds, const char *format, ...)
+{
+ va_list argp;
+
+ if (ds && format) {
+ va_start(argp, format);
+ dStr_vsprintfa(ds, format, argp);
+ va_end(argp);
+ }
+}
+
+/*
+ *- dList ---------------------------------------------------------------------
+ */
+
+/*
+ * Create a new empty list
+ */
+Dlist *dList_new(int size)
+{
+ if (size <= 0)
+ return NULL;
+
+ Dlist *l = dNew(Dlist, 1);
+ l->len = 0;
+ l->sz = size;
+ l->list = dNew(void*, l->sz);
+ return l;
+}
+
+/*
+ * Free a list (not its elements)
+ */
+void dList_free (Dlist *lp)
+{
+ if (!lp)
+ return;
+
+ dFree(lp->list);
+ dFree(lp);
+}
+
+/*
+ * Insert an element at a given position [0 based]
+ */
+void dList_insert_pos (Dlist *lp, void *data, int pos0)
+{
+ int i;
+
+ if (!lp || pos0 < 0 || pos0 > lp->len)
+ return;
+
+ if (lp->sz == lp->len) {
+ lp->sz *= 2;
+ lp->list = (void**) dRealloc (lp->list, lp->sz*sizeof(void*));
+ }
+ ++lp->len;
+
+ for (i = lp->len - 1; i > pos0; --i)
+ lp->list[i] = lp->list[i - 1];
+ lp->list[pos0] = data;
+}
+
+/*
+ * Append a data item to the list
+ */
+void dList_append (Dlist *lp, void *data)
+{
+ dList_insert_pos(lp, data, lp->len);
+}
+
+/*
+ * Prepend a data item to the list
+ */
+void dList_prepend (Dlist *lp, void *data)
+{
+ dList_insert_pos(lp, data, 0);
+}
+
+/*
+ * For completing the ADT.
+ */
+int dList_length (Dlist *lp)
+{
+ if (!lp)
+ return 0;
+ return lp->len;
+}
+
+/*
+ * Remove a data item without preserving order.
+ */
+void dList_remove_fast (Dlist *lp, const void *data)
+{
+ int i;
+
+ if (!lp)
+ return;
+
+ for (i = 0; i < lp->len; ++i) {
+ if (lp->list[i] == data) {
+ lp->list[i] = lp->list[--lp->len];
+ break;
+ }
+ }
+}
+
+/*
+ * Remove a data item preserving order.
+ */
+void dList_remove (Dlist *lp, const void *data)
+{
+ int i, j;
+
+ if (!lp)
+ return;
+
+ for (i = 0; i < lp->len; ++i) {
+ if (lp->list[i] == data) {
+ --lp->len;
+ for (j = i; j < lp->len; ++j)
+ lp->list[j] = lp->list[j + 1];
+ break;
+ }
+ }
+}
+
+/*
+ * Return the nth data item,
+ * NULL when not found or 'n0' is out of range
+ */
+void *dList_nth_data (Dlist *lp, int n0)
+{
+ if (!lp || n0 < 0 || n0 >= lp->len)
+ return NULL;
+ return lp->list[n0];
+}
+
+/*
+ * Return the found data item, or NULL if not present.
+ */
+void *dList_find (Dlist *lp, const void *data)
+{
+ int i = dList_find_idx(lp, data);
+ return (i >= 0) ? lp->list[i] : NULL;
+}
+
+/*
+ * Search a data item.
+ * Return value: its index if found, -1 if not present.
+ * (this is useful for a list of integers, for finding number zero).
+ */
+int dList_find_idx (Dlist *lp, const void *data)
+{
+ int i, ret = -1;
+
+ if (!lp)
+ return ret;
+
+ for (i = 0; i < lp->len; ++i) {
+ if (lp->list[i] == data) {
+ ret = i;
+ break;
+ }
+ }
+ return ret;
+}
+
+/*
+ * Search a data item using a custom function.
+ * func() is given the list item and the user data as parameters.
+ * Return: data item when found, NULL otherwise.
+ */
+void *dList_find_custom (Dlist *lp, const void *data, dCompareFunc func)
+{
+ int i;
+ void *ret = NULL;
+
+ if (!lp)
+ return ret;
+
+ for (i = 0; i < lp->len; ++i) {
+ if (func(lp->list[i], data) == 0) {
+ ret = lp->list[i];
+ break;
+ }
+ }
+ return ret;
+}
+
+/*
+ * QuickSort implementation.
+ * This allows for a simple compare function for all the ADT.
+ */
+static void QuickSort(void **left, void **right, dCompareFunc compare)
+{
+ void **p = left, **q = right, **t = left;
+
+ while (1) {
+ while (p != t && compare(*p, *t) < 0)
+ ++p;
+ while (q != t && compare(*q, *t) > 0)
+ --q;
+ if (p > q)
+ break;
+ if (p < q) {
+ void *tmp = *p;
+ *p = *q;
+ *q = tmp;
+ if (t == p)
+ t = q;
+ else if (t == q)
+ t = p;
+ }
+ if (++p > --q)
+ break;
+ }
+
+ if (left < q)
+ QuickSort(left, q, compare);
+ if (p < right)
+ QuickSort(p, right, compare);
+}
+
+/*
+ * Sort the list using a custom function
+ */
+void dList_sort (Dlist *lp, dCompareFunc func)
+{
+ if (lp && lp->len > 1) {
+ QuickSort(lp->list, lp->list + lp->len - 1, func);
+ }
+}
+
+/*
+ * Insert an element into a sorted list.
+ * The comparison function receives two list elements.
+ */
+void dList_insert_sorted (Dlist *lp, void *data, dCompareFunc func)
+{
+ int i, st, min, max;
+
+ if (lp) {
+ min = st = i = 0;
+ max = lp->len - 1;
+ while (min <= max) {
+ i = (min + max) / 2;
+ st = func(lp->list[i], data);
+ if (st < 0) {
+ min = i + 1;
+ } else if (st > 0) {
+ max = i - 1;
+ } else {
+ break;
+ }
+ }
+ dList_insert_pos(lp, data, (st >= 0) ? i : i+1);
+ }
+}
+
+/*
+ * Search a sorted list.
+ * Return the found data item, or NULL if not present.
+ * func() is given the list item and the user data as parameters.
+ */
+void *dList_find_sorted (Dlist *lp, const void *data, dCompareFunc func)
+{
+ int i, st, min, max;
+ void *ret = NULL;
+
+ if (lp && lp->len) {
+ min = 0;
+ max = lp->len - 1;
+ while (min <= max) {
+ i = (min + max) / 2;
+ st = func(lp->list[i], data);
+ if (st < 0) {
+ min = i + 1;
+ } else if (st > 0) {
+ max = i - 1;
+ } else {
+ ret = lp->list[i];
+ break;
+ }
+ }
+ }
+
+ return ret;
+}
+
+/*
+ *- Misc utility functions ----------------------------------------------------
+ */
+
+/*
+ * Return the current working directory in a new string
+ */
+char *dGetcwd ()
+{
+ size_t size = 128;
+
+ while (1) {
+ char *buffer = dNew(char, size);
+ if (getcwd (buffer, size) == buffer)
+ return buffer;
+ dFree (buffer);
+ if (errno != ERANGE)
+ return 0;
+ size *= 2;
+ }
+}
+
+/*
+ * Return the home directory in a static string (don't free)
+ */
+char *dGethomedir ()
+{
+ static char *homedir = NULL;
+
+ if (!homedir) {
+ if (getenv("HOME")) {
+ homedir = dStrdup(getenv("HOME"));
+
+ } else if (getenv("HOMEDRIVE") && getenv("HOMEPATH")) {
+ homedir = dStrconcat(getenv("HOMEDRIVE"), getenv("HOMEPATH"), NULL);
+ }
+ }
+ return homedir;
+}
+
+/*
+ * Get a line from a FILE stream.
+ * It handles backslash as line-continues character.
+ * Return value: read line on success, NULL on EOF.
+ */
+char *dGetline (FILE *stream)
+{
+ int ch;
+ Dstr *dstr;
+ char *line;
+
+ dReturn_val_if_fail (stream, 0);
+
+ dstr = dStr_sized_new(64);
+ while((ch = fgetc(stream)) != EOF) {
+ if (ch == '\\') {
+ /* continue with the next line */
+ while((ch = fgetc(stream)) != EOF && ch != '\n');
+ continue;
+ }
+ dStr_append_c(dstr, ch);
+ if (ch == '\n')
+ break;
+ }
+
+ line = (dstr->len) ? dstr->str : NULL;
+ dStr_free(dstr, (line) ? 0 : 1);
+ return line;
+}
+
diff --git a/dlib/dlib.h b/dlib/dlib.h
new file mode 100644
index 00000000..6caf7c97
--- /dev/null
+++ b/dlib/dlib.h
@@ -0,0 +1,158 @@
+#ifndef __DLIB_H__
+#define __DLIB_H__
+
+#include <stdio.h> /* for FILE* */
+#include <stddef.h> /* for size_t */
+#include <stdarg.h> /* for va_list */
+#include <string.h> /* for strerror */
+#include <strings.h> /* for strcasecmp, strncasecmp (POSIX 2001) */
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*
+ *-- Common macros -----------------------------------------------------------
+ */
+#ifndef FALSE
+#define FALSE (0)
+#endif
+
+#ifndef TRUE
+#define TRUE (!FALSE)
+#endif
+
+#undef MAX
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+
+#undef MIN
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+
+/*
+ *-- Casts -------------------------------------------------------------------
+ */
+/* TODO: include a void* size test in configure.in */
+#define VOIDP2INT(p) ((int)(p))
+#define INT2VOIDP(i) ((void*)(i))
+
+/*
+ *-- Memory -------------------------------------------------------------------
+ */
+#define dNew(type, count) \
+ ((type *) dMalloc ((unsigned) sizeof (type) * (count)))
+#define dNew0(type, count) \
+ ((type *) dMalloc0 ((unsigned) sizeof (type) * (count)))
+
+void *dMalloc (size_t size);
+void *dRealloc (void *mem, size_t size);
+void *dMalloc0 (size_t size);
+void dFree (void *mem);
+
+/*
+ *- Debug macros --------------------------------------------------------------
+ */
+#define D_STMT_START do
+#define D_STMT_END while (0)
+#define dReturn_if_fail(expr) \
+ D_STMT_START{ \
+ if (!(expr)) { return; }; \
+ }D_STMT_END
+#define dReturn_val_if_fail(expr,val) \
+ D_STMT_START{ \
+ if (!(expr)) { return val; }; \
+ }D_STMT_END
+
+/*
+ *- C strings -----------------------------------------------------------------
+ */
+char *dStrdup(const char *s);
+char *dStrndup(const char *s, size_t sz);
+char *dStrconcat(const char *s1, ...);
+char *dStrstrip(char *s);
+char *dStrnfill(size_t len, char c);
+char *dStrsep(char **orig, const char *delim);
+char *dStristr(const char *haystack, const char *needle);
+
+/* these are in POSIX 2001. Could be implemented if a port requires it */
+#define dStrcasecmp strcasecmp
+#define dStrncasecmp strncasecmp
+#define dStrerror strerror
+
+/*
+ *-- dStr ---------------------------------------------------------------------
+ */
+#define Dstr_char_t char
+
+typedef struct _dstr {
+ int sz; /* allocated size (private) */
+ int len;
+ Dstr_char_t *str;
+} Dstr;
+
+Dstr *dStr_new (const char *s);
+Dstr *dStr_sized_new (int sz);
+void dStr_fit (Dstr *ds);
+void dStr_free (Dstr *ds, int all);
+void dStr_append_c (Dstr *ds, int c);
+void dStr_append (Dstr *ds, const char *s);
+void dStr_append_l (Dstr *ds, const char *s, int l);
+void dStr_insert (Dstr *ds, int pos_0, const char *s);
+void dStr_insert_l (Dstr *ds, int pos_0, const char *s, int l);
+void dStr_truncate (Dstr *ds, int len);
+void dStr_erase (Dstr *ds, int pos_0, int len);
+void dStr_vsprintfa (Dstr *ds, const char *format, va_list argp);
+void dStr_vsprintf (Dstr *ds, const char *format, va_list argp);
+void dStr_sprintf (Dstr *ds, const char *format, ...);
+void dStr_sprintfa (Dstr *ds, const char *format, ...);
+
+/*
+ *-- dList --------------------------------------------------------------------
+ */
+struct Dlist_ {
+ int sz; /* allocated size (private) */
+ int len;
+ void **list;
+};
+
+typedef struct Dlist_ Dlist;
+
+/* dCompareFunc:
+ * Return: 0 if parameters are equal (for dList_find_custom).
+ * Return: 0 if equal, < 0 if (a < b), > 0 if (b < a) --for insert sorted.
+ *
+ * For finding a data node with an external key, the comparison function
+ * parameters are: first the data node, and then the key.
+ */
+typedef int (*dCompareFunc) (const void *a, const void *b);
+
+
+Dlist *dList_new(int size);
+void dList_free (Dlist *lp);
+void dList_append (Dlist *lp, void *data);
+void dList_prepend (Dlist *lp, void *data);
+int dList_length (Dlist *lp);
+void dList_remove (Dlist *lp, const void *data);
+void dList_remove_fast (Dlist *lp, const void *data);
+void *dList_nth_data (Dlist *lp, int n0);
+void *dList_find (Dlist *lp, const void *data);
+int dList_find_idx (Dlist *lp, const void *data);
+void *dList_find_custom (Dlist *lp, const void *data, dCompareFunc func);
+void dList_sort (Dlist *lp, dCompareFunc func);
+void dList_insert_sorted (Dlist *lp, void *data, dCompareFunc func);
+void *dList_find_sorted (Dlist *lp, const void *data, dCompareFunc func);
+
+/*
+ *- Misc utility functions ----------------------------------------------------
+ */
+char *dGetcwd ();
+char *dGethomedir ();
+char *dGetline (FILE *stream);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __DLIB_H__ */
+