Tue, 28 Aug 2012 16:44:32 +0200
changed version output slightly
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\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";
55 printf(helpText);
56 }
58 int exit_with_version(settings_t* settings) {
59 printf("cline - Revision: %s\n", VERSION);
60 destroy_settings_t(settings);
61 return 0;
62 }
64 int exit_with_help(settings_t* settings, int code) {
65 printHelpText();
66 destroy_settings_t(settings);
67 return code;
68 }
70 int main(int argc, char** argv) {
72 /* Settings */
73 settings_t *settings = new_settings_t();
74 if (settings == NULL) {
75 fprintf(stderr, "Memory allocation failed.\n");
76 return 1;
77 }
79 /* Get arguments */
80 char* directory = "./";
81 char* includeSuffix = NULL;
82 char* excludeSuffix = NULL;
83 int checked = 0;
85 for (int t = 1 ; t < argc ; t++) {
87 int argflags = checkArgument(argv[t], "hsSrRmvVbeE");
88 int paropt = 0;
90 /* s */
91 if ((argflags & 2) > 0) {
92 if (!checkParamOpt(&paropt) || registerArgument(&checked, 2)) {
93 return exit_with_help(settings, 1);
94 }
95 t++;
96 if (t >= argc) {
97 return exit_with_help(settings, 1);
98 }
99 includeSuffix = argv[t];
100 }
101 /* S */
102 if ((argflags & 4) > 0) {
103 if (!checkParamOpt(&paropt) || registerArgument(&checked, 4)) {
104 return exit_with_help(settings, 1);
105 }
106 t++;
107 if (t >= argc) {
108 return exit_with_help(settings, 1);
109 }
110 excludeSuffix = argv[t];
111 }
112 /* h */
113 if ((argflags & 1) > 0 || strcmp(argv[t], "--help") == 0) {
114 return exit_with_help(settings, 0);
115 }
116 /* r, R */
117 if ((argflags & 24) > 0) {
118 if (registerArgument(&checked, 24)) {
119 return exit_with_help(settings, 1);
120 }
121 settings->recursive = true;
122 }
123 /* m */
124 if ((argflags & 32) > 0) {
125 if (registerArgument(&checked, 32)) {
126 return exit_with_help(settings, 1);
127 }
128 settings->matchesOnly = true;
129 }
130 /* v */
131 if ((argflags & 64) > 0 || strcmp(argv[t], "--version") == 0) {
132 return exit_with_version(settings);
133 }
134 /* V */
135 if ((argflags & 128) > 0) {
136 if (registerArgument(&checked, 128)) {
137 return exit_with_help(settings, 1);
138 }
139 settings->verbose = false;
140 }
141 /* b */
142 if ((argflags & 256) > 0) {
143 if (!checkParamOpt(&paropt) || registerArgument(&checked, 256)) {
144 return exit_with_help(settings, 1);
145 }
146 t++;
147 if (t >= argc) {
148 return exit_with_help(settings, 1);
149 }
150 if (strcasecmp(argv[t], "ignore") == 0) {
151 settings->bfileHeuristics->level = BFILE_IGNORE;
152 } else if (strcasecmp(argv[t], "low") == 0) {
153 settings->bfileHeuristics->level = BFILE_LOW_ACCURACY;
154 } else if (strcasecmp(argv[t], "medium") == 0) {
155 settings->bfileHeuristics->level = BFILE_MEDIUM_ACCURACY;
156 } else if (strcasecmp(argv[t], "high") == 0) {
157 settings->bfileHeuristics->level = BFILE_HIGH_ACCURACY;
158 } else {
159 return exit_with_help(settings, 1);
160 }
161 }
162 /* e */
163 if ((argflags & 512) > 0) {
164 if (!checkParamOpt(&paropt) || t + 2 >= argc) {
165 return exit_with_help(settings, 1);
166 }
167 t++; add_string(settings->regex->pattern_list, argv[t]);
168 t++; add_string(settings->regex->pattern_list, argv[t]);
169 }
170 /* E */
171 if ((argflags & 1024) > 0) {
172 t++;
173 if (!checkParamOpt(&paropt) || t >= argc) {
174 return exit_with_help(settings, 1);
175 }
176 add_string(settings->regex->pattern_list, argv[t]);
177 add_string(settings->regex->pattern_list, "$");
178 }
179 if (argflags == 0) {
180 /* SHORTCUTS */
181 /* exclude-cstyle-comments */
182 if (strcmp(argv[t], "--exclude-cstyle-comments") == 0) {
183 add_string(settings->regex->pattern_list, "\\s*//");
184 add_string(settings->regex->pattern_list, "$");
185 add_string(settings->regex->pattern_list, "\\s*/\\*");
186 add_string(settings->regex->pattern_list, "\\*/\\s*");
187 }
188 /* Path */
189 else if (registerArgument(&checked, 1024)) {
190 return exit_with_help(settings, 1);
191 }
192 directory = argv[t];
193 }
194 }
196 /* Configure output */
197 if (!settings->verbose) {
198 close_stdout();
199 }
201 /* Find tokens */
202 parseCSL(includeSuffix, settings->includeSuffixes);
203 parseCSL(excludeSuffix, settings->excludeSuffixes);
205 /* Scan directory */
206 if (regex_compile_all(settings->regex)) {
207 int lines = scanDirectory((scanner_t){directory, 0}, settings);
208 destroy_settings_t(settings);
210 /* Print double line and line count */
211 for (int t = 0 ; t < 79 ; t++) {
212 printf("=");
213 }
214 printf("\n%73d lines\n", lines);
216 if (settings->confusing_lnlen && settings->regex->pattern_list->count > 0) {
217 printf("\nSome files contain too long lines.\n"
218 "The regex parser currently supports a maximum line length of %d."
219 "\nThe result might be wrong.\n", REGEX_MAX_LINELENGTH);
220 }
222 if (!settings->verbose) {
223 reopen_stdout();
224 printf("%d", lines);
225 }
226 }
228 fflush(stdout);
229 fflush(stderr);
230 return 0;
231 }