Daily bump.
[official-gcc.git] / gcc / m2 / mc-boot / GFIO.cc
blobda373933d0935d7077051b6721486382c2a7766b
1 /* do not edit automatically generated by mc from FIO. */
2 /* FIO.mod provides a simple buffered file input/output library.
4 Copyright (C) 2001-2025 Free Software Foundation, Inc.
5 Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>.
7 This file is part of GNU Modula-2.
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.
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.
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.
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/>. */
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
37 # if !defined (TRUE)
38 # define TRUE (1==1)
39 # endif
41 # if !defined (FALSE)
42 # define FALSE (1==0)
43 # endif
45 # include "GStorage.h"
46 # include "Gmcrts.h"
47 #if defined(__cplusplus)
48 # undef NULL
49 # define NULL 0
50 #endif
51 #define _FIO_C
53 #include "GFIO.h"
54 # include "GSYSTEM.h"
55 # include "GASCII.h"
56 # include "GStrLib.h"
57 # include "GStorage.h"
58 # include "GNumberIO.h"
59 # include "GIndexing.h"
60 # include "GM2RTS.h"
61 # include "Glibc.h"
62 # include "Gwrapc.h"
64 typedef unsigned int FIO_File;
66 # define MaxBufferLength (1024*16)
67 # define MaxErrorString (1024*8)
68 # define CreatePermissions 0666
69 typedef struct FIO_NameInfo_r FIO_NameInfo;
71 typedef struct FIO_buf_r FIO_buf;
73 typedef FIO_buf *FIO_Buffer;
75 typedef struct FIO_fds_r FIO_fds;
77 typedef FIO_fds *FIO_FileDescriptor;
79 typedef struct FIO__T7_a FIO__T7;
81 typedef char *FIO_PtrToChar;
83 typedef enum {FIO_successful, FIO_outofmemory, FIO_toomanyfilesopen, FIO_failed, FIO_connectionfailure, FIO_endofline, FIO_endoffile} FIO_FileStatus;
85 typedef enum {FIO_unused, FIO_openedforread, FIO_openedforwrite, FIO_openedforrandom} FIO_FileUsage;
87 struct FIO_NameInfo_r {
88 void * address;
89 unsigned int size;
92 struct FIO_buf_r {
93 bool valid;
94 long int bufstart;
95 unsigned int position;
96 void * address;
97 unsigned int filled;
98 unsigned int size;
99 unsigned int left;
100 FIO__T7 * contents;
103 struct FIO__T7_a { char array[MaxBufferLength+1]; };
104 struct FIO_fds_r {
105 int unixfd;
106 FIO_NameInfo name;
107 FIO_FileStatus state;
108 FIO_FileUsage usage;
109 bool output;
110 FIO_Buffer buffer;
111 long int abspos;
114 static Indexing_Index FileInfo;
115 static FIO_File Error;
118 IsNoError - returns a TRUE if no error has occured on file, f.
121 extern "C" bool FIO_IsNoError (FIO_File f);
124 IsActive - returns TRUE if the file, f, is still active.
127 extern "C" bool FIO_IsActive (FIO_File f);
128 extern "C" bool FIO_Exists (const char *fname_, unsigned int _fname_high);
129 extern "C" FIO_File FIO_OpenToRead (const char *fname_, unsigned int _fname_high);
130 extern "C" FIO_File FIO_OpenToWrite (const char *fname_, unsigned int _fname_high);
131 extern "C" FIO_File FIO_OpenForRandom (const char *fname_, unsigned int _fname_high, bool towrite, bool newfile);
134 Close - close a file which has been previously opened using:
135 OpenToRead, OpenToWrite, OpenForRandom.
136 It is correct to close a file which has an error status.
139 extern "C" void FIO_Close (FIO_File f);
142 exists - returns TRUE if a file named, fname exists for reading.
145 extern "C" bool FIO_exists (void * fname, unsigned int flength);
148 openToRead - attempts to open a file, fname, for reading and
149 it returns this file.
150 The success of this operation can be checked by
151 calling IsNoError.
154 extern "C" FIO_File FIO_openToRead (void * fname, unsigned int flength);
157 openToWrite - attempts to open a file, fname, for write and
158 it returns this file.
159 The success of this operation can be checked by
160 calling IsNoError.
163 extern "C" FIO_File FIO_openToWrite (void * fname, unsigned int flength);
166 openForRandom - attempts to open a file, fname, for random access
167 read or write and it returns this file.
168 The success of this operation can be checked by
169 calling IsNoError.
170 towrite, determines whether the file should be
171 opened for writing or reading.
174 extern "C" FIO_File FIO_openForRandom (void * fname, unsigned int flength, bool towrite, bool newfile);
177 FlushBuffer - flush contents of file, f.
180 extern "C" void FIO_FlushBuffer (FIO_File f);
183 ReadNBytes - reads nBytes of a file into memory area, dest, returning
184 the number of bytes actually read.
185 This function will consume from the buffer and then
186 perform direct libc reads. It is ideal for large reads.
189 extern "C" unsigned int FIO_ReadNBytes (FIO_File f, unsigned int nBytes, void * dest);
192 ReadAny - reads HIGH (a) + 1 bytes into, a. All input
193 is fully buffered, unlike ReadNBytes and thus is more
194 suited to small reads.
197 extern "C" void FIO_ReadAny (FIO_File f, unsigned char *a, unsigned int _a_high);
200 WriteNBytes - writes nBytes from memory area src to a file
201 returning the number of bytes actually written.
202 This function will flush the buffer and then
203 write the nBytes using a direct write from libc.
204 It is ideal for large writes.
207 extern "C" unsigned int FIO_WriteNBytes (FIO_File f, unsigned int nBytes, void * src);
210 WriteAny - writes HIGH (a) + 1 bytes onto, file, f. All output
211 is fully buffered, unlike WriteNBytes and thus is more
212 suited to small writes.
215 extern "C" void FIO_WriteAny (FIO_File f, unsigned char *a, unsigned int _a_high);
218 WriteChar - writes a single character to file, f.
221 extern "C" void FIO_WriteChar (FIO_File f, char ch);
224 EOF - tests to see whether a file, f, has reached end of file.
227 extern "C" bool FIO_EOF (FIO_File f);
230 EOLN - tests to see whether a file, f, is upon a newline.
231 It does NOT consume the newline.
234 extern "C" bool FIO_EOLN (FIO_File f);
237 WasEOLN - tests to see whether a file, f, has just seen a newline.
240 extern "C" bool FIO_WasEOLN (FIO_File f);
243 ReadChar - returns a character read from file f.
244 Sensible to check with IsNoError or EOF after calling
245 this function.
248 extern "C" char FIO_ReadChar (FIO_File f);
251 UnReadChar - replaces a character, ch, back into file f.
252 This character must have been read by ReadChar
253 and it does not allow successive calls. It may
254 only be called if the previous read was successful
255 or end of file was seen.
256 If the state was previously endoffile then it
257 is altered to successful.
258 Otherwise it is left alone.
261 extern "C" void FIO_UnReadChar (FIO_File f, char ch);
264 WriteLine - writes out a linefeed to file, f.
267 extern "C" void FIO_WriteLine (FIO_File f);
270 WriteString - writes a string to file, f.
273 extern "C" void FIO_WriteString (FIO_File f, const char *a_, unsigned int _a_high);
276 ReadString - reads a string from file, f, into string, a.
277 It terminates the string if HIGH is reached or
278 if a newline is seen or an error occurs.
281 extern "C" void FIO_ReadString (FIO_File f, char *a, unsigned int _a_high);
284 WriteCardinal - writes a CARDINAL to file, f.
285 It writes the binary image of the cardinal
286 to file, f.
289 extern "C" void FIO_WriteCardinal (FIO_File f, unsigned int c);
292 ReadCardinal - reads a CARDINAL from file, f.
293 It reads a binary image of a CARDINAL
294 from a file, f.
297 extern "C" unsigned int FIO_ReadCardinal (FIO_File f);
300 GetUnixFileDescriptor - returns the UNIX file descriptor of a file.
303 extern "C" int FIO_GetUnixFileDescriptor (FIO_File f);
306 SetPositionFromBeginning - sets the position from the beginning of the file.
309 extern "C" void FIO_SetPositionFromBeginning (FIO_File f, long int pos);
312 SetPositionFromEnd - sets the position from the end of the file.
315 extern "C" void FIO_SetPositionFromEnd (FIO_File f, long int pos);
318 FindPosition - returns the current absolute position in file, f.
321 extern "C" long int FIO_FindPosition (FIO_File f);
324 GetFileName - assigns, a, with the filename associated with, f.
327 extern "C" void FIO_GetFileName (FIO_File f, char *a, unsigned int _a_high);
330 getFileName - returns the address of the filename associated with, f.
333 extern "C" void * FIO_getFileName (FIO_File f);
336 getFileNameLength - returns the number of characters associated with filename, f.
339 extern "C" unsigned int FIO_getFileNameLength (FIO_File f);
342 FlushOutErr - flushes, StdOut, and, StdErr.
343 It is also called when the application calls M2RTS.Terminate.
344 (which is automatically placed in program modules by the GM2
345 scaffold).
348 extern "C" void FIO_FlushOutErr (void);
351 Max - returns the maximum of two values.
354 static unsigned int Max (unsigned int a, unsigned int b);
357 Min - returns the minimum of two values.
360 static unsigned int Min (unsigned int a, unsigned int b);
363 GetNextFreeDescriptor - returns the index to the FileInfo array indicating
364 the next free slot.
367 static FIO_File GetNextFreeDescriptor (void);
370 SetState - sets the field, state, of file, f, to, s.
373 static void SetState (FIO_File f, FIO_FileStatus s);
376 InitializeFile - initialize a file descriptor
379 static FIO_File InitializeFile (FIO_File f, void * fname, unsigned int flength, FIO_FileStatus fstate, FIO_FileUsage use, bool towrite, unsigned int buflength);
382 ConnectToUnix - connects a FIO file to a UNIX file descriptor.
385 static void ConnectToUnix (FIO_File f, bool towrite, bool newfile);
388 ReadFromBuffer - attempts to read, nBytes, from file, f.
389 It firstly consumes the buffer and then performs
390 direct unbuffered reads. This should only be used
391 when wishing to read large files.
393 The actual number of bytes read is returned.
394 -1 is returned if EOF is reached.
397 static int ReadFromBuffer (FIO_File f, void * a, unsigned int nBytes);
400 BufferedRead - will read, nBytes, through the buffer.
401 Similar to ReadFromBuffer, but this function will always
402 read into the buffer before copying into memory.
404 Useful when performing small reads.
407 static int BufferedRead (FIO_File f, unsigned int nBytes, void * dest);
410 HandleEscape - translates
411 and \t into their respective ascii codes.
414 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);
417 Cast - casts a := b
420 static void Cast (unsigned char *a, unsigned int _a_high, const unsigned char *b_, unsigned int _b_high);
423 StringFormat1 - converts string, src, into, dest, together with encapsulated
424 entity, w. It only formats the first %s or %d with n.
427 static void StringFormat1 (char *dest, unsigned int _dest_high, const char *src_, unsigned int _src_high, const unsigned char *w_, unsigned int _w_high);
430 FormatError - provides a orthoganal counterpart to the procedure below.
433 static void FormatError (const char *a_, unsigned int _a_high);
436 FormatError1 - generic error procedure taking standard format string
437 and single parameter.
440 static void FormatError1 (const char *a_, unsigned int _a_high, const unsigned char *w_, unsigned int _w_high);
443 FormatError2 - generic error procedure taking standard format string
444 and two parameters.
447 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);
450 CheckAccess - checks to see whether a file f has been
451 opened for read/write.
454 static void CheckAccess (FIO_File f, FIO_FileUsage use, bool towrite);
457 SetEndOfLine -
460 static void SetEndOfLine (FIO_File f, char ch);
463 BufferedWrite - will write, nBytes, through the buffer.
464 Similar to WriteNBytes, but this function will always
465 write into the buffer before copying into memory.
467 Useful when performing small writes.
470 static int BufferedWrite (FIO_File f, unsigned int nBytes, void * src);
473 PreInitialize - preinitialize the file descriptor.
476 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);
479 Init - initialize the modules, global variables.
482 static void Init (void);
486 Max - returns the maximum of two values.
489 static unsigned int Max (unsigned int a, unsigned int b)
491 if (a > b)
493 return a;
495 else
497 return b;
499 /* static analysis guarentees a RETURN statement will be used before here. */
500 __builtin_unreachable ();
505 Min - returns the minimum of two values.
508 static unsigned int Min (unsigned int a, unsigned int b)
510 if (a < b)
512 return a;
514 else
516 return b;
518 /* static analysis guarentees a RETURN statement will be used before here. */
519 __builtin_unreachable ();
524 GetNextFreeDescriptor - returns the index to the FileInfo array indicating
525 the next free slot.
528 static FIO_File GetNextFreeDescriptor (void)
530 FIO_File f;
531 FIO_File h;
532 FIO_FileDescriptor fd;
534 f = Error+1;
535 h = Indexing_HighIndice (FileInfo);
536 for (;;)
538 if (f <= h)
540 fd = static_cast<FIO_FileDescriptor> (Indexing_GetIndice (FileInfo, f));
541 if (fd == NULL)
543 return f;
546 f += 1;
547 if (f > h)
549 Indexing_PutIndice (FileInfo, f, NULL); /* create new slot */
550 return f; /* create new slot */
553 ReturnException ("../../gcc/m2/gm2-libs/FIO.def", 25, 1);
554 __builtin_unreachable ();
559 SetState - sets the field, state, of file, f, to, s.
562 static void SetState (FIO_File f, FIO_FileStatus s)
564 FIO_FileDescriptor fd;
566 fd = static_cast<FIO_FileDescriptor> (Indexing_GetIndice (FileInfo, f));
567 fd->state = s;
572 InitializeFile - initialize a file descriptor
575 static FIO_File InitializeFile (FIO_File f, void * fname, unsigned int flength, FIO_FileStatus fstate, FIO_FileUsage use, bool towrite, unsigned int buflength)
577 FIO_PtrToChar p;
578 FIO_FileDescriptor fd;
580 Storage_ALLOCATE ((void **) &fd, sizeof (FIO_fds));
581 if (fd == NULL)
583 SetState (Error, FIO_outofmemory);
584 return Error;
586 else
588 Indexing_PutIndice (FileInfo, f, reinterpret_cast <void *> (fd));
589 fd->name.size = flength+1; /* need to guarantee the nul for C */
590 fd->usage = use; /* need to guarantee the nul for C */
591 fd->output = towrite;
592 Storage_ALLOCATE (&fd->name.address, fd->name.size);
593 if (fd->name.address == NULL)
595 fd->state = FIO_outofmemory;
596 return f;
598 fd->name.address = libc_strncpy (fd->name.address, fname, flength);
599 /* and assign nul to the last byte */
600 p = static_cast<FIO_PtrToChar> (fd->name.address);
601 p += flength;
602 (*p) = ASCII_nul;
603 fd->abspos = 0;
604 /* now for the buffer */
605 Storage_ALLOCATE ((void **) &fd->buffer, sizeof (FIO_buf));
606 if (fd->buffer == NULL)
608 SetState (Error, FIO_outofmemory);
609 return Error;
611 else
613 fd->buffer->valid = false;
614 fd->buffer->bufstart = 0;
615 fd->buffer->size = buflength;
616 fd->buffer->position = 0;
617 fd->buffer->filled = 0;
618 if (fd->buffer->size == 0)
620 fd->buffer->address = NULL;
622 else
624 Storage_ALLOCATE (&fd->buffer->address, fd->buffer->size);
625 if (fd->buffer->address == NULL)
627 fd->state = FIO_outofmemory;
628 return f;
631 if (towrite)
633 fd->buffer->left = fd->buffer->size;
635 else
637 fd->buffer->left = 0;
639 fd->buffer->contents = static_cast<FIO__T7 *> (fd->buffer->address); /* provides easy access for reading characters */
640 fd->state = fstate; /* provides easy access for reading characters */
643 return f;
644 /* static analysis guarentees a RETURN statement will be used before here. */
645 __builtin_unreachable ();
650 ConnectToUnix - connects a FIO file to a UNIX file descriptor.
653 static void ConnectToUnix (FIO_File f, bool towrite, bool newfile)
655 FIO_FileDescriptor fd;
657 if (f != Error)
659 fd = static_cast<FIO_FileDescriptor> (Indexing_GetIndice (FileInfo, f));
660 if (fd != NULL)
662 if (towrite)
664 if (newfile)
666 fd->unixfd = libc_creat (fd->name.address, CreatePermissions);
668 else
670 fd->unixfd = libc_open (fd->name.address, (int ) (wrapc_WriteOnly ()), 0);
673 else
675 fd->unixfd = libc_open (fd->name.address, (int ) (wrapc_ReadOnly ()), 0);
677 if (fd->unixfd < 0)
679 fd->state = FIO_connectionfailure;
687 ReadFromBuffer - attempts to read, nBytes, from file, f.
688 It firstly consumes the buffer and then performs
689 direct unbuffered reads. This should only be used
690 when wishing to read large files.
692 The actual number of bytes read is returned.
693 -1 is returned if EOF is reached.
696 static int ReadFromBuffer (FIO_File f, void * a, unsigned int nBytes)
698 typedef unsigned char *ReadFromBuffer__T1;
700 void * t;
701 int result;
702 unsigned int total;
703 unsigned int n;
704 ReadFromBuffer__T1 p;
705 FIO_FileDescriptor fd;
707 if (f != Error)
709 total = 0; /* how many bytes have we read */
710 fd = static_cast<FIO_FileDescriptor> (Indexing_GetIndice (FileInfo, f)); /* how many bytes have we read */
711 /* extract from the buffer first */
712 if ((fd->buffer != NULL) && fd->buffer->valid)
714 if (fd->buffer->left > 0)
716 /* avoid gcc warning by using compound statement even if not strictly necessary. */
717 if (nBytes == 1)
719 /* too expensive to call memcpy for 1 character */
720 p = static_cast<ReadFromBuffer__T1> (a);
721 (*p) = static_cast<unsigned char> ((*fd->buffer->contents).array[fd->buffer->position]);
722 fd->buffer->left -= 1; /* remove consumed bytes */
723 fd->buffer->position += 1; /* move onwards n bytes */
724 nBytes = 0; /* reduce the amount for future direct */
725 /* read */
726 return 1;
728 else
730 n = Min (fd->buffer->left, nBytes);
731 t = fd->buffer->address;
732 t = reinterpret_cast<void *> (reinterpret_cast<char *> (t)+fd->buffer->position);
733 p = static_cast<ReadFromBuffer__T1> (libc_memcpy (a, t, static_cast<size_t> (n)));
734 fd->buffer->left -= n; /* remove consumed bytes */
735 fd->buffer->position += n; /* move onwards n bytes */
736 /* move onwards ready for direct reads */
737 a = reinterpret_cast<void *> (reinterpret_cast<char *> (a)+n);
738 nBytes -= n; /* reduce the amount for future direct */
739 /* read */
740 total += n;
741 return total; /* much cleaner to return now, */
743 /* difficult to record an error if */
745 /* the read below returns -1 */
747 if (nBytes > 0)
749 /* still more to read */
750 result = static_cast<int> (libc_read (fd->unixfd, a, static_cast<size_t> ((int ) (nBytes))));
751 if (result > 0)
753 /* avoid dangling else. */
754 total += result;
755 fd->abspos += result;
756 /* now disable the buffer as we read directly into, a. */
757 if (fd->buffer != NULL)
759 fd->buffer->valid = false;
762 else
764 if (result == 0)
766 /* eof reached */
767 fd->state = FIO_endoffile;
769 else
771 fd->state = FIO_failed;
773 /* indicate buffer is empty */
774 if (fd->buffer != NULL)
776 fd->buffer->valid = false;
777 fd->buffer->left = 0;
778 fd->buffer->position = 0;
779 if (fd->buffer->address != NULL)
781 (*fd->buffer->contents).array[fd->buffer->position] = ASCII_nul;
784 return -1;
787 return total;
789 else
791 return -1;
793 /* static analysis guarentees a RETURN statement will be used before here. */
794 __builtin_unreachable ();
799 BufferedRead - will read, nBytes, through the buffer.
800 Similar to ReadFromBuffer, but this function will always
801 read into the buffer before copying into memory.
803 Useful when performing small reads.
806 static int BufferedRead (FIO_File f, unsigned int nBytes, void * dest)
808 typedef unsigned char *BufferedRead__T3;
810 void * src;
811 int total;
812 int n;
813 BufferedRead__T3 p;
814 FIO_FileDescriptor fd;
816 if (f != Error)
818 fd = static_cast<FIO_FileDescriptor> (Indexing_GetIndice (FileInfo, f));
819 total = 0; /* how many bytes have we read */
820 if (fd != NULL) /* how many bytes have we read */
822 /* extract from the buffer first */
823 if (fd->buffer != NULL)
825 while (nBytes > 0)
827 if ((fd->buffer->left > 0) && fd->buffer->valid)
829 if (nBytes == 1)
831 /* too expensive to call memcpy for 1 character */
832 p = static_cast<BufferedRead__T3> (dest);
833 (*p) = static_cast<unsigned char> ((*fd->buffer->contents).array[fd->buffer->position]);
834 fd->buffer->left -= 1; /* remove consumed byte */
835 fd->buffer->position += 1; /* move onwards n byte */
836 total += 1; /* move onwards n byte */
837 return total;
839 else
841 n = Min (fd->buffer->left, nBytes);
842 src = fd->buffer->address;
843 src = reinterpret_cast<void *> (reinterpret_cast<char *> (src)+fd->buffer->position);
844 p = static_cast<BufferedRead__T3> (libc_memcpy (dest, src, static_cast<size_t> (n)));
845 fd->buffer->left -= n; /* remove consumed bytes */
846 fd->buffer->position += n; /* move onwards n bytes */
847 /* move onwards ready for direct reads */
848 dest = reinterpret_cast<void *> (reinterpret_cast<char *> (dest)+n);
849 nBytes -= n; /* reduce the amount for future direct */
850 /* read */
851 total += n;
854 else
856 /* refill buffer */
857 n = static_cast<int> (libc_read (fd->unixfd, fd->buffer->address, static_cast<size_t> (fd->buffer->size)));
858 if (n >= 0)
860 /* avoid dangling else. */
861 fd->buffer->valid = true;
862 fd->buffer->position = 0;
863 fd->buffer->left = n;
864 fd->buffer->filled = n;
865 fd->buffer->bufstart = fd->abspos;
866 fd->abspos += n;
867 if (n == 0)
869 /* eof reached */
870 fd->state = FIO_endoffile;
871 return -1;
874 else
876 fd->buffer->valid = false;
877 fd->buffer->position = 0;
878 fd->buffer->left = 0;
879 fd->buffer->filled = 0;
880 fd->state = FIO_failed;
881 return total;
885 return total;
889 return -1;
890 /* static analysis guarentees a RETURN statement will be used before here. */
891 __builtin_unreachable ();
896 HandleEscape - translates
897 and \t into their respective ascii codes.
900 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)
902 char src[_src_high+1];
904 /* make a local copy of each unbounded array. */
905 memcpy (src, src_, _src_high+1);
907 if (((((*i)+1) < HighSrc) && (src[(*i)] == '\\')) && ((*j) < HighDest))
909 /* avoid gcc warning by using compound statement even if not strictly necessary. */
910 if (src[(*i)+1] == 'n')
912 /* requires a newline */
913 const_cast<char *>(dest)[(*j)] = ASCII_nl;
914 (*j) += 1;
915 (*i) += 2;
917 else if (src[(*i)+1] == 't')
919 /* avoid dangling else. */
920 /* requires a tab (yuck) tempted to fake this but I better not.. */
921 const_cast<char *>(dest)[(*j)] = ASCII_tab;
922 (*j) += 1;
923 (*i) += 2;
925 else
927 /* avoid dangling else. */
928 /* copy escaped character */
929 (*i) += 1;
930 const_cast<char *>(dest)[(*j)] = src[(*i)];
931 (*j) += 1;
932 (*i) += 1;
939 Cast - casts a := b
942 static void Cast (unsigned char *a, unsigned int _a_high, const unsigned char *b_, unsigned int _b_high)
944 unsigned int i;
945 unsigned char b[_b_high+1];
947 /* make a local copy of each unbounded array. */
948 memcpy (b, b_, _b_high+1);
950 if (_a_high == _b_high)
952 for (i=0; i<=_a_high; i++)
954 const_cast<unsigned char *>(a)[i] = b[i];
957 else
959 FormatError ((const char *) "cast failed", 11);
965 StringFormat1 - converts string, src, into, dest, together with encapsulated
966 entity, w. It only formats the first %s or %d with n.
969 static void StringFormat1 (char *dest, unsigned int _dest_high, const char *src_, unsigned int _src_high, const unsigned char *w_, unsigned int _w_high)
971 typedef struct StringFormat1__T8_a StringFormat1__T8;
973 typedef char *StringFormat1__T4;
975 struct StringFormat1__T8_a { char array[MaxErrorString+1]; };
976 unsigned int HighSrc;
977 unsigned int HighDest;
978 unsigned int c;
979 unsigned int i;
980 unsigned int j;
981 StringFormat1__T8 str;
982 StringFormat1__T4 p;
983 char src[_src_high+1];
984 unsigned char w[_w_high+1];
986 /* make a local copy of each unbounded array. */
987 memcpy (src, src_, _src_high+1);
988 memcpy (w, w_, _w_high+1);
990 HighSrc = StrLib_StrLen ((const char *) src, _src_high);
991 HighDest = _dest_high;
992 p = NULL;
993 c = 0;
994 i = 0;
995 j = 0;
996 while ((((i < HighSrc) && (src[i] != ASCII_nul)) && (j < HighDest)) && (src[i] != '%'))
998 if (src[i] == '\\')
1000 HandleEscape ((char *) dest, _dest_high, (const char *) src, _src_high, &i, &j, HighSrc, HighDest);
1002 else
1004 const_cast<char *>(dest)[j] = src[i];
1005 i += 1;
1006 j += 1;
1009 if ((((i+1) < HighSrc) && (src[i] == '%')) && (j < HighDest))
1011 /* avoid gcc warning by using compound statement even if not strictly necessary. */
1012 if (src[i+1] == 's')
1014 Cast ((unsigned char *) &p, (sizeof (p)-1), (const unsigned char *) w, _w_high);
1015 while ((j < HighDest) && ((*p) != ASCII_nul))
1017 const_cast<char *>(dest)[j] = (*p);
1018 j += 1;
1019 p += 1;
1021 if (j < HighDest)
1023 const_cast<char *>(dest)[j] = ASCII_nul;
1025 j = StrLib_StrLen ((const char *) dest, _dest_high);
1026 i += 2;
1028 else if (src[i+1] == 'd')
1030 /* avoid dangling else. */
1031 const_cast<char *>(dest)[j] = ASCII_nul;
1032 Cast ((unsigned char *) &c, (sizeof (c)-1), (const unsigned char *) w, _w_high);
1033 NumberIO_CardToStr (c, 0, (char *) &str.array[0], MaxErrorString);
1034 StrLib_StrConCat ((const char *) dest, _dest_high, (const char *) &str.array[0], MaxErrorString, (char *) dest, _dest_high);
1035 j = StrLib_StrLen ((const char *) dest, _dest_high);
1036 i += 2;
1038 else
1040 /* avoid dangling else. */
1041 const_cast<char *>(dest)[j] = src[i];
1042 i += 1;
1043 j += 1;
1046 /* and finish off copying src into dest */
1047 while (((i < HighSrc) && (src[i] != ASCII_nul)) && (j < HighDest))
1049 if (src[i] == '\\')
1051 HandleEscape ((char *) dest, _dest_high, (const char *) src, _src_high, &i, &j, HighSrc, HighDest);
1053 else
1055 const_cast<char *>(dest)[j] = src[i];
1056 i += 1;
1057 j += 1;
1060 if (j < HighDest)
1062 const_cast<char *>(dest)[j] = ASCII_nul;
1068 FormatError - provides a orthoganal counterpart to the procedure below.
1071 static void FormatError (const char *a_, unsigned int _a_high)
1073 char a[_a_high+1];
1075 /* make a local copy of each unbounded array. */
1076 memcpy (a, a_, _a_high+1);
1078 FIO_WriteString (FIO_StdErr, (const char *) a, _a_high);
1083 FormatError1 - generic error procedure taking standard format string
1084 and single parameter.
1087 static void FormatError1 (const char *a_, unsigned int _a_high, const unsigned char *w_, unsigned int _w_high)
1089 typedef struct FormatError1__T9_a FormatError1__T9;
1091 struct FormatError1__T9_a { char array[MaxErrorString+1]; };
1092 FormatError1__T9 s;
1093 char a[_a_high+1];
1094 unsigned char w[_w_high+1];
1096 /* make a local copy of each unbounded array. */
1097 memcpy (a, a_, _a_high+1);
1098 memcpy (w, w_, _w_high+1);
1100 StringFormat1 ((char *) &s.array[0], MaxErrorString, (const char *) a, _a_high, (const unsigned char *) w, _w_high);
1101 FormatError ((const char *) &s.array[0], MaxErrorString);
1106 FormatError2 - generic error procedure taking standard format string
1107 and two parameters.
1110 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)
1112 typedef struct FormatError2__T10_a FormatError2__T10;
1114 struct FormatError2__T10_a { char array[MaxErrorString+1]; };
1115 FormatError2__T10 s;
1116 char a[_a_high+1];
1117 unsigned char w1[_w1_high+1];
1118 unsigned char w2[_w2_high+1];
1120 /* make a local copy of each unbounded array. */
1121 memcpy (a, a_, _a_high+1);
1122 memcpy (w1, w1_, _w1_high+1);
1123 memcpy (w2, w2_, _w2_high+1);
1125 StringFormat1 ((char *) &s.array[0], MaxErrorString, (const char *) a, _a_high, (const unsigned char *) w1, _w1_high);
1126 FormatError1 ((const char *) &s.array[0], MaxErrorString, (const unsigned char *) w2, _w2_high);
1131 CheckAccess - checks to see whether a file f has been
1132 opened for read/write.
1135 static void CheckAccess (FIO_File f, FIO_FileUsage use, bool towrite)
1137 FIO_FileDescriptor fd;
1139 if (f != Error)
1141 /* avoid dangling else. */
1142 fd = static_cast<FIO_FileDescriptor> (Indexing_GetIndice (FileInfo, f));
1143 if (fd == NULL)
1145 if (f != FIO_StdErr)
1147 FormatError ((const char *) "this file has probably been closed and not reopened successfully or alternatively never opened\\n", 96);
1149 M2RTS_HALT (-1);
1150 __builtin_unreachable ();
1152 else
1154 if ((use == FIO_openedforwrite) && (fd->usage == FIO_openedforread))
1156 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));
1157 M2RTS_HALT (-1);
1158 __builtin_unreachable ();
1160 else if ((use == FIO_openedforread) && (fd->usage == FIO_openedforwrite))
1162 /* avoid dangling else. */
1163 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));
1164 M2RTS_HALT (-1);
1165 __builtin_unreachable ();
1167 else if (fd->state == FIO_connectionfailure)
1169 /* avoid dangling else. */
1170 FormatError1 ((const char *) "this file (%s) was not successfully opened\\n", 44, (const unsigned char *) &fd->name.address, (sizeof (fd->name.address)-1));
1171 M2RTS_HALT (-1);
1172 __builtin_unreachable ();
1174 else if (towrite != fd->output)
1176 /* avoid dangling else. */
1177 if (fd->output)
1179 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));
1180 M2RTS_HALT (-1);
1181 __builtin_unreachable ();
1183 else
1185 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));
1186 M2RTS_HALT (-1);
1187 __builtin_unreachable ();
1192 else
1194 FormatError ((const char *) "this file has not been opened successfully\\n", 44);
1195 M2RTS_HALT (-1);
1196 __builtin_unreachable ();
1202 SetEndOfLine -
1205 static void SetEndOfLine (FIO_File f, char ch)
1207 FIO_FileDescriptor fd;
1209 CheckAccess (f, FIO_openedforread, false);
1210 if (f != Error)
1212 fd = static_cast<FIO_FileDescriptor> (Indexing_GetIndice (FileInfo, f));
1213 if (ch == ASCII_nl)
1215 fd->state = FIO_endofline;
1217 else
1219 fd->state = FIO_successful;
1226 BufferedWrite - will write, nBytes, through the buffer.
1227 Similar to WriteNBytes, but this function will always
1228 write into the buffer before copying into memory.
1230 Useful when performing small writes.
1233 static int BufferedWrite (FIO_File f, unsigned int nBytes, void * src)
1235 typedef unsigned char *BufferedWrite__T5;
1237 void * dest;
1238 int total;
1239 int n;
1240 BufferedWrite__T5 p;
1241 FIO_FileDescriptor fd;
1243 if (f != Error)
1245 fd = static_cast<FIO_FileDescriptor> (Indexing_GetIndice (FileInfo, f));
1246 if (fd != NULL)
1248 total = 0; /* how many bytes have we read */
1249 if (fd->buffer != NULL) /* how many bytes have we read */
1251 /* place into the buffer first */
1252 while (nBytes > 0)
1254 if (fd->buffer->left > 0)
1256 if (nBytes == 1)
1258 /* too expensive to call memcpy for 1 character */
1259 p = static_cast<BufferedWrite__T5> (src);
1260 (*fd->buffer->contents).array[fd->buffer->position] = static_cast<char> ((*p));
1261 fd->buffer->left -= 1; /* reduce space */
1262 fd->buffer->position += 1; /* move onwards n byte */
1263 total += 1; /* move onwards n byte */
1264 return total;
1266 else
1268 n = Min (fd->buffer->left, nBytes);
1269 dest = fd->buffer->address;
1270 dest = reinterpret_cast<void *> (reinterpret_cast<char *> (dest)+fd->buffer->position);
1271 p = static_cast<BufferedWrite__T5> (libc_memcpy (dest, src, static_cast<size_t> ((unsigned int ) (n))));
1272 fd->buffer->left -= n; /* remove consumed bytes */
1273 fd->buffer->position += n; /* move onwards n bytes */
1274 /* move ready for further writes */
1275 src = reinterpret_cast<void *> (reinterpret_cast<char *> (src)+n);
1276 nBytes -= n; /* reduce the amount for future writes */
1277 total += n; /* reduce the amount for future writes */
1280 else
1282 FIO_FlushBuffer (f);
1283 if ((fd->state != FIO_successful) && (fd->state != FIO_endofline))
1285 nBytes = 0;
1289 return total;
1293 return -1;
1294 /* static analysis guarentees a RETURN statement will be used before here. */
1295 __builtin_unreachable ();
1300 PreInitialize - preinitialize the file descriptor.
1303 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)
1305 FIO_FileDescriptor fd;
1306 FIO_FileDescriptor fe;
1307 char fname[_fname_high+1];
1309 /* make a local copy of each unbounded array. */
1310 memcpy (fname, fname_, _fname_high+1);
1312 if ((InitializeFile (f, const_cast<void*> (static_cast<const void*>(fname)), StrLib_StrLen ((const char *) fname, _fname_high), state, use, towrite, bufsize)) == f)
1314 fd = static_cast<FIO_FileDescriptor> (Indexing_GetIndice (FileInfo, f));
1315 if (f == Error)
1317 fe = static_cast<FIO_FileDescriptor> (Indexing_GetIndice (FileInfo, FIO_StdErr));
1318 if (fe == NULL)
1320 M2RTS_HALT (-1);
1321 __builtin_unreachable ();
1323 else
1325 fd->unixfd = fe->unixfd; /* the error channel */
1328 else
1330 fd->unixfd = osfd;
1333 else
1335 M2RTS_HALT (-1);
1336 __builtin_unreachable ();
1342 Init - initialize the modules, global variables.
1345 static void Init (void)
1347 FileInfo = Indexing_InitIndex (0);
1348 Error = 0;
1349 PreInitialize (Error, (const char *) "error", 5, FIO_toomanyfilesopen, FIO_unused, false, -1, 0);
1350 FIO_StdIn = 1;
1351 PreInitialize (FIO_StdIn, (const char *) "<stdin>", 7, FIO_successful, FIO_openedforread, false, 0, MaxBufferLength);
1352 FIO_StdOut = 2;
1353 PreInitialize (FIO_StdOut, (const char *) "<stdout>", 8, FIO_successful, FIO_openedforwrite, true, 1, MaxBufferLength);
1354 FIO_StdErr = 3;
1355 PreInitialize (FIO_StdErr, (const char *) "<stderr>", 8, FIO_successful, FIO_openedforwrite, true, 2, MaxBufferLength);
1356 if (! (M2RTS_InstallTerminationProcedure ((PROC ) {(PROC_t) FIO_FlushOutErr})))
1358 M2RTS_HALT (-1);
1359 __builtin_unreachable ();
1365 IsNoError - returns a TRUE if no error has occured on file, f.
1368 extern "C" bool FIO_IsNoError (FIO_File f)
1370 FIO_FileDescriptor fd;
1372 if (f == Error)
1374 return false;
1376 else
1378 fd = static_cast<FIO_FileDescriptor> (Indexing_GetIndice (FileInfo, f));
1379 return (fd != NULL) && (((fd->state == FIO_successful) || (fd->state == FIO_endoffile)) || (fd->state == FIO_endofline));
1381 /* static analysis guarentees a RETURN statement will be used before here. */
1382 __builtin_unreachable ();
1387 IsActive - returns TRUE if the file, f, is still active.
1390 extern "C" bool FIO_IsActive (FIO_File f)
1392 if (f == Error)
1394 return false;
1396 else
1398 return (Indexing_GetIndice (FileInfo, f)) != NULL;
1400 /* static analysis guarentees a RETURN statement will be used before here. */
1401 __builtin_unreachable ();
1404 extern "C" bool FIO_Exists (const char *fname_, unsigned int _fname_high)
1406 char fname[_fname_high+1];
1408 /* make a local copy of each unbounded array. */
1409 memcpy (fname, fname_, _fname_high+1);
1412 The following functions are wrappers for the above.
1414 return FIO_exists (const_cast<void*> (static_cast<const void*>(fname)), StrLib_StrLen ((const char *) fname, _fname_high));
1415 /* static analysis guarentees a RETURN statement will be used before here. */
1416 __builtin_unreachable ();
1419 extern "C" FIO_File FIO_OpenToRead (const char *fname_, unsigned int _fname_high)
1421 char fname[_fname_high+1];
1423 /* make a local copy of each unbounded array. */
1424 memcpy (fname, fname_, _fname_high+1);
1426 return FIO_openToRead (const_cast<void*> (static_cast<const void*>(fname)), StrLib_StrLen ((const char *) fname, _fname_high));
1427 /* static analysis guarentees a RETURN statement will be used before here. */
1428 __builtin_unreachable ();
1431 extern "C" FIO_File FIO_OpenToWrite (const char *fname_, unsigned int _fname_high)
1433 char fname[_fname_high+1];
1435 /* make a local copy of each unbounded array. */
1436 memcpy (fname, fname_, _fname_high+1);
1438 return FIO_openToWrite (const_cast<void*> (static_cast<const void*>(fname)), StrLib_StrLen ((const char *) fname, _fname_high));
1439 /* static analysis guarentees a RETURN statement will be used before here. */
1440 __builtin_unreachable ();
1443 extern "C" FIO_File FIO_OpenForRandom (const char *fname_, unsigned int _fname_high, bool towrite, bool newfile)
1445 char fname[_fname_high+1];
1447 /* make a local copy of each unbounded array. */
1448 memcpy (fname, fname_, _fname_high+1);
1450 return FIO_openForRandom (const_cast<void*> (static_cast<const void*>(fname)), StrLib_StrLen ((const char *) fname, _fname_high), towrite, newfile);
1451 /* static analysis guarentees a RETURN statement will be used before here. */
1452 __builtin_unreachable ();
1457 Close - close a file which has been previously opened using:
1458 OpenToRead, OpenToWrite, OpenForRandom.
1459 It is correct to close a file which has an error status.
1462 extern "C" void FIO_Close (FIO_File f)
1464 FIO_FileDescriptor fd;
1466 if (f != Error)
1468 fd = static_cast<FIO_FileDescriptor> (Indexing_GetIndice (FileInfo, f));
1470 we allow users to close files which have an error status
1472 if (fd != NULL)
1474 FIO_FlushBuffer (f);
1475 if (fd->unixfd >= 0)
1477 if ((libc_close (fd->unixfd)) != 0)
1479 FormatError1 ((const char *) "failed to close file (%s)\\n", 27, (const unsigned char *) &fd->name.address, (sizeof (fd->name.address)-1));
1480 fd->state = FIO_failed; /* --fixme-- too late to notify user (unless we return a BOOLEAN) */
1483 if (fd->name.address != NULL)
1485 Storage_DEALLOCATE (&fd->name.address, fd->name.size);
1487 if (fd->buffer != NULL)
1489 if (fd->buffer->address != NULL)
1491 Storage_DEALLOCATE (&fd->buffer->address, fd->buffer->size);
1493 Storage_DEALLOCATE ((void **) &fd->buffer, sizeof (FIO_buf));
1494 fd->buffer = NULL;
1496 Storage_DEALLOCATE ((void **) &fd, sizeof (FIO_fds));
1497 Indexing_PutIndice (FileInfo, f, NULL);
1504 exists - returns TRUE if a file named, fname exists for reading.
1507 extern "C" bool FIO_exists (void * fname, unsigned int flength)
1509 FIO_File f;
1511 f = FIO_openToRead (fname, flength);
1512 if (FIO_IsNoError (f))
1514 FIO_Close (f);
1515 return true;
1517 else
1519 FIO_Close (f);
1520 return false;
1522 /* static analysis guarentees a RETURN statement will be used before here. */
1523 __builtin_unreachable ();
1528 openToRead - attempts to open a file, fname, for reading and
1529 it returns this file.
1530 The success of this operation can be checked by
1531 calling IsNoError.
1534 extern "C" FIO_File FIO_openToRead (void * fname, unsigned int flength)
1536 FIO_File f;
1538 f = GetNextFreeDescriptor ();
1539 if (f == Error)
1541 SetState (f, FIO_toomanyfilesopen);
1543 else
1545 f = InitializeFile (f, fname, flength, FIO_successful, FIO_openedforread, false, MaxBufferLength);
1546 ConnectToUnix (f, false, false);
1548 return f;
1549 /* static analysis guarentees a RETURN statement will be used before here. */
1550 __builtin_unreachable ();
1555 openToWrite - attempts to open a file, fname, for write and
1556 it returns this file.
1557 The success of this operation can be checked by
1558 calling IsNoError.
1561 extern "C" FIO_File FIO_openToWrite (void * fname, unsigned int flength)
1563 FIO_File f;
1565 f = GetNextFreeDescriptor ();
1566 if (f == Error)
1568 SetState (f, FIO_toomanyfilesopen);
1570 else
1572 f = InitializeFile (f, fname, flength, FIO_successful, FIO_openedforwrite, true, MaxBufferLength);
1573 ConnectToUnix (f, true, true);
1575 return f;
1576 /* static analysis guarentees a RETURN statement will be used before here. */
1577 __builtin_unreachable ();
1582 openForRandom - attempts to open a file, fname, for random access
1583 read or write and it returns this file.
1584 The success of this operation can be checked by
1585 calling IsNoError.
1586 towrite, determines whether the file should be
1587 opened for writing or reading.
1590 extern "C" FIO_File FIO_openForRandom (void * fname, unsigned int flength, bool towrite, bool newfile)
1592 FIO_File f;
1594 f = GetNextFreeDescriptor ();
1595 if (f == Error)
1597 SetState (f, FIO_toomanyfilesopen);
1599 else
1601 f = InitializeFile (f, fname, flength, FIO_successful, FIO_openedforrandom, towrite, MaxBufferLength);
1602 ConnectToUnix (f, towrite, newfile);
1604 return f;
1605 /* static analysis guarentees a RETURN statement will be used before here. */
1606 __builtin_unreachable ();
1611 FlushBuffer - flush contents of file, f.
1614 extern "C" void FIO_FlushBuffer (FIO_File f)
1616 FIO_FileDescriptor fd;
1618 if (f != Error)
1620 fd = static_cast<FIO_FileDescriptor> (Indexing_GetIndice (FileInfo, f));
1621 if (fd != NULL)
1623 if (fd->output && (fd->buffer != NULL))
1625 if ((fd->buffer->position == 0) || ((libc_write (fd->unixfd, fd->buffer->address, static_cast<size_t> (fd->buffer->position))) == ((int ) (fd->buffer->position))))
1627 fd->abspos += fd->buffer->position;
1628 fd->buffer->bufstart = fd->abspos;
1629 fd->buffer->position = 0;
1630 fd->buffer->filled = 0;
1631 fd->buffer->left = fd->buffer->size;
1633 else
1635 fd->state = FIO_failed;
1644 ReadNBytes - reads nBytes of a file into memory area, dest, returning
1645 the number of bytes actually read.
1646 This function will consume from the buffer and then
1647 perform direct libc reads. It is ideal for large reads.
1650 extern "C" unsigned int FIO_ReadNBytes (FIO_File f, unsigned int nBytes, void * dest)
1652 typedef char *ReadNBytes__T2;
1654 int n;
1655 ReadNBytes__T2 p;
1657 if (f != Error)
1659 CheckAccess (f, FIO_openedforread, false);
1660 n = ReadFromBuffer (f, dest, nBytes);
1661 if (n <= 0)
1663 return 0;
1665 else
1667 p = static_cast<ReadNBytes__T2> (dest);
1668 p += n-1;
1669 SetEndOfLine (f, (*p));
1670 return n;
1673 else
1675 return 0;
1677 /* static analysis guarentees a RETURN statement will be used before here. */
1678 __builtin_unreachable ();
1683 ReadAny - reads HIGH (a) + 1 bytes into, a. All input
1684 is fully buffered, unlike ReadNBytes and thus is more
1685 suited to small reads.
1688 extern "C" void FIO_ReadAny (FIO_File f, unsigned char *a, unsigned int _a_high)
1690 CheckAccess (f, FIO_openedforread, false);
1691 if ((BufferedRead (f, _a_high+1, a)) == ((int ) (_a_high+1)))
1693 SetEndOfLine (f, static_cast<char> (a[_a_high]));
1699 WriteNBytes - writes nBytes from memory area src to a file
1700 returning the number of bytes actually written.
1701 This function will flush the buffer and then
1702 write the nBytes using a direct write from libc.
1703 It is ideal for large writes.
1706 extern "C" unsigned int FIO_WriteNBytes (FIO_File f, unsigned int nBytes, void * src)
1708 int total;
1709 FIO_FileDescriptor fd;
1711 CheckAccess (f, FIO_openedforwrite, true);
1712 FIO_FlushBuffer (f);
1713 if (f != Error)
1715 fd = static_cast<FIO_FileDescriptor> (Indexing_GetIndice (FileInfo, f));
1716 if (fd != NULL)
1718 total = static_cast<int> (libc_write (fd->unixfd, src, static_cast<size_t> ((int ) (nBytes))));
1719 if (total < 0)
1721 fd->state = FIO_failed;
1722 return 0;
1724 else
1726 fd->abspos += (unsigned int ) (total);
1727 if (fd->buffer != NULL)
1729 fd->buffer->bufstart = fd->abspos;
1731 return (unsigned int ) (total);
1735 return 0;
1736 /* static analysis guarentees a RETURN statement will be used before here. */
1737 __builtin_unreachable ();
1742 WriteAny - writes HIGH (a) + 1 bytes onto, file, f. All output
1743 is fully buffered, unlike WriteNBytes and thus is more
1744 suited to small writes.
1747 extern "C" void FIO_WriteAny (FIO_File f, unsigned char *a, unsigned int _a_high)
1749 CheckAccess (f, FIO_openedforwrite, true);
1750 if ((BufferedWrite (f, _a_high+1, a)) == ((int ) (_a_high+1)))
1751 {} /* empty. */
1756 WriteChar - writes a single character to file, f.
1759 extern "C" void FIO_WriteChar (FIO_File f, char ch)
1761 CheckAccess (f, FIO_openedforwrite, true);
1762 if ((BufferedWrite (f, sizeof (ch), &ch)) == ((int ) (sizeof (ch))))
1763 {} /* empty. */
1768 EOF - tests to see whether a file, f, has reached end of file.
1771 extern "C" bool FIO_EOF (FIO_File f)
1773 FIO_FileDescriptor fd;
1775 CheckAccess (f, FIO_openedforread, false);
1776 if (f != Error)
1778 fd = static_cast<FIO_FileDescriptor> (Indexing_GetIndice (FileInfo, f));
1779 if (fd != NULL)
1781 return fd->state == FIO_endoffile;
1784 return true;
1785 /* static analysis guarentees a RETURN statement will be used before here. */
1786 __builtin_unreachable ();
1791 EOLN - tests to see whether a file, f, is upon a newline.
1792 It does NOT consume the newline.
1795 extern "C" bool FIO_EOLN (FIO_File f)
1797 char ch;
1798 FIO_FileDescriptor fd;
1800 CheckAccess (f, FIO_openedforread, false);
1802 we will read a character and then push it back onto the input stream,
1803 having noted the file status, we also reset the status.
1805 if (f != Error)
1807 fd = static_cast<FIO_FileDescriptor> (Indexing_GetIndice (FileInfo, f));
1808 if (fd != NULL)
1810 if ((fd->state == FIO_successful) || (fd->state == FIO_endofline))
1812 ch = FIO_ReadChar (f);
1813 if ((fd->state == FIO_successful) || (fd->state == FIO_endofline))
1815 FIO_UnReadChar (f, ch);
1817 return ch == ASCII_nl;
1821 return false;
1822 /* static analysis guarentees a RETURN statement will be used before here. */
1823 __builtin_unreachable ();
1828 WasEOLN - tests to see whether a file, f, has just seen a newline.
1831 extern "C" bool FIO_WasEOLN (FIO_File f)
1833 FIO_FileDescriptor fd;
1835 CheckAccess (f, FIO_openedforread, false);
1836 if (f == Error)
1838 return false;
1840 else
1842 fd = static_cast<FIO_FileDescriptor> (Indexing_GetIndice (FileInfo, f));
1843 return (fd != NULL) && (fd->state == FIO_endofline);
1845 /* static analysis guarentees a RETURN statement will be used before here. */
1846 __builtin_unreachable ();
1851 ReadChar - returns a character read from file f.
1852 Sensible to check with IsNoError or EOF after calling
1853 this function.
1856 extern "C" char FIO_ReadChar (FIO_File f)
1858 char ch;
1860 CheckAccess (f, FIO_openedforread, false);
1861 if ((BufferedRead (f, sizeof (ch), &ch)) == ((int ) (sizeof (ch))))
1863 SetEndOfLine (f, ch);
1864 return ch;
1866 else
1868 return ASCII_nul;
1870 /* static analysis guarentees a RETURN statement will be used before here. */
1871 __builtin_unreachable ();
1876 UnReadChar - replaces a character, ch, back into file f.
1877 This character must have been read by ReadChar
1878 and it does not allow successive calls. It may
1879 only be called if the previous read was successful
1880 or end of file was seen.
1881 If the state was previously endoffile then it
1882 is altered to successful.
1883 Otherwise it is left alone.
1886 extern "C" void FIO_UnReadChar (FIO_File f, char ch)
1888 FIO_FileDescriptor fd;
1889 unsigned int n;
1890 void * a;
1891 void * b;
1893 CheckAccess (f, FIO_openedforread, false);
1894 if (f != Error)
1896 fd = static_cast<FIO_FileDescriptor> (Indexing_GetIndice (FileInfo, f));
1897 if (((fd->state == FIO_successful) || (fd->state == FIO_endoffile)) || (fd->state == FIO_endofline))
1899 /* avoid dangling else. */
1900 if ((fd->buffer != NULL) && fd->buffer->valid)
1902 /* we assume that a ReadChar has occurred, we will check just in case. */
1903 if (fd->state == FIO_endoffile)
1905 fd->buffer->position = MaxBufferLength;
1906 fd->buffer->left = 0;
1907 fd->buffer->filled = 0;
1908 fd->state = FIO_successful;
1910 if (fd->buffer->position > 0)
1912 fd->buffer->position -= 1;
1913 fd->buffer->left += 1;
1914 (*fd->buffer->contents).array[fd->buffer->position] = ch;
1916 else
1918 /* if possible make room and store ch */
1919 if (fd->buffer->filled == fd->buffer->size)
1921 FormatError1 ((const char *) "performing too many UnReadChar calls on file (%d)\\n", 51, (const unsigned char *) &f, (sizeof (f)-1));
1923 else
1925 n = fd->buffer->filled-fd->buffer->position;
1926 b = &(*fd->buffer->contents).array[fd->buffer->position];
1927 a = &(*fd->buffer->contents).array[fd->buffer->position+1];
1928 a = libc_memcpy (a, b, static_cast<size_t> (n));
1929 fd->buffer->filled += 1;
1930 (*fd->buffer->contents).array[fd->buffer->position] = ch;
1935 else
1937 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 WriteLine - writes out a linefeed to file, f.
1947 extern "C" void FIO_WriteLine (FIO_File f)
1949 FIO_WriteChar (f, ASCII_nl);
1954 WriteString - writes a string to file, f.
1957 extern "C" void FIO_WriteString (FIO_File f, const char *a_, unsigned int _a_high)
1959 unsigned int l;
1960 char a[_a_high+1];
1962 /* make a local copy of each unbounded array. */
1963 memcpy (a, a_, _a_high+1);
1965 l = StrLib_StrLen ((const char *) a, _a_high);
1966 if ((FIO_WriteNBytes (f, l, const_cast<void*> (static_cast<const void*>(a)))) != l)
1967 {} /* empty. */
1972 ReadString - reads a string from file, f, into string, a.
1973 It terminates the string if HIGH is reached or
1974 if a newline is seen or an error occurs.
1977 extern "C" void FIO_ReadString (FIO_File f, char *a, unsigned int _a_high)
1979 unsigned int high;
1980 unsigned int i;
1981 char ch;
1983 CheckAccess (f, FIO_openedforread, false);
1984 high = _a_high;
1985 i = 0;
1986 do {
1987 ch = FIO_ReadChar (f);
1988 if (i <= high)
1990 /* avoid gcc warning by using compound statement even if not strictly necessary. */
1991 if (((ch == ASCII_nl) || (! (FIO_IsNoError (f)))) || (FIO_EOF (f)))
1993 const_cast<char *>(a)[i] = ASCII_nul;
1994 i += 1;
1996 else
1998 const_cast<char *>(a)[i] = ch;
1999 i += 1;
2002 } while (! ((((ch == ASCII_nl) || (i > high)) || (! (FIO_IsNoError (f)))) || (FIO_EOF (f))));
2007 WriteCardinal - writes a CARDINAL to file, f.
2008 It writes the binary image of the cardinal
2009 to file, f.
2012 extern "C" void FIO_WriteCardinal (FIO_File f, unsigned int c)
2014 FIO_WriteAny (f, (unsigned char *) &c, (sizeof (c)-1));
2019 ReadCardinal - reads a CARDINAL from file, f.
2020 It reads a binary image of a CARDINAL
2021 from a file, f.
2024 extern "C" unsigned int FIO_ReadCardinal (FIO_File f)
2026 unsigned int c;
2028 FIO_ReadAny (f, (unsigned char *) &c, (sizeof (c)-1));
2029 return c;
2030 /* static analysis guarentees a RETURN statement will be used before here. */
2031 __builtin_unreachable ();
2036 GetUnixFileDescriptor - returns the UNIX file descriptor of a file.
2039 extern "C" int FIO_GetUnixFileDescriptor (FIO_File f)
2041 FIO_FileDescriptor fd;
2043 if (f != Error)
2045 fd = static_cast<FIO_FileDescriptor> (Indexing_GetIndice (FileInfo, f));
2046 if (fd != NULL)
2048 return fd->unixfd;
2051 FormatError1 ((const char *) "file %d has not been opened or is out of range\\n", 48, (const unsigned char *) &f, (sizeof (f)-1));
2052 return -1;
2053 /* static analysis guarentees a RETURN statement will be used before here. */
2054 __builtin_unreachable ();
2059 SetPositionFromBeginning - sets the position from the beginning of the file.
2062 extern "C" void FIO_SetPositionFromBeginning (FIO_File f, long int pos)
2064 long int offset;
2065 FIO_FileDescriptor fd;
2067 if (f != Error)
2069 fd = static_cast<FIO_FileDescriptor> (Indexing_GetIndice (FileInfo, f));
2070 if (fd != NULL)
2072 /* always force the lseek, until we are confident that abspos is always correct,
2073 basically it needs some hard testing before we should remove the OR TRUE. */
2074 if ((fd->abspos != pos) || true)
2076 FIO_FlushBuffer (f);
2077 if (fd->buffer != NULL)
2079 if (fd->output)
2081 fd->buffer->left = fd->buffer->size;
2083 else
2085 fd->buffer->left = 0;
2087 fd->buffer->position = 0;
2088 fd->buffer->filled = 0;
2090 offset = static_cast<long int> (libc_lseek (fd->unixfd, (off_t ) (pos), wrapc_SeekSet ()));
2091 if ((offset >= 0) && (pos == offset))
2093 fd->abspos = pos;
2095 else
2097 fd->state = FIO_failed;
2098 fd->abspos = 0;
2100 if (fd->buffer != NULL)
2102 fd->buffer->valid = false;
2103 fd->buffer->bufstart = fd->abspos;
2112 SetPositionFromEnd - sets the position from the end of the file.
2115 extern "C" void FIO_SetPositionFromEnd (FIO_File f, long int pos)
2117 long int offset;
2118 FIO_FileDescriptor fd;
2120 if (f != Error)
2122 fd = static_cast<FIO_FileDescriptor> (Indexing_GetIndice (FileInfo, f));
2123 if (fd != NULL)
2125 FIO_FlushBuffer (f);
2126 if (fd->buffer != NULL)
2128 if (fd->output)
2130 fd->buffer->left = fd->buffer->size;
2132 else
2134 fd->buffer->left = 0;
2136 fd->buffer->position = 0;
2137 fd->buffer->filled = 0;
2139 offset = static_cast<long int> (libc_lseek (fd->unixfd, (off_t ) (pos), wrapc_SeekEnd ()));
2140 if (offset >= 0)
2142 fd->abspos = offset;
2144 else
2146 fd->state = FIO_failed;
2147 fd->abspos = 0;
2148 offset = 0;
2150 if (fd->buffer != NULL)
2152 fd->buffer->valid = false;
2153 fd->buffer->bufstart = offset;
2161 FindPosition - returns the current absolute position in file, f.
2164 extern "C" long int FIO_FindPosition (FIO_File f)
2166 FIO_FileDescriptor fd;
2168 if (f != Error)
2170 fd = static_cast<FIO_FileDescriptor> (Indexing_GetIndice (FileInfo, f));
2171 if (fd != NULL)
2173 if ((fd->buffer == NULL) || ! fd->buffer->valid)
2175 return fd->abspos;
2177 else
2179 return fd->buffer->bufstart+((long int ) (fd->buffer->position));
2183 return 0;
2184 /* static analysis guarentees a RETURN statement will be used before here. */
2185 __builtin_unreachable ();
2190 GetFileName - assigns, a, with the filename associated with, f.
2193 extern "C" void FIO_GetFileName (FIO_File f, char *a, unsigned int _a_high)
2195 typedef char *GetFileName__T6;
2197 unsigned int i;
2198 GetFileName__T6 p;
2199 FIO_FileDescriptor fd;
2201 if (f != Error)
2203 fd = static_cast<FIO_FileDescriptor> (Indexing_GetIndice (FileInfo, f));
2204 if (fd == NULL)
2206 FormatError ((const char *) "this file has probably been closed and not reopened successfully or alternatively never opened\\n", 96);
2207 M2RTS_HALT (-1);
2208 __builtin_unreachable ();
2210 else
2212 if (fd->name.address == NULL)
2214 StrLib_StrCopy ((const char *) "", 0, (char *) a, _a_high);
2216 else
2218 p = static_cast<GetFileName__T6> (fd->name.address);
2219 i = 0;
2220 while (((*p) != ASCII_nul) && (i <= _a_high))
2222 const_cast<char *>(a)[i] = (*p);
2223 p += 1;
2224 i += 1;
2233 getFileName - returns the address of the filename associated with, f.
2236 extern "C" void * FIO_getFileName (FIO_File f)
2238 FIO_FileDescriptor fd;
2240 if (f != Error)
2242 fd = static_cast<FIO_FileDescriptor> (Indexing_GetIndice (FileInfo, f));
2243 if (fd == NULL)
2245 FormatError ((const char *) "this file has probably been closed and not reopened successfully or alternatively never opened\\n", 96);
2246 M2RTS_HALT (-1);
2247 __builtin_unreachable ();
2249 else
2251 return fd->name.address;
2254 return NULL;
2255 /* static analysis guarentees a RETURN statement will be used before here. */
2256 __builtin_unreachable ();
2261 getFileNameLength - returns the number of characters associated with filename, f.
2264 extern "C" unsigned int FIO_getFileNameLength (FIO_File f)
2266 FIO_FileDescriptor fd;
2268 if (f != Error)
2270 fd = static_cast<FIO_FileDescriptor> (Indexing_GetIndice (FileInfo, f));
2271 if (fd == NULL)
2273 FormatError ((const char *) "this file has probably been closed and not reopened successfully or alternatively never opened\\n", 96);
2274 M2RTS_HALT (-1);
2275 __builtin_unreachable ();
2277 else
2279 return fd->name.size;
2282 return 0;
2283 /* static analysis guarentees a RETURN statement will be used before here. */
2284 __builtin_unreachable ();
2289 FlushOutErr - flushes, StdOut, and, StdErr.
2290 It is also called when the application calls M2RTS.Terminate.
2291 (which is automatically placed in program modules by the GM2
2292 scaffold).
2295 extern "C" void FIO_FlushOutErr (void)
2297 if (FIO_IsNoError (FIO_StdOut))
2299 FIO_FlushBuffer (FIO_StdOut);
2301 if (FIO_IsNoError (FIO_StdErr))
2303 FIO_FlushBuffer (FIO_StdErr);
2307 extern "C" void _M2_FIO_init (__attribute__((unused)) int argc, __attribute__((unused)) char *argv[], __attribute__((unused)) char *envp[])
2309 Init ();
2312 extern "C" void _M2_FIO_fini (__attribute__((unused)) int argc, __attribute__((unused)) char *argv[], __attribute__((unused)) char *envp[])
2314 FIO_FlushOutErr ();