cline.c

changeset 34
fa9bda32de17
parent 32
51d6e45a7592
equal deleted inserted replaced
33:1a2d7298bc82 34:fa9bda32de17
1 /*
2 * cline.c
3 *
4 * Created on: 23.05.2011
5 * Author: Mike
6 */
7
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"
14
15 void printHelpText() {
16 const char* helpText =
17 "\nUsage:"
18 "\n cline [Options] [Directories...]"
19 "\n cline [Options] [Directories...]"
20 "\n\nCounts the line terminator characters (\\n) within all"
21 " files in the specified\ndirectories."
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\nShortcuts:"
38 "\n --exclude-cstyle-comments"
39 "\n = -E \"\\s*//\" -e \"\\s*/\\*\" \"\\*/\\s*\""
40 "\n\n"
41 "The default call without any options is:"
42 "\n cline ./\n\n"
43 "So each file in the working directory is counted. If you want to count C"
44 "\nsource code in your working directory and its subdirectories, type:"
45 "\n cline -rs .c\n"
46 "\nIf you want to exclude comment lines, you may use the -e/-E option."
47 "\nAfter a line matches the regex pattern <start> any following line is"
48 "\nnot counted unless a line matches the <end> pattern. A line is still "
49 "\ncounted when it does not start or end with the respective patterns."
50 "\nPlease note, that cline does not remove whitespace characters as this"
51 "\nmight not be reasonable in some cases."
52 "\n\nExample (C without comments):"
53 "\n cline -s .c,.h --exclude-cstyle-comments";
54
55 printf(helpText);
56 }
57
58 int exit_with_version(settings_t* settings) {
59 printf("cline - Revision: %s\n", VERSION);
60 destroy_settings_t(settings);
61 return 0;
62 }
63
64 int exit_with_help(settings_t* settings, int code) {
65 printHelpText();
66 destroy_settings_t(settings);
67 return code;
68 }
69
70 int main(int argc, char** argv) {
71
72 /* Settings */
73 settings_t *settings = new_settings_t();
74 if (settings == NULL) {
75 fprintf(stderr, "Memory allocation failed.\n");
76 return 1;
77 }
78
79 /* Get arguments */
80 string_list_t *directories = new_string_list_t();
81 if (directories == NULL) {
82 fprintf(stderr, "Memory allocation failed.\n");
83 return 1;
84 }
85 char* includeSuffix = NULL;
86 char* excludeSuffix = NULL;
87 int checked = 0;
88
89 for (int t = 1 ; t < argc ; t++) {
90
91 int argflags = checkArgument(argv[t], "hsSrRmvVbeE");
92 int paropt = 0;
93
94 /* s */
95 if ((argflags & 2) > 0) {
96 if (!checkParamOpt(&paropt) || registerArgument(&checked, 2)) {
97 return exit_with_help(settings, 1);
98 }
99 t++;
100 if (t >= argc) {
101 return exit_with_help(settings, 1);
102 }
103 includeSuffix = argv[t];
104 }
105 /* S */
106 if ((argflags & 4) > 0) {
107 if (!checkParamOpt(&paropt) || registerArgument(&checked, 4)) {
108 return exit_with_help(settings, 1);
109 }
110 t++;
111 if (t >= argc) {
112 return exit_with_help(settings, 1);
113 }
114 excludeSuffix = argv[t];
115 }
116 /* h */
117 if ((argflags & 1) > 0 || strcmp(argv[t], "--help") == 0) {
118 return exit_with_help(settings, 0);
119 }
120 /* r, R */
121 if ((argflags & 24) > 0) {
122 if (registerArgument(&checked, 24)) {
123 return exit_with_help(settings, 1);
124 }
125 settings->recursive = true;
126 }
127 /* m */
128 if ((argflags & 32) > 0) {
129 if (registerArgument(&checked, 32)) {
130 return exit_with_help(settings, 1);
131 }
132 settings->matchesOnly = true;
133 }
134 /* v */
135 if ((argflags & 64) > 0 || strcmp(argv[t], "--version") == 0) {
136 return exit_with_version(settings);
137 }
138 /* V */
139 if ((argflags & 128) > 0) {
140 if (registerArgument(&checked, 128)) {
141 return exit_with_help(settings, 1);
142 }
143 settings->verbose = false;
144 }
145 /* b */
146 if ((argflags & 256) > 0) {
147 if (!checkParamOpt(&paropt) || registerArgument(&checked, 256)) {
148 return exit_with_help(settings, 1);
149 }
150 t++;
151 if (t >= argc) {
152 return exit_with_help(settings, 1);
153 }
154 if (strcasecmp(argv[t], "ignore") == 0) {
155 settings->bfileHeuristics->level = BFILE_IGNORE;
156 } else if (strcasecmp(argv[t], "low") == 0) {
157 settings->bfileHeuristics->level = BFILE_LOW_ACCURACY;
158 } else if (strcasecmp(argv[t], "medium") == 0) {
159 settings->bfileHeuristics->level = BFILE_MEDIUM_ACCURACY;
160 } else if (strcasecmp(argv[t], "high") == 0) {
161 settings->bfileHeuristics->level = BFILE_HIGH_ACCURACY;
162 } else {
163 return exit_with_help(settings, 1);
164 }
165 }
166 /* e */
167 if ((argflags & 512) > 0) {
168 if (!checkParamOpt(&paropt) || t + 2 >= argc) {
169 return exit_with_help(settings, 1);
170 }
171 t++; add_string(settings->regex->pattern_list, argv[t]);
172 t++; add_string(settings->regex->pattern_list, argv[t]);
173 }
174 /* E */
175 if ((argflags & 1024) > 0) {
176 t++;
177 if (!checkParamOpt(&paropt) || t >= argc) {
178 return exit_with_help(settings, 1);
179 }
180 add_string(settings->regex->pattern_list, argv[t]);
181 add_string(settings->regex->pattern_list, "$");
182 }
183 if (argflags == 0) {
184 /* SHORTCUTS */
185 /* exclude-cstyle-comments */
186 if (strcmp(argv[t], "--exclude-cstyle-comments") == 0) {
187 add_string(settings->regex->pattern_list, "\\s*//");
188 add_string(settings->regex->pattern_list, "$");
189 add_string(settings->regex->pattern_list, "\\s*/\\*");
190 add_string(settings->regex->pattern_list, "\\*/\\s*");
191 }
192 /* Path */
193 else {
194 add_string(directories, argv[t]);
195 }
196 }
197 }
198
199 /* Configure output */
200 if (!settings->verbose) {
201 close_stdout();
202 }
203
204 /* Find tokens */
205 parseCSL(includeSuffix, settings->includeSuffixes);
206 parseCSL(excludeSuffix, settings->excludeSuffixes);
207
208 /* Scan directories */
209 if (regex_compile_all(settings->regex)) {
210 int lines = 0;
211 if (directories->count == 0) {
212 add_string(directories, ".");
213 }
214 for (int t = 0 ; t < directories->count ; t++) {
215 if (t > 0) {
216 for (int u = 0 ; u < 79 ; u++) {
217 printf("-");
218 }
219 printf("\n");
220 }
221 lines += scanDirectory((scanner_t){directories->items[t], 0}, settings);
222 }
223 destroy_string_list_t(directories);
224
225 /* Print double line and line count */
226 for (int t = 0 ; t < 79 ; t++) {
227 printf("=");
228 }
229 printf("\n%73d lines\n", lines);
230
231 if (settings->confusing_lnlen && settings->regex->pattern_list->count > 0) {
232 printf("\nSome files contain too long lines.\n"
233 "The regex parser currently supports a maximum line length of %d."
234 "\nThe result might be wrong.\n", REGEX_MAX_LINELENGTH);
235 }
236
237 if (!settings->verbose) {
238 reopen_stdout();
239 printf("%d", lines);
240 }
241 destroy_settings_t(settings);
242 }
243
244 fflush(stdout);
245 fflush(stderr);
246 return 0;
247 }

mercurial