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