Main.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. #include <dirent.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. static const char** filters = NULL;
  6. static int filterAmount = 0;
  7. static char path[PATH_MAX] = {'\0'};
  8. static int pathLength = 0;
  9. typedef struct {
  10. char path[PATH_MAX];
  11. int lines;
  12. } LineFile;
  13. static LineFile* lineFiles = NULL;
  14. static size_t lineFileIndex = 0;
  15. static size_t lineFileCapacity = 0;
  16. static void addLineFile(int lines) {
  17. while(lineFileIndex >= lineFileCapacity) {
  18. lineFileCapacity += 16;
  19. lineFiles = realloc(lineFiles, sizeof(LineFile) * lineFileCapacity);
  20. }
  21. LineFile* lf = lineFiles + lineFileIndex++;
  22. memcpy(lf->path, path, sizeof(path));
  23. lf->lines = lines;
  24. }
  25. static void appendToPath(const char* s) {
  26. for(int i = 0; pathLength < (PATH_MAX - 1) && s[i] != '\0'; i++) {
  27. path[pathLength++] = s[i];
  28. }
  29. path[pathLength] = '\0';
  30. }
  31. static int enterPath(const char* name) {
  32. int length = pathLength;
  33. appendToPath("/");
  34. appendToPath(name);
  35. return length;
  36. }
  37. static void resetPath(int marker) {
  38. path[marker] = '\0';
  39. pathLength = marker;
  40. }
  41. static void countLines(void) {
  42. FILE* file = fopen(path, "r");
  43. if(file == NULL) {
  44. return;
  45. }
  46. int lines = 0;
  47. while(1) {
  48. int c = fgetc(file);
  49. if(c == EOF) {
  50. lines++;
  51. break;
  52. } else if(c == '\n') {
  53. lines++;
  54. }
  55. }
  56. addLineFile(lines);
  57. fclose(file);
  58. }
  59. static void handleFile(const char* name) {
  60. size_t end = strlen(name);
  61. for(int i = 0; i < filterAmount; i++) {
  62. if(*filters[i] == '-') {
  63. continue;
  64. }
  65. size_t l = strlen(filters[i]);
  66. if(end >= l && !strcmp(filters[i], name + (end - l))) {
  67. int marker = enterPath(name);
  68. countLines();
  69. resetPath(marker);
  70. return;
  71. }
  72. }
  73. }
  74. static int isAllowedName(const char* name) {
  75. for(int i = 0; i < filterAmount; i++) {
  76. if(*filters[i] != '-') {
  77. continue;
  78. }
  79. if(!strcmp(name, filters[i] + 1)) {
  80. return 0;
  81. }
  82. }
  83. return 1;
  84. }
  85. static void scanFolder(void) {
  86. DIR* dir = opendir(path);
  87. if(dir == NULL) {
  88. return;
  89. }
  90. while(1) {
  91. struct dirent* entry = readdir(dir);
  92. if(entry == NULL) {
  93. break;
  94. } else if(!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..")) {
  95. continue;
  96. } else if(entry->d_type == DT_DIR) {
  97. const char* name = entry->d_name;
  98. if(isAllowedName(name)) {
  99. int marker = enterPath(name);
  100. scanFolder();
  101. resetPath(marker);
  102. }
  103. } else if(entry->d_type == DT_REG) {
  104. handleFile(entry->d_name);
  105. }
  106. }
  107. closedir(dir);
  108. }
  109. static int compareLineFiles(const void* a, const void* b) {
  110. const LineFile* lnA = a;
  111. const LineFile* lnB = b;
  112. if(lnA->lines < lnB->lines) {
  113. return -1;
  114. }
  115. return lnA->lines == lnB->lines ? 0 : 1;
  116. }
  117. int main(int argAmount, const char** args) {
  118. if(argAmount < 3) {
  119. puts("Use '-' before a name to exclude such paths");
  120. if(argAmount > 0) {
  121. printf("%s <path> <ending_1> [ending_2] ...\n", args[0]);
  122. } else {
  123. puts("... <path> <ending_1> [ending_2] ...");
  124. }
  125. return 0;
  126. }
  127. filters = args + 2;
  128. filterAmount = argAmount - 2;
  129. appendToPath(args[1]);
  130. scanFolder();
  131. qsort(lineFiles, lineFileIndex, sizeof(LineFile), compareLineFiles);
  132. int allLines = 0;
  133. for(size_t i = 0; i < lineFileIndex; i++) {
  134. LineFile* ln = lineFiles + i;
  135. printf("%6d | %s\n", ln->lines, ln->path);
  136. allLines += ln->lines;
  137. }
  138. printf("Lines: %d\n", allLines);
  139. free(lineFiles);
  140. return 0;
  141. }