Mon, 23 May 2011 16:42:44 +0200
cline project init
0 | 1 | #include <stdio.h> |
2 | #include <string.h> | |
3 | #include <stdbool.h> | |
4 | #include <stdlib.h> | |
5 | #include <dirent.h> | |
6 | ||
7 | static int suffixc; | |
8 | static char** suffixv; | |
9 | static bool recursive; | |
10 | static bool includeSuffixes; | |
11 | ||
12 | bool testSuffix(char* filename) | |
13 | { | |
14 | bool ret = false; | |
15 | int tokenlen, fnamelen = strlen(filename); | |
16 | for (int t = 0 ; t < suffixc ; t++) | |
17 | { | |
18 | tokenlen = strlen(suffixv[t]); | |
19 | if (fnamelen >= tokenlen) | |
20 | { | |
21 | if (strncmp(filename+fnamelen-tokenlen, suffixv[t], tokenlen) == 0) | |
22 | { | |
23 | ret = true; | |
24 | break; | |
25 | } | |
26 | } | |
27 | } | |
28 | return ret ^ !includeSuffixes; | |
29 | } | |
30 | ||
31 | int scanDirectory(DIR *dir, const int spaces, char* currdir) | |
32 | { | |
33 | DIR *subdir; | |
34 | char* subdirname; | |
35 | struct dirent *entry; | |
36 | int lines, digits, a; | |
37 | int lineSum = 0; | |
38 | ||
39 | while ((entry = readdir(dir)) != NULL) | |
40 | { | |
41 | if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) | |
42 | { | |
43 | // Print occurence | |
44 | char entryname[strlen(entry->d_name)+spaces]; | |
45 | for (int t = 0 ; t < spaces ; t++) | |
46 | { | |
47 | entryname[t]=' '; | |
48 | } | |
49 | entryname[spaces] = 0; | |
50 | strcat(entryname, entry->d_name); | |
51 | printf("%-60s", entryname); | |
52 | ||
53 | // Check for subdirectory | |
54 | char subdirname[(1+strlen(currdir)+strlen(entry->d_name))]; | |
55 | strcpy(subdirname, currdir); | |
56 | strcat(subdirname, "/"); | |
57 | strcat(subdirname, entry->d_name); | |
58 | if ((subdir = opendir(subdirname)) != NULL) | |
59 | { | |
60 | printf("\n"); | |
61 | if (recursive) | |
62 | { | |
63 | lineSum += scanDirectory(subdir, spaces+1, subdirname); | |
64 | } | |
65 | closedir(subdir); | |
66 | continue; | |
67 | } | |
68 | ||
69 | // Count lines | |
70 | lines = 0; | |
71 | char filename[(1+strlen(currdir)+strlen(entry->d_name))]; | |
72 | strcpy(filename, currdir); | |
73 | strcat(filename, "/"); | |
74 | strcat(filename, entry->d_name); | |
75 | if (testSuffix(filename)) | |
76 | { | |
77 | FILE *file = fopen(filename, "r"); | |
78 | if (file == NULL) | |
79 | { | |
80 | perror(" File acces failed"); | |
81 | continue; | |
82 | } | |
83 | ||
84 | do | |
85 | { | |
86 | a = fgetc(file); | |
87 | ||
88 | if (a == 10) | |
89 | { | |
90 | lines++; | |
91 | } | |
92 | } while (a != EOF); | |
93 | fclose(file); | |
94 | ||
95 | // Print line count | |
96 | printf("%14d lines\n", lines); | |
97 | ||
98 | lineSum += lines; | |
99 | } | |
100 | else | |
101 | { | |
102 | // Print hint | |
103 | printf("%20s\n", "no match"); | |
104 | } | |
105 | } | |
106 | } | |
107 | return lineSum; | |
108 | } | |
109 | ||
110 | int main(int argc, char** argv) | |
111 | { | |
112 | // Help text | |
113 | const char* helpText = | |
114 | "\nUsage:\n%s [-h|--help|(-s=<suffix>|-S=<suffix>)|(-r|-R)|<directory>]" | |
115 | "\n\nCounts the line terminator characters (\\n) within all" | |
116 | " files in the specified\ndirectory." | |
117 | "\n\nOptions:" | |
118 | "\n -h, --help - this help text" | |
119 | "\n -s=<suffixes> - only count files with these suffixes (separated" | |
120 | "\n by commas)" | |
121 | "\n -S=<suffixes> - count any file except those with these suffixes" | |
122 | "\n (separated by commas)" | |
123 | "\n -R - excludes subdirectories" | |
124 | "\n -r - includes subdirecotires" | |
125 | "\n\n" | |
126 | "The default call without any options is:" | |
127 | "\n %s -r ./ -S=\n" | |
128 | "That means each file in each subdirectory is counted. If you want to count" | |
129 | "\nC source code in your working directory and its subdirectories, type:" | |
130 | "\n %s -s=.c\n"; | |
131 | ||
132 | // Program name | |
133 | char* prgName = strrchr(argv[0], '/'); | |
134 | if (prgName == NULL) | |
135 | { | |
136 | prgName = argv[0]; | |
137 | } | |
138 | else | |
139 | { | |
140 | prgName++; | |
141 | } | |
142 | ||
143 | // Defaults | |
144 | char* _suffix = ""; | |
145 | char* _directory = "./"; | |
146 | ||
147 | // Get arguments | |
148 | char* directory; | |
149 | char* suffix; | |
150 | bool showHelp = false; | |
151 | recursive = true; | |
152 | includeSuffixes = false; | |
153 | char checked = 0; | |
154 | ||
155 | for (int t = 1 ; t < argc ; t++) | |
156 | { | |
157 | if (strncmp(argv[t], "-s=", 3) == 0) | |
158 | { | |
159 | if ((checked & 1) > 0) | |
160 | { | |
161 | printf(helpText, prgName, prgName, prgName); | |
162 | return -1; | |
163 | } | |
164 | includeSuffixes = true; | |
165 | suffix = argv[t]+3; | |
166 | checked |= 1; | |
167 | } | |
168 | else if (strncmp(argv[t], "-S=", 3) == 0) | |
169 | { | |
170 | if ((checked & 1) > 0) | |
171 | { | |
172 | printf(helpText, prgName, prgName, prgName); | |
173 | return -1; | |
174 | } | |
175 | includeSuffixes = false; | |
176 | suffix = argv[t]+3; | |
177 | checked |= 1; | |
178 | } | |
179 | else if (strcmp(argv[t], "-h") == 0 || strcmp(argv[t], "--help") == 0) | |
180 | { | |
181 | if ((checked & 2) > 0) | |
182 | { | |
183 | printf(helpText, prgName, prgName, prgName); | |
184 | return -1; | |
185 | } | |
186 | checked |= 2; | |
187 | showHelp = true; | |
188 | } | |
189 | else if (strcmp(argv[t], "-r") == 0) | |
190 | { | |
191 | if ((checked & 4) > 0) | |
192 | { | |
193 | printf(helpText, prgName, prgName, prgName); | |
194 | return -1; | |
195 | } | |
196 | checked |= 4; | |
197 | recursive = true; | |
198 | } | |
199 | else if (strcmp(argv[t], "-R") == 0) | |
200 | { | |
201 | if ((checked & 4) > 0) | |
202 | { | |
203 | printf(helpText, prgName, prgName, prgName); | |
204 | return -1; | |
205 | } | |
206 | checked |= 4; | |
207 | recursive = false; | |
208 | } | |
209 | else | |
210 | { | |
211 | if ((checked & 8) > 0) | |
212 | { | |
213 | printf(helpText, prgName, prgName, prgName); | |
214 | return -1; | |
215 | } | |
216 | checked |= 8; | |
217 | directory = argv[t]; | |
218 | } | |
219 | } | |
220 | ||
221 | // Show help and quit | |
222 | if (showHelp) | |
223 | { | |
224 | printf(helpText, prgName, prgName, prgName); | |
225 | return 0; | |
226 | } | |
227 | ||
228 | // Default values | |
229 | if ((checked & 1) == 0) | |
230 | { | |
231 | suffix = _suffix; | |
232 | } | |
233 | ||
234 | if ((checked & 8) == 0) | |
235 | { | |
236 | directory = _directory; | |
237 | } | |
238 | ||
239 | // Find tokens | |
240 | char* finder; | |
241 | suffixc = 1; | |
242 | finder = strchr(suffix, ','); | |
243 | while (finder != NULL) | |
244 | { | |
245 | suffixc++; | |
246 | finder = strchr(finder+1, ','); | |
247 | } | |
248 | suffixv = (char**) malloc(sizeof(suffixv)*suffixc); | |
249 | if (suffixv == NULL) | |
250 | { | |
251 | fprintf(stderr, "Memory allocation failed.\n"); | |
252 | return 1; | |
253 | } | |
254 | finder = strtok(suffix, ","); | |
255 | int c = 0; | |
256 | while (finder != NULL) | |
257 | { | |
258 | suffixv[c] = finder; | |
259 | c++; | |
260 | finder = strtok(NULL, ","); | |
261 | } | |
262 | ||
263 | // Open directory | |
264 | DIR *dir = opendir(directory); | |
265 | if (dir == NULL) | |
266 | { | |
267 | perror("Operation failed"); | |
268 | free(suffixv); | |
269 | return 1; | |
270 | } | |
271 | ||
272 | // Scan directory | |
273 | int lines = scanDirectory(dir, 0, directory); | |
274 | ||
275 | // Print double line and line count | |
276 | for (int t = 0 ; t < 80 ; t++) | |
277 | { | |
278 | printf("="); | |
279 | } | |
280 | printf("\n%74d lines\n", lines); | |
281 | ||
282 | closedir(dir); | |
283 | free(suffixv); | |
284 | return 0; | |
285 | } |