# For simple projects you could just do:
# SRCFILES += $(wildcard ccan/*/*.c)
-CFLAGS=-g -O3 -Wall -Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes -Wmissing-declarations -Werror -I. $(DEPGEN)
+#CFLAGS=-g -O3 -Wall -Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes -Wmissing-declarations -Werror -I. $(DEPGEN)
+CFLAGS=-g -Wall -Wstrict-prototypes -Wold-style-definition -Werror -I. $(DEPGEN)
# Automatic dependency generation: makes ccan/*.d files.
DEPGEN=-MD
--- /dev/null
+#include <stdio.h>
+#include <string.h>
+
+/**
+ * asort - typesafe array sort (qsort)
+ *
+ * qsort() is the standard routine for sorting an array of objects.
+ * Unfortunately, it has two problems:
+ * 1) It isn't typesafe,
+ * 2) The comparison function doesn't take a context pointer.
+ *
+ * asort does both.
+ *
+ * Licence: LGPL
+ *
+ * Example:
+ * #include <ccan/asort/asort.h>
+ * #include <stdio.h>
+ * #include <string.h>
+ *
+ * static int cmp(const char **a, const char **n, bool *casefold)
+ * {
+ * if (*casefold)
+ * return strcasecmp(*a, *b);
+ * else
+ * return strcmp(*a, *b);
+ * }
+ *
+ * int main(int argc, char *argv[])
+ * {
+ * bool casefold = false;
+ * unsigned int i;
+ *
+ * if (argc < 2) {
+ * fprintf(stderr, "Usage: %s [-i] <list>...\n"
+ * "Sort arguments (-i = ignore case)\n",
+ * argv[0]);
+ * exit(1);
+ * }
+ *
+ * if (strcmp(argv[1], "-i") == 0) {
+ * casefold = true;
+ * argc--;
+ * argv++;
+ * }
+ * asort(&argv[1], argc-1, cmp, &casefold);
+ * for (i = 1; i < argc; i++)
+ * printf("%s ", argv[i]);
+ * printf("\n");
+ * return 0;
+ * }
+ */
+int main(int argc, char *argv[])
+{
+ if (argc != 2)
+ return 1;
+
+ if (strcmp(argv[1], "depends") == 0) {
+ printf("ccan/typesafe_cb\n");
+ printf("ccan/array_size\n");
+ return 0;
+ }
+
+ return 1;
+}
--- /dev/null
+#include <ccan/asort/asort.h>
+#include <stdlib.h>
+
+void _asort(void *base, size_t nmemb, size_t size,
+ int(*compar)(const void *, const void *, const void *ctx),
+ const void *ctx)
+{
+#if HAVE_NESTED_FUNCTIONS
+ /* This gives bogus "warning: no previous prototype for ‘cmp’"
+ * with gcc 4 with -Wmissing-prototypes. But there's no way
+ * to predeclare it, so we lose. */
+ int cmp(const void *a, const void *b)
+ {
+ return compar(a, b, ctx);
+ }
+ qsort(base, nmemb, size, cmp);
+#else
+ #error "Need to open-code quicksort?"
+ /* qsort is a classic "needed more real-life testing" API. */
+#endif
+}
--- /dev/null
+#ifndef CCAN_ASORT_H
+#define CCAN_ASORT_H
+#include <ccan/typesafe_cb/typesafe_cb.h>
+#include <stdlib.h>
+
+/**
+ * asort - sort an array of elements
+ * @base: pointer to data to sort
+ * @num: number of elements
+ * @cmp: pointer to comparison function
+ * @ctx: a context pointer for the cmp function
+ *
+ * This function does a sort on the given array. The resulting array
+ * will be in ascending sorted order by the provided comparison function.
+ *
+ * The @cmp function should exactly match the type of the @base and
+ * @ctx arguments. Otherwise it can take three const void *.
+ */
+#if HAVE_TYPEOF
+#define asort(base, num, cmp, ctx) \
+_asort((base), (num), sizeof(*(base)), \
+ cast_if_type((cmp), \
+ int (*)(const __typeof__(*(base)) *, \
+ const __typeof__(*(base)) *, \
+ __typeof__(ctx)), \
+ int (*)(const void *, const void *, const void *)), (ctx))
+#else
+#define asort(base, num, cmp, ctx) \
+ _asort((base), (num), sizeof(*(base)), \
+ (int (*)(const void *, const void *, const void *))(cmp), ctx)
+#endif
+
+void _asort(void *base, size_t nmemb, size_t size,
+ int(*compar)(const void *, const void *, const void *),
+ const void *ctx);
+
+#endif /* CCAN_ASORT_H */
--- /dev/null
+#include <ccan/asort/asort.h>
+#include <ccan/asort/asort.c>
+
+static int cmp(char *const *a, char *const *b, int *flag)
+{
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+#ifdef FAIL
+ char flag;
+#if !HAVE_TYPEOF
+#error "Unfortunately we don't fail if no typeof."
+#endif
+#else
+ int flag;
+#endif
+ asort(argv+1, argc-1, cmp, &flag);
+ return 0;
+}
--- /dev/null
+#include <ccan/asearch/asearch.h>
+#include <ccan/array_size/array_size.h>
+#include <ccan/tap/tap.h>
+#include <stdlib.h>
+
+static int cmp(const int *key, const char *const *elem)
+{
+ return *key - atoi(*elem);
+}
+
+int main(void)
+{
+ const char *args[] = { "1", "4", "7", "9" };
+ int key = 7;
+ const char **p;
+
+ plan_tests(1);
+ p = asearch(&key, args, ARRAY_SIZE(args), cmp);
+ ok1(p == &args[2]);
+
+ return exit_status();
+}
--- /dev/null
+#include <ccan/asort/asort.h>
+#include <ccan/asort/asort.c>
+#include <ccan/array_size/array_size.h>
+#include <ccan/tap/tap.h>
+#include <limits.h>
+#include <stdbool.h>
+
+static int test_cmp(const int *key, const int *elt, int *flag)
+{
+ if (*key < *elt)
+ return -1 * *flag;
+ else if (*key > *elt)
+ return 1 * *flag;
+
+ return 0;
+}
+
+static bool is_sorted(const int arr[], unsigned int size)
+{
+ unsigned int i;
+
+ for (i = 1; i < size; i++)
+ if (arr[i] < arr[i-1])
+ return false;
+ return true;
+}
+
+static bool is_reverse_sorted(const int arr[], unsigned int size)
+{
+ unsigned int i;
+
+ for (i = 1; i < size; i++)
+ if (arr[i] > arr[i-1])
+ return false;
+ return true;
+}
+
+static void psuedo_random_array(int arr[], unsigned int size)
+{
+ unsigned int i;
+
+ for (i = 0; i < size; i++)
+ arr[i] = i * (INT_MAX / 4 - 7);
+}
+
+#define TEST_SIZE 100
+
+int main(void)
+{
+ int tmparr[TEST_SIZE];
+ int multiplier = 1;
+
+ plan_tests(4);
+
+ psuedo_random_array(tmparr, TEST_SIZE);
+ ok1(!is_sorted(tmparr, TEST_SIZE));
+ ok1(!is_reverse_sorted(tmparr, TEST_SIZE));
+
+ asort(tmparr, TEST_SIZE, test_cmp, &multiplier);
+ ok1(is_sorted(tmparr, TEST_SIZE));
+
+ psuedo_random_array(tmparr, TEST_SIZE);
+ multiplier = -1;
+ asort(tmparr, TEST_SIZE, test_cmp, &multiplier);
+ ok1(is_reverse_sorted(tmparr, TEST_SIZE));
+
+ return exit_status();
+}
/* Simple config.h for gcc. */
-#define HAVE_TYPEOF 1
#define HAVE_ALIGNOF 1
-#define HAVE_STATEMENT_EXPR 1
-#define HAVE_BUILTIN_EXPECT 1
#define HAVE_ATTRIBUTE_PRINTF 1
-#define HAVE_BUILTIN_TYPES_COMPATIBLE_P 1
+#define HAVE_BIG_ENDIAN 0
#define HAVE_BUILTIN_CHOOSE_EXPR 1
+#define HAVE_BUILTIN_EXPECT 1
+#define HAVE_BUILTIN_TYPES_COMPATIBLE_P 1
+#define HAVE_GETPAGESIZE 1
#define HAVE_LITTLE_ENDIAN 1
-#define HAVE_BIG_ENDIAN 0
#define HAVE_MMAP 1
-#define HAVE_GETPAGESIZE 1
+#define HAVE_NESTED_FUNCTIONS 1
+#define HAVE_STATEMENT_EXPR 1
+#define HAVE_TYPEOF 1
#define HAVE_UTIME 1
#define SPACE_CHARS " \f\n\r\t\v"
/* FIXME: Remove some -I */
-#define CFLAGS "-g -Wall -Wundef -Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes -Wmissing-declarations -Werror -Iccan/ -I. -I.. -I../.."
+/* FIXME: Nested functions break with -Wmissing-prototypes -Wmissing-declarations */
+#define CFLAGS "-g -Wall -Wundef -Wstrict-prototypes -Wold-style-definition -Werror -Iccan/ -I. -I.. -I../.."
/* This actually compiles and runs the info file to get dependencies. */
char **get_deps(const void *ctx, const char *dir, const char *name,