/*
 * Mini sort implementation for busybox
 *
 *
 * Copyright (C) 1999 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[] =
"Usage: sort [OPTION]... [FILE]...\n\n"
;

/* 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;
}

/* Initialize Line with string */
static Line *
line_init(Line *self, const char *string)
{
    self->data = malloc((strlen(string) + 1) * sizeof(char));
    if (self->data == NULL) { return NULL; }
    strcpy(self->data, string);
    self->next = NULL;
    return self;
}

/* Construct Line from FILE* */
static Line *
line_newFromFile(FILE *src)
{
    char    buffer[max];
    Line    *self;

    if (fgets(buffer, max, src)) {
	self = line_alloc();
	if (self == NULL) { return NULL; }
	line_init(self, buffer);
	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 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 (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);
    }
}


/*
 * I need a list
 * to insert lines into
 * then I need to sort this list
 * and finally print it
 */

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 'g':
		    /* what's the diff between -g && -n? */
		    compare = compare_numeric;	    
		    break;
		case 'h':
		    usage(sort_usage);
		    break;
		case 'n':
		    /* what's the diff between -g && -n? */
		    compare = compare_numeric;	    
		    break;
		case 'r':
		    /* reverse */
		    break;
		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.8 1999/12/23 22:46:10 beppu Exp $ */
