123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- #include <dirent.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- static const char** filters = NULL;
- static int filterAmount = 0;
- static char path[PATH_MAX] = {'\0'};
- static int pathLength = 0;
- typedef struct {
- char path[PATH_MAX];
- int lines;
- } LineFile;
- static LineFile* lineFiles = NULL;
- static size_t lineFileIndex = 0;
- static size_t lineFileCapacity = 0;
- static void addLineFile(int lines) {
- while(lineFileIndex >= lineFileCapacity) {
- lineFileCapacity += 16;
- lineFiles = realloc(lineFiles, sizeof(LineFile) * lineFileCapacity);
- }
- LineFile* lf = lineFiles + lineFileIndex++;
- memcpy(lf->path, path, sizeof(path));
- lf->lines = lines;
- }
- static void appendToPath(const char* s) {
- for(int i = 0; pathLength < (PATH_MAX - 1) && s[i] != '\0'; i++) {
- path[pathLength++] = s[i];
- }
- path[pathLength] = '\0';
- }
- static int enterPath(const char* name) {
- int length = pathLength;
- appendToPath("/");
- appendToPath(name);
- return length;
- }
- static void resetPath(int marker) {
- path[marker] = '\0';
- pathLength = marker;
- }
- static void countLines(void) {
- FILE* file = fopen(path, "r");
- if(file == NULL) {
- return;
- }
- int lines = 0;
- while(1) {
- int c = fgetc(file);
- if(c == EOF) {
- lines++;
- break;
- } else if(c == '\n') {
- lines++;
- }
- }
- addLineFile(lines);
- fclose(file);
- }
- static void handleFile(const char* name) {
- size_t end = strlen(name);
- for(int i = 0; i < filterAmount; i++) {
- if(*filters[i] == '-') {
- continue;
- }
- size_t l = strlen(filters[i]);
- if(end >= l && !strcmp(filters[i], name + (end - l))) {
- int marker = enterPath(name);
- countLines();
- resetPath(marker);
- return;
- }
- }
- }
- static int isAllowedName(const char* name) {
- for(int i = 0; i < filterAmount; i++) {
- if(*filters[i] != '-') {
- continue;
- }
- if(!strcmp(name, filters[i] + 1)) {
- return 0;
- }
- }
- return 1;
- }
- static void scanFolder(void) {
- DIR* dir = opendir(path);
- if(dir == NULL) {
- return;
- }
- while(1) {
- struct dirent* entry = readdir(dir);
- if(entry == NULL) {
- break;
- } else if(!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..")) {
- continue;
- } else if(entry->d_type == DT_DIR) {
- const char* name = entry->d_name;
- if(isAllowedName(name)) {
- int marker = enterPath(name);
- scanFolder();
- resetPath(marker);
- }
- } else if(entry->d_type == DT_REG) {
- handleFile(entry->d_name);
- }
- }
- closedir(dir);
- }
- static int compareLineFiles(const void* a, const void* b) {
- const LineFile* lnA = a;
- const LineFile* lnB = b;
- if(lnA->lines < lnB->lines) {
- return -1;
- }
- return lnA->lines == lnB->lines ? 0 : 1;
- }
- int main(int argAmount, const char** args) {
- if(argAmount < 3) {
- puts("Use '-' before a name to exclude such paths");
- if(argAmount > 0) {
- printf("%s <path> <ending_1> [ending_2] ...\n", args[0]);
- } else {
- puts("... <path> <ending_1> [ending_2] ...");
- }
- return 0;
- }
- filters = args + 2;
- filterAmount = argAmount - 2;
- appendToPath(args[1]);
- scanFolder();
- qsort(lineFiles, lineFileIndex, sizeof(LineFile), compareLineFiles);
- int allLines = 0;
- for(size_t i = 0; i < lineFileIndex; i++) {
- LineFile* ln = lineFiles + i;
- printf("%6d | %s\n", ln->lines, ln->path);
- allLines += ln->lines;
- }
- printf("Lines: %d\n", allLines);
- free(lineFiles);
- return 0;
- }
|