sort.c 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. /* vim: tabstop=4 shiftwidth=4 noexpandtab
  2. * This file is part of ToaruOS and is released under the terms
  3. * of the NCSA / University of Illinois License - see LICENSE.md
  4. * Copyright (C) 2018 K. Lange
  5. *
  6. * sort - Sort standard in or files.
  7. *
  8. * Currently implemented with a naive insertion sort.
  9. */
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <unistd.h>
  13. #include <string.h>
  14. #include <getopt.h>
  15. #include <errno.h>
  16. #include <ctype.h>
  17. #include <toaru/list.h>
  18. int compare(const char * a, const char * b) {
  19. while (1) {
  20. while (*a == *b || tolower(*a) == tolower(*b)) {
  21. if (!*a) return 0;
  22. a++;
  23. b++;
  24. }
  25. while (*a && !isalnum(*a)) a++;
  26. while (*b && !isalnum(*b)) b++;
  27. if (tolower(*a) == tolower(*b)) continue;
  28. if (tolower(*a) < tolower(*b)) return -1;
  29. return 1;
  30. }
  31. }
  32. int main(int argc, char * argv[]) {
  33. int reverse = 0;
  34. int opt;
  35. list_t * lines = list_create();
  36. list_t * files = list_create();
  37. while ((opt = getopt(argc, argv, "r")) != -1) {
  38. switch (opt) {
  39. case 'r':
  40. reverse = 1;
  41. break;
  42. }
  43. }
  44. if (optind == argc) {
  45. /* No arguments */
  46. list_insert(files, stdin);
  47. } else {
  48. while (optind < argc) {
  49. FILE * f = fopen(argv[optind], "r");
  50. if (!f) {
  51. fprintf(stderr, "%s: %s: %s\n", argv[0], argv[optind], strerror(errno));
  52. } else {
  53. list_insert(files, f);
  54. }
  55. optind++;
  56. }
  57. }
  58. char line_buf[4096] = {0};
  59. foreach (node, files) {
  60. FILE * f = node->value;
  61. while (!feof(f)) {
  62. if (!fgets(line_buf, 4096, f)) {
  63. break;
  64. }
  65. if (!strchr(line_buf,'\n')) {
  66. fprintf(stderr, "%s: oversized line\n", argv[0]);
  67. }
  68. char * line = strdup(line_buf);
  69. node_t * next = NULL;
  70. foreach (lnode, lines) {
  71. char * cmp = lnode->value;
  72. if (reverse ? (compare(cmp, line) < 0) : (compare(line, cmp) < 0)) {
  73. next = lnode;
  74. break;
  75. }
  76. }
  77. if (next) {
  78. list_insert_before(lines, next, line);
  79. } else {
  80. list_insert(lines, line);
  81. }
  82. }
  83. }
  84. foreach (lnode, lines) {
  85. char * line = lnode->value;
  86. fprintf(stdout, "%s", line);
  87. }
  88. return 0;
  89. }