which lets you compile out most of the "--help" output, saving up to 17k. Renamed mnc to nc. -Erik
		
			
				
	
	
		
			308 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			308 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* vi: set sw=4 ts=4: */
 | 
						|
/*
 | 
						|
 * Mini sort implementation for busybox
 | 
						|
 *
 | 
						|
 *
 | 
						|
 * Copyright (C) 1999,2000 by Lineo, inc.
 | 
						|
 * Written by John Beppu <beppu@lineo.com>
 | 
						|
 *
 | 
						|
 * 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 of the License, 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
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
#include "internal.h"
 | 
						|
#include <sys/types.h>
 | 
						|
#include <fcntl.h>
 | 
						|
#include <dirent.h>
 | 
						|
#include <stdio.h>
 | 
						|
#include <errno.h>
 | 
						|
 | 
						|
static const char sort_usage[] = "sort [-n]"
 | 
						|
#ifdef BB_FEATURE_SORT_REVERSE
 | 
						|
" [-r]"
 | 
						|
#endif
 | 
						|
" [FILE]...\n"
 | 
						|
#ifndef BB_FEATURE_TRIVIAL_HELP
 | 
						|
"\nSorts lines of text in the specified files\n"
 | 
						|
#endif
 | 
						|
;
 | 
						|
 | 
						|
#ifdef BB_FEATURE_SORT_REVERSE
 | 
						|
#define APPLY_REVERSE(x) (reverse ? -(x) : (x))
 | 
						|
static int reverse = 0;
 | 
						|
#else
 | 
						|
#define APPLY_REVERSE(x) (x)
 | 
						|
#endif
 | 
						|
 | 
						|
/* typedefs _______________________________________________________________ */
 | 
						|
 | 
						|
/* line node */
 | 
						|
typedef struct Line {
 | 
						|
	char *data;					/* line data */
 | 
						|
	struct Line *next;			/* pointer to next line node */
 | 
						|
} Line;
 | 
						|
 | 
						|
/* singly-linked list of lines */
 | 
						|
typedef struct {
 | 
						|
	int len;					/* number of Lines */
 | 
						|
	Line **sorted;				/* array fed to qsort */
 | 
						|
	Line *head;					/* head of List */
 | 
						|
	Line *current;				/* current Line */
 | 
						|
} List;
 | 
						|
 | 
						|
/* comparison function */
 | 
						|
typedef int (Compare) (const void *, const void *);
 | 
						|
 | 
						|
 | 
						|
/* methods ________________________________________________________________ */
 | 
						|
 | 
						|
static const int max = 1024;
 | 
						|
 | 
						|
/* mallocate Line */
 | 
						|
static Line *line_alloc()
 | 
						|
{
 | 
						|
	Line *self;
 | 
						|
	self = malloc(1 * sizeof(Line));
 | 
						|
	return self;
 | 
						|
}
 | 
						|
 | 
						|
/* Construct Line from FILE* */
 | 
						|
static Line *line_newFromFile(FILE * src)
 | 
						|
{
 | 
						|
	Line *self;
 | 
						|
	char *cstring = NULL;
 | 
						|
 | 
						|
	if ((cstring = cstring_lineFromFile(src))) {
 | 
						|
		self = line_alloc();
 | 
						|
		if (self == NULL) {
 | 
						|
			return NULL;
 | 
						|
		}
 | 
						|
		self->data = cstring;
 | 
						|
		self->next = NULL;
 | 
						|
		return self;
 | 
						|
	}
 | 
						|
	return NULL;
 | 
						|
}
 | 
						|
 | 
						|
/* Line destructor */
 | 
						|
static Line *line_release(Line * self)
 | 
						|
{
 | 
						|
	if (self->data) {
 | 
						|
		free(self->data);
 | 
						|
		free(self);
 | 
						|
	}
 | 
						|
	return self;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* Comparison */
 | 
						|
 | 
						|
/* ascii order */
 | 
						|
static int compare_ascii(const void *a, const void *b)
 | 
						|
{
 | 
						|
	Line **doh;
 | 
						|
	Line *x, *y;
 | 
						|
 | 
						|
	doh = (Line **) a;
 | 
						|
	x = *doh;
 | 
						|
	doh = (Line **) b;
 | 
						|
	y = *doh;
 | 
						|
 | 
						|
	// fprintf(stdout, "> %p: %s< %p: %s", x, x->data, y, y->data);
 | 
						|
	return APPLY_REVERSE(strcmp(x->data, y->data));
 | 
						|
}
 | 
						|
 | 
						|
/* numeric order */
 | 
						|
static int compare_numeric(const void *a, const void *b)
 | 
						|
{
 | 
						|
	Line **doh;
 | 
						|
	Line *x, *y;
 | 
						|
	int xint, yint;
 | 
						|
 | 
						|
	doh = (Line **) a;
 | 
						|
	x = *doh;
 | 
						|
	doh = (Line **) b;
 | 
						|
	y = *doh;
 | 
						|
 | 
						|
	xint = strtoul(x->data, NULL, 10);
 | 
						|
	yint = strtoul(y->data, NULL, 10);
 | 
						|
 | 
						|
	return APPLY_REVERSE(xint - yint);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* List */
 | 
						|
 | 
						|
/* */
 | 
						|
static List *list_init(List * self)
 | 
						|
{
 | 
						|
	self->len = 0;
 | 
						|
	self->sorted = NULL;
 | 
						|
	self->head = NULL;
 | 
						|
	self->current = NULL;
 | 
						|
	return self;
 | 
						|
}
 | 
						|
 | 
						|
/* for simplicity, the List gains ownership of the line */
 | 
						|
static List *list_insert(List * self, Line * line)
 | 
						|
{
 | 
						|
	if (line == NULL) {
 | 
						|
		return NULL;
 | 
						|
	}
 | 
						|
 | 
						|
	/* first insertion */
 | 
						|
	if (self->head == NULL) {
 | 
						|
		self->head = line;
 | 
						|
		self->current = line;
 | 
						|
 | 
						|
	/* all subsequent insertions */
 | 
						|
	} else {
 | 
						|
		self->current->next = line;
 | 
						|
		self->current = line;
 | 
						|
	}
 | 
						|
	self->len++;
 | 
						|
	return self;
 | 
						|
}
 | 
						|
 | 
						|
/* order the list according to compare() */
 | 
						|
static List *list_sort(List * self, Compare * compare)
 | 
						|
{
 | 
						|
	int i;
 | 
						|
	Line *line;
 | 
						|
 | 
						|
	/* mallocate array of Line*s */
 | 
						|
	self->sorted = (Line **) malloc(self->len * sizeof(Line *));
 | 
						|
	if (self->sorted == NULL) {
 | 
						|
		return NULL;
 | 
						|
	}
 | 
						|
 | 
						|
	/* fill array w/ List's contents */
 | 
						|
	i = 0;
 | 
						|
	line = self->head;
 | 
						|
	while (line) {
 | 
						|
		self->sorted[i++] = line;
 | 
						|
		line = line->next;
 | 
						|
	}
 | 
						|
 | 
						|
	/* apply qsort */
 | 
						|
	qsort(self->sorted, self->len, sizeof(Line *), compare);
 | 
						|
	return self;
 | 
						|
}
 | 
						|
 | 
						|
/* precondition:  list must be sorted */
 | 
						|
static List *list_writeToFile(List * self, FILE * dst)
 | 
						|
{
 | 
						|
	int i;
 | 
						|
	Line **line = self->sorted;
 | 
						|
 | 
						|
	if (self->sorted == NULL) {
 | 
						|
		return NULL;
 | 
						|
	}
 | 
						|
	for (i = 0; i < self->len; i++) {
 | 
						|
		fprintf(dst, "%s", line[i]->data);
 | 
						|
	}
 | 
						|
	return self;
 | 
						|
}
 | 
						|
 | 
						|
/* deallocate */
 | 
						|
static void list_release(List * self)
 | 
						|
{
 | 
						|
	Line *i;
 | 
						|
	Line *die;
 | 
						|
 | 
						|
	i = self->head;
 | 
						|
	while (i) {
 | 
						|
		die = i;
 | 
						|
		i = die->next;
 | 
						|
		line_release(die);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
int sort_main(int argc, char **argv)
 | 
						|
{
 | 
						|
	int i;
 | 
						|
	char opt;
 | 
						|
	List list;
 | 
						|
	Line *l;
 | 
						|
	Compare *compare;
 | 
						|
 | 
						|
	/* init */
 | 
						|
	compare = compare_ascii;
 | 
						|
	list_init(&list);
 | 
						|
 | 
						|
	/* parse argv[] */
 | 
						|
	for (i = 1; i < argc; i++) {
 | 
						|
		if (argv[i][0] == '-') {
 | 
						|
			opt = argv[i][1];
 | 
						|
			switch (opt) {
 | 
						|
			case 'h':
 | 
						|
				usage(sort_usage);
 | 
						|
				break;
 | 
						|
			case 'n':
 | 
						|
				/* numeric comparison */
 | 
						|
				compare = compare_numeric;
 | 
						|
				break;
 | 
						|
#ifdef BB_FEATURE_SORT_REVERSE
 | 
						|
			case 'r':
 | 
						|
				/* reverse */
 | 
						|
				reverse = 1;
 | 
						|
				break;
 | 
						|
#endif
 | 
						|
			default:
 | 
						|
				fprintf(stderr, "sort: invalid option -- %c\n", opt);
 | 
						|
				usage(sort_usage);
 | 
						|
			}
 | 
						|
		} else {
 | 
						|
			break;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	/* this could be factored better */
 | 
						|
 | 
						|
	/* work w/ stdin */
 | 
						|
	if (i >= argc) {
 | 
						|
		while ((l = line_newFromFile(stdin))) {
 | 
						|
			list_insert(&list, l);
 | 
						|
		}
 | 
						|
		list_sort(&list, compare);
 | 
						|
		list_writeToFile(&list, stdout);
 | 
						|
		list_release(&list);
 | 
						|
 | 
						|
		/* work w/ what's left in argv[] */
 | 
						|
	} else {
 | 
						|
		FILE *src;
 | 
						|
 | 
						|
		for (; i < argc; i++) {
 | 
						|
			src = fopen(argv[i], "r");
 | 
						|
			if (src == NULL) {
 | 
						|
				break;
 | 
						|
			}
 | 
						|
			while ((l = line_newFromFile(src))) {
 | 
						|
				list_insert(&list, l);
 | 
						|
			}
 | 
						|
			fclose(src);
 | 
						|
		}
 | 
						|
		list_sort(&list, compare);
 | 
						|
		list_writeToFile(&list, stdout);
 | 
						|
		list_release(&list);
 | 
						|
	}
 | 
						|
 | 
						|
	exit(0);
 | 
						|
}
 | 
						|
 | 
						|
/* $Id: sort.c,v 1.16 2000/05/12 19:41:47 erik Exp $ */
 |