HuntnGather – Blame information for rev 43

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