universe@10: /* universe@10: * cline.c universe@10: * universe@10: * Created on: 23.05.2011 universe@20: * Author: Mike universe@10: */ universe@10: universe@3: #include "cline.h" universe@10: #include "scanner.h" universe@10: #include "settings.h" universe@12: #include "arguments.h" universe@16: #include "stream.h" universe@27: #include "regex_parser.h" universe@0: universe@12: void printHelpText() { universe@0: const char* helpText = universe@1: "\nUsage:" universe@27: "\n cline [Options] [Directory]" universe@27: "\n cline [Options] [Directory]" universe@0: "\n\nCounts the line terminator characters (\\n) within all" universe@0: " files in the specified\ndirectory." universe@0: "\n\nOptions:" universe@21: "\n -b - binary file heuristics level (default medium)" universe@21: "\n One of: ignore low medium high" universe@28: "\n -E - Excludes any line matching the " universe@27: "\n -e - Excludes lines between and " universe@28: "\n You may use these options multiple times" universe@0: "\n -h, --help - this help text" universe@1: "\n -m - print information about matching files only" universe@1: "\n -s - only count files with these suffixes (separated" universe@0: "\n by commas)" universe@1: "\n -S - count any file except those with these suffixes" universe@0: "\n (separated by commas)" universe@1: "\n -r, -R - includes subdirectories" universe@14: "\n -v, --version - print out version information" universe@16: "\n -V - turn verbose output off, print the result only" universe@0: "\n\n" universe@1: "The default call without any options is:" universe@28: "\n cline ./\n\n" universe@7: "So each file in the working directory is counted. If you want to count C" universe@7: "\nsource code in your working directory and its subdirectories, type:" universe@27: "\n cline -rs .c\n" universe@28: "\nIf you want to exclude comment lines, you may use the -e/-E option." universe@27: "\nAfter a line matches the regex pattern any following line is" universe@28: "\nnot counted unless a line matches the pattern. A line is still " universe@28: "\ncounted when it does not start or end with the respective patterns." universe@28: "\nPlease note, that cline does not remove whitespace characters as this" universe@28: "\nmight not be reasonable in some cases." universe@28: "\n\nExample (C comments):" universe@28: "\n cline -s .c,.h -E \"\\s*//\" -e \"\\s*/\\*\" \"\\*/\\s*\""; universe@1: universe@12: printf(helpText); universe@1: } universe@1: universe@14: int exit_with_version(settings_t* settings) { universe@16: printf("cline - Revision: %s", VERSION); universe@14: destroy_settings_t(settings); universe@14: return 0; universe@14: } universe@14: universe@12: int exit_with_help(settings_t* settings, int code) { universe@12: printHelpText(); universe@8: destroy_settings_t(settings); universe@8: return code; universe@8: } universe@8: universe@1: int main(int argc, char** argv) { universe@0: universe@22: /* Settings */ universe@3: settings_t *settings = new_settings_t(); universe@5: if (settings == NULL) { universe@5: fprintf(stderr, "Memory allocation failed.\n"); universe@5: return 1; universe@5: } universe@3: universe@22: /* Get arguments */ universe@7: char* directory = "./"; universe@30: char* includeSuffix = NULL; universe@30: char* excludeSuffix = NULL; universe@8: int checked = 0; universe@0: universe@1: for (int t = 1 ; t < argc ; t++) { universe@1: universe@28: int argflags = checkArgument(argv[t], "hsSrRmvVbeE"); universe@30: int paropt = 0; universe@1: universe@30: /* s */ universe@30: if ((argflags & 2) > 0) { universe@30: if (!checkParamOpt(&paropt) || registerArgument(&checked, 2)) { universe@12: return exit_with_help(settings, 1); universe@0: } universe@1: t++; universe@1: if (t >= argc) { universe@12: return exit_with_help(settings, 1); universe@1: } universe@30: includeSuffix = argv[t]; universe@30: } universe@30: /* S */ universe@30: if ((argflags & 4) > 0) { universe@30: if (!checkParamOpt(&paropt) || registerArgument(&checked, 4)) { universe@30: return exit_with_help(settings, 1); universe@30: } universe@30: t++; universe@30: if (t >= argc) { universe@30: return exit_with_help(settings, 1); universe@30: } universe@30: excludeSuffix = argv[t]; universe@0: } universe@22: /* h */ universe@1: if ((argflags & 1) > 0 || strcmp(argv[t], "--help") == 0) { universe@14: return exit_with_help(settings, 0); universe@0: } universe@22: /* r, R */ universe@1: if ((argflags & 24) > 0) { universe@8: if (registerArgument(&checked, 24)) { universe@12: return exit_with_help(settings, 1); universe@0: } universe@3: settings->recursive = true; universe@0: } universe@22: /* m */ universe@1: if ((argflags & 32) > 0) { universe@8: if (registerArgument(&checked, 32)) { universe@12: return exit_with_help(settings, 1); universe@0: } universe@3: settings->matchesOnly = true; universe@0: } universe@22: /* v */ universe@14: if ((argflags & 64) > 0 || strcmp(argv[t], "--version") == 0) { universe@14: return exit_with_version(settings); universe@14: } universe@22: /* V */ universe@16: if ((argflags & 128) > 0) { universe@16: if (registerArgument(&checked, 128)) { universe@16: return exit_with_help(settings, 1); universe@16: } universe@16: settings->verbose = false; universe@16: } universe@22: /* b */ universe@21: if ((argflags & 256) > 0) { universe@30: if (!checkParamOpt(&paropt) || registerArgument(&checked, 256)) { universe@21: return exit_with_help(settings, 1); universe@21: } universe@21: t++; universe@21: if (t >= argc) { universe@21: return exit_with_help(settings, 1); universe@21: } universe@24: if (strcasecmp(argv[t], "ignore") == 0) { universe@21: settings->bfileHeuristics->level = BFILE_IGNORE; universe@24: } else if (strcasecmp(argv[t], "low") == 0) { universe@21: settings->bfileHeuristics->level = BFILE_LOW_ACCURACY; universe@24: } else if (strcasecmp(argv[t], "medium") == 0) { universe@21: settings->bfileHeuristics->level = BFILE_MEDIUM_ACCURACY; universe@24: } else if (strcasecmp(argv[t], "high") == 0) { universe@21: settings->bfileHeuristics->level = BFILE_HIGH_ACCURACY; universe@21: } else { universe@21: return exit_with_help(settings, 1); universe@21: } universe@21: } universe@28: /* e */ universe@27: if ((argflags & 512) > 0) { universe@30: if (!checkParamOpt(&paropt) || t + 2 >= argc) { universe@27: return exit_with_help(settings, 1); universe@27: } universe@27: t++; add_string(settings->regex->pattern_list, argv[t]); universe@27: t++; add_string(settings->regex->pattern_list, argv[t]); universe@27: } universe@28: /* E */ universe@28: if ((argflags & 1024) > 0) { universe@28: t++; universe@30: if (!checkParamOpt(&paropt) || t >= argc) { universe@28: return exit_with_help(settings, 1); universe@28: } universe@28: add_string(settings->regex->pattern_list, argv[t]); universe@28: add_string(settings->regex->pattern_list, "$"); universe@28: } universe@22: /* Path */ universe@1: if (argflags == 0) { universe@8: if (registerArgument(&checked, 1024)) { universe@12: return exit_with_help(settings, 1); universe@0: } universe@0: directory = argv[t]; universe@0: } universe@0: } universe@0: universe@22: /* Configure output */ universe@16: if (!settings->verbose) { universe@16: close_stdout(); universe@16: } universe@16: universe@22: /* Find tokens */ universe@30: parseCSL(includeSuffix, settings->includeSuffixes); universe@30: parseCSL(excludeSuffix, settings->excludeSuffixes); universe@0: universe@22: /* Scan directory */ universe@28: if (regex_compile_all(settings->regex)) { universe@28: int lines = scanDirectory((scanner_t){directory, 0}, settings); universe@28: destroy_settings_t(settings); universe@0: universe@28: /* Print double line and line count */ universe@28: for (int t = 0 ; t < 79 ; t++) { universe@28: printf("="); universe@28: } universe@28: printf("\n%73d lines\n", lines); universe@0: universe@28: if (settings->confusing_lnlen && settings->regex->pattern_list->count > 0) { universe@28: printf("\nSome files contain too long lines.\n" universe@28: "The regex parser currently supports a maximum line length of %d." universe@28: "\nThe result might be wrong.\n", REGEX_MAX_LINELENGTH); universe@28: } universe@25: universe@28: if (!settings->verbose) { universe@28: reopen_stdout(); universe@28: printf("%d", lines); universe@28: } universe@16: } universe@16: universe@16: fflush(stdout); universe@28: fflush(stderr); universe@0: return 0; universe@0: }