wc.cpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. #include <AK/String.h>
  2. #include <AK/Vector.h>
  3. #include <LibCore/CArgsParser.h>
  4. #include <ctype.h>
  5. #include <stdio.h>
  6. static bool output_chars = false;
  7. static bool output_words = false;
  8. static bool output_lines = false;
  9. struct Count {
  10. String file;
  11. unsigned long chars = 0;
  12. unsigned long words = 0;
  13. unsigned long lines = 0;
  14. };
  15. int wc(const String& filename, Vector<Count>& counts);
  16. void report(const Count& count)
  17. {
  18. if (output_lines) {
  19. printf("%lu ", count.lines);
  20. }
  21. if (output_words) {
  22. printf("%lu ", count.words);
  23. }
  24. if (output_chars) {
  25. printf("%lu ", count.chars);
  26. }
  27. printf("%s\n", count.file.characters());
  28. }
  29. void report(const Vector<Count>& counts)
  30. {
  31. Count total { "total" };
  32. for (const auto& c : counts) {
  33. report(c);
  34. total.lines += c.lines;
  35. total.words += c.words;
  36. total.chars += c.chars;
  37. }
  38. if (counts.size() > 1) {
  39. report(total);
  40. }
  41. fflush(stdout);
  42. }
  43. int count_words(const char* s)
  44. {
  45. int n = 0;
  46. bool in_word = false;
  47. for (; *s; ++s) {
  48. if (!isspace(*s)) {
  49. if (!in_word) {
  50. in_word = true;
  51. ++n;
  52. }
  53. } else if (in_word) {
  54. in_word = false;
  55. }
  56. }
  57. return n;
  58. }
  59. int main(int argc, char** argv)
  60. {
  61. if (argc < 2) {
  62. printf("usage: wc [-c|-m] [-lw] [file...]\n");
  63. return 0;
  64. }
  65. CArgsParser args_parser("wc");
  66. args_parser.add_arg("l", "Include lines in count");
  67. args_parser.add_arg("c", "Include bytes in count");
  68. args_parser.add_arg("m", "Include chars in count");
  69. args_parser.add_arg("w", "Include words in count");
  70. CArgsParserResult args = args_parser.parse(argc, (char**)argv);
  71. if (args.is_present("l")) {
  72. output_lines = true;
  73. }
  74. if (args.is_present("c")) {
  75. output_chars = true;
  76. }
  77. if (args.is_present("m")) {
  78. output_chars = true;
  79. }
  80. if (args.is_present("w")) {
  81. output_words = true;
  82. }
  83. if (!output_lines && !output_words && !output_chars) {
  84. output_lines = output_chars = output_words = true;
  85. }
  86. Vector<String> files = args.get_single_values();
  87. Vector<Count> counts;
  88. int status;
  89. if (files.is_empty()) {
  90. status = wc("", counts);
  91. if (status != 0)
  92. return status;
  93. } else {
  94. for (const auto& f : files) {
  95. status = wc(f, counts);
  96. if (status != 0)
  97. return status;
  98. }
  99. }
  100. report(counts);
  101. return 0;
  102. }
  103. int wc(const String& filename, Vector<Count>& counts)
  104. {
  105. FILE* fp = nullptr;
  106. if (filename == "" || filename == "-") {
  107. fp = stdin;
  108. } else {
  109. fp = fopen(filename.characters(), "r");
  110. if (fp == nullptr) {
  111. fprintf(stderr, "wc: Could not open file '%s'\n", filename.characters());
  112. return 1;
  113. }
  114. }
  115. Count count { filename };
  116. char* line = nullptr;
  117. size_t len = 0;
  118. ssize_t n_read = 0;
  119. while ((n_read = getline(&line, &len, fp)) != -1) {
  120. count.lines++;
  121. count.words += count_words(line);
  122. count.chars += n_read;
  123. }
  124. counts.append(count);
  125. fclose(fp);
  126. if (line) {
  127. free(line);
  128. }
  129. return 0;
  130. }