diff options
author | Matt Kraai <kraai@debian.org> | 2000-12-20 20:49:56 +0000 |
---|---|---|
committer | Matt Kraai <kraai@debian.org> | 2000-12-20 20:49:56 +0000 |
commit | 5e8c0ffb75f5578069d75988abc2657e9f2a2bc8 (patch) | |
tree | 206b720a8cd62da502baac79484a7464b8003639 /coreutils | |
parent | e75f6a972c3307881adc1bb2aacc4b1e21417883 (diff) | |
download | busybox-w32-5e8c0ffb75f5578069d75988abc2657e9f2a2bc8.tar.gz busybox-w32-5e8c0ffb75f5578069d75988abc2657e9f2a2bc8.tar.bz2 busybox-w32-5e8c0ffb75f5578069d75988abc2657e9f2a2bc8.zip |
Rewrote.
Diffstat (limited to 'coreutils')
-rw-r--r-- | coreutils/sort.c | 276 |
1 files changed, 37 insertions, 239 deletions
diff --git a/coreutils/sort.c b/coreutils/sort.c index b0bf6e494..efff6b653 100644 --- a/coreutils/sort.c +++ b/coreutils/sort.c | |||
@@ -3,8 +3,7 @@ | |||
3 | * Mini sort implementation for busybox | 3 | * Mini sort implementation for busybox |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * Copyright (C) 1999,2000 by Lineo, inc. | 6 | * Copyright (C) 2000 by Matt Kraai <kraai@alumni.carnegiemellon.edu> |
7 | * Written by John Beppu <beppu@lineo.com> | ||
8 | * | 7 | * |
9 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
10 | * it under the terms of the GNU General Public License as published by | 9 | * it under the terms of the GNU General Public License as published by |
@@ -23,267 +22,66 @@ | |||
23 | */ | 22 | */ |
24 | 23 | ||
25 | #include "busybox.h" | 24 | #include "busybox.h" |
26 | #include <sys/types.h> | ||
27 | #include <fcntl.h> | ||
28 | #include <dirent.h> | ||
29 | #include <stdio.h> | ||
30 | #include <errno.h> | ||
31 | 25 | ||
32 | #ifdef BB_FEATURE_SORT_REVERSE | 26 | int compare_ascii(const void *x, const void *y) |
33 | #define APPLY_REVERSE(x) (reverse ? -(x) : (x)) | ||
34 | static int reverse = 0; | ||
35 | #else | ||
36 | #define APPLY_REVERSE(x) (x) | ||
37 | #endif | ||
38 | |||
39 | /* typedefs _______________________________________________________________ */ | ||
40 | |||
41 | /* line node */ | ||
42 | typedef struct Line { | ||
43 | char *data; /* line data */ | ||
44 | struct Line *next; /* pointer to next line node */ | ||
45 | } Line; | ||
46 | |||
47 | /* singly-linked list of lines */ | ||
48 | typedef struct { | ||
49 | int len; /* number of Lines */ | ||
50 | Line **sorted; /* array fed to qsort */ | ||
51 | Line *head; /* head of List */ | ||
52 | Line *current; /* current Line */ | ||
53 | } List; | ||
54 | |||
55 | /* comparison function */ | ||
56 | typedef int (Compare) (const void *, const void *); | ||
57 | |||
58 | |||
59 | /* methods ________________________________________________________________ */ | ||
60 | |||
61 | static const int max = 1024; | ||
62 | |||
63 | /* mallocate Line */ | ||
64 | static Line *line_alloc() | ||
65 | { | ||
66 | Line *self; | ||
67 | self = xmalloc(1 * sizeof(Line)); | ||
68 | return self; | ||
69 | } | ||
70 | |||
71 | /* Construct Line from FILE* */ | ||
72 | static Line *line_newFromFile(FILE * src) | ||
73 | { | ||
74 | Line *self; | ||
75 | char *cstring = NULL; | ||
76 | |||
77 | if ((cstring = get_line_from_file(src))) { | ||
78 | self = line_alloc(); | ||
79 | self->data = cstring; | ||
80 | self->next = NULL; | ||
81 | return self; | ||
82 | } | ||
83 | return NULL; | ||
84 | } | ||
85 | |||
86 | /* Line destructor */ | ||
87 | static Line *line_release(Line * self) | ||
88 | { | ||
89 | if (self->data) { | ||
90 | free(self->data); | ||
91 | free(self); | ||
92 | } | ||
93 | return self; | ||
94 | } | ||
95 | |||
96 | |||
97 | /* Comparison */ | ||
98 | |||
99 | /* ascii order */ | ||
100 | static int compare_ascii(const void *a, const void *b) | ||
101 | { | ||
102 | Line **val; | ||
103 | Line *x, *y; | ||
104 | |||
105 | val = (Line **) a; | ||
106 | x = *val; | ||
107 | val = (Line **) b; | ||
108 | y = *val; | ||
109 | |||
110 | // fprintf(stdout, "> %p: %s< %p: %s", x, x->data, y, y->data); | ||
111 | return APPLY_REVERSE(strcmp(x->data, y->data)); | ||
112 | } | ||
113 | |||
114 | /* numeric order */ | ||
115 | static int compare_numeric(const void *a, const void *b) | ||
116 | { | ||
117 | Line **val; | ||
118 | Line *x, *y; | ||
119 | int xint, yint; | ||
120 | |||
121 | val = (Line **) a; | ||
122 | x = *val; | ||
123 | val = (Line **) b; | ||
124 | y = *val; | ||
125 | |||
126 | xint = strtoul(x->data, NULL, 10); | ||
127 | yint = strtoul(y->data, NULL, 10); | ||
128 | |||
129 | return APPLY_REVERSE(xint - yint); | ||
130 | } | ||
131 | |||
132 | |||
133 | /* List */ | ||
134 | |||
135 | /* */ | ||
136 | static List *list_init(List * self) | ||
137 | { | ||
138 | self->len = 0; | ||
139 | self->sorted = NULL; | ||
140 | self->head = NULL; | ||
141 | self->current = NULL; | ||
142 | return self; | ||
143 | } | ||
144 | |||
145 | /* for simplicity, the List gains ownership of the line */ | ||
146 | static List *list_insert(List * self, Line * line) | ||
147 | { | ||
148 | if (line == NULL) { | ||
149 | return NULL; | ||
150 | } | ||
151 | |||
152 | /* first insertion */ | ||
153 | if (self->head == NULL) { | ||
154 | self->head = line; | ||
155 | self->current = line; | ||
156 | |||
157 | /* all subsequent insertions */ | ||
158 | } else { | ||
159 | self->current->next = line; | ||
160 | self->current = line; | ||
161 | } | ||
162 | self->len++; | ||
163 | return self; | ||
164 | } | ||
165 | |||
166 | /* order the list according to compare() */ | ||
167 | static List *list_sort(List * self, Compare * compare) | ||
168 | { | 27 | { |
169 | int i; | 28 | return strcmp(*(char **)x, *(char **)y); |
170 | Line *line; | ||
171 | |||
172 | /* mallocate array of Line*s */ | ||
173 | self->sorted = (Line **) xmalloc(self->len * sizeof(Line *)); | ||
174 | |||
175 | /* fill array w/ List's contents */ | ||
176 | i = 0; | ||
177 | line = self->head; | ||
178 | while (line) { | ||
179 | self->sorted[i++] = line; | ||
180 | line = line->next; | ||
181 | } | ||
182 | |||
183 | /* apply qsort */ | ||
184 | qsort(self->sorted, self->len, sizeof(Line *), compare); | ||
185 | return self; | ||
186 | } | ||
187 | |||
188 | /* precondition: list must be sorted */ | ||
189 | static List *list_writeToFile(List * self, FILE * dst) | ||
190 | { | ||
191 | int i; | ||
192 | Line **line = self->sorted; | ||
193 | |||
194 | if (self->sorted == NULL) { | ||
195 | return NULL; | ||
196 | } | ||
197 | for (i = 0; i < self->len; i++) { | ||
198 | fprintf(dst, "%s", line[i]->data); | ||
199 | } | ||
200 | return self; | ||
201 | } | 29 | } |
202 | 30 | ||
203 | /* deallocate */ | 31 | int compare_numeric(const void *x, const void *y) |
204 | static void list_release(List * self) | ||
205 | { | 32 | { |
206 | Line *i; | 33 | return atoi(*(char **)x) - atoi(*(char **)y); |
207 | Line *die; | ||
208 | |||
209 | i = self->head; | ||
210 | while (i) { | ||
211 | die = i; | ||
212 | i = die->next; | ||
213 | line_release(die); | ||
214 | } | ||
215 | } | 34 | } |
216 | 35 | ||
217 | |||
218 | |||
219 | int sort_main(int argc, char **argv) | 36 | int sort_main(int argc, char **argv) |
220 | { | 37 | { |
221 | int i; | 38 | FILE *fp; |
222 | char opt; | 39 | char *line, **lines = NULL; |
223 | List list; | 40 | int i, opt, nlines = 0; |
224 | Line *l; | 41 | int (*compare)(const void *, const void *) = compare_ascii; |
225 | Compare *compare; | 42 | #ifdef BB_FEATURE_SORT_REVERSE |
226 | 43 | int reverse = FALSE; | |
227 | /* init */ | 44 | #endif |
228 | compare = compare_ascii; | ||
229 | list_init(&list); | ||
230 | 45 | ||
231 | /* parse argv[] */ | 46 | while ((opt = getopt(argc, argv, "nr")) != -1) { |
232 | for (i = 1; i < argc; i++) { | 47 | switch (opt) { |
233 | if (argv[i][0] == '-') { | ||
234 | opt = argv[i][1]; | ||
235 | switch (opt) { | ||
236 | case 'h': | ||
237 | usage(sort_usage); | ||
238 | break; | ||
239 | case 'n': | 48 | case 'n': |
240 | /* numeric comparison */ | ||
241 | compare = compare_numeric; | 49 | compare = compare_numeric; |
242 | break; | 50 | break; |
243 | #ifdef BB_FEATURE_SORT_REVERSE | 51 | #ifdef BB_FEATURE_SORT_REVERSE |
244 | case 'r': | 52 | case 'r': |
245 | /* reverse */ | 53 | reverse = TRUE; |
246 | reverse = 1; | ||
247 | break; | 54 | break; |
248 | #endif | 55 | #endif |
249 | default: | 56 | default: |
250 | error_msg("invalid option -- %c\n", opt); | ||
251 | usage(sort_usage); | 57 | usage(sort_usage); |
252 | } | ||
253 | } else { | ||
254 | break; | ||
255 | } | 58 | } |
256 | } | 59 | } |
257 | 60 | ||
258 | if (i >= argc) { | 61 | /* read the input */ |
62 | for (i = optind; i == optind || i < argc; i++) { | ||
63 | if (argv[i] == NULL) | ||
64 | fp = stdin; | ||
65 | else | ||
66 | fp = xfopen(argv[i], "r"); | ||
259 | 67 | ||
260 | /* work w/ stdin */ | 68 | while ((line = get_line_from_file(fp)) != NULL) { |
261 | while ((l = line_newFromFile(stdin))) { | 69 | lines = xrealloc(lines, sizeof(char *) * (nlines + 1)); |
262 | list_insert(&list, l); | 70 | lines[nlines++] = line; |
263 | } | 71 | } |
264 | |||
265 | } else { | ||
266 | |||
267 | /* work w/ what's left in argv[] */ | ||
268 | FILE *src; | ||
269 | |||
270 | for (; i < argc; i++) { | ||
271 | src = fopen(argv[i], "r"); | ||
272 | if (src == NULL) { | ||
273 | break; | ||
274 | } | ||
275 | while ((l = line_newFromFile(src))) { | ||
276 | list_insert(&list, l); | ||
277 | } | ||
278 | fclose(src); | ||
279 | } | ||
280 | |||
281 | } | 72 | } |
282 | list_sort(&list, compare); | ||
283 | list_writeToFile(&list, stdout); | ||
284 | list_release(&list); | ||
285 | 73 | ||
286 | return(0); | 74 | /* sort it */ |
287 | } | 75 | qsort(lines, nlines, sizeof(char *), compare); |
288 | 76 | ||
289 | /* $Id: sort.c,v 1.24 2000/12/07 19:56:48 markw Exp $ */ | 77 | /* print it */ |
78 | #ifdef BB_FEATURE_SORT_REVERSE | ||
79 | if (reverse) | ||
80 | for (i = nlines - 1; 0 <= i; i--) | ||
81 | fputs(lines[i], stdout); | ||
82 | else | ||
83 | #endif | ||
84 | for (i = 0; i < nlines; i++) | ||
85 | fputs(lines[i], stdout); | ||
86 | return EXIT_SUCCESS; | ||
87 | } | ||