HuntnGather – Blame information for rev 38

Subversion Repositories:
Rev:
Rev Author Line No. Line
33 office 1 ///////////////////////////////////////////////////////////////////////////
2 // Copyright (C) 2021 Wizardry and Steamworks - License: MIT //
3 ///////////////////////////////////////////////////////////////////////////
4  
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
38 office 8 #include <ctype.h>
33 office 9 #if !defined ___AmigaOS___
10 #include <dirent.h>
11 #include <sys/stat.h>
12 #include <signal.h>
13 #endif
14  
15 #include <sys/types.h>
16 #include <sys/syslimits.h>
17  
18 #if defined ___AmigaOS___
19 #include <proto/dos.h>
20 #include <proto/exec.h>
21 #include <proto/locale.h>
22 #include <clib/utility_protos.h>
23 #endif
24  
25 #if defined ___AsyncIO___
26 #include <asyncio.h>
27 #endif
28  
29 #include "/shared/utilities.h"
30  
31 /*
32 *
33 * Returns largest of strings.
34 */
35 #if defined ___AmigaOS___
36 LONG StringLenMax(char *a, char *b) {
37 LONG p = strlen(a);
38 LONG q = strlen(b);
39 #else
40 int StrlenMax(char *a, char *b) {
41 int q = strlen(a);
38 office 42 int p = strlen(b);
33 office 43 #endif
44 return p > q ? p : q;
45 }
46  
47 /*
48 *
37 office 49 * Returns largest of strings.
50 */
51 #if defined ___AmigaOS___
52 LONG StringLenMin(char *a, char *b) {
53 LONG p = strlen(a);
54 LONG q = strlen(b);
55 #else
38 office 56 int StrlenMin(char *a, char *b) {
37 office 57 int q = strlen(a);
38 office 58 int p = strlen(b);
37 office 59 #endif
60 return p > q ? q : p;
61 }
62  
63 /*
64 *
33 office 65 * Converts a string to case.
66 */
67 void StrUpr(char *s) {
68 while(*s != '\0') {
69 #if defined ___AmigaOS___
70 *s = ToUpper(*s);
71 #else
72 *s = toupper((unsigned char)*s);
73 #endif
74 ++s;
75 }
76 }
77  
78 /*
79 *
80 * Gets the filesystem type of a file or directory.
81 */
82 FS_TYPE GetFsType(char *path) {
83 #if defined ___AmigaOS___
84 struct FileInfoBlock *FIB;
85 BPTR lock;
86 #else
87 struct stat dirStat;
88 #endif
89  
90 #if defined ___AmigaOS___
91 if((lock = Lock(path, ACCESS_READ)) == NULL) {
92 fprintf(stderr, "Lock failed for path '%s'.\n", path);
93 return UNKNOWN;
94 }
95  
96 if((FIB = AllocDosObject(DOS_FIB, NULL)) == NULL) {
97 fprintf(stderr, "Could not allocated file information block for path '%s'.\n", path);
98 UnLock(lock);
99 return UNKNOWN;
100 }
101  
102 if(Examine(lock, FIB) == FALSE) {
103 fprintf(stderr, "Path '%s' could not be examined.\n", path);
104 UnLock(lock);
105 FreeDosObject(DOS_FIB, FIB);
38 office 106 FIB = NULL;
33 office 107 return UNKNOWN;
108 }
109  
110 if(FIB->fib_DirEntryType < 0) {
111 UnLock(lock);
112 FreeDosObject(DOS_FIB, FIB);
38 office 113 FIB = NULL;
33 office 114 return REGULAR;
115 #else
116 stat(path, &dirStat);
117 if(!S_ISDIR(dirStat.st_mode)) {
118 return REGULAR;
119 #endif
120 }
121  
122 #if defined ___AmigaOS___
123 UnLock(lock);
124 FreeDosObject(DOS_FIB, FIB);
38 office 125 FIB = NULL;
33 office 126 #endif
127  
128 return DIRECTORY;
129 }
130  
131 /*
132 *
133 * Counts the lines of a file.
134 */
135 int CountFileLines(char *dbFile) {
136 #if defined ___AsyncIO___
137 struct AsyncFile *fp;
138 LONG c;
139 #else
140 FILE *fp;
141 char c;
142 #endif
143 int lines;
144  
145 #if defined ___AsyncIO___
146 if((fp = OpenAsync(dbFile, MODE_READ, ASYNC_BUF)) == NULL) {
147 #else
148 if((fp = fopen(dbFile, "r")) == NULL) {
149 #endif
150 fprintf(stderr, "Could not open file '%s' for reading.\n", dbFile);
151 return -1;
152 }
153  
154 lines = 0;
155 if(PROGRAM_VERBOSE) {
156 fprintf(stdout, "Counting lines in '%s'...\r", dbFile);
157 }
158  
159 #if defined ___AsyncIO___
160 while(PROGRAM_RUN && (c = ReadCharAsync(fp)) != -1) {
161 #else
38 office 162 while(PROGRAM_RUN && fscanf(fp, "%c", &c) == 1) {
33 office 163 #endif
164 #if defined ___AmigaOS___
165 // Check if CTRL+C was pressed and abort the program.
166 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
167 PROGRAM_RUN = FALSE;
168 continue;
169 }
170 #endif
171 switch(c) {
172 case '\n':
173 ++lines;
174  
175 if(PROGRAM_VERBOSE) {
176 fprintf(stdout, "Counting lines in '%s': %d.\r", dbFile, lines);
177 }
178 break;
179 }
180 }
181  
182 #if defined ___AsyncIO___
183 CloseAsync(fp);
184 #else
185 fclose(fp);
186 #endif
187  
188 if(PROGRAM_VERBOSE) {
189 fprintf(stdout, "\n");
190 }
191  
192 return lines;
193 }
194  
195 /*
196 *
197 * Gets the absolute path to file by name.
198 */
199 char *PathToAbsolute(char *path) {
200 char *abs;
201 #if defined ___AmigaOS___
202 BPTR lock;
203 #endif
204  
205 #if defined ___AmigaOS___
206 if((abs = malloc(PATH_MAX * sizeof(*abs))) == NULL) {
207 fprintf(stderr, "Memory allocation failure.\n");
208 return NULL;
209 }
210 if((lock = Lock(path, SHARED_LOCK)) == 0) {
211 fprintf(stderr, "Lock failed for path '%s'.\n", path);
212 return NULL;
213 }
214 if(NameFromLock(lock, abs, PATH_MAX) == FALSE) {
215 fprintf(stderr, "Full path for '%s' could not be retrieved.\n", path);
216 UnLock(lock);
217 return NULL;
218 }
219 UnLock(lock);
220 #else
221 /*
222 * On POSIX this should be:
223 * abs = realpath(path, NULL);
224 *
225 */
226 if((abs = malloc((strlen(path) + 1) * sizeof(*abs))) == NULL) {
227 fprintf(stderr, "Memory allocation failure.\n");
228 return NULL;
229 }
230 sprintf(abs, "%s", path);
231 #endif
232  
233 return abs;
234 }
235  
236 /*
237 *
238 * Compares path parts for equality.
239 */
240 #if defined ___AmigaOS___
241 BOOL PathCompare(char *path, char *look) {
242 #else
243 int PathCompare(char *path, char *look) {
244 #endif
245 char *a;
246 char *b;
247  
248 for(a = path, b = look; *a != '\0' && *b != '\0'; ++a, ++b) {
249 if(*b != '\0' && *a != *b) {
250 return FALSE;
251 }
252 }
253  
254 return *b == '\0';
255 }
256  
257 /*
258 *
259 * Creates a temporary file and returns its name.
260 */
261 char *CreateTemporaryFile(void) {
262 char *name;
263  
264 name = tmpnam(NULL);
265  
266 return name;
267 }
268  
269 /*
270 *
271 * Create multiple temporary files and return their names.
272 */
38 office 273 VECTOR *CreateTemporaryFiles(int files) {
274 VECTOR *tmpNames;
33 office 275  
38 office 276 if((tmpNames = malloc(1 * sizeof(*tmpNames))) == NULL) {
33 office 277 fprintf(stderr, "Memory allocation failure.\n");
278 return NULL;
279 }
280  
38 office 281 if((tmpNames->array = malloc(files * sizeof(*tmpNames->array))) == NULL) {
282 fprintf(stderr, "Memory allocation failure.\n");
283 return NULL;
284 }
285  
33 office 286 if(PROGRAM_VERBOSE) {
287 fprintf(stdout, "Creating temporary files...\r");
288 }
289  
38 office 290 tmpNames->length = 0;
291 while(PROGRAM_RUN && --files > -1) {
33 office 292 #if defined ___AmigaOS___
293 // Check if CTRL+C was pressed and abort the program.
294 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
295 PROGRAM_RUN = FALSE;
296 continue;
297 }
298 #endif
38 office 299 tmpNames[files] = CreateTemporaryFile();
300 ++tmpNames->length;
33 office 301  
302 if(PROGRAM_VERBOSE) {
303 fprintf(stdout, "Creating temporary files: %d%%.\r", 100 - (int)(((float)count / files) * 100.0));
304 }
305 }
306  
307 if(PROGRAM_VERBOSE) {
308 fprintf(stdout, "\n");
309 }
310  
311 return tmpNames;
312 }
313  
314 /*
315 *
316 * Skips a line in a file.
317 */
318 #if defined ___AsyncIO___
319 void SkipLine(struct AsyncFile *fp) {
320 LONG c;
321 while(PROGRAM_RUN && (c = ReadCharAsync(fp)) != -1) {
322 #else
323 void SkipLine(FILE *fp) {
324 char c;
325 while(PROGRAM_RUN && fscanf(fp, "%c", &c) == 1) {
326 #endif
327 #if defined ___AmigaOS___
328 // Check if CTRL+C was pressed and abort the program.
329 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
330 PROGRAM_RUN = FALSE;
331 continue;
332 }
333 #endif
334 switch(c) {
335 case '\n':
336 return;
337 }
338 }
339 }
340  
38 office 341 /*
342 *
343 * Peeks for the next line in a file.
344 */
345 #if defined ___AsyncIO___
346 dbLine *PeekLine(struct AsyncFile *fp) {
347 #else
348 dbLine *PeekLine(FILE *fp) {
349 #endif
350 dbLine *line;
33 office 351  
38 office 352 // Read the next line.
353 if((line = ReadLine(fp)) == NULL) {
354 return NULL;
355 }
356  
357 // Rewind the file by the number of read characters.
358 #if defined ___AsyncIO___
359 if(SeekAsync(fp, -(line->length + 1), MODE_CURRENT) == -1) {
360 fprintf(stderr, "Could not seek in file.\n");
361 free(line->string);
362 free(line);
363 line = NULL;
364 return NULL;
365 }
366 #else
367 if(fseek(fp, -(line->length + 1), SEEK_CUR) != 0) {
368 fprintf(stderr, "Could not seek in file.\n");
369 free(line->string);
370 free(line);
371 line = NULL;
372 return NULL;
373 }
374 #endif
375  
376 return line;
377 }
378  
33 office 379 /*
380 *
38 office 381 * Reads the next line in a file.
33 office 382 */
383 #if defined ___AsyncIO___
38 office 384 dbLine *ReadLine(struct AsyncFile *fp) {
33 office 385 LONG c;
386 #else
38 office 387 dbLine *ReadLine(FILE *fp) {
33 office 388 char c;
389 #endif
390 int i;
38 office 391 dbLine *line;
33 office 392  
393 i = 0;
394 #if defined ___AsyncIO___
395 while(PROGRAM_RUN && (c = ReadCharAsync(fp)) != -1) {
396 #else
397 while(PROGRAM_RUN && fscanf(fp, "%c", &c) == 1) {
398 #endif
399 #if defined ___AmigaOS___
400 // Check if CTRL+C was pressed and abort the program.
401 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
402 PROGRAM_RUN = FALSE;
403 continue;
404 }
405 #endif
406 switch(c) {
407 case '\n':
408 // Rewind the file by the number of read characters.
409 #if defined ___AsyncIO___
410 if(SeekAsync(fp, -(i + 1), MODE_CURRENT) == -1) {
411 fprintf(stderr, "Could not seek in file.\n");
38 office 412 fprintf(stderr, "index at: %d\n", i);
33 office 413 return NULL;
414 }
415 #else
416 if(fseek(fp, -(i + 1), SEEK_CUR) != 0) {
417 fprintf(stderr, "Could not seek in file.\n");
418 return NULL;
419 }
420 #endif
38 office 421 goto LINE;
33 office 422 }
38 office 423  
33 office 424 ++i;
425 }
426  
38 office 427 LINE:
428  
429 if(i == 0) {
430 return NULL;
431 }
432  
433 if((line = malloc(1 * sizeof(*line))) == NULL) {
434 fprintf(stderr, "Memory allocation error.\n");
435 return NULL;
436 }
437  
438 if((line->string = malloc((i + 1) * sizeof(*line->string))) == NULL) {
439 fprintf(stderr, "Memory allocation error.\n");
33 office 440 free(line);
38 office 441 line = NULL;
442 return NULL;
33 office 443 }
444  
445 #if defined ___AsyncIO___
38 office 446 if(ReadAsync(fp, line->string, i) != i) {
33 office 447 #else
38 office 448 if(fread(line->string, sizeof(char), i, fp) != i) {
33 office 449 #endif
38 office 450 fprintf(stderr, "Unable to read line.\n");
451 free(line->string);
452 free(line);
453 line = NULL;
33 office 454 return NULL;
455 }
456  
38 office 457 // Clear newline.
33 office 458 #if defined ___AsyncIO___
38 office 459 ReadCharAsync(fp);
33 office 460 #else
38 office 461 fgetc(fp);
33 office 462 #endif
463  
38 office 464 line->length = i;
33 office 465  
38 office 466 return line;
33 office 467 }
468  
469 /*
470 *
471 * Delete a file.
472 */
473 #if defined ___AmigaOS___
474 BOOL RemoveFile(char *name) {
475 return DeleteFile(name);
476 #else
477 int RemoveFile(char *name) {
478 return remove(name) == 0;
479 #endif
480 }
481  
482  
483 /*
484 *
485 * Deletes files.
486 */
487 void RemoveFiles(char **names, int count) {
488 int i;
489 for(i = 0; i < count; ++i) {
490 if(RemoveFile(names[i]) == FALSE) {
491 fprintf(stderr, "Could not remove file '%s'.\n", names[i]);
492 continue;
493 }
494 fprintf(stderr, "Removing file '%s'\n", names[i]);
495 }
496 }
497  
498 /*
499 *
500 * Copies a file to another file by name.
501 */
502 void CopyFile(char *a, char *b) {
503 #if defined ___AsyncIO___
504 struct AsyncFile *ap;
505 struct AsyncFile *bp;
506 LONG c;
507 #else
508 FILE *ap;
509 FILE *bp;
510 char c;
511 #endif
512  
513 // Open database file for writing.
514 #if defined ___AsyncIO___
515 if((ap = OpenAsync(a, MODE_READ, ASYNC_BUF)) == NULL) {
516 #else
517 if((ap = fopen(a, "r")) == NULL) {
518 #endif
519 fprintf(stderr, "Could not open file '%s' for reading.\n", a);
520 return;
521 }
522  
523 // Open temporary file for reading.
524 #if defined ___AsyncIO___
525 if((bp = OpenAsync(b, MODE_WRITE, ASYNC_BUF)) == NULL) {
526 #else
527 if((bp = fopen(b, "w")) == NULL) {
528 #endif
529 fprintf(stderr, "Could not open file '%s' for writing.\n", b);
530  
531 // Close database file.
532 #if defined ___AsyncIO___
533 CloseAsync(ap);
534 #else
535 fclose(ap);
536 #endif
537  
538 return;
539 }
540  
541 #if defined ___AsyncIO___
542 while(PROGRAM_RUN && (c = ReadCharAsync(ap)) != -1) {
543 #else
544 while(PROGRAM_RUN && fscanf(ap, "%c", &c) == 1) {
545 #endif
546 #if defined ___AmigaOS___
547 // Check if CTRL+C was pressed and abort the program.
548 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
549 PROGRAM_RUN = FALSE;
550 continue;
551 }
552 #endif
553 #if defined ___AsyncIO___
554 if(WriteCharAsync(bp, (UBYTE)c) != 1) {
555 #else
556 if(fprintf(bp, "%c", c) != 1) {
557 #endif
558 fprintf(stderr, "Could not write to file '%s'.\n", b);
559 break;
560 }
561 }
562  
563 #if defined ___AsyncIO___
564 CloseAsync(ap);
565 CloseAsync(bp);
566 #else
567 fclose(ap);
568 fclose(bp);
569 #endif
570 }
571  
572 /*
573 *
574 * Create a database entry from a line of text.
575 */
38 office 576 dbEntry* CreateDatabaseEntry(dbLine *line) {
33 office 577 dbEntry *entry;
578 char *ptr;
579 int side;
580 int i;
581 int j;
582  
583 if((entry = malloc(1 * sizeof(*entry))) == NULL) {
584 fprintf(stderr, "Memory allocation failure.\n");
585 return NULL;
586 }
587  
38 office 588 if((entry->name = malloc((line->length + 1) * sizeof(*entry->name))) == NULL) {
33 office 589 fprintf(stderr, "Memory allocation failure.\n");
590 return NULL;
591 }
592  
38 office 593 if((entry->path = malloc((line->length + 1) * sizeof(*entry->path))) == NULL) {
33 office 594 fprintf(stderr, "Memory allocation failure.\n");
595 return NULL;
596 }
597  
38 office 598 for(ptr = line->string, side = 0, i = 0, j = 0; PROGRAM_RUN && *ptr != '\0'; ++ptr) {
33 office 599 #if defined ___AmigaOS___
600 // Check if CTRL+C was pressed and abort the program.
601 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
602 PROGRAM_RUN = FALSE;
603 continue;
604 }
605 #endif
606 switch(*ptr) {
607 case '\t':
608 entry->name[i] = '\0';
609 ++side;
610 break;
611 case '\n':
612 entry->path[j] = '\0';
613 return entry;
614 default:
615 switch(side) {
616 case 0:
617 entry->name[i++] = *ptr;
618 break;
619 case 1:
620 entry->path[j++] = *ptr;
621 break;
622 }
623 break;
624 }
625 }
626  
627 return entry;
628 }
629  
37 office 630 /*
631 * Compare two strings.
632 */
633 #if defined ___AmigaOS___
634 BOOL StringMatch(char *a, char *b) {
635 #else
636 int StringMatch(char *a, char *b) {
637 #endif
638 #if defined ___AmigaOS___
639 ULONG size;
640 BOOL success;
641 UBYTE *pattern;
33 office 642  
37 office 643 // "must be at least 2 times as large plus 2 bytes"
644 size = strlen(b) * 2 + 2;
645  
646 success = FALSE;
647  
648 if(pattern = AllocVec(size, MEMF_ANY|MEMF_CLEAR)) {
649 switch(ParsePatternNoCase(b, pattern, (LONG)size)) {
650 case 1: // the pattern contains wildcards
651 success = MatchPatternNoCase(pattern, a);
652  
653 break;
654 case 0: // no wildcards so fall back to exact name match
655 #if defined ___NOCASE_FS___
656 success = (Strnicmp(a, b, StringLenMax(a, b)) == 0);
657 #else
658 success = (StrnCmp(a, b, StringLenMax(a, b)) == 0);
659 #endif
660  
661 break;
662 }
663  
664 FreeVec(pattern);
38 office 665 pattern = NULL;
37 office 666 }
667  
668 return success;
669 #else
670 int success;
671 char *e = a;
672 char *n = b;
673  
674 success = FALSE;
675  
676 #if defined ___NOCASE_FS___
38 office 677 StrUpr(e);
678 StrUpr(n);
37 office 679 #endif
680  
681 // search for substring
682 success = strstr(e, n) != NULL;
683  
684 return success;
685 #endif
686 }
687  
688  
689  
690  
691