--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cline.c Mon May 23 16:42:44 2011 +0200 @@ -0,0 +1,285 @@ +#include <stdio.h> +#include <string.h> +#include <stdbool.h> +#include <stdlib.h> +#include <dirent.h> + +static int suffixc; +static char** suffixv; +static bool recursive; +static bool includeSuffixes; + +bool testSuffix(char* filename) +{ + bool ret = false; + int tokenlen, fnamelen = strlen(filename); + for (int t = 0 ; t < suffixc ; t++) + { + tokenlen = strlen(suffixv[t]); + if (fnamelen >= tokenlen) + { + if (strncmp(filename+fnamelen-tokenlen, suffixv[t], tokenlen) == 0) + { + ret = true; + break; + } + } + } + return ret ^ !includeSuffixes; +} + +int scanDirectory(DIR *dir, const int spaces, char* currdir) +{ + DIR *subdir; + char* subdirname; + struct dirent *entry; + int lines, digits, a; + int lineSum = 0; + + while ((entry = readdir(dir)) != NULL) + { + if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) + { + // Print occurence + char entryname[strlen(entry->d_name)+spaces]; + for (int t = 0 ; t < spaces ; t++) + { + entryname[t]=' '; + } + entryname[spaces] = 0; + strcat(entryname, entry->d_name); + printf("%-60s", entryname); + + // Check for subdirectory + char subdirname[(1+strlen(currdir)+strlen(entry->d_name))]; + strcpy(subdirname, currdir); + strcat(subdirname, "/"); + strcat(subdirname, entry->d_name); + if ((subdir = opendir(subdirname)) != NULL) + { + printf("\n"); + if (recursive) + { + lineSum += scanDirectory(subdir, spaces+1, subdirname); + } + closedir(subdir); + continue; + } + + // Count lines + lines = 0; + char filename[(1+strlen(currdir)+strlen(entry->d_name))]; + strcpy(filename, currdir); + strcat(filename, "/"); + strcat(filename, entry->d_name); + if (testSuffix(filename)) + { + FILE *file = fopen(filename, "r"); + if (file == NULL) + { + perror(" File acces failed"); + continue; + } + + do + { + a = fgetc(file); + + if (a == 10) + { + lines++; + } + } while (a != EOF); + fclose(file); + + // Print line count + printf("%14d lines\n", lines); + + lineSum += lines; + } + else + { + // Print hint + printf("%20s\n", "no match"); + } + } + } + return lineSum; +} + +int main(int argc, char** argv) +{ + // Help text + const char* helpText = + "\nUsage:\n%s [-h|--help|(-s=<suffix>|-S=<suffix>)|(-r|-R)|<directory>]" + "\n\nCounts the line terminator characters (\\n) within all" + " files in the specified\ndirectory." + "\n\nOptions:" + "\n -h, --help - this help text" + "\n -s=<suffixes> - only count files with these suffixes (separated" + "\n by commas)" + "\n -S=<suffixes> - count any file except those with these suffixes" + "\n (separated by commas)" + "\n -R - excludes subdirectories" + "\n -r - includes subdirecotires" + "\n\n" + "The default call without any options is:" + "\n %s -r ./ -S=\n" + "That means each file in each subdirectory is counted. If you want to count" + "\nC source code in your working directory and its subdirectories, type:" + "\n %s -s=.c\n"; + + // Program name + char* prgName = strrchr(argv[0], '/'); + if (prgName == NULL) + { + prgName = argv[0]; + } + else + { + prgName++; + } + + // Defaults + char* _suffix = ""; + char* _directory = "./"; + + // Get arguments + char* directory; + char* suffix; + bool showHelp = false; + recursive = true; + includeSuffixes = false; + char checked = 0; + + for (int t = 1 ; t < argc ; t++) + { + if (strncmp(argv[t], "-s=", 3) == 0) + { + if ((checked & 1) > 0) + { + printf(helpText, prgName, prgName, prgName); + return -1; + } + includeSuffixes = true; + suffix = argv[t]+3; + checked |= 1; + } + else if (strncmp(argv[t], "-S=", 3) == 0) + { + if ((checked & 1) > 0) + { + printf(helpText, prgName, prgName, prgName); + return -1; + } + includeSuffixes = false; + suffix = argv[t]+3; + checked |= 1; + } + else if (strcmp(argv[t], "-h") == 0 || strcmp(argv[t], "--help") == 0) + { + if ((checked & 2) > 0) + { + printf(helpText, prgName, prgName, prgName); + return -1; + } + checked |= 2; + showHelp = true; + } + else if (strcmp(argv[t], "-r") == 0) + { + if ((checked & 4) > 0) + { + printf(helpText, prgName, prgName, prgName); + return -1; + } + checked |= 4; + recursive = true; + } + else if (strcmp(argv[t], "-R") == 0) + { + if ((checked & 4) > 0) + { + printf(helpText, prgName, prgName, prgName); + return -1; + } + checked |= 4; + recursive = false; + } + else + { + if ((checked & 8) > 0) + { + printf(helpText, prgName, prgName, prgName); + return -1; + } + checked |= 8; + directory = argv[t]; + } + } + + // Show help and quit + if (showHelp) + { + printf(helpText, prgName, prgName, prgName); + return 0; + } + + // Default values + if ((checked & 1) == 0) + { + suffix = _suffix; + } + + if ((checked & 8) == 0) + { + directory = _directory; + } + + // Find tokens + char* finder; + suffixc = 1; + finder = strchr(suffix, ','); + while (finder != NULL) + { + suffixc++; + finder = strchr(finder+1, ','); + } + suffixv = (char**) malloc(sizeof(suffixv)*suffixc); + if (suffixv == NULL) + { + fprintf(stderr, "Memory allocation failed.\n"); + return 1; + } + finder = strtok(suffix, ","); + int c = 0; + while (finder != NULL) + { + suffixv[c] = finder; + c++; + finder = strtok(NULL, ","); + } + + // Open directory + DIR *dir = opendir(directory); + if (dir == NULL) + { + perror("Operation failed"); + free(suffixv); + return 1; + } + + // Scan directory + int lines = scanDirectory(dir, 0, directory); + + // Print double line and line count + for (int t = 0 ; t < 80 ; t++) + { + printf("="); + } + printf("\n%74d lines\n", lines); + + closedir(dir); + free(suffixv); + return 0; +}