Thu, 26 Jan 2012 15:55:52 +0100
added regexp_parser struct and compile function
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 <start> <end> - Excludes lines between <start> and <end>"
26 "\n You may use this option multiple times"
27 "\n -h, --help - this help text"
28 "\n -m - print information about matching files only"
29 "\n -s <suffixes> - only count files with these suffixes (separated"
30 "\n by commas)"
31 "\n -S <suffixes> - count any file except those with these suffixes"
32 "\n (separated by commas)"
33 "\n -r, -R - includes subdirectories"
34 "\n -v, --version - print out version information"
35 "\n -V - turn verbose output off, print the result only"
36 "\n\n"
37 "The default call without any options is:"
38 "\n cline ./\n"
39 "So each file in the working directory is counted. If you want to count C"
40 "\nsource code in your working directory and its subdirectories, type:"
41 "\n cline -rs .c\n"
42 "\nIf you want to exclude comment lines, you may use the -e option."
43 "\nAfter a line matches the regex pattern <start> any following line is"
44 "\nnot counted unless a line matches the <end> pattern.";
46 printf(helpText);
47 }
49 int exit_with_version(settings_t* settings) {
50 printf("cline - Revision: %s", VERSION);
51 destroy_settings_t(settings);
52 return 0;
53 }
55 int exit_with_help(settings_t* settings, int code) {
56 printHelpText();
57 destroy_settings_t(settings);
58 return code;
59 }
61 int main(int argc, char** argv) {
63 /* Settings */
64 settings_t *settings = new_settings_t();
65 if (settings == NULL) {
66 fprintf(stderr, "Memory allocation failed.\n");
67 return 1;
68 }
70 /* Get arguments */
71 char* directory = "./";
72 char* suffix = " ";
73 int checked = 0;
75 for (int t = 1 ; t < argc ; t++) {
77 int argflags = checkArgument(argv[t], "hsSrRmvVbe");
79 /* s, S */
80 if ((argflags & 6) > 0) {
81 if (registerArgument(&checked, 6)) {
82 return exit_with_help(settings, 1);
83 }
84 settings->includeSuffixes = (argflags & 2) > 0;
85 t++;
86 if (t >= argc) {
87 return exit_with_help(settings, 1);
88 }
89 suffix = argv[t];
90 }
91 /* h */
92 if ((argflags & 1) > 0 || strcmp(argv[t], "--help") == 0) {
93 return exit_with_help(settings, 0);
94 }
95 /* r, R */
96 if ((argflags & 24) > 0) {
97 if (registerArgument(&checked, 24)) {
98 return exit_with_help(settings, 1);
99 }
100 settings->recursive = true;
101 }
102 /* m */
103 if ((argflags & 32) > 0) {
104 if (registerArgument(&checked, 32)) {
105 return exit_with_help(settings, 1);
106 }
107 settings->matchesOnly = true;
108 }
109 /* v */
110 if ((argflags & 64) > 0 || strcmp(argv[t], "--version") == 0) {
111 return exit_with_version(settings);
112 }
113 /* V */
114 if ((argflags & 128) > 0) {
115 if (registerArgument(&checked, 128)) {
116 return exit_with_help(settings, 1);
117 }
118 settings->verbose = false;
119 }
120 /* b */
121 if ((argflags & 256) > 0) {
122 if (registerArgument(&checked, 256)) {
123 return exit_with_help(settings, 1);
124 }
125 t++;
126 if (t >= argc) {
127 return exit_with_help(settings, 1);
128 }
129 if (strcasecmp(argv[t], "ignore") == 0) {
130 settings->bfileHeuristics->level = BFILE_IGNORE;
131 } else if (strcasecmp(argv[t], "low") == 0) {
132 settings->bfileHeuristics->level = BFILE_LOW_ACCURACY;
133 } else if (strcasecmp(argv[t], "medium") == 0) {
134 settings->bfileHeuristics->level = BFILE_MEDIUM_ACCURACY;
135 } else if (strcasecmp(argv[t], "high") == 0) {
136 settings->bfileHeuristics->level = BFILE_HIGH_ACCURACY;
137 } else {
138 return exit_with_help(settings, 1);
139 }
140 }
141 if ((argflags & 512) > 0) {
142 if (t + 2 >= argc) {
143 return exit_with_help(settings, 1);
144 }
145 t++; add_string(settings->regex->pattern_list, argv[t]);
146 t++; add_string(settings->regex->pattern_list, argv[t]);
147 }
148 /* Path */
149 if (argflags == 0) {
150 if (registerArgument(&checked, 1024)) {
151 return exit_with_help(settings, 1);
152 }
153 directory = argv[t];
154 }
155 }
157 /* Configure output */
158 if (!settings->verbose) {
159 close_stdout();
160 }
162 /* Find tokens */
163 char* finder = strtok(suffix, ",");
164 while (finder != NULL) {
165 add_string(settings->suffixList, finder);
166 finder = strtok(NULL, ",");
167 }
169 /* Scan directory */
170 regex_compile_all(settings->regex);
171 int lines = scanDirectory((scanner_t){directory, 0}, settings);
172 destroy_settings_t(settings);
174 /* Print double line and line count */
175 for (int t = 0 ; t < 79 ; t++) {
176 printf("=");
177 }
178 printf("\n%73d lines\n", lines);
180 if (settings->confusing_lnlen && settings->regex->pattern_list->count > 0) {
181 printf("\nSome files contain too long lines.\n"
182 "The regex parser currently supports a maximum line length of %d."
183 "\nThe result might be wrong.\n", REGEX_MAX_LINELENGTH);
184 }
186 if (!settings->verbose) {
187 reopen_stdout();
188 printf("%d", lines);
189 }
191 fflush(stdout);
192 return 0;
193 }