Thu, 09 Feb 2012 15:56:18 +0100
allow parallel use of -s and -S
1 /*
2 * cline.c
3 *
4 * Created on: 23.05.2011
5 * Author: Mike
6 */
8 #include "cline.h"
9 #include "scanner.h"
10 #include "settings.h"
11 #include "arguments.h"
12 #include "stream.h"
13 #include "regex_parser.h"
15 void printHelpText() {
16 const char* helpText =
17 "\nUsage:"
18 "\n cline [Options] [Directory]"
19 "\n cline [Options] [Directory]"
20 "\n\nCounts the line terminator characters (\\n) within all"
21 " files in the specified\ndirectory."
22 "\n\nOptions:"
23 "\n -b <level> - binary file heuristics level (default medium)"
24 "\n One of: ignore low medium high"
25 "\n -E <pattern> - Excludes any line matching the <pattern>"
26 "\n -e <start> <end> - Excludes lines between <start> and <end>"
27 "\n You may use these options multiple times"
28 "\n -h, --help - this help text"
29 "\n -m - print information about matching files only"
30 "\n -s <suffixes> - only count files with these suffixes (separated"
31 "\n by commas)"
32 "\n -S <suffixes> - count any file except those with these suffixes"
33 "\n (separated by commas)"
34 "\n -r, -R - includes subdirectories"
35 "\n -v, --version - print out version information"
36 "\n -V - turn verbose output off, print the result only"
37 "\n\n"
38 "The default call without any options is:"
39 "\n cline ./\n\n"
40 "So each file in the working directory is counted. If you want to count C"
41 "\nsource code in your working directory and its subdirectories, type:"
42 "\n cline -rs .c\n"
43 "\nIf you want to exclude comment lines, you may use the -e/-E option."
44 "\nAfter a line matches the regex pattern <start> any following line is"
45 "\nnot counted unless a line matches the <end> pattern. A line is still "
46 "\ncounted when it does not start or end with the respective patterns."
47 "\nPlease note, that cline does not remove whitespace characters as this"
48 "\nmight not be reasonable in some cases."
49 "\n\nExample (C comments):"
50 "\n cline -s .c,.h -E \"\\s*//\" -e \"\\s*/\\*\" \"\\*/\\s*\"";
52 printf(helpText);
53 }
55 int exit_with_version(settings_t* settings) {
56 printf("cline - Revision: %s", VERSION);
57 destroy_settings_t(settings);
58 return 0;
59 }
61 int exit_with_help(settings_t* settings, int code) {
62 printHelpText();
63 destroy_settings_t(settings);
64 return code;
65 }
67 int main(int argc, char** argv) {
69 /* Settings */
70 settings_t *settings = new_settings_t();
71 if (settings == NULL) {
72 fprintf(stderr, "Memory allocation failed.\n");
73 return 1;
74 }
76 /* Get arguments */
77 char* directory = "./";
78 char* includeSuffix = NULL;
79 char* excludeSuffix = NULL;
80 int checked = 0;
82 for (int t = 1 ; t < argc ; t++) {
84 int argflags = checkArgument(argv[t], "hsSrRmvVbeE");
85 int paropt = 0;
87 /* s */
88 if ((argflags & 2) > 0) {
89 if (!checkParamOpt(&paropt) || registerArgument(&checked, 2)) {
90 return exit_with_help(settings, 1);
91 }
92 t++;
93 if (t >= argc) {
94 return exit_with_help(settings, 1);
95 }
96 includeSuffix = argv[t];
97 }
98 /* S */
99 if ((argflags & 4) > 0) {
100 if (!checkParamOpt(&paropt) || registerArgument(&checked, 4)) {
101 return exit_with_help(settings, 1);
102 }
103 t++;
104 if (t >= argc) {
105 return exit_with_help(settings, 1);
106 }
107 excludeSuffix = argv[t];
108 }
109 /* h */
110 if ((argflags & 1) > 0 || strcmp(argv[t], "--help") == 0) {
111 return exit_with_help(settings, 0);
112 }
113 /* r, R */
114 if ((argflags & 24) > 0) {
115 if (registerArgument(&checked, 24)) {
116 return exit_with_help(settings, 1);
117 }
118 settings->recursive = true;
119 }
120 /* m */
121 if ((argflags & 32) > 0) {
122 if (registerArgument(&checked, 32)) {
123 return exit_with_help(settings, 1);
124 }
125 settings->matchesOnly = true;
126 }
127 /* v */
128 if ((argflags & 64) > 0 || strcmp(argv[t], "--version") == 0) {
129 return exit_with_version(settings);
130 }
131 /* V */
132 if ((argflags & 128) > 0) {
133 if (registerArgument(&checked, 128)) {
134 return exit_with_help(settings, 1);
135 }
136 settings->verbose = false;
137 }
138 /* b */
139 if ((argflags & 256) > 0) {
140 if (!checkParamOpt(&paropt) || registerArgument(&checked, 256)) {
141 return exit_with_help(settings, 1);
142 }
143 t++;
144 if (t >= argc) {
145 return exit_with_help(settings, 1);
146 }
147 if (strcasecmp(argv[t], "ignore") == 0) {
148 settings->bfileHeuristics->level = BFILE_IGNORE;
149 } else if (strcasecmp(argv[t], "low") == 0) {
150 settings->bfileHeuristics->level = BFILE_LOW_ACCURACY;
151 } else if (strcasecmp(argv[t], "medium") == 0) {
152 settings->bfileHeuristics->level = BFILE_MEDIUM_ACCURACY;
153 } else if (strcasecmp(argv[t], "high") == 0) {
154 settings->bfileHeuristics->level = BFILE_HIGH_ACCURACY;
155 } else {
156 return exit_with_help(settings, 1);
157 }
158 }
159 /* e */
160 if ((argflags & 512) > 0) {
161 if (!checkParamOpt(&paropt) || t + 2 >= argc) {
162 return exit_with_help(settings, 1);
163 }
164 t++; add_string(settings->regex->pattern_list, argv[t]);
165 t++; add_string(settings->regex->pattern_list, argv[t]);
166 }
167 /* E */
168 if ((argflags & 1024) > 0) {
169 t++;
170 if (!checkParamOpt(&paropt) || t >= argc) {
171 return exit_with_help(settings, 1);
172 }
173 add_string(settings->regex->pattern_list, argv[t]);
174 add_string(settings->regex->pattern_list, "$");
175 }
176 /* Path */
177 if (argflags == 0) {
178 if (registerArgument(&checked, 1024)) {
179 return exit_with_help(settings, 1);
180 }
181 directory = argv[t];
182 }
183 }
185 /* Configure output */
186 if (!settings->verbose) {
187 close_stdout();
188 }
190 /* Find tokens */
191 parseCSL(includeSuffix, settings->includeSuffixes);
192 parseCSL(excludeSuffix, settings->excludeSuffixes);
194 /* Scan directory */
195 if (regex_compile_all(settings->regex)) {
196 int lines = scanDirectory((scanner_t){directory, 0}, settings);
197 destroy_settings_t(settings);
199 /* Print double line and line count */
200 for (int t = 0 ; t < 79 ; t++) {
201 printf("=");
202 }
203 printf("\n%73d lines\n", lines);
205 if (settings->confusing_lnlen && settings->regex->pattern_list->count > 0) {
206 printf("\nSome files contain too long lines.\n"
207 "The regex parser currently supports a maximum line length of %d."
208 "\nThe result might be wrong.\n", REGEX_MAX_LINELENGTH);
209 }
211 if (!settings->verbose) {
212 reopen_stdout();
213 printf("%d", lines);
214 }
215 }
217 fflush(stdout);
218 fflush(stderr);
219 return 0;
220 }