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