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