aboutsummaryrefslogtreecommitdiff
path: root/coreutils
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2009-12-13 02:09:22 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2009-12-13 02:09:22 +0100
commitaa42d13e320250d3573c6be975876a612c00e91f (patch)
tree822cacf0626690e608e15df32659c65caac29b36 /coreutils
parent31e2e7b86388e4ece09f37866bd1411f357cafbd (diff)
downloadbusybox-w32-aa42d13e320250d3573c6be975876a612c00e91f.tar.gz
busybox-w32-aa42d13e320250d3573c6be975876a612c00e91f.tar.bz2
busybox-w32-aa42d13e320250d3573c6be975876a612c00e91f.zip
sort: make sort -o FILE FILE (same FILE) work. Closes bug 785. -3 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'coreutils')
-rw-r--r--coreutils/sort.c56
1 files changed, 36 insertions, 20 deletions
diff --git a/coreutils/sort.c b/coreutils/sort.c
index e2e7983a1..5c3fa1a71 100644
--- a/coreutils/sort.c
+++ b/coreutils/sort.c
@@ -278,27 +278,32 @@ static unsigned str2u(char **str)
278int sort_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 278int sort_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
279int sort_main(int argc UNUSED_PARAM, char **argv) 279int sort_main(int argc UNUSED_PARAM, char **argv)
280{ 280{
281 FILE *fp, *outfile = stdout; 281 char *line, **lines;
282 char *line, **lines = NULL;
283 char *str_ignored, *str_o, *str_t; 282 char *str_ignored, *str_o, *str_t;
284 llist_t *lst_k = NULL; 283 llist_t *lst_k = NULL;
285 int i, flag; 284 int i, flag;
286 int linecount = 0; 285 int linecount;
286 unsigned opts;
287 287
288 xfunc_error_retval = 2; 288 xfunc_error_retval = 2;
289 289
290 /* Parse command line options */ 290 /* Parse command line options */
291 /* -o and -t can be given at most once */ 291 /* -o and -t can be given at most once */
292 opt_complementary = "o--o:t--t:" /* -t, -o: maximum one of each */ 292 opt_complementary = "o--o:t--t:" /* -t, -o: at most one of each */
293 "k::"; /* -k takes list */ 293 "k::"; /* -k takes list */
294 getopt32(argv, OPT_STR, &str_ignored, &str_ignored, &str_o, &lst_k, &str_t); 294 opts = getopt32(argv, OPT_STR, &str_ignored, &str_ignored, &str_o, &lst_k, &str_t);
295 /* global b strips leading and trailing spaces */
296 if (opts & FLAG_b)
297 option_mask32 |= FLAG_bb;
295#if ENABLE_FEATURE_SORT_BIG 298#if ENABLE_FEATURE_SORT_BIG
296 if (option_mask32 & FLAG_o) outfile = xfopen_for_write(str_o); 299 if (opts & FLAG_t) {
297 if (option_mask32 & FLAG_t) {
298 if (!str_t[0] || str_t[1]) 300 if (!str_t[0] || str_t[1])
299 bb_error_msg_and_die("bad -t parameter"); 301 bb_error_msg_and_die("bad -t parameter");
300 key_separator = str_t[0]; 302 key_separator = str_t[0];
301 } 303 }
304 /* note: below this point we use option_mask32, not opts,
305 * since that reduces register pressure and makes code smaller */
306
302 /* parse sort key */ 307 /* parse sort key */
303 while (lst_k) { 308 while (lst_k) {
304 enum { 309 enum {
@@ -315,7 +320,6 @@ int sort_main(int argc UNUSED_PARAM, char **argv)
315 }; 320 };
316 struct sort_key *key = add_key(); 321 struct sort_key *key = add_key();
317 char *str_k = llist_pop(&lst_k); 322 char *str_k = llist_pop(&lst_k);
318 const char *temp2;
319 323
320 i = 0; /* i==0 before comma, 1 after (-k3,6) */ 324 i = 0; /* i==0 before comma, 1 after (-k3,6) */
321 while (*str_k) { 325 while (*str_k) {
@@ -327,11 +331,13 @@ int sort_main(int argc UNUSED_PARAM, char **argv)
327 key->range[2*i+1] = str2u(&str_k); 331 key->range[2*i+1] = str2u(&str_k);
328 } 332 }
329 while (*str_k) { 333 while (*str_k) {
334 const char *temp2;
335
330 if (*str_k == ',' && !i++) { 336 if (*str_k == ',' && !i++) {
331 str_k++; 337 str_k++;
332 break; 338 break;
333 } /* no else needed: fall through to syntax error 339 } /* no else needed: fall through to syntax error
334 because comma isn't in OPT_STR */ 340 because comma isn't in OPT_STR */
335 temp2 = strchr(OPT_STR, *str_k); 341 temp2 = strchr(OPT_STR, *str_k);
336 if (!temp2) 342 if (!temp2)
337 bb_error_msg_and_die("unknown key option"); 343 bb_error_msg_and_die("unknown key option");
@@ -339,27 +345,29 @@ int sort_main(int argc UNUSED_PARAM, char **argv)
339 if (flag & ~FLAG_allowed_for_k) 345 if (flag & ~FLAG_allowed_for_k)
340 bb_error_msg_and_die("unknown sort type"); 346 bb_error_msg_and_die("unknown sort type");
341 /* b after ',' means strip _trailing_ space */ 347 /* b after ',' means strip _trailing_ space */
342 if (i && flag == FLAG_b) flag = FLAG_bb; 348 if (i && flag == FLAG_b)
349 flag = FLAG_bb;
343 key->flags |= flag; 350 key->flags |= flag;
344 str_k++; 351 str_k++;
345 } 352 }
346 } 353 }
347 } 354 }
348#endif 355#endif
349 /* global b strips leading and trailing spaces */
350 if (option_mask32 & FLAG_b) option_mask32 |= FLAG_bb;
351 356
352 /* Open input files and read data */ 357 /* Open input files and read data */
353 argv += optind; 358 argv += optind;
354 if (!*argv) 359 if (!*argv)
355 *--argv = (char*)"-"; 360 *--argv = (char*)"-";
361 linecount = 0;
362 lines = NULL;
356 do { 363 do {
357 /* coreutils 6.9 compat: abort on first open error, 364 /* coreutils 6.9 compat: abort on first open error,
358 * do not continue to next file: */ 365 * do not continue to next file: */
359 fp = xfopen_stdin(*argv); 366 FILE *fp = xfopen_stdin(*argv);
360 for (;;) { 367 for (;;) {
361 line = GET_LINE(fp); 368 line = GET_LINE(fp);
362 if (!line) break; 369 if (!line)
370 break;
363 lines = xrealloc_vector(lines, 6, linecount); 371 lines = xrealloc_vector(lines, 6, linecount);
364 lines[linecount++] = line; 372 lines[linecount++] = line;
365 } 373 }
@@ -373,16 +381,17 @@ int sort_main(int argc UNUSED_PARAM, char **argv)
373 /* handle -c */ 381 /* handle -c */
374 if (option_mask32 & FLAG_c) { 382 if (option_mask32 & FLAG_c) {
375 int j = (option_mask32 & FLAG_u) ? -1 : 0; 383 int j = (option_mask32 & FLAG_u) ? -1 : 0;
376 for (i = 1; i < linecount; i++) 384 for (i = 1; i < linecount; i++) {
377 if (compare_keys(&lines[i-1], &lines[i]) > j) { 385 if (compare_keys(&lines[i-1], &lines[i]) > j) {
378 fprintf(stderr, "Check line %d\n", i); 386 fprintf(stderr, "Check line %u\n", i);
379 return EXIT_FAILURE; 387 return EXIT_FAILURE;
380 } 388 }
389 }
381 return EXIT_SUCCESS; 390 return EXIT_SUCCESS;
382 } 391 }
383#endif 392#endif
384 /* Perform the actual sort */ 393 /* Perform the actual sort */
385 qsort(lines, linecount, sizeof(char *), compare_keys); 394 qsort(lines, linecount, sizeof(lines[0]), compare_keys);
386 /* handle -u */ 395 /* handle -u */
387 if (option_mask32 & FLAG_u) { 396 if (option_mask32 & FLAG_u) {
388 flag = 0; 397 flag = 0;
@@ -390,17 +399,24 @@ int sort_main(int argc UNUSED_PARAM, char **argv)
390 /* -- disabling last-resort compare... */ 399 /* -- disabling last-resort compare... */
391 option_mask32 |= FLAG_s; 400 option_mask32 |= FLAG_s;
392 for (i = 1; i < linecount; i++) { 401 for (i = 1; i < linecount; i++) {
393 if (!compare_keys(&lines[flag], &lines[i])) 402 if (compare_keys(&lines[flag], &lines[i]) == 0)
394 free(lines[i]); 403 free(lines[i]);
395 else 404 else
396 lines[++flag] = lines[i]; 405 lines[++flag] = lines[i];
397 } 406 }
398 if (linecount) linecount = flag+1; 407 if (linecount)
408 linecount = flag+1;
399 } 409 }
410
400 /* Print it */ 411 /* Print it */
412#if ENABLE_FEATURE_SORT_BIG
413 /* Open output file _after_ we read all input ones */
414 if (option_mask32 & FLAG_o)
415 xmove_fd(xopen3(str_o, O_WRONLY, 0666), STDOUT_FILENO);
416#endif
401 flag = (option_mask32 & FLAG_z) ? '\0' : '\n'; 417 flag = (option_mask32 & FLAG_z) ? '\0' : '\n';
402 for (i = 0; i < linecount; i++) 418 for (i = 0; i < linecount; i++)
403 fprintf(outfile, "%s%c", lines[i], flag); 419 printf("%s%c", lines[i], flag);
404 420
405 fflush_stdout_and_exit(EXIT_SUCCESS); 421 fflush_stdout_and_exit(EXIT_SUCCESS);
406} 422}