HuntnGather – Blame information for rev 39

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;
39 office 275 int total;
33 office 276  
38 office 277 if((tmpNames = malloc(1 * sizeof(*tmpNames))) == NULL) {
33 office 278 fprintf(stderr, "Memory allocation failure.\n");
279 return NULL;
280 }
281  
38 office 282 if((tmpNames->array = malloc(files * sizeof(*tmpNames->array))) == NULL) {
283 fprintf(stderr, "Memory allocation failure.\n");
284 return NULL;
285 }
286  
33 office 287 if(PROGRAM_VERBOSE) {
288 fprintf(stdout, "Creating temporary files...\r");
289 }
290  
38 office 291 tmpNames->length = 0;
39 office 292 total = files;
38 office 293 while(PROGRAM_RUN && --files > -1) {
33 office 294 #if defined ___AmigaOS___
295 // Check if CTRL+C was pressed and abort the program.
296 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
297 PROGRAM_RUN = FALSE;
298 continue;
299 }
300 #endif
39 office 301 tmpNames->array[files] = CreateTemporaryFile();
38 office 302 ++tmpNames->length;
33 office 303  
304 if(PROGRAM_VERBOSE) {
39 office 305 fprintf(stdout, "Creating temporary files: %d%%.\r", (int)(((float)tmpNames->length / total) * 100.0));
33 office 306 }
307 }
308  
309 if(PROGRAM_VERBOSE) {
310 fprintf(stdout, "\n");
311 }
312  
313 return tmpNames;
314 }
315  
316 /*
317 *
318 * Skips a line in a file.
319 */
320 #if defined ___AsyncIO___
321 void SkipLine(struct AsyncFile *fp) {
322 LONG c;
323 while(PROGRAM_RUN && (c = ReadCharAsync(fp)) != -1) {
324 #else
325 void SkipLine(FILE *fp) {
326 char c;
327 while(PROGRAM_RUN && fscanf(fp, "%c", &c) == 1) {
328 #endif
329 #if defined ___AmigaOS___
330 // Check if CTRL+C was pressed and abort the program.
331 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
332 PROGRAM_RUN = FALSE;
333 continue;
334 }
335 #endif
336 switch(c) {
337 case '\n':
338 return;
339 }
340 }
341 }
342  
38 office 343 /*
344 *
345 * Peeks for the next line in a file.
346 */
347 #if defined ___AsyncIO___
348 dbLine *PeekLine(struct AsyncFile *fp) {
349 #else
350 dbLine *PeekLine(FILE *fp) {
351 #endif
352 dbLine *line;
33 office 353  
38 office 354 // Read the next line.
355 if((line = ReadLine(fp)) == NULL) {
356 return NULL;
357 }
358  
359 // Rewind the file by the number of read characters.
360 #if defined ___AsyncIO___
361 if(SeekAsync(fp, -(line->length + 1), MODE_CURRENT) == -1) {
362 fprintf(stderr, "Could not seek in file.\n");
363 free(line->string);
364 free(line);
365 line = NULL;
366 return NULL;
367 }
368 #else
369 if(fseek(fp, -(line->length + 1), SEEK_CUR) != 0) {
370 fprintf(stderr, "Could not seek in file.\n");
371 free(line->string);
372 free(line);
373 line = NULL;
374 return NULL;
375 }
376 #endif
377  
378 return line;
379 }
380  
33 office 381 /*
382 *
38 office 383 * Reads the next line in a file.
33 office 384 */
385 #if defined ___AsyncIO___
38 office 386 dbLine *ReadLine(struct AsyncFile *fp) {
33 office 387 LONG c;
388 #else
38 office 389 dbLine *ReadLine(FILE *fp) {
33 office 390 char c;
391 #endif
392 int i;
38 office 393 dbLine *line;
33 office 394  
395 i = 0;
396 #if defined ___AsyncIO___
397 while(PROGRAM_RUN && (c = ReadCharAsync(fp)) != -1) {
398 #else
399 while(PROGRAM_RUN && fscanf(fp, "%c", &c) == 1) {
400 #endif
401 #if defined ___AmigaOS___
402 // Check if CTRL+C was pressed and abort the program.
403 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
404 PROGRAM_RUN = FALSE;
405 continue;
406 }
407 #endif
408 switch(c) {
409 case '\n':
410 // Rewind the file by the number of read characters.
411 #if defined ___AsyncIO___
412 if(SeekAsync(fp, -(i + 1), MODE_CURRENT) == -1) {
413 fprintf(stderr, "Could not seek in file.\n");
38 office 414 fprintf(stderr, "index at: %d\n", i);
33 office 415 return NULL;
416 }
417 #else
418 if(fseek(fp, -(i + 1), SEEK_CUR) != 0) {
419 fprintf(stderr, "Could not seek in file.\n");
420 return NULL;
421 }
422 #endif
38 office 423 goto LINE;
33 office 424 }
38 office 425  
33 office 426 ++i;
427 }
428  
38 office 429 LINE:
430  
431 if(i == 0) {
432 return NULL;
433 }
434  
435 if((line = malloc(1 * sizeof(*line))) == NULL) {
436 fprintf(stderr, "Memory allocation error.\n");
437 return NULL;
438 }
439  
440 if((line->string = malloc((i + 1) * sizeof(*line->string))) == NULL) {
441 fprintf(stderr, "Memory allocation error.\n");
33 office 442 free(line);
38 office 443 line = NULL;
444 return NULL;
33 office 445 }
446  
447 #if defined ___AsyncIO___
38 office 448 if(ReadAsync(fp, line->string, i) != i) {
33 office 449 #else
38 office 450 if(fread(line->string, sizeof(char), i, fp) != i) {
33 office 451 #endif
38 office 452 fprintf(stderr, "Unable to read line.\n");
453 free(line->string);
454 free(line);
455 line = NULL;
33 office 456 return NULL;
457 }
458  
38 office 459 // Clear newline.
33 office 460 #if defined ___AsyncIO___
38 office 461 ReadCharAsync(fp);
33 office 462 #else
38 office 463 fgetc(fp);
33 office 464 #endif
465  
38 office 466 line->length = i;
33 office 467  
38 office 468 return line;
33 office 469 }
470  
471 /*
472 *
473 * Delete a file.
474 */
475 #if defined ___AmigaOS___
476 BOOL RemoveFile(char *name) {
477 return DeleteFile(name);
478 #else
479 int RemoveFile(char *name) {
480 return remove(name) == 0;
481 #endif
482 }
483  
484 /*
485 *
486 * Deletes files.
487 */
39 office 488 void RemoveFiles(VECTOR *names) {
33 office 489 int i;
39 office 490 for(i = 0; i < names->length; ++i) {
491 if(RemoveFile(names->array[i]) == FALSE) {
492 fprintf(stderr, "Could not remove file '%s'.\n", (char *)names->array[i]);
33 office 493 continue;
494 }
39 office 495 fprintf(stderr, "Removing file '%s'\n", (char *)names->array[i]);
33 office 496 }
497 }
498  
499 /*
500 *
501 * Copies a file to another file by name.
502 */
503 void CopyFile(char *a, char *b) {
504 #if defined ___AsyncIO___
505 struct AsyncFile *ap;
506 struct AsyncFile *bp;
507 LONG c;
508 #else
509 FILE *ap;
510 FILE *bp;
511 char c;
512 #endif
513  
514 // Open database file for writing.
515 #if defined ___AsyncIO___
516 if((ap = OpenAsync(a, MODE_READ, ASYNC_BUF)) == NULL) {
517 #else
518 if((ap = fopen(a, "r")) == NULL) {
519 #endif
520 fprintf(stderr, "Could not open file '%s' for reading.\n", a);
521 return;
522 }
523  
524 // Open temporary file for reading.
525 #if defined ___AsyncIO___
526 if((bp = OpenAsync(b, MODE_WRITE, ASYNC_BUF)) == NULL) {
527 #else
528 if((bp = fopen(b, "w")) == NULL) {
529 #endif
530 fprintf(stderr, "Could not open file '%s' for writing.\n", b);
531  
532 // Close database file.
533 #if defined ___AsyncIO___
534 CloseAsync(ap);
535 #else
536 fclose(ap);
537 #endif
538  
539 return;
540 }
541  
542 #if defined ___AsyncIO___
543 while(PROGRAM_RUN && (c = ReadCharAsync(ap)) != -1) {
544 #else
545 while(PROGRAM_RUN && fscanf(ap, "%c", &c) == 1) {
546 #endif
547 #if defined ___AmigaOS___
548 // Check if CTRL+C was pressed and abort the program.
549 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
550 PROGRAM_RUN = FALSE;
551 continue;
552 }
553 #endif
554 #if defined ___AsyncIO___
555 if(WriteCharAsync(bp, (UBYTE)c) != 1) {
556 #else
557 if(fprintf(bp, "%c", c) != 1) {
558 #endif
559 fprintf(stderr, "Could not write to file '%s'.\n", b);
560 break;
561 }
562 }
563  
564 #if defined ___AsyncIO___
565 CloseAsync(ap);
566 CloseAsync(bp);
567 #else
568 fclose(ap);
569 fclose(bp);
570 #endif
571 }
572  
573 /*
574 *
575 * Create a database entry from a line of text.
576 */
38 office 577 dbEntry* CreateDatabaseEntry(dbLine *line) {
33 office 578 dbEntry *entry;
579 char *ptr;
580 int side;
581 int i;
582 int j;
583  
584 if((entry = malloc(1 * sizeof(*entry))) == NULL) {
585 fprintf(stderr, "Memory allocation failure.\n");
586 return NULL;
587 }
588  
38 office 589 if((entry->name = malloc((line->length + 1) * sizeof(*entry->name))) == NULL) {
33 office 590 fprintf(stderr, "Memory allocation failure.\n");
591 return NULL;
592 }
593  
38 office 594 if((entry->path = malloc((line->length + 1) * sizeof(*entry->path))) == NULL) {
33 office 595 fprintf(stderr, "Memory allocation failure.\n");
596 return NULL;
597 }
598  
38 office 599 for(ptr = line->string, side = 0, i = 0, j = 0; PROGRAM_RUN && *ptr != '\0'; ++ptr) {
33 office 600 #if defined ___AmigaOS___
601 // Check if CTRL+C was pressed and abort the program.
602 if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
603 PROGRAM_RUN = FALSE;
604 continue;
605 }
606 #endif
607 switch(*ptr) {
608 case '\t':
609 entry->name[i] = '\0';
610 ++side;
611 break;
612 case '\n':
613 entry->path[j] = '\0';
614 return entry;
615 default:
616 switch(side) {
617 case 0:
618 entry->name[i++] = *ptr;
619 break;
620 case 1:
621 entry->path[j++] = *ptr;
622 break;
623 }
624 break;
625 }
626 }
627  
628 return entry;
629 }
630  
37 office 631 /*
632 * Compare two strings.
633 */
634 #if defined ___AmigaOS___
635 BOOL StringMatch(char *a, char *b) {
636 #else
637 int StringMatch(char *a, char *b) {
638 #endif
639 #if defined ___AmigaOS___
640 ULONG size;
641 BOOL success;
642 UBYTE *pattern;
33 office 643  
37 office 644 // "must be at least 2 times as large plus 2 bytes"
645 size = strlen(b) * 2 + 2;
646  
647 success = FALSE;
648  
649 if(pattern = AllocVec(size, MEMF_ANY|MEMF_CLEAR)) {
650 switch(ParsePatternNoCase(b, pattern, (LONG)size)) {
651 case 1: // the pattern contains wildcards
652 success = MatchPatternNoCase(pattern, a);
653  
654 break;
655 case 0: // no wildcards so fall back to exact name match
656 #if defined ___NOCASE_FS___
657 success = (Strnicmp(a, b, StringLenMax(a, b)) == 0);
658 #else
659 success = (StrnCmp(a, b, StringLenMax(a, b)) == 0);
660 #endif
661  
662 break;
663 }
664  
665 FreeVec(pattern);
38 office 666 pattern = NULL;
37 office 667 }
668  
669 return success;
670 #else
671 int success;
672 char *e = a;
673 char *n = b;
674  
675 success = FALSE;
676  
677 #if defined ___NOCASE_FS___
38 office 678 StrUpr(e);
679 StrUpr(n);
37 office 680 #endif
681  
682 // search for substring
683 success = strstr(e, n) != NULL;
684  
685 return success;
686 #endif
687 }
688  
689  
690  
691  
692