HuntnGather – Blame information for rev 41

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 *
41 office 133 * Get the size of a file.
134 */
135 int GetFileSize(char *dbFile) {
136 #if defined ___AsyncIO___
137 struct AsyncFile *fp;
138 #else
139 FILE *fp;
140 #endif
141 int size;
142  
143 #if defined ___AsyncIO___
144 if((fp = OpenAsync(dbFile, MODE_READ, ASYNC_BUF)) == NULL) {
145 #else
146 if((fp = fopen(dbFile, "r")) == NULL) {
147 #endif
148 fprintf(stderr, "Could not open file '%s' for reading.\n", dbFile);
149 return -1;
150 }
151  
152 #if defined ___AsyncIO___
153 SeekAsync(fp, 0, MODE_END);
154 size = SeekAsync(fp, 0, MODE_CURRENT);
155 #else
156 fseek(fp, 0L, SEEK_END);
157 size = ftell(fp);
158 #endif
159  
160 #if defined ___AsyncIO___
161 CloseAsync(fp);
162 #else
163 fclose(fp);
164 #endif
165  
166 return size;
167 }
168  
169 /*
170 *
33 office 171 * Counts the lines of a file.
172 */
173 int CountFileLines(char *dbFile) {
174 #if defined ___AsyncIO___
175 struct AsyncFile *fp;
176 #else
177 FILE *fp;
178 #endif
179 int lines;
41 office 180 dbLine *line = NULL;
33 office 181  
182 #if defined ___AsyncIO___
183 if((fp = OpenAsync(dbFile, MODE_READ, ASYNC_BUF)) == NULL) {
184 #else
185 if((fp = fopen(dbFile, "r")) == NULL) {
186 #endif
187 fprintf(stderr, "Could not open file '%s' for reading.\n", dbFile);
188 return -1;
189 }
190  
191 if(PROGRAM_VERBOSE) {
192 fprintf(stdout, "Counting lines in '%s'...\r", dbFile);
193 }
194  
41 office 195 lines = 0;
196 while(PROGRAM_RUN && (line = ReadLine(fp)) != NULL) {
33 office 197 #if defined ___AmigaOS___
198 // Check if CTRL+C was pressed and abort the program.
199 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
200 PROGRAM_RUN = FALSE;
201 continue;
202 }
203 #endif
204  
41 office 205 ++lines;
206  
207 if(PROGRAM_VERBOSE) {
208 fprintf(stdout, "Counting lines in '%s': %d.\r", dbFile, lines);
33 office 209 }
41 office 210  
211 free(line->string);
212 free(line);
213 line = NULL;
33 office 214 }
215  
41 office 216 if(line != NULL) {
217 free(line->string);
218 free(line);
219 line = NULL;
220 }
221  
33 office 222 #if defined ___AsyncIO___
223 CloseAsync(fp);
224 #else
225 fclose(fp);
226 #endif
227  
228 if(PROGRAM_VERBOSE) {
229 fprintf(stdout, "\n");
230 }
231  
232 return lines;
233 }
234  
235 /*
236 *
237 * Gets the absolute path to file by name.
238 */
239 char *PathToAbsolute(char *path) {
240 char *abs;
241 #if defined ___AmigaOS___
242 BPTR lock;
243 #endif
244  
245 #if defined ___AmigaOS___
246 if((abs = malloc(PATH_MAX * sizeof(*abs))) == NULL) {
247 fprintf(stderr, "Memory allocation failure.\n");
248 return NULL;
249 }
250 if((lock = Lock(path, SHARED_LOCK)) == 0) {
251 fprintf(stderr, "Lock failed for path '%s'.\n", path);
252 return NULL;
253 }
254 if(NameFromLock(lock, abs, PATH_MAX) == FALSE) {
255 fprintf(stderr, "Full path for '%s' could not be retrieved.\n", path);
256 UnLock(lock);
257 return NULL;
258 }
259 UnLock(lock);
260 #else
261 /*
262 * On POSIX this should be:
263 * abs = realpath(path, NULL);
264 *
265 */
266 if((abs = malloc((strlen(path) + 1) * sizeof(*abs))) == NULL) {
267 fprintf(stderr, "Memory allocation failure.\n");
268 return NULL;
269 }
270 sprintf(abs, "%s", path);
271 #endif
272  
273 return abs;
274 }
275  
276 /*
277 *
278 * Compares path parts for equality.
279 */
280 #if defined ___AmigaOS___
281 BOOL PathCompare(char *path, char *look) {
282 #else
283 int PathCompare(char *path, char *look) {
284 #endif
285 char *a;
286 char *b;
287  
288 for(a = path, b = look; *a != '\0' && *b != '\0'; ++a, ++b) {
289 if(*b != '\0' && *a != *b) {
290 return FALSE;
291 }
292 }
293  
294 return *b == '\0';
295 }
296  
297 /*
298 *
299 * Creates a temporary file and returns its name.
300 */
301 char *CreateTemporaryFile(void) {
302 char *name;
303  
304 name = tmpnam(NULL);
305  
306 return name;
307 }
308  
309 /*
310 *
311 * Create multiple temporary files and return their names.
312 */
38 office 313 VECTOR *CreateTemporaryFiles(int files) {
314 VECTOR *tmpNames;
39 office 315 int total;
33 office 316  
38 office 317 if((tmpNames = malloc(1 * sizeof(*tmpNames))) == NULL) {
33 office 318 fprintf(stderr, "Memory allocation failure.\n");
319 return NULL;
320 }
321  
38 office 322 if((tmpNames->array = malloc(files * sizeof(*tmpNames->array))) == NULL) {
323 fprintf(stderr, "Memory allocation failure.\n");
324 return NULL;
325 }
326  
33 office 327 if(PROGRAM_VERBOSE) {
328 fprintf(stdout, "Creating temporary files...\r");
329 }
330  
38 office 331 tmpNames->length = 0;
39 office 332 total = files;
38 office 333 while(PROGRAM_RUN && --files > -1) {
33 office 334 #if defined ___AmigaOS___
335 // Check if CTRL+C was pressed and abort the program.
336 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
337 PROGRAM_RUN = FALSE;
338 continue;
339 }
340 #endif
39 office 341 tmpNames->array[files] = CreateTemporaryFile();
38 office 342 ++tmpNames->length;
33 office 343  
344 if(PROGRAM_VERBOSE) {
39 office 345 fprintf(stdout, "Creating temporary files: %d%%.\r", (int)(((float)tmpNames->length / total) * 100.0));
33 office 346 }
347 }
348  
349 if(PROGRAM_VERBOSE) {
350 fprintf(stdout, "\n");
351 }
352  
353 return tmpNames;
354 }
355  
356 /*
357 *
358 * Skips a line in a file.
359 */
360 #if defined ___AsyncIO___
361 void SkipLine(struct AsyncFile *fp) {
362 LONG c;
363 while(PROGRAM_RUN && (c = ReadCharAsync(fp)) != -1) {
364 #else
365 void SkipLine(FILE *fp) {
366 char c;
367 while(PROGRAM_RUN && fscanf(fp, "%c", &c) == 1) {
368 #endif
369 #if defined ___AmigaOS___
370 // Check if CTRL+C was pressed and abort the program.
371 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
372 PROGRAM_RUN = FALSE;
373 continue;
374 }
375 #endif
376 switch(c) {
377 case '\n':
378 return;
379 }
380 }
381 }
382  
38 office 383 /*
384 *
385 * Peeks for the next line in a file.
386 */
387 #if defined ___AsyncIO___
388 dbLine *PeekLine(struct AsyncFile *fp) {
389 #else
390 dbLine *PeekLine(FILE *fp) {
391 #endif
392 dbLine *line;
33 office 393  
38 office 394 // Read the next line.
395 if((line = ReadLine(fp)) == NULL) {
396 return NULL;
397 }
398  
399 // Rewind the file by the number of read characters.
400 #if defined ___AsyncIO___
401 if(SeekAsync(fp, -(line->length + 1), MODE_CURRENT) == -1) {
402 fprintf(stderr, "Could not seek in file.\n");
403 free(line->string);
404 free(line);
405 line = NULL;
406 return NULL;
407 }
408 #else
409 if(fseek(fp, -(line->length + 1), SEEK_CUR) != 0) {
410 fprintf(stderr, "Could not seek in file.\n");
411 free(line->string);
412 free(line);
413 line = NULL;
414 return NULL;
415 }
416 #endif
417  
418 return line;
419 }
420  
33 office 421 /*
422 *
38 office 423 * Reads the next line in a file.
33 office 424 */
425 #if defined ___AsyncIO___
38 office 426 dbLine *ReadLine(struct AsyncFile *fp) {
33 office 427 LONG c;
428 #else
38 office 429 dbLine *ReadLine(FILE *fp) {
33 office 430 char c;
431 #endif
432 int i;
38 office 433 dbLine *line;
33 office 434  
435 i = 0;
436 #if defined ___AsyncIO___
437 while(PROGRAM_RUN && (c = ReadCharAsync(fp)) != -1) {
438 #else
439 while(PROGRAM_RUN && fscanf(fp, "%c", &c) == 1) {
440 #endif
441 #if defined ___AmigaOS___
442 // Check if CTRL+C was pressed and abort the program.
443 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
444 PROGRAM_RUN = FALSE;
445 continue;
446 }
447 #endif
448 switch(c) {
449 case '\n':
450 // Rewind the file by the number of read characters.
451 #if defined ___AsyncIO___
452 if(SeekAsync(fp, -(i + 1), MODE_CURRENT) == -1) {
453 fprintf(stderr, "Could not seek in file.\n");
38 office 454 fprintf(stderr, "index at: %d\n", i);
33 office 455 return NULL;
456 }
457 #else
458 if(fseek(fp, -(i + 1), SEEK_CUR) != 0) {
459 fprintf(stderr, "Could not seek in file.\n");
460 return NULL;
461 }
462 #endif
38 office 463 goto LINE;
33 office 464 }
38 office 465  
33 office 466 ++i;
467 }
468  
38 office 469 LINE:
470  
471 if(i == 0) {
472 return NULL;
473 }
474  
475 if((line = malloc(1 * sizeof(*line))) == NULL) {
476 fprintf(stderr, "Memory allocation error.\n");
477 return NULL;
478 }
479  
480 if((line->string = malloc((i + 1) * sizeof(*line->string))) == NULL) {
481 fprintf(stderr, "Memory allocation error.\n");
33 office 482 free(line);
38 office 483 line = NULL;
484 return NULL;
33 office 485 }
486  
487 #if defined ___AsyncIO___
38 office 488 if(ReadAsync(fp, line->string, i) != i) {
33 office 489 #else
38 office 490 if(fread(line->string, sizeof(char), i, fp) != i) {
33 office 491 #endif
38 office 492 fprintf(stderr, "Unable to read line.\n");
493 free(line->string);
494 free(line);
495 line = NULL;
33 office 496 return NULL;
497 }
498  
38 office 499 // Clear newline.
33 office 500 #if defined ___AsyncIO___
38 office 501 ReadCharAsync(fp);
33 office 502 #else
38 office 503 fgetc(fp);
33 office 504 #endif
505  
38 office 506 line->length = i;
33 office 507  
38 office 508 return line;
33 office 509 }
510  
511 /*
512 *
513 * Delete a file.
514 */
515 #if defined ___AmigaOS___
516 BOOL RemoveFile(char *name) {
517 return DeleteFile(name);
518 #else
519 int RemoveFile(char *name) {
520 return remove(name) == 0;
521 #endif
522 }
523  
524 /*
525 *
526 * Deletes files.
527 */
39 office 528 void RemoveFiles(VECTOR *names) {
33 office 529 int i;
39 office 530 for(i = 0; i < names->length; ++i) {
531 if(RemoveFile(names->array[i]) == FALSE) {
532 fprintf(stderr, "Could not remove file '%s'.\n", (char *)names->array[i]);
33 office 533 continue;
534 }
39 office 535 fprintf(stderr, "Removing file '%s'\n", (char *)names->array[i]);
33 office 536 }
537 }
538  
539 /*
540 *
541 * Copies a file to another file by name.
542 */
543 void CopyFile(char *a, char *b) {
544 #if defined ___AsyncIO___
545 struct AsyncFile *ap;
546 struct AsyncFile *bp;
547 LONG c;
548 #else
549 FILE *ap;
550 FILE *bp;
551 char c;
552 #endif
553  
554 // Open database file for writing.
555 #if defined ___AsyncIO___
556 if((ap = OpenAsync(a, MODE_READ, ASYNC_BUF)) == NULL) {
557 #else
558 if((ap = fopen(a, "r")) == NULL) {
559 #endif
560 fprintf(stderr, "Could not open file '%s' for reading.\n", a);
561 return;
562 }
563  
564 // Open temporary file for reading.
565 #if defined ___AsyncIO___
566 if((bp = OpenAsync(b, MODE_WRITE, ASYNC_BUF)) == NULL) {
567 #else
568 if((bp = fopen(b, "w")) == NULL) {
569 #endif
570 fprintf(stderr, "Could not open file '%s' for writing.\n", b);
571  
572 // Close database file.
573 #if defined ___AsyncIO___
574 CloseAsync(ap);
575 #else
576 fclose(ap);
577 #endif
578  
579 return;
580 }
581  
582 #if defined ___AsyncIO___
583 while(PROGRAM_RUN && (c = ReadCharAsync(ap)) != -1) {
584 #else
585 while(PROGRAM_RUN && fscanf(ap, "%c", &c) == 1) {
586 #endif
587 #if defined ___AmigaOS___
588 // Check if CTRL+C was pressed and abort the program.
589 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
590 PROGRAM_RUN = FALSE;
591 continue;
592 }
593 #endif
594 #if defined ___AsyncIO___
595 if(WriteCharAsync(bp, (UBYTE)c) != 1) {
596 #else
597 if(fprintf(bp, "%c", c) != 1) {
598 #endif
599 fprintf(stderr, "Could not write to file '%s'.\n", b);
600 break;
601 }
602 }
603  
604 #if defined ___AsyncIO___
605 CloseAsync(ap);
606 CloseAsync(bp);
607 #else
608 fclose(ap);
609 fclose(bp);
610 #endif
611 }
612  
613 /*
614 *
615 * Create a database entry from a line of text.
616 */
38 office 617 dbEntry* CreateDatabaseEntry(dbLine *line) {
33 office 618 dbEntry *entry;
619 char *ptr;
620 int side;
621 int i;
622 int j;
623  
624 if((entry = malloc(1 * sizeof(*entry))) == NULL) {
625 fprintf(stderr, "Memory allocation failure.\n");
626 return NULL;
627 }
628  
38 office 629 if((entry->name = malloc((line->length + 1) * sizeof(*entry->name))) == NULL) {
33 office 630 fprintf(stderr, "Memory allocation failure.\n");
631 return NULL;
632 }
633  
38 office 634 if((entry->path = malloc((line->length + 1) * sizeof(*entry->path))) == NULL) {
33 office 635 fprintf(stderr, "Memory allocation failure.\n");
636 return NULL;
637 }
638  
38 office 639 for(ptr = line->string, side = 0, i = 0, j = 0; PROGRAM_RUN && *ptr != '\0'; ++ptr) {
33 office 640 #if defined ___AmigaOS___
641 // Check if CTRL+C was pressed and abort the program.
642 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
643 PROGRAM_RUN = FALSE;
644 continue;
645 }
646 #endif
647 switch(*ptr) {
648 case '\t':
649 entry->name[i] = '\0';
650 ++side;
651 break;
652 case '\n':
653 entry->path[j] = '\0';
654 return entry;
655 default:
656 switch(side) {
657 case 0:
658 entry->name[i++] = *ptr;
659 break;
660 case 1:
661 entry->path[j++] = *ptr;
662 break;
663 }
664 break;
665 }
666 }
667  
668 return entry;
669 }
670  
37 office 671 /*
672 * Compare two strings.
673 */
674 #if defined ___AmigaOS___
675 BOOL StringMatch(char *a, char *b) {
676 #else
677 int StringMatch(char *a, char *b) {
678 #endif
679 #if defined ___AmigaOS___
680 ULONG size;
681 BOOL success;
682 UBYTE *pattern;
33 office 683  
37 office 684 // "must be at least 2 times as large plus 2 bytes"
685 size = strlen(b) * 2 + 2;
686  
687 success = FALSE;
688  
689 if(pattern = AllocVec(size, MEMF_ANY|MEMF_CLEAR)) {
690 switch(ParsePatternNoCase(b, pattern, (LONG)size)) {
691 case 1: // the pattern contains wildcards
692 success = MatchPatternNoCase(pattern, a);
693  
694 break;
695 case 0: // no wildcards so fall back to exact name match
696 #if defined ___NOCASE_FS___
697 success = (Strnicmp(a, b, StringLenMax(a, b)) == 0);
698 #else
699 success = (StrnCmp(a, b, StringLenMax(a, b)) == 0);
700 #endif
701  
702 break;
703 }
704  
705 FreeVec(pattern);
38 office 706 pattern = NULL;
37 office 707 }
708  
709 return success;
710 #else
711 int success;
712 char *e = a;
713 char *n = b;
714  
715 success = FALSE;
716  
717 #if defined ___NOCASE_FS___
38 office 718 StrUpr(e);
719 StrUpr(n);
37 office 720 #endif
721  
722 // search for substring
723 success = strstr(e, n) != NULL;
724  
725 return success;
726 #endif
727 }
728  
729  
730  
731  
732