27 |
27 |
28 #include "scanner.h" |
28 #include "scanner.h" |
29 #include "bfile_heuristics.h" |
29 #include "bfile_heuristics.h" |
30 #include "regex_parser.h" |
30 #include "regex_parser.h" |
31 #include <sys/stat.h> |
31 #include <sys/stat.h> |
|
32 #include <ctype.h> |
32 |
33 |
33 typedef struct filelist filelist_t; |
34 typedef struct filelist filelist_t; |
34 |
35 |
35 struct filelist { |
36 struct filelist { |
36 char *displayname; |
37 char *displayname; |
37 int displayname_len; |
38 unsigned displayname_len; |
38 char *filename; |
39 char *filename; |
39 char *ext; |
40 char *ext; |
40 int st_mode; |
41 unsigned st_mode; |
41 filelist_t *next; |
42 filelist_t *next; |
42 }; |
43 }; |
43 |
44 |
44 static bool testSuffix(char* filename, string_list_t* list) { |
45 static bool testSuffix(char* filename, string_list_t* list) { |
45 bool ret = false; |
46 bool ret = false; |
46 int tokenlen, fnamelen = strlen(filename); |
47 size_t tokenlen, fnamelen = strlen(filename); |
47 for (int t = 0 ; t < list->count ; t++) { |
48 for (size_t t = 0 ; t < list->count ; t++) { |
48 tokenlen = strlen(list->items[t]); |
49 tokenlen = strlen(list->items[t]); |
49 if (fnamelen >= tokenlen && tokenlen > 0) { |
50 if (fnamelen >= tokenlen && tokenlen > 0) { |
50 if (strncmp(filename+fnamelen-tokenlen, |
51 if (strncmp(filename+fnamelen-tokenlen, |
51 list->items[t], tokenlen) == 0) { |
52 list->items[t], tokenlen) == 0) { |
52 ret = true; |
53 ret = true; |
55 } |
56 } |
56 } |
57 } |
57 return ret; |
58 return ret; |
58 } |
59 } |
59 |
60 |
60 static void addLinesPerExtension(scanresult_ext_t* result, |
61 static void addResultPerExtension(scanresult_ext_t* result, |
61 char* ext, int lines) { |
62 char* ext, unsigned value) { |
62 if (!result) return; |
63 if (!result) return; |
63 |
64 |
64 if (!ext) ext = "w/o"; |
65 if (!ext) ext = "w/o"; |
65 |
66 |
66 for (int i = 0 ; i < result->count ; i++) { |
67 for (unsigned i = 0 ; i < result->count ; i++) { |
67 if (strcasecmp(result->extensions[i], ext) == 0) { |
68 if (strcasecmp(result->extensions[i], ext) == 0) { |
68 result->lines[i] += lines; |
69 result->result[i] += value; |
69 return; |
70 return; |
70 } |
71 } |
71 } |
72 } |
72 |
73 |
73 if (result->count == result->capacity) { |
74 if (result->count == result->capacity) { |
74 int newcap = result->capacity+8; |
75 unsigned newcap = result->capacity+8; |
75 char** extarr = realloc(result->extensions, newcap*sizeof(char*)); |
76 char** extarr = realloc(result->extensions, newcap*sizeof(char*)); |
76 int* linesarr = realloc(result->lines, newcap*sizeof(int)); |
77 unsigned* resultarr = realloc(result->result, newcap*sizeof(unsigned)); |
77 if (!extarr || !linesarr) { |
78 if (!extarr || !resultarr) { |
78 fprintf(stderr, "Memory allocation error.\n"); |
79 fprintf(stderr, "Memory allocation error.\n"); |
79 abort(); |
80 abort(); |
80 } |
81 } |
81 result->extensions = extarr; |
82 result->extensions = extarr; |
82 result->lines = linesarr; |
83 result->result = resultarr; |
83 result->capacity = newcap; |
84 result->capacity = newcap; |
84 } |
85 } |
85 |
86 |
86 result->extensions[result->count] = strdup(ext); |
87 result->extensions[result->count] = strdup(ext); |
87 result->lines[result->count] = lines; |
88 result->result[result->count] = value; |
88 result->count++; |
89 result->count++; |
89 } |
90 } |
90 |
91 |
91 scanresult_t* new_scanresult_t(settings_t* settings) { |
92 scanresult_t* new_scanresult_t(settings_t* settings) { |
92 scanresult_t* result = calloc(1, sizeof(scanresult_t)); |
93 scanresult_t* result = calloc(1, sizeof(scanresult_t)); |
204 scanresult_t recresult; |
204 scanresult_t recresult; |
205 recresult.ext = result->ext; |
205 recresult.ext = result->ext; |
206 scanDirectory( |
206 scanDirectory( |
207 (scanner_t) {filelist->filename, scanner.spaces+1}, |
207 (scanner_t) {filelist->filename, scanner.spaces+1}, |
208 settings, recoutput, &recresult); |
208 settings, recoutput, &recresult); |
209 result->lines += recresult.lines; |
209 result->result += recresult.result; |
210 if (!settings->matchesOnly || recoutput->count > 0) { |
210 if (!settings->matchesOnly || recoutput->count > 0) { |
211 outbuf = (char*) malloc(81); |
211 outbuf = (char*) malloc(81); |
212 snprintf(outbuf, 81, "%*s/%*s%13d lines\n", |
212 snprintf(outbuf, 81, "%*s/%*s%13u %s\n", |
213 filelist->displayname_len+scanner.spaces, filelist->displayname, |
213 filelist->displayname_len+scanner.spaces, filelist->displayname, |
214 60-filelist->displayname_len-scanner.spaces-1, "", |
214 60-filelist->displayname_len-scanner.spaces-1, "", |
215 recresult.lines); |
215 recresult.result, result_type); |
216 add_string(output, outbuf); |
216 add_string(output, outbuf); |
217 for (int i = 0 ; i < recoutput->count ; i++) { |
217 for (unsigned i = 0 ; i < recoutput->count ; i++) { |
218 add_string(output, recoutput->items[i]); |
218 add_string(output, recoutput->items[i]); |
219 } |
219 } |
220 } |
220 } |
221 destroy_string_list_t(recoutput); |
221 destroy_string_list_t(recoutput); |
222 } else { |
222 } else { |
223 outbuf = (char*) malloc(81); |
223 outbuf = (char*) malloc(81); |
224 snprintf(outbuf, 81, "%*s\n", filelist->displayname_len+scanner.spaces, |
224 snprintf(outbuf, 81, "%*s\n", |
225 filelist->displayname); |
225 filelist->displayname_len+scanner.spaces, |
|
226 filelist->displayname); |
226 add_string(output, outbuf); |
227 add_string(output, outbuf); |
227 } |
228 } |
228 } else { |
229 } else { |
229 if ((settings->includeSuffixes->count == 0 |
230 if ((settings->includeSuffixes->count == 0 |
230 || testSuffix(filelist->displayname, settings->includeSuffixes)) |
231 || testSuffix(filelist->displayname, settings->includeSuffixes)) |
231 && !testSuffix(filelist->displayname, settings->excludeSuffixes)) { |
232 && !testSuffix(filelist->displayname, settings->excludeSuffixes)) { |
232 |
233 |
233 /* Count lines */ |
234 /* Count */ |
234 int lines = 0; |
235 unsigned res_value = 0; |
235 bfile = false; |
236 bfile = false; |
236 bfile_reset(settings->bfileHeuristics); |
237 bfile_reset(settings->bfileHeuristics); |
237 regex_parser_reset(settings->regex); |
238 regex_parser_reset(settings->regex); |
238 char line_buffer[REGEX_MAX_LINELENGTH]; |
239 char line_buffer[MAX_LINELENGTH]; |
239 int line_buffer_offset = 0; |
240 unsigned line_buffer_pos = 0; |
240 |
241 |
241 FILE *file = fopen(filelist->filename, "r"); |
242 FILE *file = fopen(filelist->filename, "r"); |
242 if (file == NULL) { |
243 if (file == NULL) { |
243 outbuf = (char*) malloc(81); |
244 outbuf = (char*) malloc(81); |
244 snprintf(outbuf, 81, "%*s", filelist->displayname_len+scanner.spaces, |
245 snprintf(outbuf, 81, "%*s", |
245 filelist->displayname); |
246 filelist->displayname_len+scanner.spaces, |
|
247 filelist->displayname); |
246 add_string(output, outbuf); |
248 add_string(output, outbuf); |
247 perror(" File acces failed"); |
249 perror(" File acces failed"); |
248 } else { |
250 } else { |
|
251 int a; |
249 do { |
252 do { |
250 a = fgetc(file); |
253 a = fgetc(file); |
251 |
254 |
252 bfile = bfile_check(settings->bfileHeuristics, a); |
255 bfile = bfile_check(settings->bfileHeuristics, a); |
253 |
256 |
|
257 /* ignore carriage return completely */ |
|
258 if (a == 13) continue; |
|
259 |
254 if (a == 10 || a == EOF) { |
260 if (a == 10 || a == EOF) { |
255 line_buffer[line_buffer_offset] = 0; |
261 line_buffer[line_buffer_pos] = 0; |
256 if (regex_parser_do(settings->regex, line_buffer) == 0) { |
262 if (regex_parser_do(settings->regex, line_buffer) == 0) { |
257 /* Only subtract lines when matching has finished */ |
263 /* Subtract excluded lines/chars when matching has finished */ |
258 if (!regex_parser_matching(settings->regex)) { |
264 if (!regex_parser_matching(settings->regex)) { |
259 lines -= settings->regex->matched_lines; |
265 res_value -= settings->regex->matched_counted; |
260 } |
266 } |
261 } |
267 } |
262 |
268 |
263 line_buffer_offset = 0; |
269 if (settings->count_chars) { |
264 lines++; |
270 for (size_t i = 0 ; i < line_buffer_pos ; i++) { |
|
271 if (!isspace(line_buffer[i])) res_value++; |
|
272 } |
|
273 } else { |
|
274 res_value++; |
|
275 } |
|
276 line_buffer_pos = 0; |
265 } else { |
277 } else { |
266 if (line_buffer_offset < REGEX_MAX_LINELENGTH) { |
278 if (line_buffer_pos < MAX_LINELENGTH) { |
267 line_buffer[line_buffer_offset] = a; |
279 line_buffer[line_buffer_pos] = (char) a; |
268 line_buffer_offset++; |
280 line_buffer_pos++; |
269 } else { |
281 } else { |
270 line_buffer[line_buffer_offset-1] = 0; |
282 line_buffer[line_buffer_pos - 1] = 0; |
271 settings->confusing_lnlen = true; |
283 settings->confusing_lnlen = true; |
272 } |
284 } |
273 } |
285 } |
274 } while (!bfile && a != EOF); |
286 } while (!bfile && a != EOF); |
275 fclose(file); |
287 fclose(file); |
283 filelist->displayname, |
295 filelist->displayname, |
284 60-filelist->displayname_len-scanner.spaces, "", "binary"); |
296 60-filelist->displayname_len-scanner.spaces, "", "binary"); |
285 add_string(output, outbuf); |
297 add_string(output, outbuf); |
286 } |
298 } |
287 } else { |
299 } else { |
288 addLinesPerExtension(result->ext, filelist->ext, lines); |
300 addResultPerExtension(result->ext, filelist->ext, res_value); |
289 result->lines += lines; |
301 result->result += res_value; |
290 outbuf = (char*) malloc(81); |
302 outbuf = (char*) malloc(81); |
291 snprintf(outbuf, 81, "%*s%*s%13d lines\n", |
303 snprintf(outbuf, 81, "%*s%*s%13u %s\n", |
292 filelist->displayname_len+scanner.spaces, filelist->displayname, |
304 filelist->displayname_len+scanner.spaces, |
293 60-filelist->displayname_len-scanner.spaces, "", lines); |
305 filelist->displayname, |
|
306 60-filelist->displayname_len-scanner.spaces, |
|
307 "", |
|
308 res_value, |
|
309 result_type |
|
310 ); |
294 add_string(output, outbuf); |
311 add_string(output, outbuf); |
295 } |
312 } |
296 } |
313 } |
297 } else { |
314 } else { |
298 if (!settings->matchesOnly) { |
315 if (!settings->matchesOnly) { |