Fix calls to {m,c,re}alloc so that they use x{m,c,re}alloc instead of
[oweals/busybox.git] / coreutils / sort.c
index bab832f801e99ff5f1f4b2328a74f999b5ec5da8..a74f96ad08b60b5c94f7af12bb99a5879b9fb525 100644 (file)
@@ -1,8 +1,9 @@
+/* vi: set sw=4 ts=4: */
 /*
- * Mini find implementation for busybox
+ * Mini sort implementation for busybox
  *
  *
- * Copyright (C) 1999 by Lineo, inc.
+ * 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
 #include <stdio.h>
 #include <errno.h>
 
-static const char sort_usage[] =
-"Usage: sort [OPTION]... [FILE]...\n\n"
-;
+#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 */
+       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 */
+       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 *);
+typedef int (Compare) (const void *, const void *);
 
 
 /* methods ________________________________________________________________ */
@@ -58,212 +61,231 @@ typedef int (Compare)(const void *, const void *);
 static const int max = 1024;
 
 /* mallocate Line */
-static Line *
-line_alloc()
+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;
+       Line *self;
+       self = xmalloc(1 * sizeof(Line));
+       return self;
 }
 
 /* Construct Line from FILE* */
-static Line *
-line_newFromFile(FILE *src)
+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 *self;
+       char *cstring = NULL;
+
+       if ((cstring = get_line_from_file(src))) {
+               self = line_alloc();
+               self->data = cstring;
+               self->next = NULL;
+               return self;
+       }
+       return NULL;
 }
 
 /* Line destructor */
-static Line *
-line_release(Line *self)
+static Line *line_release(Line * self)
 {
-    if (self->data) { 
-       free(self->data); 
-       free(self);
-    }
-    return self;
+       if (self->data) {
+               free(self->data);
+               free(self);
+       }
+       return self;
 }
 
 
 /* Comparison */
 
-static int
-compare_ascii(const void *a, const void *b)
+/* ascii order */
+static int compare_ascii(const void *a, const void *b)
 {
-    return 0;
+       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));
 }
 
-static int
-compare_numeric(const void *a, const void *b)
+/* numeric order */
+static int compare_numeric(const void *a, const void *b)
 {
-    return 0;
+       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)
+static List *list_init(List * self)
 {
-    self->len     = 0;
-    self->sorted  = NULL;
-    self->head    = NULL;
-    self->current = NULL;
-    return 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)
+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;
+       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)
+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, sizeof(Line*), self->len, compare);
-    return self;
+       int i;
+       Line *line;
+
+       /* mallocate array of Line*s */
+       self->sorted = (Line **) xmalloc(self->len * sizeof(Line *));
+
+       /* 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)
+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;
+       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)
+static void list_release(List * self)
 {
-    Line *i;
-    Line *die;
-
-    i = self->head;
-    while (i) {
-       die = i;
-       i = die->next;
-       line_release(die);
-    }
+       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 sort_main(int argc, char **argv)
 {
-    int            i;
-    char    opt;
-    List    list;
-    Line    *l;
-
-    /* default behaviour */
-
-    /* parse argv[] */
-    for (i = 1; i < argc; i++) {
-       if (argv[i][0] == '-') {
-           opt = argv[i][1];
-           switch (opt) {
-               case 'h':
-                   usage(sort_usage);
-                   break;
-               default:
-                   fprintf(stderr, "sort: invalid option -- %c\n", opt);
-                   usage(sort_usage);
-           }
-       } else {
-           break;
+       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:
+                               errorMsg("invalid option -- %c\n", opt);
+                               usage(sort_usage);
+                       }
+               } else {
+                       break;
+               }
        }
-    }
 
-    /* initialize list */
-    list_init(&list);
+       /* this could be factored better */
 
-    /* go through remaining args (if any) */
-    if (i >= argc) {
-       while ( (l = line_newFromFile(stdin))) {
-           list_insert(&list, l);
-       }
-       list_sort(&list, compare_ascii);
-       list_writeToFile(&list, stdout);
-       list_release(&list);
-    } else {
-       for ( ; i < argc; i++) {
+       /* 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);
+       return(0);
 }
 
-/* $Id: sort.c,v 1.5 1999/12/22 22:27:01 beppu Exp $ */
-/* 
- * $Log: sort.c,v $
- * Revision 1.5  1999/12/22 22:27:01  beppu
- * playing w/ $Log$
- *
- */
+/* $Id: sort.c,v 1.21 2000/09/13 02:46:13 kraai Exp $ */