source@mandoc.bsd.lv
 help / color / mirror / Atom feed
* mdocml: bring back support for sorting
@ 2016-10-18 23:58 schwarze
  0 siblings, 0 replies; only message in thread
From: schwarze @ 2016-10-18 23:58 UTC (permalink / raw)
  To: source

Log Message:
-----------
bring back support for sorting

Modified Files:
--------------
    mdocml:
        compat_fts.c
        compat_fts.h

Revision Data
-------------
Index: compat_fts.h
===================================================================
RCS file: /home/cvs/mdocml/mdocml/compat_fts.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -Lcompat_fts.h -Lcompat_fts.h -u -p -r1.3 -r1.4
--- compat_fts.h
+++ compat_fts.h
@@ -38,9 +38,12 @@
 typedef struct {
 	struct _ftsent *fts_cur;	/* current node */
 	struct _ftsent *fts_child;	/* linked list of children */
+	struct _ftsent **fts_array;	/* sort array */
 	dev_t fts_dev;			/* starting device # */
 	char *fts_path;			/* path for this descent */
 	size_t fts_pathlen;		/* sizeof(path) */
+	int fts_nitems;			/* elements in the sort array */
+	int (*fts_compar)();		/* compare function */
 
 #define	FTS_NOCHDIR	0x0004		/* don't change directories */
 #define	FTS_PHYSICAL	0x0010		/* physical walk */
@@ -94,7 +97,8 @@ typedef struct _ftsent {
 
 
 int	 fts_close(FTS *);
-FTS	*fts_open(char * const *, int, void *);
+FTS	*fts_open(char * const *, int,
+	    int (*)(const FTSENT **, const FTSENT **));
 FTSENT	*fts_read(FTS *);
 int	 fts_set(FTS *, FTSENT *, int);
 
Index: compat_fts.c
===================================================================
RCS file: /home/cvs/mdocml/mdocml/compat_fts.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -Lcompat_fts.c -Lcompat_fts.c -u -p -r1.11 -r1.12
--- compat_fts.c
+++ compat_fts.c
@@ -59,6 +59,7 @@ static void	 fts_load(FTS *, FTSENT *);
 static size_t	 fts_maxarglen(char * const *);
 static void	 fts_padjust(FTS *, FTSENT *);
 static int	 fts_palloc(FTS *, size_t);
+static FTSENT	*fts_sort(FTS *, FTSENT *, int);
 static unsigned short	 fts_stat(FTS *, FTSENT *);
 
 #define	ISDOT(a)	(a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2])))
@@ -77,7 +78,8 @@ static unsigned short	 fts_stat(FTS *, F
 #define	SET(opt)	(sp->fts_options |= (opt))
 
 FTS *
-fts_open(char * const *argv, int options, void *dummy)
+fts_open(char * const *argv, int options,
+    int (*compar)(const FTSENT **, const FTSENT **))
 {
 	FTS *sp;
 	FTSENT *p, *root;
@@ -99,6 +101,7 @@ fts_open(char * const *argv, int options
 	/* Allocate/initialize the stream */
 	if ((sp = calloc(1, sizeof(FTS))) == NULL)
 		return (NULL);
+	sp->fts_compar = compar;
 	sp->fts_options = options;
 
 	/*
@@ -126,14 +129,25 @@ fts_open(char * const *argv, int options
 		if (p->fts_info == FTS_DOT)
 			p->fts_info = FTS_D;
 
-		p->fts_link = NULL;
-		if (root == NULL)
-			tmp = root = p;
-		else {
-			tmp->fts_link = p;
-			tmp = p;
+		/*
+		 * If comparison routine supplied, traverse in sorted
+		 * order; otherwise traverse in the order specified.
+		 */
+		if (compar) {
+			p->fts_link = root;
+			root = p;
+		} else {
+			p->fts_link = NULL;
+			if (root == NULL)
+				tmp = root = p;
+			else {
+				tmp->fts_link = p;
+				tmp = p;
+			}
 		}
 	}
+	if (compar && nitems > 1)
+		root = fts_sort(sp, root, nitems);
 
 	/*
 	 * Allocate a dummy pointer and make fts_read think that we've just
@@ -203,6 +217,7 @@ fts_close(FTS *sp)
 	/* Free up child linked list, sort array, path buffer, stream ptr.*/
 	if (sp->fts_child)
 		fts_lfree(sp->fts_child);
+	free(sp->fts_array);
 	free(sp->fts_path);
 	free(sp);
 
@@ -490,6 +505,10 @@ mem1:				saved_errno = errno;
 		cur->fts_info = FTS_DP;
 		return (NULL);
 	}
+
+	/* Sort the entries. */
+	if (sp->fts_compar && nitems > 1)
+		head = fts_sort(sp, head, nitems);
 	return (head);
 }
 
@@ -544,6 +563,40 @@ fts_stat(FTS *sp, FTSENT *p)
 	if (S_ISREG(sbp->st_mode))
 		return (FTS_F);
 	return (FTS_DEFAULT);
+}
+
+static FTSENT *
+fts_sort(FTS *sp, FTSENT *head, int nitems)
+{
+	FTSENT **ap, *p;
+
+	/*
+	 * Construct an array of pointers to the structures and call qsort(3).
+	 * Reassemble the array in the order returned by qsort.  If unable to
+	 * sort for memory reasons, return the directory entries in their
+	 * current order.  Allocate enough space for the current needs plus
+	 * 40 so don't realloc one entry at a time.
+	 */
+	if (nitems > sp->fts_nitems) {
+		struct _ftsent **a;
+
+		sp->fts_nitems = nitems + 40;
+		if ((a = reallocarray(sp->fts_array,
+		    sp->fts_nitems, sizeof(FTSENT *))) == NULL) {
+			free(sp->fts_array);
+			sp->fts_array = NULL;
+			sp->fts_nitems = 0;
+			return (head);
+		}
+		sp->fts_array = a;
+	}
+	for (ap = sp->fts_array, p = head; p; p = p->fts_link)
+		*ap++ = p;
+	qsort(sp->fts_array, nitems, sizeof(FTSENT *), sp->fts_compar);
+	for (head = *(ap = sp->fts_array); --nitems; ++ap)
+		ap[0]->fts_link = ap[1];
+	ap[0]->fts_link = NULL;
+	return (head);
 }
 
 static FTSENT *
--
 To unsubscribe send an email to source+unsubscribe@mdocml.bsd.lv

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2016-10-18 23:58 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-10-18 23:58 mdocml: bring back support for sorting schwarze

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).