]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/m2/mc-boot/GFIO.cc
Update copyright years.
[thirdparty/gcc.git] / gcc / m2 / mc-boot / GFIO.cc
1 /* do not edit automatically generated by mc from FIO. */
2 /* FIO.mod provides a simple buffered file input/output library.
3
4 Copyright (C) 2001-2024 Free Software Foundation, Inc.
5 Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>.
6
7 This file is part of GNU Modula-2.
8
9 GNU Modula-2 is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3, or (at your option)
12 any later version.
13
14 GNU Modula-2 is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 General Public License for more details.
18
19 Under Section 7 of GPL version 3, you are granted additional
20 permissions described in the GCC Runtime Library Exception, version
21 3.1, as published by the Free Software Foundation.
22
23 You should have received a copy of the GNU General Public License and
24 a copy of the GCC Runtime Library Exception along with this program;
25 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
26 <http://www.gnu.org/licenses/>. */
27
28 #include "config.h"
29 #include "system.h"
30 #include <stdbool.h>
31 # if !defined (PROC_D)
32 # define PROC_D
33 typedef void (*PROC_t) (void);
34 typedef struct { PROC_t proc; } PROC;
35 # endif
36
37 # if !defined (TRUE)
38 # define TRUE (1==1)
39 # endif
40
41 # if !defined (FALSE)
42 # define FALSE (1==0)
43 # endif
44
45 # include "GStorage.h"
46 # include "Gmcrts.h"
47 #if defined(__cplusplus)
48 # undef NULL
49 # define NULL 0
50 #endif
51 #define _FIO_H
52 #define _FIO_C
53
54 # include "GSYSTEM.h"
55 # include "GASCII.h"
56 # include "GStrLib.h"
57 # include "GStorage.h"
58 # include "GNumberIO.h"
59 # include "Glibc.h"
60 # include "GIndexing.h"
61 # include "GM2RTS.h"
62
63 typedef unsigned int FIO_File;
64
65 FIO_File FIO_StdErr;
66 FIO_File FIO_StdOut;
67 FIO_File FIO_StdIn;
68 # define SEEK_SET 0
69 # define SEEK_END 2
70 # define UNIXREADONLY 0
71 # define UNIXWRITEONLY 1
72 # define CreatePermissions 0666
73 # define MaxBufferLength (1024*16)
74 # define MaxErrorString (1024*8)
75 typedef struct FIO_NameInfo_r FIO_NameInfo;
76
77 typedef struct FIO_buf_r FIO_buf;
78
79 typedef FIO_buf *FIO_Buffer;
80
81 typedef struct FIO_fds_r FIO_fds;
82
83 typedef FIO_fds *FIO_FileDescriptor;
84
85 typedef struct FIO__T7_a FIO__T7;
86
87 typedef char *FIO_PtrToChar;
88
89 typedef enum {FIO_successful, FIO_outofmemory, FIO_toomanyfilesopen, FIO_failed, FIO_connectionfailure, FIO_endofline, FIO_endoffile} FIO_FileStatus;
90
91 typedef enum {FIO_unused, FIO_openedforread, FIO_openedforwrite, FIO_openedforrandom} FIO_FileUsage;
92
93 struct FIO_NameInfo_r {
94 void *address;
95 unsigned int size;
96 };
97
98 struct FIO_buf_r {
99 bool valid;
100 long int bufstart;
101 unsigned int position;
102 void *address;
103 unsigned int filled;
104 unsigned int size;
105 unsigned int left;
106 FIO__T7 *contents;
107 };
108
109 struct FIO__T7_a { char array[MaxBufferLength+1]; };
110 struct FIO_fds_r {
111 int unixfd;
112 FIO_NameInfo name;
113 FIO_FileStatus state;
114 FIO_FileUsage usage;
115 bool output;
116 FIO_Buffer buffer;
117 long int abspos;
118 };
119
120 static Indexing_Index FileInfo;
121 static FIO_File Error;
122
123 /*
124 IsNoError - returns a TRUE if no error has occured on file, f.
125 */
126
127 extern "C" bool FIO_IsNoError (FIO_File f);
128
129 /*
130 IsActive - returns TRUE if the file, f, is still active.
131 */
132
133 extern "C" bool FIO_IsActive (FIO_File f);
134 extern "C" bool FIO_Exists (const char *fname_, unsigned int _fname_high);
135 extern "C" FIO_File FIO_OpenToRead (const char *fname_, unsigned int _fname_high);
136 extern "C" FIO_File FIO_OpenToWrite (const char *fname_, unsigned int _fname_high);
137 extern "C" FIO_File FIO_OpenForRandom (const char *fname_, unsigned int _fname_high, bool towrite, bool newfile);
138
139 /*
140 Close - close a file which has been previously opened using:
141 OpenToRead, OpenToWrite, OpenForRandom.
142 It is correct to close a file which has an error status.
143 */
144
145 extern "C" void FIO_Close (FIO_File f);
146
147 /*
148 exists - returns TRUE if a file named, fname exists for reading.
149 */
150
151 extern "C" bool FIO_exists (void * fname, unsigned int flength);
152
153 /*
154 openToRead - attempts to open a file, fname, for reading and
155 it returns this file.
156 The success of this operation can be checked by
157 calling IsNoError.
158 */
159
160 extern "C" FIO_File FIO_openToRead (void * fname, unsigned int flength);
161
162 /*
163 openToWrite - attempts to open a file, fname, for write and
164 it returns this file.
165 The success of this operation can be checked by
166 calling IsNoError.
167 */
168
169 extern "C" FIO_File FIO_openToWrite (void * fname, unsigned int flength);
170
171 /*
172 openForRandom - attempts to open a file, fname, for random access
173 read or write and it returns this file.
174 The success of this operation can be checked by
175 calling IsNoError.
176 towrite, determines whether the file should be
177 opened for writing or reading.
178 */
179
180 extern "C" FIO_File FIO_openForRandom (void * fname, unsigned int flength, bool towrite, bool newfile);
181
182 /*
183 FlushBuffer - flush contents of file, f.
184 */
185
186 extern "C" void FIO_FlushBuffer (FIO_File f);
187
188 /*
189 ReadNBytes - reads nBytes of a file into memory area, dest, returning
190 the number of bytes actually read.
191 This function will consume from the buffer and then
192 perform direct libc reads. It is ideal for large reads.
193 */
194
195 extern "C" unsigned int FIO_ReadNBytes (FIO_File f, unsigned int nBytes, void * dest);
196
197 /*
198 ReadAny - reads HIGH (a) + 1 bytes into, a. All input
199 is fully buffered, unlike ReadNBytes and thus is more
200 suited to small reads.
201 */
202
203 extern "C" void FIO_ReadAny (FIO_File f, unsigned char *a, unsigned int _a_high);
204
205 /*
206 WriteNBytes - writes nBytes from memory area src to a file
207 returning the number of bytes actually written.
208 This function will flush the buffer and then
209 write the nBytes using a direct write from libc.
210 It is ideal for large writes.
211 */
212
213 extern "C" unsigned int FIO_WriteNBytes (FIO_File f, unsigned int nBytes, void * src);
214
215 /*
216 WriteAny - writes HIGH (a) + 1 bytes onto, file, f. All output
217 is fully buffered, unlike WriteNBytes and thus is more
218 suited to small writes.
219 */
220
221 extern "C" void FIO_WriteAny (FIO_File f, unsigned char *a, unsigned int _a_high);
222
223 /*
224 WriteChar - writes a single character to file, f.
225 */
226
227 extern "C" void FIO_WriteChar (FIO_File f, char ch);
228
229 /*
230 EOF - tests to see whether a file, f, has reached end of file.
231 */
232
233 extern "C" bool FIO_EOF (FIO_File f);
234
235 /*
236 EOLN - tests to see whether a file, f, is upon a newline.
237 It does NOT consume the newline.
238 */
239
240 extern "C" bool FIO_EOLN (FIO_File f);
241
242 /*
243 WasEOLN - tests to see whether a file, f, has just seen a newline.
244 */
245
246 extern "C" bool FIO_WasEOLN (FIO_File f);
247
248 /*
249 ReadChar - returns a character read from file f.
250 Sensible to check with IsNoError or EOF after calling
251 this function.
252 */
253
254 extern "C" char FIO_ReadChar (FIO_File f);
255
256 /*
257 UnReadChar - replaces a character, ch, back into file f.
258 This character must have been read by ReadChar
259 and it does not allow successive calls. It may
260 only be called if the previous read was successful
261 or end of file was seen.
262 If the state was previously endoffile then it
263 is altered to successful.
264 Otherwise it is left alone.
265 */
266
267 extern "C" void FIO_UnReadChar (FIO_File f, char ch);
268
269 /*
270 WriteLine - writes out a linefeed to file, f.
271 */
272
273 extern "C" void FIO_WriteLine (FIO_File f);
274
275 /*
276 WriteString - writes a string to file, f.
277 */
278
279 extern "C" void FIO_WriteString (FIO_File f, const char *a_, unsigned int _a_high);
280
281 /*
282 ReadString - reads a string from file, f, into string, a.
283 It terminates the string if HIGH is reached or
284 if a newline is seen or an error occurs.
285 */
286
287 extern "C" void FIO_ReadString (FIO_File f, char *a, unsigned int _a_high);
288
289 /*
290 WriteCardinal - writes a CARDINAL to file, f.
291 It writes the binary image of the cardinal
292 to file, f.
293 */
294
295 extern "C" void FIO_WriteCardinal (FIO_File f, unsigned int c);
296
297 /*
298 ReadCardinal - reads a CARDINAL from file, f.
299 It reads a binary image of a CARDINAL
300 from a file, f.
301 */
302
303 extern "C" unsigned int FIO_ReadCardinal (FIO_File f);
304
305 /*
306 GetUnixFileDescriptor - returns the UNIX file descriptor of a file.
307 */
308
309 extern "C" int FIO_GetUnixFileDescriptor (FIO_File f);
310
311 /*
312 SetPositionFromBeginning - sets the position from the beginning of the file.
313 */
314
315 extern "C" void FIO_SetPositionFromBeginning (FIO_File f, long int pos);
316
317 /*
318 SetPositionFromEnd - sets the position from the end of the file.
319 */
320
321 extern "C" void FIO_SetPositionFromEnd (FIO_File f, long int pos);
322
323 /*
324 FindPosition - returns the current absolute position in file, f.
325 */
326
327 extern "C" long int FIO_FindPosition (FIO_File f);
328
329 /*
330 GetFileName - assigns, a, with the filename associated with, f.
331 */
332
333 extern "C" void FIO_GetFileName (FIO_File f, char *a, unsigned int _a_high);
334
335 /*
336 getFileName - returns the address of the filename associated with, f.
337 */
338
339 extern "C" void * FIO_getFileName (FIO_File f);
340
341 /*
342 getFileNameLength - returns the number of characters associated with filename, f.
343 */
344
345 extern "C" unsigned int FIO_getFileNameLength (FIO_File f);
346
347 /*
348 FlushOutErr - flushes, StdOut, and, StdErr.
349 It is also called when the application calls M2RTS.Terminate.
350 (which is automatically placed in program modules by the GM2
351 scaffold).
352 */
353
354 extern "C" void FIO_FlushOutErr (void);
355
356 /*
357 Max - returns the maximum of two values.
358 */
359
360 static unsigned int Max (unsigned int a, unsigned int b);
361
362 /*
363 Min - returns the minimum of two values.
364 */
365
366 static unsigned int Min (unsigned int a, unsigned int b);
367
368 /*
369 GetNextFreeDescriptor - returns the index to the FileInfo array indicating
370 the next free slot.
371 */
372
373 static FIO_File GetNextFreeDescriptor (void);
374
375 /*
376 SetState - sets the field, state, of file, f, to, s.
377 */
378
379 static void SetState (FIO_File f, FIO_FileStatus s);
380
381 /*
382 InitializeFile - initialize a file descriptor
383 */
384
385 static FIO_File InitializeFile (FIO_File f, void * fname, unsigned int flength, FIO_FileStatus fstate, FIO_FileUsage use, bool towrite, unsigned int buflength);
386
387 /*
388 ConnectToUnix - connects a FIO file to a UNIX file descriptor.
389 */
390
391 static void ConnectToUnix (FIO_File f, bool towrite, bool newfile);
392
393 /*
394 ReadFromBuffer - attempts to read, nBytes, from file, f.
395 It firstly consumes the buffer and then performs
396 direct unbuffered reads. This should only be used
397 when wishing to read large files.
398
399 The actual number of bytes read is returned.
400 -1 is returned if EOF is reached.
401 */
402
403 static int ReadFromBuffer (FIO_File f, void * a, unsigned int nBytes);
404
405 /*
406 BufferedRead - will read, nBytes, through the buffer.
407 Similar to ReadFromBuffer, but this function will always
408 read into the buffer before copying into memory.
409
410 Useful when performing small reads.
411 */
412
413 static int BufferedRead (FIO_File f, unsigned int nBytes, void * dest);
414
415 /*
416 HandleEscape - translates
417 and \t into their respective ascii codes.
418 */
419
420 static void HandleEscape (char *dest, unsigned int _dest_high, const char *src_, unsigned int _src_high, unsigned int *i, unsigned int *j, unsigned int HighSrc, unsigned int HighDest);
421
422 /*
423 Cast - casts a := b
424 */
425
426 static void Cast (unsigned char *a, unsigned int _a_high, const unsigned char *b_, unsigned int _b_high);
427
428 /*
429 StringFormat1 - converts string, src, into, dest, together with encapsulated
430 entity, w. It only formats the first %s or %d with n.
431 */
432
433 static void StringFormat1 (char *dest, unsigned int _dest_high, const char *src_, unsigned int _src_high, const unsigned char *w_, unsigned int _w_high);
434
435 /*
436 FormatError - provides a orthoganal counterpart to the procedure below.
437 */
438
439 static void FormatError (const char *a_, unsigned int _a_high);
440
441 /*
442 FormatError1 - generic error procedure taking standard format string
443 and single parameter.
444 */
445
446 static void FormatError1 (const char *a_, unsigned int _a_high, const unsigned char *w_, unsigned int _w_high);
447
448 /*
449 FormatError2 - generic error procedure taking standard format string
450 and two parameters.
451 */
452
453 static void FormatError2 (const char *a_, unsigned int _a_high, const unsigned char *w1_, unsigned int _w1_high, const unsigned char *w2_, unsigned int _w2_high);
454
455 /*
456 CheckAccess - checks to see whether a file f has been
457 opened for read/write.
458 */
459
460 static void CheckAccess (FIO_File f, FIO_FileUsage use, bool towrite);
461
462 /*
463 SetEndOfLine -
464 */
465
466 static void SetEndOfLine (FIO_File f, char ch);
467
468 /*
469 BufferedWrite - will write, nBytes, through the buffer.
470 Similar to WriteNBytes, but this function will always
471 write into the buffer before copying into memory.
472
473 Useful when performing small writes.
474 */
475
476 static int BufferedWrite (FIO_File f, unsigned int nBytes, void * src);
477
478 /*
479 PreInitialize - preinitialize the file descriptor.
480 */
481
482 static void PreInitialize (FIO_File f, const char *fname_, unsigned int _fname_high, FIO_FileStatus state, FIO_FileUsage use, bool towrite, int osfd, unsigned int bufsize);
483
484 /*
485 Init - initialize the modules, global variables.
486 */
487
488 static void Init (void);
489
490
491 /*
492 Max - returns the maximum of two values.
493 */
494
495 static unsigned int Max (unsigned int a, unsigned int b)
496 {
497 if (a > b)
498 {
499 return a;
500 }
501 else
502 {
503 return b;
504 }
505 /* static analysis guarentees a RETURN statement will be used before here. */
506 __builtin_unreachable ();
507 }
508
509
510 /*
511 Min - returns the minimum of two values.
512 */
513
514 static unsigned int Min (unsigned int a, unsigned int b)
515 {
516 if (a < b)
517 {
518 return a;
519 }
520 else
521 {
522 return b;
523 }
524 /* static analysis guarentees a RETURN statement will be used before here. */
525 __builtin_unreachable ();
526 }
527
528
529 /*
530 GetNextFreeDescriptor - returns the index to the FileInfo array indicating
531 the next free slot.
532 */
533
534 static FIO_File GetNextFreeDescriptor (void)
535 {
536 FIO_File f;
537 FIO_File h;
538 FIO_FileDescriptor fd;
539
540 f = Error+1;
541 h = Indexing_HighIndice (FileInfo);
542 for (;;)
543 {
544 if (f <= h)
545 {
546 fd = static_cast<FIO_FileDescriptor> (Indexing_GetIndice (FileInfo, f));
547 if (fd == NULL)
548 {
549 return f;
550 }
551 }
552 f += 1;
553 if (f > h)
554 {
555 Indexing_PutIndice (FileInfo, f, NULL); /* create new slot */
556 return f; /* create new slot */
557 }
558 }
559 ReturnException ("../../gcc-read-write/gcc/m2/gm2-libs/FIO.def", 25, 1);
560 __builtin_unreachable ();
561 }
562
563
564 /*
565 SetState - sets the field, state, of file, f, to, s.
566 */
567
568 static void SetState (FIO_File f, FIO_FileStatus s)
569 {
570 FIO_FileDescriptor fd;
571
572 fd = static_cast<FIO_FileDescriptor> (Indexing_GetIndice (FileInfo, f));
573 fd->state = s;
574 }
575
576
577 /*
578 InitializeFile - initialize a file descriptor
579 */
580
581 static FIO_File InitializeFile (FIO_File f, void * fname, unsigned int flength, FIO_FileStatus fstate, FIO_FileUsage use, bool towrite, unsigned int buflength)
582 {
583 FIO_PtrToChar p;
584 FIO_FileDescriptor fd;
585
586 Storage_ALLOCATE ((void **) &fd, sizeof (FIO_fds));
587 if (fd == NULL)
588 {
589 SetState (Error, FIO_outofmemory);
590 return Error;
591 }
592 else
593 {
594 Indexing_PutIndice (FileInfo, f, reinterpret_cast<void *> (fd));
595 fd->name.size = flength+1; /* need to guarantee the nul for C */
596 fd->usage = use; /* need to guarantee the nul for C */
597 fd->output = towrite;
598 Storage_ALLOCATE (&fd->name.address, fd->name.size);
599 if (fd->name.address == NULL)
600 {
601 fd->state = FIO_outofmemory;
602 return f;
603 }
604 fd->name.address = libc_strncpy (fd->name.address, fname, flength);
605 /* and assign nul to the last byte */
606 p = static_cast<FIO_PtrToChar> (fd->name.address);
607 p += flength;
608 (*p) = ASCII_nul;
609 fd->abspos = 0;
610 /* now for the buffer */
611 Storage_ALLOCATE ((void **) &fd->buffer, sizeof (FIO_buf));
612 if (fd->buffer == NULL)
613 {
614 SetState (Error, FIO_outofmemory);
615 return Error;
616 }
617 else
618 {
619 fd->buffer->valid = false;
620 fd->buffer->bufstart = 0;
621 fd->buffer->size = buflength;
622 fd->buffer->position = 0;
623 fd->buffer->filled = 0;
624 if (fd->buffer->size == 0)
625 {
626 fd->buffer->address = NULL;
627 }
628 else
629 {
630 Storage_ALLOCATE (&fd->buffer->address, fd->buffer->size);
631 if (fd->buffer->address == NULL)
632 {
633 fd->state = FIO_outofmemory;
634 return f;
635 }
636 }
637 if (towrite)
638 {
639 fd->buffer->left = fd->buffer->size;
640 }
641 else
642 {
643 fd->buffer->left = 0;
644 }
645 fd->buffer->contents = reinterpret_cast<FIO__T7 *> (fd->buffer->address); /* provides easy access for reading characters */
646 fd->state = fstate; /* provides easy access for reading characters */
647 }
648 }
649 return f;
650 /* static analysis guarentees a RETURN statement will be used before here. */
651 __builtin_unreachable ();
652 }
653
654
655 /*
656 ConnectToUnix - connects a FIO file to a UNIX file descriptor.
657 */
658
659 static void ConnectToUnix (FIO_File f, bool towrite, bool newfile)
660 {
661 FIO_FileDescriptor fd;
662
663 if (f != Error)
664 {
665 fd = static_cast<FIO_FileDescriptor> (Indexing_GetIndice (FileInfo, f));
666 if (fd != NULL)
667 {
668 if (towrite)
669 {
670 if (newfile)
671 {
672 fd->unixfd = libc_creat (fd->name.address, CreatePermissions);
673 }
674 else
675 {
676 fd->unixfd = libc_open (fd->name.address, UNIXWRITEONLY, 0);
677 }
678 }
679 else
680 {
681 fd->unixfd = libc_open (fd->name.address, UNIXREADONLY, 0);
682 }
683 if (fd->unixfd < 0)
684 {
685 fd->state = FIO_connectionfailure;
686 }
687 }
688 }
689 }
690
691
692 /*
693 ReadFromBuffer - attempts to read, nBytes, from file, f.
694 It firstly consumes the buffer and then performs
695 direct unbuffered reads. This should only be used
696 when wishing to read large files.
697
698 The actual number of bytes read is returned.
699 -1 is returned if EOF is reached.
700 */
701
702 static int ReadFromBuffer (FIO_File f, void * a, unsigned int nBytes)
703 {
704 typedef unsigned char *ReadFromBuffer__T1;
705
706 void * t;
707 int result;
708 unsigned int total;
709 unsigned int n;
710 ReadFromBuffer__T1 p;
711 FIO_FileDescriptor fd;
712
713 if (f != Error)
714 {
715 total = 0; /* how many bytes have we read */
716 fd = static_cast<FIO_FileDescriptor> (Indexing_GetIndice (FileInfo, f)); /* how many bytes have we read */
717 /* extract from the buffer first */
718 if ((fd->buffer != NULL) && fd->buffer->valid)
719 {
720 if (fd->buffer->left > 0)
721 {
722 /* avoid gcc warning by using compound statement even if not strictly necessary. */
723 if (nBytes == 1)
724 {
725 /* too expensive to call memcpy for 1 character */
726 p = static_cast<ReadFromBuffer__T1> (a);
727 (*p) = static_cast<unsigned char> ((*fd->buffer->contents).array[fd->buffer->position]);
728 fd->buffer->left -= 1; /* remove consumed bytes */
729 fd->buffer->position += 1; /* move onwards n bytes */
730 nBytes = 0; /* reduce the amount for future direct */
731 /* read */
732 return 1;
733 }
734 else
735 {
736 n = Min (fd->buffer->left, nBytes);
737 t = fd->buffer->address;
738 t = reinterpret_cast<void *> (reinterpret_cast<char *> (t)+fd->buffer->position);
739 p = static_cast<ReadFromBuffer__T1> (libc_memcpy (a, t, static_cast<size_t> (n)));
740 fd->buffer->left -= n; /* remove consumed bytes */
741 fd->buffer->position += n; /* move onwards n bytes */
742 /* move onwards ready for direct reads */
743 a = reinterpret_cast<void *> (reinterpret_cast<char *> (a)+n);
744 nBytes -= n; /* reduce the amount for future direct */
745 /* read */
746 total += n;
747 return total; /* much cleaner to return now, */
748 }
749 /* difficult to record an error if */
750 }
751 /* the read below returns -1 */
752 }
753 if (nBytes > 0)
754 {
755 /* still more to read */
756 result = static_cast<int> (libc_read (fd->unixfd, a, static_cast<size_t> ((int ) (nBytes))));
757 if (result > 0)
758 {
759 /* avoid dangling else. */
760 total += result;
761 fd->abspos += result;
762 /* now disable the buffer as we read directly into, a. */
763 if (fd->buffer != NULL)
764 {
765 fd->buffer->valid = false;
766 }
767 }
768 else
769 {
770 if (result == 0)
771 {
772 /* eof reached */
773 fd->state = FIO_endoffile;
774 }
775 else
776 {
777 fd->state = FIO_failed;
778 }
779 /* indicate buffer is empty */
780 if (fd->buffer != NULL)
781 {
782 fd->buffer->valid = false;
783 fd->buffer->left = 0;
784 fd->buffer->position = 0;
785 if (fd->buffer->address != NULL)
786 {
787 (*fd->buffer->contents).array[fd->buffer->position] = ASCII_nul;
788 }
789 }
790 return -1;
791 }
792 }
793 return total;
794 }
795 else
796 {
797 return -1;
798 }
799 /* static analysis guarentees a RETURN statement will be used before here. */
800 __builtin_unreachable ();
801 }
802
803
804 /*
805 BufferedRead - will read, nBytes, through the buffer.
806 Similar to ReadFromBuffer, but this function will always
807 read into the buffer before copying into memory.
808
809 Useful when performing small reads.
810 */
811
812 static int BufferedRead (FIO_File f, unsigned int nBytes, void * dest)
813 {
814 typedef unsigned char *BufferedRead__T3;
815
816 void * src;
817 int total;
818 int n;
819 BufferedRead__T3 p;
820 FIO_FileDescriptor fd;
821
822 if (f != Error)
823 {
824 fd = static_cast<FIO_FileDescriptor> (Indexing_GetIndice (FileInfo, f));
825 total = 0; /* how many bytes have we read */
826 if (fd != NULL) /* how many bytes have we read */
827 {
828 /* extract from the buffer first */
829 if (fd->buffer != NULL)
830 {
831 while (nBytes > 0)
832 {
833 if ((fd->buffer->left > 0) && fd->buffer->valid)
834 {
835 if (nBytes == 1)
836 {
837 /* too expensive to call memcpy for 1 character */
838 p = static_cast<BufferedRead__T3> (dest);
839 (*p) = static_cast<unsigned char> ((*fd->buffer->contents).array[fd->buffer->position]);
840 fd->buffer->left -= 1; /* remove consumed byte */
841 fd->buffer->position += 1; /* move onwards n byte */
842 total += 1; /* move onwards n byte */
843 return total;
844 }
845 else
846 {
847 n = Min (fd->buffer->left, nBytes);
848 src = fd->buffer->address;
849 src = reinterpret_cast<void *> (reinterpret_cast<char *> (src)+fd->buffer->position);
850 p = static_cast<BufferedRead__T3> (libc_memcpy (dest, src, static_cast<size_t> (n)));
851 fd->buffer->left -= n; /* remove consumed bytes */
852 fd->buffer->position += n; /* move onwards n bytes */
853 /* move onwards ready for direct reads */
854 dest = reinterpret_cast<void *> (reinterpret_cast<char *> (dest)+n);
855 nBytes -= n; /* reduce the amount for future direct */
856 /* read */
857 total += n;
858 }
859 }
860 else
861 {
862 /* refill buffer */
863 n = static_cast<int> (libc_read (fd->unixfd, fd->buffer->address, static_cast<size_t> (fd->buffer->size)));
864 if (n >= 0)
865 {
866 /* avoid dangling else. */
867 fd->buffer->valid = true;
868 fd->buffer->position = 0;
869 fd->buffer->left = n;
870 fd->buffer->filled = n;
871 fd->buffer->bufstart = fd->abspos;
872 fd->abspos += n;
873 if (n == 0)
874 {
875 /* eof reached */
876 fd->state = FIO_endoffile;
877 return -1;
878 }
879 }
880 else
881 {
882 fd->buffer->valid = false;
883 fd->buffer->position = 0;
884 fd->buffer->left = 0;
885 fd->buffer->filled = 0;
886 fd->state = FIO_failed;
887 return total;
888 }
889 }
890 }
891 return total;
892 }
893 }
894 }
895 return -1;
896 /* static analysis guarentees a RETURN statement will be used before here. */
897 __builtin_unreachable ();
898 }
899
900
901 /*
902 HandleEscape - translates
903 and \t into their respective ascii codes.
904 */
905
906 static void HandleEscape (char *dest, unsigned int _dest_high, const char *src_, unsigned int _src_high, unsigned int *i, unsigned int *j, unsigned int HighSrc, unsigned int HighDest)
907 {
908 char src[_src_high+1];
909
910 /* make a local copy of each unbounded array. */
911 memcpy (src, src_, _src_high+1);
912
913 if (((((*i)+1) < HighSrc) && (src[(*i)] == '\\')) && ((*j) < HighDest))
914 {
915 /* avoid gcc warning by using compound statement even if not strictly necessary. */
916 if (src[(*i)+1] == 'n')
917 {
918 /* requires a newline */
919 dest[(*j)] = ASCII_nl;
920 (*j) += 1;
921 (*i) += 2;
922 }
923 else if (src[(*i)+1] == 't')
924 {
925 /* avoid dangling else. */
926 /* requires a tab (yuck) tempted to fake this but I better not.. */
927 dest[(*j)] = ASCII_tab;
928 (*j) += 1;
929 (*i) += 2;
930 }
931 else
932 {
933 /* avoid dangling else. */
934 /* copy escaped character */
935 (*i) += 1;
936 dest[(*j)] = src[(*i)];
937 (*j) += 1;
938 (*i) += 1;
939 }
940 }
941 }
942
943
944 /*
945 Cast - casts a := b
946 */
947
948 static void Cast (unsigned char *a, unsigned int _a_high, const unsigned char *b_, unsigned int _b_high)
949 {
950 unsigned int i;
951 unsigned char b[_b_high+1];
952
953 /* make a local copy of each unbounded array. */
954 memcpy (b, b_, _b_high+1);
955
956 if (_a_high == _b_high)
957 {
958 for (i=0; i<=_a_high; i++)
959 {
960 a[i] = b[i];
961 }
962 }
963 else
964 {
965 FormatError ((const char *) "cast failed", 11);
966 }
967 }
968
969
970 /*
971 StringFormat1 - converts string, src, into, dest, together with encapsulated
972 entity, w. It only formats the first %s or %d with n.
973 */
974
975 static void StringFormat1 (char *dest, unsigned int _dest_high, const char *src_, unsigned int _src_high, const unsigned char *w_, unsigned int _w_high)
976 {
977 typedef struct StringFormat1__T8_a StringFormat1__T8;
978
979 typedef char *StringFormat1__T4;
980
981 struct StringFormat1__T8_a { char array[MaxErrorString+1]; };
982 unsigned int HighSrc;
983 unsigned int HighDest;
984 unsigned int c;
985 unsigned int i;
986 unsigned int j;
987 StringFormat1__T8 str;
988 StringFormat1__T4 p;
989 char src[_src_high+1];
990 unsigned char w[_w_high+1];
991
992 /* make a local copy of each unbounded array. */
993 memcpy (src, src_, _src_high+1);
994 memcpy (w, w_, _w_high+1);
995
996 HighSrc = StrLib_StrLen ((const char *) src, _src_high);
997 HighDest = _dest_high;
998 p = NULL;
999 c = 0;
1000 i = 0;
1001 j = 0;
1002 while ((((i < HighSrc) && (src[i] != ASCII_nul)) && (j < HighDest)) && (src[i] != '%'))
1003 {
1004 if (src[i] == '\\')
1005 {
1006 HandleEscape ((char *) dest, _dest_high, (const char *) src, _src_high, &i, &j, HighSrc, HighDest);
1007 }
1008 else
1009 {
1010 dest[j] = src[i];
1011 i += 1;
1012 j += 1;
1013 }
1014 }
1015 if ((((i+1) < HighSrc) && (src[i] == '%')) && (j < HighDest))
1016 {
1017 /* avoid gcc warning by using compound statement even if not strictly necessary. */
1018 if (src[i+1] == 's')
1019 {
1020 Cast ((unsigned char *) &p, (sizeof (p)-1), (const unsigned char *) w, _w_high);
1021 while ((j < HighDest) && ((*p) != ASCII_nul))
1022 {
1023 dest[j] = (*p);
1024 j += 1;
1025 p += 1;
1026 }
1027 if (j < HighDest)
1028 {
1029 dest[j] = ASCII_nul;
1030 }
1031 j = StrLib_StrLen ((const char *) dest, _dest_high);
1032 i += 2;
1033 }
1034 else if (src[i+1] == 'd')
1035 {
1036 /* avoid dangling else. */
1037 dest[j] = ASCII_nul;
1038 Cast ((unsigned char *) &c, (sizeof (c)-1), (const unsigned char *) w, _w_high);
1039 NumberIO_CardToStr (c, 0, (char *) &str.array[0], MaxErrorString);
1040 StrLib_StrConCat ((const char *) dest, _dest_high, (const char *) &str.array[0], MaxErrorString, (char *) dest, _dest_high);
1041 j = StrLib_StrLen ((const char *) dest, _dest_high);
1042 i += 2;
1043 }
1044 else
1045 {
1046 /* avoid dangling else. */
1047 dest[j] = src[i];
1048 i += 1;
1049 j += 1;
1050 }
1051 }
1052 /* and finish off copying src into dest */
1053 while (((i < HighSrc) && (src[i] != ASCII_nul)) && (j < HighDest))
1054 {
1055 if (src[i] == '\\')
1056 {
1057 HandleEscape ((char *) dest, _dest_high, (const char *) src, _src_high, &i, &j, HighSrc, HighDest);
1058 }
1059 else
1060 {
1061 dest[j] = src[i];
1062 i += 1;
1063 j += 1;
1064 }
1065 }
1066 if (j < HighDest)
1067 {
1068 dest[j] = ASCII_nul;
1069 }
1070 }
1071
1072
1073 /*
1074 FormatError - provides a orthoganal counterpart to the procedure below.
1075 */
1076
1077 static void FormatError (const char *a_, unsigned int _a_high)
1078 {
1079 char a[_a_high+1];
1080
1081 /* make a local copy of each unbounded array. */
1082 memcpy (a, a_, _a_high+1);
1083
1084 FIO_WriteString (FIO_StdErr, (const char *) a, _a_high);
1085 }
1086
1087
1088 /*
1089 FormatError1 - generic error procedure taking standard format string
1090 and single parameter.
1091 */
1092
1093 static void FormatError1 (const char *a_, unsigned int _a_high, const unsigned char *w_, unsigned int _w_high)
1094 {
1095 typedef struct FormatError1__T9_a FormatError1__T9;
1096
1097 struct FormatError1__T9_a { char array[MaxErrorString+1]; };
1098 FormatError1__T9 s;
1099 char a[_a_high+1];
1100 unsigned char w[_w_high+1];
1101
1102 /* make a local copy of each unbounded array. */
1103 memcpy (a, a_, _a_high+1);
1104 memcpy (w, w_, _w_high+1);
1105
1106 StringFormat1 ((char *) &s.array[0], MaxErrorString, (const char *) a, _a_high, (const unsigned char *) w, _w_high);
1107 FormatError ((const char *) &s.array[0], MaxErrorString);
1108 }
1109
1110
1111 /*
1112 FormatError2 - generic error procedure taking standard format string
1113 and two parameters.
1114 */
1115
1116 static void FormatError2 (const char *a_, unsigned int _a_high, const unsigned char *w1_, unsigned int _w1_high, const unsigned char *w2_, unsigned int _w2_high)
1117 {
1118 typedef struct FormatError2__T10_a FormatError2__T10;
1119
1120 struct FormatError2__T10_a { char array[MaxErrorString+1]; };
1121 FormatError2__T10 s;
1122 char a[_a_high+1];
1123 unsigned char w1[_w1_high+1];
1124 unsigned char w2[_w2_high+1];
1125
1126 /* make a local copy of each unbounded array. */
1127 memcpy (a, a_, _a_high+1);
1128 memcpy (w1, w1_, _w1_high+1);
1129 memcpy (w2, w2_, _w2_high+1);
1130
1131 StringFormat1 ((char *) &s.array[0], MaxErrorString, (const char *) a, _a_high, (const unsigned char *) w1, _w1_high);
1132 FormatError1 ((const char *) &s.array[0], MaxErrorString, (const unsigned char *) w2, _w2_high);
1133 }
1134
1135
1136 /*
1137 CheckAccess - checks to see whether a file f has been
1138 opened for read/write.
1139 */
1140
1141 static void CheckAccess (FIO_File f, FIO_FileUsage use, bool towrite)
1142 {
1143 FIO_FileDescriptor fd;
1144
1145 if (f != Error)
1146 {
1147 /* avoid dangling else. */
1148 fd = static_cast<FIO_FileDescriptor> (Indexing_GetIndice (FileInfo, f));
1149 if (fd == NULL)
1150 {
1151 if (f != FIO_StdErr)
1152 {
1153 FormatError ((const char *) "this file has probably been closed and not reopened successfully or alternatively never opened\\n", 96);
1154 }
1155 M2RTS_HALT (-1);
1156 __builtin_unreachable ();
1157 }
1158 else
1159 {
1160 if ((use == FIO_openedforwrite) && (fd->usage == FIO_openedforread))
1161 {
1162 FormatError1 ((const char *) "this file (%s) has been opened for reading but is now being written\\n", 69, (const unsigned char *) &fd->name.address, (sizeof (fd->name.address)-1));
1163 M2RTS_HALT (-1);
1164 __builtin_unreachable ();
1165 }
1166 else if ((use == FIO_openedforread) && (fd->usage == FIO_openedforwrite))
1167 {
1168 /* avoid dangling else. */
1169 FormatError1 ((const char *) "this file (%s) has been opened for writing but is now being read\\n", 66, (const unsigned char *) &fd->name.address, (sizeof (fd->name.address)-1));
1170 M2RTS_HALT (-1);
1171 __builtin_unreachable ();
1172 }
1173 else if (fd->state == FIO_connectionfailure)
1174 {
1175 /* avoid dangling else. */
1176 FormatError1 ((const char *) "this file (%s) was not successfully opened\\n", 44, (const unsigned char *) &fd->name.address, (sizeof (fd->name.address)-1));
1177 M2RTS_HALT (-1);
1178 __builtin_unreachable ();
1179 }
1180 else if (towrite != fd->output)
1181 {
1182 /* avoid dangling else. */
1183 if (fd->output)
1184 {
1185 FormatError1 ((const char *) "this file (%s) was opened for writing but is now being read\\n", 61, (const unsigned char *) &fd->name.address, (sizeof (fd->name.address)-1));
1186 M2RTS_HALT (-1);
1187 __builtin_unreachable ();
1188 }
1189 else
1190 {
1191 FormatError1 ((const char *) "this file (%s) was opened for reading but is now being written\\n", 64, (const unsigned char *) &fd->name.address, (sizeof (fd->name.address)-1));
1192 M2RTS_HALT (-1);
1193 __builtin_unreachable ();
1194 }
1195 }
1196 }
1197 }
1198 else
1199 {
1200 FormatError ((const char *) "this file has not been opened successfully\\n", 44);
1201 M2RTS_HALT (-1);
1202 __builtin_unreachable ();
1203 }
1204 }
1205
1206
1207 /*
1208 SetEndOfLine -
1209 */
1210
1211 static void SetEndOfLine (FIO_File f, char ch)
1212 {
1213 FIO_FileDescriptor fd;
1214
1215 CheckAccess (f, FIO_openedforread, false);
1216 if (f != Error)
1217 {
1218 fd = static_cast<FIO_FileDescriptor> (Indexing_GetIndice (FileInfo, f));
1219 if (ch == ASCII_nl)
1220 {
1221 fd->state = FIO_endofline;
1222 }
1223 else
1224 {
1225 fd->state = FIO_successful;
1226 }
1227 }
1228 }
1229
1230
1231 /*
1232 BufferedWrite - will write, nBytes, through the buffer.
1233 Similar to WriteNBytes, but this function will always
1234 write into the buffer before copying into memory.
1235
1236 Useful when performing small writes.
1237 */
1238
1239 static int BufferedWrite (FIO_File f, unsigned int nBytes, void * src)
1240 {
1241 typedef unsigned char *BufferedWrite__T5;
1242
1243 void * dest;
1244 int total;
1245 int n;
1246 BufferedWrite__T5 p;
1247 FIO_FileDescriptor fd;
1248
1249 if (f != Error)
1250 {
1251 fd = static_cast<FIO_FileDescriptor> (Indexing_GetIndice (FileInfo, f));
1252 if (fd != NULL)
1253 {
1254 total = 0; /* how many bytes have we read */
1255 if (fd->buffer != NULL) /* how many bytes have we read */
1256 {
1257 /* place into the buffer first */
1258 while (nBytes > 0)
1259 {
1260 if (fd->buffer->left > 0)
1261 {
1262 if (nBytes == 1)
1263 {
1264 /* too expensive to call memcpy for 1 character */
1265 p = static_cast<BufferedWrite__T5> (src);
1266 (*fd->buffer->contents).array[fd->buffer->position] = static_cast<char> ((*p));
1267 fd->buffer->left -= 1; /* reduce space */
1268 fd->buffer->position += 1; /* move onwards n byte */
1269 total += 1; /* move onwards n byte */
1270 return total;
1271 }
1272 else
1273 {
1274 n = Min (fd->buffer->left, nBytes);
1275 dest = fd->buffer->address;
1276 dest = reinterpret_cast<void *> (reinterpret_cast<char *> (dest)+fd->buffer->position);
1277 p = static_cast<BufferedWrite__T5> (libc_memcpy (dest, src, static_cast<size_t> ((unsigned int ) (n))));
1278 fd->buffer->left -= n; /* remove consumed bytes */
1279 fd->buffer->position += n; /* move onwards n bytes */
1280 /* move ready for further writes */
1281 src = reinterpret_cast<void *> (reinterpret_cast<char *> (src)+n);
1282 nBytes -= n; /* reduce the amount for future writes */
1283 total += n; /* reduce the amount for future writes */
1284 }
1285 }
1286 else
1287 {
1288 FIO_FlushBuffer (f);
1289 if ((fd->state != FIO_successful) && (fd->state != FIO_endofline))
1290 {
1291 nBytes = 0;
1292 }
1293 }
1294 }
1295 return total;
1296 }
1297 }
1298 }
1299 return -1;
1300 /* static analysis guarentees a RETURN statement will be used before here. */
1301 __builtin_unreachable ();
1302 }
1303
1304
1305 /*
1306 PreInitialize - preinitialize the file descriptor.
1307 */
1308
1309 static void PreInitialize (FIO_File f, const char *fname_, unsigned int _fname_high, FIO_FileStatus state, FIO_FileUsage use, bool towrite, int osfd, unsigned int bufsize)
1310 {
1311 FIO_FileDescriptor fd;
1312 FIO_FileDescriptor fe;
1313 char fname[_fname_high+1];
1314
1315 /* make a local copy of each unbounded array. */
1316 memcpy (fname, fname_, _fname_high+1);
1317
1318 if ((InitializeFile (f, &fname, StrLib_StrLen ((const char *) fname, _fname_high), state, use, towrite, bufsize)) == f)
1319 {
1320 fd = static_cast<FIO_FileDescriptor> (Indexing_GetIndice (FileInfo, f));
1321 if (f == Error)
1322 {
1323 fe = static_cast<FIO_FileDescriptor> (Indexing_GetIndice (FileInfo, FIO_StdErr));
1324 if (fe == NULL)
1325 {
1326 M2RTS_HALT (-1);
1327 __builtin_unreachable ();
1328 }
1329 else
1330 {
1331 fd->unixfd = fe->unixfd; /* the error channel */
1332 }
1333 }
1334 else
1335 {
1336 fd->unixfd = osfd;
1337 }
1338 }
1339 else
1340 {
1341 M2RTS_HALT (-1);
1342 __builtin_unreachable ();
1343 }
1344 }
1345
1346
1347 /*
1348 Init - initialize the modules, global variables.
1349 */
1350
1351 static void Init (void)
1352 {
1353 FileInfo = Indexing_InitIndex (0);
1354 Error = 0;
1355 PreInitialize (Error, (const char *) "error", 5, FIO_toomanyfilesopen, FIO_unused, false, -1, 0);
1356 FIO_StdIn = 1;
1357 PreInitialize (FIO_StdIn, (const char *) "<stdin>", 7, FIO_successful, FIO_openedforread, false, 0, MaxBufferLength);
1358 FIO_StdOut = 2;
1359 PreInitialize (FIO_StdOut, (const char *) "<stdout>", 8, FIO_successful, FIO_openedforwrite, true, 1, MaxBufferLength);
1360 FIO_StdErr = 3;
1361 PreInitialize (FIO_StdErr, (const char *) "<stderr>", 8, FIO_successful, FIO_openedforwrite, true, 2, MaxBufferLength);
1362 if (! (M2RTS_InstallTerminationProcedure ((PROC ) {(PROC_t) FIO_FlushOutErr})))
1363 {
1364 M2RTS_HALT (-1);
1365 __builtin_unreachable ();
1366 }
1367 }
1368
1369
1370 /*
1371 IsNoError - returns a TRUE if no error has occured on file, f.
1372 */
1373
1374 extern "C" bool FIO_IsNoError (FIO_File f)
1375 {
1376 FIO_FileDescriptor fd;
1377
1378 if (f == Error)
1379 {
1380 return false;
1381 }
1382 else
1383 {
1384 fd = static_cast<FIO_FileDescriptor> (Indexing_GetIndice (FileInfo, f));
1385 return (fd != NULL) && (((fd->state == FIO_successful) || (fd->state == FIO_endoffile)) || (fd->state == FIO_endofline));
1386 }
1387 /* static analysis guarentees a RETURN statement will be used before here. */
1388 __builtin_unreachable ();
1389 }
1390
1391
1392 /*
1393 IsActive - returns TRUE if the file, f, is still active.
1394 */
1395
1396 extern "C" bool FIO_IsActive (FIO_File f)
1397 {
1398 if (f == Error)
1399 {
1400 return false;
1401 }
1402 else
1403 {
1404 return (Indexing_GetIndice (FileInfo, f)) != NULL;
1405 }
1406 /* static analysis guarentees a RETURN statement will be used before here. */
1407 __builtin_unreachable ();
1408 }
1409
1410 extern "C" bool FIO_Exists (const char *fname_, unsigned int _fname_high)
1411 {
1412 char fname[_fname_high+1];
1413
1414 /* make a local copy of each unbounded array. */
1415 memcpy (fname, fname_, _fname_high+1);
1416
1417 /*
1418 The following functions are wrappers for the above.
1419 */
1420 return FIO_exists (&fname, StrLib_StrLen ((const char *) fname, _fname_high));
1421 /* static analysis guarentees a RETURN statement will be used before here. */
1422 __builtin_unreachable ();
1423 }
1424
1425 extern "C" FIO_File FIO_OpenToRead (const char *fname_, unsigned int _fname_high)
1426 {
1427 char fname[_fname_high+1];
1428
1429 /* make a local copy of each unbounded array. */
1430 memcpy (fname, fname_, _fname_high+1);
1431
1432 return FIO_openToRead (&fname, StrLib_StrLen ((const char *) fname, _fname_high));
1433 /* static analysis guarentees a RETURN statement will be used before here. */
1434 __builtin_unreachable ();
1435 }
1436
1437 extern "C" FIO_File FIO_OpenToWrite (const char *fname_, unsigned int _fname_high)
1438 {
1439 char fname[_fname_high+1];
1440
1441 /* make a local copy of each unbounded array. */
1442 memcpy (fname, fname_, _fname_high+1);
1443
1444 return FIO_openToWrite (&fname, StrLib_StrLen ((const char *) fname, _fname_high));
1445 /* static analysis guarentees a RETURN statement will be used before here. */
1446 __builtin_unreachable ();
1447 }
1448
1449 extern "C" FIO_File FIO_OpenForRandom (const char *fname_, unsigned int _fname_high, bool towrite, bool newfile)
1450 {
1451 char fname[_fname_high+1];
1452
1453 /* make a local copy of each unbounded array. */
1454 memcpy (fname, fname_, _fname_high+1);
1455
1456 return FIO_openForRandom (&fname, StrLib_StrLen ((const char *) fname, _fname_high), towrite, newfile);
1457 /* static analysis guarentees a RETURN statement will be used before here. */
1458 __builtin_unreachable ();
1459 }
1460
1461
1462 /*
1463 Close - close a file which has been previously opened using:
1464 OpenToRead, OpenToWrite, OpenForRandom.
1465 It is correct to close a file which has an error status.
1466 */
1467
1468 extern "C" void FIO_Close (FIO_File f)
1469 {
1470 FIO_FileDescriptor fd;
1471
1472 if (f != Error)
1473 {
1474 fd = static_cast<FIO_FileDescriptor> (Indexing_GetIndice (FileInfo, f));
1475 /*
1476 we allow users to close files which have an error status
1477 */
1478 if (fd != NULL)
1479 {
1480 FIO_FlushBuffer (f);
1481 if (fd->unixfd >= 0)
1482 {
1483 if ((libc_close (fd->unixfd)) != 0)
1484 {
1485 FormatError1 ((const char *) "failed to close file (%s)\\n", 27, (const unsigned char *) &fd->name.address, (sizeof (fd->name.address)-1));
1486 fd->state = FIO_failed; /* --fixme-- too late to notify user (unless we return a BOOLEAN) */
1487 }
1488 }
1489 if (fd->name.address != NULL)
1490 {
1491 Storage_DEALLOCATE (&fd->name.address, fd->name.size);
1492 }
1493 if (fd->buffer != NULL)
1494 {
1495 if (fd->buffer->address != NULL)
1496 {
1497 Storage_DEALLOCATE (&fd->buffer->address, fd->buffer->size);
1498 }
1499 Storage_DEALLOCATE ((void **) &fd->buffer, sizeof (FIO_buf));
1500 fd->buffer = NULL;
1501 }
1502 Storage_DEALLOCATE ((void **) &fd, sizeof (FIO_fds));
1503 Indexing_PutIndice (FileInfo, f, NULL);
1504 }
1505 }
1506 }
1507
1508
1509 /*
1510 exists - returns TRUE if a file named, fname exists for reading.
1511 */
1512
1513 extern "C" bool FIO_exists (void * fname, unsigned int flength)
1514 {
1515 FIO_File f;
1516
1517 f = FIO_openToRead (fname, flength);
1518 if (FIO_IsNoError (f))
1519 {
1520 FIO_Close (f);
1521 return true;
1522 }
1523 else
1524 {
1525 FIO_Close (f);
1526 return false;
1527 }
1528 /* static analysis guarentees a RETURN statement will be used before here. */
1529 __builtin_unreachable ();
1530 }
1531
1532
1533 /*
1534 openToRead - attempts to open a file, fname, for reading and
1535 it returns this file.
1536 The success of this operation can be checked by
1537 calling IsNoError.
1538 */
1539
1540 extern "C" FIO_File FIO_openToRead (void * fname, unsigned int flength)
1541 {
1542 FIO_File f;
1543
1544 f = GetNextFreeDescriptor ();
1545 if (f == Error)
1546 {
1547 SetState (f, FIO_toomanyfilesopen);
1548 }
1549 else
1550 {
1551 f = InitializeFile (f, fname, flength, FIO_successful, FIO_openedforread, false, MaxBufferLength);
1552 ConnectToUnix (f, false, false);
1553 }
1554 return f;
1555 /* static analysis guarentees a RETURN statement will be used before here. */
1556 __builtin_unreachable ();
1557 }
1558
1559
1560 /*
1561 openToWrite - attempts to open a file, fname, for write and
1562 it returns this file.
1563 The success of this operation can be checked by
1564 calling IsNoError.
1565 */
1566
1567 extern "C" FIO_File FIO_openToWrite (void * fname, unsigned int flength)
1568 {
1569 FIO_File f;
1570
1571 f = GetNextFreeDescriptor ();
1572 if (f == Error)
1573 {
1574 SetState (f, FIO_toomanyfilesopen);
1575 }
1576 else
1577 {
1578 f = InitializeFile (f, fname, flength, FIO_successful, FIO_openedforwrite, true, MaxBufferLength);
1579 ConnectToUnix (f, true, true);
1580 }
1581 return f;
1582 /* static analysis guarentees a RETURN statement will be used before here. */
1583 __builtin_unreachable ();
1584 }
1585
1586
1587 /*
1588 openForRandom - attempts to open a file, fname, for random access
1589 read or write and it returns this file.
1590 The success of this operation can be checked by
1591 calling IsNoError.
1592 towrite, determines whether the file should be
1593 opened for writing or reading.
1594 */
1595
1596 extern "C" FIO_File FIO_openForRandom (void * fname, unsigned int flength, bool towrite, bool newfile)
1597 {
1598 FIO_File f;
1599
1600 f = GetNextFreeDescriptor ();
1601 if (f == Error)
1602 {
1603 SetState (f, FIO_toomanyfilesopen);
1604 }
1605 else
1606 {
1607 f = InitializeFile (f, fname, flength, FIO_successful, FIO_openedforrandom, towrite, MaxBufferLength);
1608 ConnectToUnix (f, towrite, newfile);
1609 }
1610 return f;
1611 /* static analysis guarentees a RETURN statement will be used before here. */
1612 __builtin_unreachable ();
1613 }
1614
1615
1616 /*
1617 FlushBuffer - flush contents of file, f.
1618 */
1619
1620 extern "C" void FIO_FlushBuffer (FIO_File f)
1621 {
1622 FIO_FileDescriptor fd;
1623
1624 if (f != Error)
1625 {
1626 fd = static_cast<FIO_FileDescriptor> (Indexing_GetIndice (FileInfo, f));
1627 if (fd != NULL)
1628 {
1629 if (fd->output && (fd->buffer != NULL))
1630 {
1631 if ((fd->buffer->position == 0) || ((libc_write (fd->unixfd, fd->buffer->address, static_cast<size_t> (fd->buffer->position))) == ((int ) (fd->buffer->position))))
1632 {
1633 fd->abspos += fd->buffer->position;
1634 fd->buffer->bufstart = fd->abspos;
1635 fd->buffer->position = 0;
1636 fd->buffer->filled = 0;
1637 fd->buffer->left = fd->buffer->size;
1638 }
1639 else
1640 {
1641 fd->state = FIO_failed;
1642 }
1643 }
1644 }
1645 }
1646 }
1647
1648
1649 /*
1650 ReadNBytes - reads nBytes of a file into memory area, dest, returning
1651 the number of bytes actually read.
1652 This function will consume from the buffer and then
1653 perform direct libc reads. It is ideal for large reads.
1654 */
1655
1656 extern "C" unsigned int FIO_ReadNBytes (FIO_File f, unsigned int nBytes, void * dest)
1657 {
1658 typedef char *ReadNBytes__T2;
1659
1660 int n;
1661 ReadNBytes__T2 p;
1662
1663 if (f != Error)
1664 {
1665 CheckAccess (f, FIO_openedforread, false);
1666 n = ReadFromBuffer (f, dest, nBytes);
1667 if (n <= 0)
1668 {
1669 return 0;
1670 }
1671 else
1672 {
1673 p = static_cast<ReadNBytes__T2> (dest);
1674 p += n-1;
1675 SetEndOfLine (f, (*p));
1676 return n;
1677 }
1678 }
1679 else
1680 {
1681 return 0;
1682 }
1683 /* static analysis guarentees a RETURN statement will be used before here. */
1684 __builtin_unreachable ();
1685 }
1686
1687
1688 /*
1689 ReadAny - reads HIGH (a) + 1 bytes into, a. All input
1690 is fully buffered, unlike ReadNBytes and thus is more
1691 suited to small reads.
1692 */
1693
1694 extern "C" void FIO_ReadAny (FIO_File f, unsigned char *a, unsigned int _a_high)
1695 {
1696 CheckAccess (f, FIO_openedforread, false);
1697 if ((BufferedRead (f, _a_high+1, a)) == ((int ) (_a_high+1)))
1698 {
1699 SetEndOfLine (f, static_cast<char> (a[_a_high]));
1700 }
1701 }
1702
1703
1704 /*
1705 WriteNBytes - writes nBytes from memory area src to a file
1706 returning the number of bytes actually written.
1707 This function will flush the buffer and then
1708 write the nBytes using a direct write from libc.
1709 It is ideal for large writes.
1710 */
1711
1712 extern "C" unsigned int FIO_WriteNBytes (FIO_File f, unsigned int nBytes, void * src)
1713 {
1714 int total;
1715 FIO_FileDescriptor fd;
1716
1717 CheckAccess (f, FIO_openedforwrite, true);
1718 FIO_FlushBuffer (f);
1719 if (f != Error)
1720 {
1721 fd = static_cast<FIO_FileDescriptor> (Indexing_GetIndice (FileInfo, f));
1722 if (fd != NULL)
1723 {
1724 total = static_cast<int> (libc_write (fd->unixfd, src, static_cast<size_t> ((int ) (nBytes))));
1725 if (total < 0)
1726 {
1727 fd->state = FIO_failed;
1728 return 0;
1729 }
1730 else
1731 {
1732 fd->abspos += (unsigned int ) (total);
1733 if (fd->buffer != NULL)
1734 {
1735 fd->buffer->bufstart = fd->abspos;
1736 }
1737 return (unsigned int ) (total);
1738 }
1739 }
1740 }
1741 return 0;
1742 /* static analysis guarentees a RETURN statement will be used before here. */
1743 __builtin_unreachable ();
1744 }
1745
1746
1747 /*
1748 WriteAny - writes HIGH (a) + 1 bytes onto, file, f. All output
1749 is fully buffered, unlike WriteNBytes and thus is more
1750 suited to small writes.
1751 */
1752
1753 extern "C" void FIO_WriteAny (FIO_File f, unsigned char *a, unsigned int _a_high)
1754 {
1755 CheckAccess (f, FIO_openedforwrite, true);
1756 if ((BufferedWrite (f, _a_high+1, a)) == ((int ) (_a_high+1)))
1757 {} /* empty. */
1758 }
1759
1760
1761 /*
1762 WriteChar - writes a single character to file, f.
1763 */
1764
1765 extern "C" void FIO_WriteChar (FIO_File f, char ch)
1766 {
1767 CheckAccess (f, FIO_openedforwrite, true);
1768 if ((BufferedWrite (f, sizeof (ch), &ch)) == ((int ) (sizeof (ch))))
1769 {} /* empty. */
1770 }
1771
1772
1773 /*
1774 EOF - tests to see whether a file, f, has reached end of file.
1775 */
1776
1777 extern "C" bool FIO_EOF (FIO_File f)
1778 {
1779 FIO_FileDescriptor fd;
1780
1781 CheckAccess (f, FIO_openedforread, false);
1782 if (f != Error)
1783 {
1784 fd = static_cast<FIO_FileDescriptor> (Indexing_GetIndice (FileInfo, f));
1785 if (fd != NULL)
1786 {
1787 return fd->state == FIO_endoffile;
1788 }
1789 }
1790 return true;
1791 /* static analysis guarentees a RETURN statement will be used before here. */
1792 __builtin_unreachable ();
1793 }
1794
1795
1796 /*
1797 EOLN - tests to see whether a file, f, is upon a newline.
1798 It does NOT consume the newline.
1799 */
1800
1801 extern "C" bool FIO_EOLN (FIO_File f)
1802 {
1803 char ch;
1804 FIO_FileDescriptor fd;
1805
1806 CheckAccess (f, FIO_openedforread, false);
1807 /*
1808 we will read a character and then push it back onto the input stream,
1809 having noted the file status, we also reset the status.
1810 */
1811 if (f != Error)
1812 {
1813 fd = static_cast<FIO_FileDescriptor> (Indexing_GetIndice (FileInfo, f));
1814 if (fd != NULL)
1815 {
1816 if ((fd->state == FIO_successful) || (fd->state == FIO_endofline))
1817 {
1818 ch = FIO_ReadChar (f);
1819 if ((fd->state == FIO_successful) || (fd->state == FIO_endofline))
1820 {
1821 FIO_UnReadChar (f, ch);
1822 }
1823 return ch == ASCII_nl;
1824 }
1825 }
1826 }
1827 return false;
1828 /* static analysis guarentees a RETURN statement will be used before here. */
1829 __builtin_unreachable ();
1830 }
1831
1832
1833 /*
1834 WasEOLN - tests to see whether a file, f, has just seen a newline.
1835 */
1836
1837 extern "C" bool FIO_WasEOLN (FIO_File f)
1838 {
1839 FIO_FileDescriptor fd;
1840
1841 CheckAccess (f, FIO_openedforread, false);
1842 if (f == Error)
1843 {
1844 return false;
1845 }
1846 else
1847 {
1848 fd = static_cast<FIO_FileDescriptor> (Indexing_GetIndice (FileInfo, f));
1849 return (fd != NULL) && (fd->state == FIO_endofline);
1850 }
1851 /* static analysis guarentees a RETURN statement will be used before here. */
1852 __builtin_unreachable ();
1853 }
1854
1855
1856 /*
1857 ReadChar - returns a character read from file f.
1858 Sensible to check with IsNoError or EOF after calling
1859 this function.
1860 */
1861
1862 extern "C" char FIO_ReadChar (FIO_File f)
1863 {
1864 char ch;
1865
1866 CheckAccess (f, FIO_openedforread, false);
1867 if ((BufferedRead (f, sizeof (ch), &ch)) == ((int ) (sizeof (ch))))
1868 {
1869 SetEndOfLine (f, ch);
1870 return ch;
1871 }
1872 else
1873 {
1874 return ASCII_nul;
1875 }
1876 /* static analysis guarentees a RETURN statement will be used before here. */
1877 __builtin_unreachable ();
1878 }
1879
1880
1881 /*
1882 UnReadChar - replaces a character, ch, back into file f.
1883 This character must have been read by ReadChar
1884 and it does not allow successive calls. It may
1885 only be called if the previous read was successful
1886 or end of file was seen.
1887 If the state was previously endoffile then it
1888 is altered to successful.
1889 Otherwise it is left alone.
1890 */
1891
1892 extern "C" void FIO_UnReadChar (FIO_File f, char ch)
1893 {
1894 FIO_FileDescriptor fd;
1895 unsigned int n;
1896 void * a;
1897 void * b;
1898
1899 CheckAccess (f, FIO_openedforread, false);
1900 if (f != Error)
1901 {
1902 fd = static_cast<FIO_FileDescriptor> (Indexing_GetIndice (FileInfo, f));
1903 if (((fd->state == FIO_successful) || (fd->state == FIO_endoffile)) || (fd->state == FIO_endofline))
1904 {
1905 /* avoid dangling else. */
1906 if ((fd->buffer != NULL) && fd->buffer->valid)
1907 {
1908 /* we assume that a ReadChar has occurred, we will check just in case. */
1909 if (fd->state == FIO_endoffile)
1910 {
1911 fd->buffer->position = MaxBufferLength;
1912 fd->buffer->left = 0;
1913 fd->buffer->filled = 0;
1914 fd->state = FIO_successful;
1915 }
1916 if (fd->buffer->position > 0)
1917 {
1918 fd->buffer->position -= 1;
1919 fd->buffer->left += 1;
1920 (*fd->buffer->contents).array[fd->buffer->position] = ch;
1921 }
1922 else
1923 {
1924 /* if possible make room and store ch */
1925 if (fd->buffer->filled == fd->buffer->size)
1926 {
1927 FormatError1 ((const char *) "performing too many UnReadChar calls on file (%d)\\n", 51, (const unsigned char *) &f, (sizeof (f)-1));
1928 }
1929 else
1930 {
1931 n = fd->buffer->filled-fd->buffer->position;
1932 b = &(*fd->buffer->contents).array[fd->buffer->position];
1933 a = &(*fd->buffer->contents).array[fd->buffer->position+1];
1934 a = libc_memcpy (a, b, static_cast<size_t> (n));
1935 fd->buffer->filled += 1;
1936 (*fd->buffer->contents).array[fd->buffer->position] = ch;
1937 }
1938 }
1939 }
1940 }
1941 else
1942 {
1943 FormatError1 ((const char *) "UnReadChar can only be called if the previous read was successful or end of file, error on file (%d)\\n", 102, (const unsigned char *) &f, (sizeof (f)-1));
1944 }
1945 }
1946 }
1947
1948
1949 /*
1950 WriteLine - writes out a linefeed to file, f.
1951 */
1952
1953 extern "C" void FIO_WriteLine (FIO_File f)
1954 {
1955 FIO_WriteChar (f, ASCII_nl);
1956 }
1957
1958
1959 /*
1960 WriteString - writes a string to file, f.
1961 */
1962
1963 extern "C" void FIO_WriteString (FIO_File f, const char *a_, unsigned int _a_high)
1964 {
1965 unsigned int l;
1966 char a[_a_high+1];
1967
1968 /* make a local copy of each unbounded array. */
1969 memcpy (a, a_, _a_high+1);
1970
1971 l = StrLib_StrLen ((const char *) a, _a_high);
1972 if ((FIO_WriteNBytes (f, l, &a)) != l)
1973 {} /* empty. */
1974 }
1975
1976
1977 /*
1978 ReadString - reads a string from file, f, into string, a.
1979 It terminates the string if HIGH is reached or
1980 if a newline is seen or an error occurs.
1981 */
1982
1983 extern "C" void FIO_ReadString (FIO_File f, char *a, unsigned int _a_high)
1984 {
1985 unsigned int high;
1986 unsigned int i;
1987 char ch;
1988
1989 CheckAccess (f, FIO_openedforread, false);
1990 high = _a_high;
1991 i = 0;
1992 do {
1993 ch = FIO_ReadChar (f);
1994 if (i <= high)
1995 {
1996 /* avoid gcc warning by using compound statement even if not strictly necessary. */
1997 if (((ch == ASCII_nl) || (! (FIO_IsNoError (f)))) || (FIO_EOF (f)))
1998 {
1999 a[i] = ASCII_nul;
2000 i += 1;
2001 }
2002 else
2003 {
2004 a[i] = ch;
2005 i += 1;
2006 }
2007 }
2008 } while (! ((((ch == ASCII_nl) || (i > high)) || (! (FIO_IsNoError (f)))) || (FIO_EOF (f))));
2009 }
2010
2011
2012 /*
2013 WriteCardinal - writes a CARDINAL to file, f.
2014 It writes the binary image of the cardinal
2015 to file, f.
2016 */
2017
2018 extern "C" void FIO_WriteCardinal (FIO_File f, unsigned int c)
2019 {
2020 FIO_WriteAny (f, (unsigned char *) &c, (sizeof (c)-1));
2021 }
2022
2023
2024 /*
2025 ReadCardinal - reads a CARDINAL from file, f.
2026 It reads a binary image of a CARDINAL
2027 from a file, f.
2028 */
2029
2030 extern "C" unsigned int FIO_ReadCardinal (FIO_File f)
2031 {
2032 unsigned int c;
2033
2034 FIO_ReadAny (f, (unsigned char *) &c, (sizeof (c)-1));
2035 return c;
2036 /* static analysis guarentees a RETURN statement will be used before here. */
2037 __builtin_unreachable ();
2038 }
2039
2040
2041 /*
2042 GetUnixFileDescriptor - returns the UNIX file descriptor of a file.
2043 */
2044
2045 extern "C" int FIO_GetUnixFileDescriptor (FIO_File f)
2046 {
2047 FIO_FileDescriptor fd;
2048
2049 if (f != Error)
2050 {
2051 fd = static_cast<FIO_FileDescriptor> (Indexing_GetIndice (FileInfo, f));
2052 if (fd != NULL)
2053 {
2054 return fd->unixfd;
2055 }
2056 }
2057 FormatError1 ((const char *) "file %d has not been opened or is out of range\\n", 48, (const unsigned char *) &f, (sizeof (f)-1));
2058 return -1;
2059 /* static analysis guarentees a RETURN statement will be used before here. */
2060 __builtin_unreachable ();
2061 }
2062
2063
2064 /*
2065 SetPositionFromBeginning - sets the position from the beginning of the file.
2066 */
2067
2068 extern "C" void FIO_SetPositionFromBeginning (FIO_File f, long int pos)
2069 {
2070 long int offset;
2071 FIO_FileDescriptor fd;
2072
2073 if (f != Error)
2074 {
2075 fd = static_cast<FIO_FileDescriptor> (Indexing_GetIndice (FileInfo, f));
2076 if (fd != NULL)
2077 {
2078 /* always force the lseek, until we are confident that abspos is always correct,
2079 basically it needs some hard testing before we should remove the OR TRUE. */
2080 if ((fd->abspos != pos) || true)
2081 {
2082 FIO_FlushBuffer (f);
2083 if (fd->buffer != NULL)
2084 {
2085 if (fd->output)
2086 {
2087 fd->buffer->left = fd->buffer->size;
2088 }
2089 else
2090 {
2091 fd->buffer->left = 0;
2092 }
2093 fd->buffer->position = 0;
2094 fd->buffer->filled = 0;
2095 }
2096 offset = libc_lseek (fd->unixfd, pos, SEEK_SET);
2097 if ((offset >= 0) && (pos == offset))
2098 {
2099 fd->abspos = pos;
2100 }
2101 else
2102 {
2103 fd->state = FIO_failed;
2104 fd->abspos = 0;
2105 }
2106 if (fd->buffer != NULL)
2107 {
2108 fd->buffer->valid = false;
2109 fd->buffer->bufstart = fd->abspos;
2110 }
2111 }
2112 }
2113 }
2114 }
2115
2116
2117 /*
2118 SetPositionFromEnd - sets the position from the end of the file.
2119 */
2120
2121 extern "C" void FIO_SetPositionFromEnd (FIO_File f, long int pos)
2122 {
2123 long int offset;
2124 FIO_FileDescriptor fd;
2125
2126 if (f != Error)
2127 {
2128 fd = static_cast<FIO_FileDescriptor> (Indexing_GetIndice (FileInfo, f));
2129 if (fd != NULL)
2130 {
2131 FIO_FlushBuffer (f);
2132 if (fd->buffer != NULL)
2133 {
2134 if (fd->output)
2135 {
2136 fd->buffer->left = fd->buffer->size;
2137 }
2138 else
2139 {
2140 fd->buffer->left = 0;
2141 }
2142 fd->buffer->position = 0;
2143 fd->buffer->filled = 0;
2144 }
2145 offset = libc_lseek (fd->unixfd, pos, SEEK_END);
2146 if (offset >= 0)
2147 {
2148 fd->abspos = offset;
2149 }
2150 else
2151 {
2152 fd->state = FIO_failed;
2153 fd->abspos = 0;
2154 offset = 0;
2155 }
2156 if (fd->buffer != NULL)
2157 {
2158 fd->buffer->valid = false;
2159 fd->buffer->bufstart = offset;
2160 }
2161 }
2162 }
2163 }
2164
2165
2166 /*
2167 FindPosition - returns the current absolute position in file, f.
2168 */
2169
2170 extern "C" long int FIO_FindPosition (FIO_File f)
2171 {
2172 FIO_FileDescriptor fd;
2173
2174 if (f != Error)
2175 {
2176 fd = static_cast<FIO_FileDescriptor> (Indexing_GetIndice (FileInfo, f));
2177 if (fd != NULL)
2178 {
2179 if ((fd->buffer == NULL) || ! fd->buffer->valid)
2180 {
2181 return fd->abspos;
2182 }
2183 else
2184 {
2185 return fd->buffer->bufstart+((long int ) (fd->buffer->position));
2186 }
2187 }
2188 }
2189 return 0;
2190 /* static analysis guarentees a RETURN statement will be used before here. */
2191 __builtin_unreachable ();
2192 }
2193
2194
2195 /*
2196 GetFileName - assigns, a, with the filename associated with, f.
2197 */
2198
2199 extern "C" void FIO_GetFileName (FIO_File f, char *a, unsigned int _a_high)
2200 {
2201 typedef char *GetFileName__T6;
2202
2203 unsigned int i;
2204 GetFileName__T6 p;
2205 FIO_FileDescriptor fd;
2206
2207 if (f != Error)
2208 {
2209 fd = static_cast<FIO_FileDescriptor> (Indexing_GetIndice (FileInfo, f));
2210 if (fd == NULL)
2211 {
2212 FormatError ((const char *) "this file has probably been closed and not reopened successfully or alternatively never opened\\n", 96);
2213 M2RTS_HALT (-1);
2214 __builtin_unreachable ();
2215 }
2216 else
2217 {
2218 if (fd->name.address == NULL)
2219 {
2220 StrLib_StrCopy ((const char *) "", 0, (char *) a, _a_high);
2221 }
2222 else
2223 {
2224 p = static_cast<GetFileName__T6> (fd->name.address);
2225 i = 0;
2226 while (((*p) != ASCII_nul) && (i <= _a_high))
2227 {
2228 a[i] = (*p);
2229 p += 1;
2230 i += 1;
2231 }
2232 }
2233 }
2234 }
2235 }
2236
2237
2238 /*
2239 getFileName - returns the address of the filename associated with, f.
2240 */
2241
2242 extern "C" void * FIO_getFileName (FIO_File f)
2243 {
2244 FIO_FileDescriptor fd;
2245
2246 if (f != Error)
2247 {
2248 fd = static_cast<FIO_FileDescriptor> (Indexing_GetIndice (FileInfo, f));
2249 if (fd == NULL)
2250 {
2251 FormatError ((const char *) "this file has probably been closed and not reopened successfully or alternatively never opened\\n", 96);
2252 M2RTS_HALT (-1);
2253 __builtin_unreachable ();
2254 }
2255 else
2256 {
2257 return fd->name.address;
2258 }
2259 }
2260 return NULL;
2261 /* static analysis guarentees a RETURN statement will be used before here. */
2262 __builtin_unreachable ();
2263 }
2264
2265
2266 /*
2267 getFileNameLength - returns the number of characters associated with filename, f.
2268 */
2269
2270 extern "C" unsigned int FIO_getFileNameLength (FIO_File f)
2271 {
2272 FIO_FileDescriptor fd;
2273
2274 if (f != Error)
2275 {
2276 fd = static_cast<FIO_FileDescriptor> (Indexing_GetIndice (FileInfo, f));
2277 if (fd == NULL)
2278 {
2279 FormatError ((const char *) "this file has probably been closed and not reopened successfully or alternatively never opened\\n", 96);
2280 M2RTS_HALT (-1);
2281 __builtin_unreachable ();
2282 }
2283 else
2284 {
2285 return fd->name.size;
2286 }
2287 }
2288 return 0;
2289 /* static analysis guarentees a RETURN statement will be used before here. */
2290 __builtin_unreachable ();
2291 }
2292
2293
2294 /*
2295 FlushOutErr - flushes, StdOut, and, StdErr.
2296 It is also called when the application calls M2RTS.Terminate.
2297 (which is automatically placed in program modules by the GM2
2298 scaffold).
2299 */
2300
2301 extern "C" void FIO_FlushOutErr (void)
2302 {
2303 if (FIO_IsNoError (FIO_StdOut))
2304 {
2305 FIO_FlushBuffer (FIO_StdOut);
2306 }
2307 if (FIO_IsNoError (FIO_StdErr))
2308 {
2309 FIO_FlushBuffer (FIO_StdErr);
2310 }
2311 }
2312
2313 extern "C" void _M2_FIO_init (__attribute__((unused)) int argc,__attribute__((unused)) char *argv[],__attribute__((unused)) char *envp[])
2314 {
2315 Init ();
2316 }
2317
2318 extern "C" void _M2_FIO_fini (__attribute__((unused)) int argc,__attribute__((unused)) char *argv[],__attribute__((unused)) char *envp[])
2319 {
2320 FIO_FlushOutErr ();
2321 }