bore

basic core utilities (PD)
git clone git://bvnf.space/bore.git
Log | Files | Refs | README

sort.c (2682B)


      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
#define _XOPEN_SOURCE 700
#include <errno.h>
#include <limits.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

enum FLAGS {
    FLAG_r = 1 << 0,
};

int flags;

int
alphacompare(const void *s1, const void *s2) {
    int ret = strcoll(*(const char **) s1, *(const char **) s2);
    if (flags & FLAG_r)
        ret *= -1;
    return ret;
}

void
free_lines(char **lines, int n) {
    for (int i = 0; i < n; i++)
        free(lines[i]);
    free(lines);
}


int
sort(FILE *f) {
    char **lines = malloc(sizeof(char *));
    if (lines == NULL) {
        fprintf(stderr, "sort: %s\n", strerror(errno));
        return 1;
    }
    size_t lsize = sizeof(char *);
    size_t lused = 0;
    int i = 0;
    char *buf = NULL;
    ssize_t bufused = 0;
    size_t bufsize = 0;
    while ((bufused = getline(&buf, &bufsize, f)) != -1) {
        if (bufused + lused > lsize) {
            char **tmp = realloc(lines, bufused + lused);
            if (tmp == NULL) {
                fprintf(stderr, "sort: %s\n", strerror(errno));
                free_lines(lines, i);
                free(buf);
                return 1;
            }
            lused += bufused;
            lines = tmp;
        }
        lines[i] = strndup(buf, bufused);
        //strncpy(lines[i], buf, bufused);
        lines[i][bufused] = '\0';
        i++;
        bufused = 0;
    }
    if (ferror(f)) {
        fprintf(stderr, "sort: %s\n", strerror(errno));
        free_lines(lines, i);
        free(buf);
        return 1;
    }

    qsort(lines, i, sizeof lines[0], alphacompare);

    for (int j = 0; j < i; j++) {
        printf("%s", lines[j]);
    }

    free_lines(lines, i);
    free(buf);
    return 0;
}

int
main(int argc, char **argv) {
    setlocale(LC_ALL, "");
    int c;
    int ret = 0;
    flags = 0;
    while ((c = getopt(argc, argv, "r")) != -1) {
        switch (c) {
            case 'r':
                flags |= FLAG_r;
                break;
        }
    }
    argc -= optind;
    argv += optind - 1;

    if (argc == 0)
        return sort(stdin);

    while (*++argv) {
        FILE *f;
        if (**argv == '-' && *(*argv + 1) == '\0')
            f = stdin;
        else {
            f = fopen(*argv, "r");
            if (f == NULL) {
                fprintf(stderr, "sort: %s: %s\n", *argv, strerror(errno));
                ret = 1;
                continue;
            }
        }
        if (sort(f) != 0)
            ret = 1;

        if (f != stdin && fclose(f) == EOF) {
            fprintf(stderr, "sort: %s: %s\n", *argv, strerror(errno));
            ret = 1;
            continue;
        }
    }
    return ret;
}