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