Branch
Hash :
d81bc5f5
Author :
Thomas de Grivel
Date :
2025-09-20T17:59:17
fix off-by-minus-one when converting \r\n at end of line
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 124 125 126 127 128
/* kc3
* Copyright from 2022 to 2025 kmx.io <contact@kmx.io>
*
* Permission is hereby granted to use this software granted the above
* copyright notice and this permission paragraph are included in all
* copies and substantial portions of this software.
*
* THIS SOFTWARE IS PROVIDED "AS-IS" WITHOUT ANY GUARANTEE OF
* PURPOSE AND PERFORMANCE. IN NO EVENT WHATSOEVER SHALL THE
* AUTHOR BE CONSIDERED LIABLE FOR THE USE AND PERFORMANCE OF
* THIS SOFTWARE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct str {
char *str_ptr;
size_t str_size;
} s_str;
static void error (const char *message);
static int str_compare (const void *a, const void *b);
static void usage (void);
static const char *g_argv0 = "sort";
static int g_unique = 0;
static void error (const char *message)
{
fputs(message, stderr);
exit(1);
}
int main (int argc, char **argv)
{
size_t i;
char *line;
ssize_t line_len;
size_t line_size;
s_str *str;
size_t str_count;
size_t str_max;
s_str *str2;
size_t str2_max;
if (! argc || ! argv || ! argv[0])
usage();
g_argv0 = argv[0];
if (argc > 1) {
if (argc > 2)
usage();
if (argv[1][0] == '-' &&
argv[1][1] == 'u' &&
! argv[1][2])
g_unique = 1;
else
usage();
}
str_max = 512;
str = calloc(str_max, sizeof(s_str));
i = 0;
while (1) {
line = NULL;
line_size = 0;
if ((line_len = getline(&line, &line_size, stdin)) <= 0)
break;
if (line[line_len - 1] == '\n') {
line[--line_len] = 0;
if (line_len > 0 && line[line_len - 1] == '\r')
line[--line_len] = 0;
}
if (i >= str_max) {
str2_max = str_max + 512;
str2 = calloc(str2_max, sizeof(s_str));
memcpy(str2, str, str_max * sizeof(s_str));
free(str);
str = str2;
str_max = str2_max;
}
str[i].str_ptr = line;
str[i].str_size = line_len;
i++;
}
if (ferror(stdin) || ! feof(stdin))
error("sort: getline");
str_count = i;
if (str_count) {
qsort(str, str_count, sizeof(str[0]), str_compare);
i = 0;
while (i < str_count) {
if (! g_unique || ! i || str_compare(str + i - 1, str + i)) {
if ((str[i].str_size &&
fwrite(str[i].str_ptr, str[i].str_size, 1, stdout) <= 0) ||
fwrite("\n", 1, 1, stdout) <= 0)
error("sort: fwrite stdout");
}
i++;
}
fflush(stdout);
}
return 0;
}
static int str_compare (const void *a, const void *b)
{
size_t len;
int r;
const s_str *str_a;
const s_str *str_b;
str_a = a;
str_b = b;
len = (str_a->str_size < str_b->str_size) ?
str_a->str_size :
str_b->str_size;
if ((r = memcmp(str_a->str_ptr, str_b->str_ptr, len)))
return r;
if (str_a->str_size < str_b->str_size)
return -1;
if (str_a->str_size > str_b->str_size)
return 1;
return 0;
}
static void usage (void)
{
fprintf(stderr, "Usage: %s [-u]\n", g_argv0);
exit(1);
}