Browse Source

New asort routine; unf. breaks under -Wmissing-prototypes etc :(

Rusty Russell 16 years ago
parent
commit
009f261242

+ 2 - 1
Makefile-ccan

@@ -2,7 +2,8 @@
 # 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

+ 65 - 0
ccan/asort/_info

@@ -0,0 +1,65 @@
+#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;
+}

+ 21 - 0
ccan/asort/asort.c

@@ -0,0 +1,21 @@
+#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
+}

+ 37 - 0
ccan/asort/asort.h

@@ -0,0 +1,37 @@
+#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 */

+ 21 - 0
ccan/asort/test/compile_fail-context-type.c

@@ -0,0 +1,21 @@
+#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;
+}

+ 22 - 0
ccan/asort/test/run-strings.c

@@ -0,0 +1,22 @@
+#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();
+}

+ 68 - 0
ccan/asort/test/run.c

@@ -0,0 +1,68 @@
+#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();
+}

+ 7 - 6
config.h

@@ -1,13 +1,14 @@
 /* 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

+ 2 - 1
tools/tools.h

@@ -9,7 +9,8 @@
 #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,