src/cline.c

changeset 34
fa9bda32de17
parent 33
1a2d7298bc82
child 35
35120de6ee53
equal deleted inserted replaced
33:1a2d7298bc82 34:fa9bda32de17
1 /*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3 * Copyright 2011 Mike Becker. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 * cline.c
27 *
28 * Created on: 23.05.2011
29 * Author: Mike
30 */
31
32 #include "cline.h"
33 #include "scanner.h"
34 #include "settings.h"
35 #include "arguments.h"
36 #include "stream.h"
37 #include "regex_parser.h"
38
39 void printHelpText() {
40 printf(
41 "\nUsage:"
42 "\n cline [Options] [Directories...]"
43 "\n cline [Options] [Directories...]"
44 "\n\nCounts the line terminator characters (\\n) within all"
45 " files in the specified\ndirectories."
46 "\n\nOptions:"
47 "\n -b <level> - binary file heuristics level (default medium)"
48 "\n One of: ignore low medium high"
49 "\n -E <pattern> - Excludes any line matching the <pattern>"
50 "\n -e <start> <end> - Excludes lines between <start> and <end>"
51 "\n You may use these options multiple times"
52 "\n -h, --help - this help text"
53 "\n -m - print information about matching files only"
54 "\n -s <suffixes> - only count files with these suffixes (separated"
55 "\n by commas)"
56 "\n -S <suffixes> - count any file except those with these suffixes"
57 "\n (separated by commas)"
58 "\n -r, -R - includes subdirectories"
59 "\n -v, --version - print out version information"
60 "\n -V - turn verbose output off, print the result only"
61 "\n\nShortcuts:"
62 "\n --exclude-cstyle-comments"
63 "\n = -E \"\\s*//\" -e \"\\s*/\\*\" \"\\*/\\s*\""
64 "\n\n"
65 "The default call without any options is:"
66 "\n cline ./\n\n"
67 "So each file in the working directory is counted. If you want to count C"
68 "\nsource code in your working directory and its subdirectories, type:"
69 "\n cline -rs .c\n"
70 "\nIf you want to exclude comment lines, you may use the -e/-E option."
71 "\nAfter a line matches the regex pattern <start> any following line is"
72 "\nnot counted unless a line matches the <end> pattern. A line is still "
73 "\ncounted when it does not start or end with the respective patterns."
74 "\nPlease note, that cline does not remove whitespace characters as this"
75 "\nmight not be reasonable in some cases."
76 "\n\nExample (C without comments):"
77 "\n cline -s .c,.h --exclude-cstyle-comments");
78 }
79
80 int exit_with_version(settings_t* settings) {
81 printf("cline - Revision: %s\n", VERSION);
82 destroy_settings_t(settings);
83 return 0;
84 }
85
86 int exit_with_help(settings_t* settings, int code) {
87 printHelpText();
88 destroy_settings_t(settings);
89 return code;
90 }
91
92 int main(int argc, char** argv) {
93
94 /* Settings */
95 settings_t *settings = new_settings_t();
96 if (settings == NULL) {
97 fprintf(stderr, "Memory allocation failed.\n");
98 return 1;
99 }
100
101 /* Get arguments */
102 string_list_t *directories = new_string_list_t();
103 if (directories == NULL) {
104 fprintf(stderr, "Memory allocation failed.\n");
105 return 1;
106 }
107 char* includeSuffix = NULL;
108 char* excludeSuffix = NULL;
109 int checked = 0;
110
111 for (int t = 1 ; t < argc ; t++) {
112
113 int argflags = checkArgument(argv[t], "hsSrRmvVbeE");
114 int paropt = 0;
115
116 /* s */
117 if ((argflags & 2) > 0) {
118 if (!checkParamOpt(&paropt) || registerArgument(&checked, 2)) {
119 return exit_with_help(settings, 1);
120 }
121 t++;
122 if (t >= argc) {
123 return exit_with_help(settings, 1);
124 }
125 includeSuffix = argv[t];
126 }
127 /* S */
128 if ((argflags & 4) > 0) {
129 if (!checkParamOpt(&paropt) || registerArgument(&checked, 4)) {
130 return exit_with_help(settings, 1);
131 }
132 t++;
133 if (t >= argc) {
134 return exit_with_help(settings, 1);
135 }
136 excludeSuffix = argv[t];
137 }
138 /* h */
139 if ((argflags & 1) > 0 || strcmp(argv[t], "--help") == 0) {
140 return exit_with_help(settings, 0);
141 }
142 /* r, R */
143 if ((argflags & 24) > 0) {
144 if (registerArgument(&checked, 24)) {
145 return exit_with_help(settings, 1);
146 }
147 settings->recursive = true;
148 }
149 /* m */
150 if ((argflags & 32) > 0) {
151 if (registerArgument(&checked, 32)) {
152 return exit_with_help(settings, 1);
153 }
154 settings->matchesOnly = true;
155 }
156 /* v */
157 if ((argflags & 64) > 0 || strcmp(argv[t], "--version") == 0) {
158 return exit_with_version(settings);
159 }
160 /* V */
161 if ((argflags & 128) > 0) {
162 if (registerArgument(&checked, 128)) {
163 return exit_with_help(settings, 1);
164 }
165 settings->verbose = false;
166 }
167 /* b */
168 if ((argflags & 256) > 0) {
169 if (!checkParamOpt(&paropt) || registerArgument(&checked, 256)) {
170 return exit_with_help(settings, 1);
171 }
172 t++;
173 if (t >= argc) {
174 return exit_with_help(settings, 1);
175 }
176 if (strcasecmp(argv[t], "ignore") == 0) {
177 settings->bfileHeuristics->level = BFILE_IGNORE;
178 } else if (strcasecmp(argv[t], "low") == 0) {
179 settings->bfileHeuristics->level = BFILE_LOW_ACCURACY;
180 } else if (strcasecmp(argv[t], "medium") == 0) {
181 settings->bfileHeuristics->level = BFILE_MEDIUM_ACCURACY;
182 } else if (strcasecmp(argv[t], "high") == 0) {
183 settings->bfileHeuristics->level = BFILE_HIGH_ACCURACY;
184 } else {
185 return exit_with_help(settings, 1);
186 }
187 }
188 /* e */
189 if ((argflags & 512) > 0) {
190 if (!checkParamOpt(&paropt) || t + 2 >= argc) {
191 return exit_with_help(settings, 1);
192 }
193 t++; add_string(settings->regex->pattern_list, argv[t]);
194 t++; add_string(settings->regex->pattern_list, argv[t]);
195 }
196 /* E */
197 if ((argflags & 1024) > 0) {
198 t++;
199 if (!checkParamOpt(&paropt) || t >= argc) {
200 return exit_with_help(settings, 1);
201 }
202 add_string(settings->regex->pattern_list, argv[t]);
203 add_string(settings->regex->pattern_list, "$");
204 }
205 if (argflags == 0) {
206 /* SHORTCUTS */
207 /* exclude-cstyle-comments */
208 if (strcmp(argv[t], "--exclude-cstyle-comments") == 0) {
209 add_string(settings->regex->pattern_list, "\\s*//");
210 add_string(settings->regex->pattern_list, "$");
211 add_string(settings->regex->pattern_list, "\\s*/\\*");
212 add_string(settings->regex->pattern_list, "\\*/\\s*");
213 }
214 /* Path */
215 else {
216 add_string(directories, argv[t]);
217 }
218 }
219 }
220
221 /* Configure output */
222 if (!settings->verbose) {
223 close_stdout();
224 }
225
226 /* Find tokens */
227 parseCSL(includeSuffix, settings->includeSuffixes);
228 parseCSL(excludeSuffix, settings->excludeSuffixes);
229
230 /* Scan directories */
231 if (regex_compile_all(settings->regex)) {
232 int lines = 0;
233 if (directories->count == 0) {
234 add_string(directories, ".");
235 }
236 for (int t = 0 ; t < directories->count ; t++) {
237 if (t > 0) {
238 for (int u = 0 ; u < 79 ; u++) {
239 printf("-");
240 }
241 printf("\n");
242 }
243 lines += scanDirectory((scanner_t){directories->items[t], 0}, settings);
244 }
245 destroy_string_list_t(directories);
246
247 /* Print double line and line count */
248 for (int t = 0 ; t < 79 ; t++) {
249 printf("=");
250 }
251 printf("\n%73d lines\n", lines);
252
253 if (settings->confusing_lnlen && settings->regex->pattern_list->count > 0) {
254 printf("\nSome files contain too long lines.\n"
255 "The regex parser currently supports a maximum line length of %d."
256 "\nThe result might be wrong.\n", REGEX_MAX_LINELENGTH);
257 }
258
259 if (!settings->verbose) {
260 reopen_stdout();
261 printf("%d", lines);
262 }
263 destroy_settings_t(settings);
264 }
265
266 fflush(stdout);
267 fflush(stderr);
268 return 0;
269 }

mercurial