]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/m2/pge-boot/GFIO.cc
Update copyright years.
[thirdparty/gcc.git] / gcc / m2 / pge-boot / GFIO.cc
CommitLineData
fbd2eda1
GM
1/* do not edit automatically generated by mc from FIO. */
2/* FIO.mod provides a simple buffered file input/output library.
3
a945c346 4Copyright (C) 2001-2024 Free Software Foundation, Inc.
fbd2eda1
GM
5Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>.
6
7This file is part of GNU Modula-2.
8
9GNU Modula-2 is free software; you can redistribute it and/or modify
10it under the terms of the GNU General Public License as published by
11the Free Software Foundation; either version 3, or (at your option)
12any later version.
13
14GNU Modula-2 is distributed in the hope that it will be useful, but
15WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17General Public License for more details.
18
19Under Section 7 of GPL version 3, you are granted additional
20permissions described in the GCC Runtime Library Exception, version
213.1, as published by the Free Software Foundation.
22
23You should have received a copy of the GNU General Public License and
24a copy of the GCC Runtime Library Exception along with this program;
25see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
26<http://www.gnu.org/licenses/>. */
27
9525daf0 28#include <stdbool.h>
fbd2eda1
GM
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
66typedef unsigned int FIO_File;
67
68FIO_File FIO_StdErr;
69FIO_File FIO_StdOut;
70FIO_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)
78typedef struct FIO_NameInfo_r FIO_NameInfo;
79
80typedef struct FIO_buf_r FIO_buf;
81
82typedef FIO_buf *FIO_Buffer;
83
84typedef struct FIO_fds_r FIO_fds;
85
86typedef FIO_fds *FIO_FileDescriptor;
87
88typedef struct FIO__T7_a FIO__T7;
89
90typedef char *FIO_PtrToChar;
91
92typedef enum {FIO_successful, FIO_outofmemory, FIO_toomanyfilesopen, FIO_failed, FIO_connectionfailure, FIO_endofline, FIO_endoffile} FIO_FileStatus;
93
94typedef enum {FIO_unused, FIO_openedforread, FIO_openedforwrite, FIO_openedforrandom} FIO_FileUsage;
95
96struct FIO_NameInfo_r {
97 void *address;
98 unsigned int size;
99 };
100
101struct FIO_buf_r {
9525daf0 102 bool valid;
fbd2eda1
GM
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
112struct FIO__T7_a { char array[MaxBufferLength+1]; };
113struct FIO_fds_r {
114 int unixfd;
115 FIO_NameInfo name;
116 FIO_FileStatus state;
117 FIO_FileUsage usage;
9525daf0 118 bool output;
fbd2eda1
GM
119 FIO_Buffer buffer;
120 long int abspos;
121 };
122
123static Indexing_Index FileInfo;
124static FIO_File Error;
125
126/*
127 IsNoError - returns a TRUE if no error has occured on file, f.
128*/
129
9525daf0 130extern "C" bool FIO_IsNoError (FIO_File f);
fbd2eda1
GM
131
132/*
133 IsActive - returns TRUE if the file, f, is still active.
134*/
135
9525daf0
GM
136extern "C" bool FIO_IsActive (FIO_File f);
137extern "C" bool FIO_Exists (const char *fname_, unsigned int _fname_high);
fbd2eda1
GM
138extern "C" FIO_File FIO_OpenToRead (const char *fname_, unsigned int _fname_high);
139extern "C" FIO_File FIO_OpenToWrite (const char *fname_, unsigned int _fname_high);
9525daf0 140extern "C" FIO_File FIO_OpenForRandom (const char *fname_, unsigned int _fname_high, bool towrite, bool newfile);
fbd2eda1
GM
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
148extern "C" void FIO_Close (FIO_File f);
149
150/*
151 exists - returns TRUE if a file named, fname exists for reading.
152*/
153
9525daf0 154extern "C" bool FIO_exists (void * fname, unsigned int flength);
fbd2eda1
GM
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
163extern "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
172extern "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
9525daf0 183extern "C" FIO_File FIO_openForRandom (void * fname, unsigned int flength, bool towrite, bool newfile);
fbd2eda1
GM
184
185/*
186 FlushBuffer - flush contents of file, f.
187*/
188
189extern "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
198extern "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
206extern "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
216extern "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
224extern "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
230extern "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
9525daf0 236extern "C" bool FIO_EOF (FIO_File f);
fbd2eda1
GM
237
238/*
239 EOLN - tests to see whether a file, f, is upon a newline.
240 It does NOT consume the newline.
241*/
242
9525daf0 243extern "C" bool FIO_EOLN (FIO_File f);
fbd2eda1
GM
244
245/*
246 WasEOLN - tests to see whether a file, f, has just seen a newline.
247*/
248
9525daf0 249extern "C" bool FIO_WasEOLN (FIO_File f);
fbd2eda1
GM
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
257extern "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
270extern "C" void FIO_UnReadChar (FIO_File f, char ch);
271
272/*
273 WriteLine - writes out a linefeed to file, f.
274*/
275
276extern "C" void FIO_WriteLine (FIO_File f);
277
278/*
279 WriteString - writes a string to file, f.
280*/
281
282extern "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
290extern "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
298extern "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
306extern "C" unsigned int FIO_ReadCardinal (FIO_File f);
307
308/*
309 GetUnixFileDescriptor - returns the UNIX file descriptor of a file.
310*/
311
312extern "C" int FIO_GetUnixFileDescriptor (FIO_File f);
313
314/*
315 SetPositionFromBeginning - sets the position from the beginning of the file.
316*/
317
318extern "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
324extern "C" void FIO_SetPositionFromEnd (FIO_File f, long int pos);
325
326/*
327 FindPosition - returns the current absolute position in file, f.
328*/
329
330extern "C" long int FIO_FindPosition (FIO_File f);
331
332/*
333 GetFileName - assigns, a, with the filename associated with, f.
334*/
335
336extern "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
342extern "C" void * FIO_getFileName (FIO_File f);
343
344/*
345 getFileNameLength - returns the number of characters associated with filename, f.
346*/
347
348extern "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
357extern "C" void FIO_FlushOutErr (void);
358
359/*
360 Max - returns the maximum of two values.
361*/
362
363static unsigned int Max (unsigned int a, unsigned int b);
364
365/*
366 Min - returns the minimum of two values.
367*/
368
369static 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
376static FIO_File GetNextFreeDescriptor (void);
377
378/*
379 SetState - sets the field, state, of file, f, to, s.
380*/
381
382static void SetState (FIO_File f, FIO_FileStatus s);
383
384/*
385 InitializeFile - initialize a file descriptor
386*/
387
9525daf0 388static FIO_File InitializeFile (FIO_File f, void * fname, unsigned int flength, FIO_FileStatus fstate, FIO_FileUsage use, bool towrite, unsigned int buflength);
fbd2eda1
GM
389
390/*
391 ConnectToUnix - connects a FIO file to a UNIX file descriptor.
392*/
393
9525daf0 394static void ConnectToUnix (FIO_File f, bool towrite, bool newfile);
fbd2eda1
GM
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
406static 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
416static 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
423static 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
429static 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
436static 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
442static 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
449static 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
456static 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
9525daf0 463static void CheckAccess (FIO_File f, FIO_FileUsage use, bool towrite);
fbd2eda1
GM
464
465/*
466 SetEndOfLine -
467*/
468
469static 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
479static int BufferedWrite (FIO_File f, unsigned int nBytes, void * a);
480
481/*
482 PreInitialize - preinitialize the file descriptor.
483*/
484
9525daf0 485static 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);
fbd2eda1
GM
486
487/*
488 Init - initialize the modules, global variables.
489*/
490
491static void Init (void);
492
493
494/*
495 Max - returns the maximum of two values.
496*/
497
498static 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
517static 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
537static 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
571static 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
9525daf0 584static FIO_File InitializeFile (FIO_File f, void * fname, unsigned int flength, FIO_FileStatus fstate, FIO_FileUsage use, bool towrite, unsigned int buflength)
fbd2eda1
GM
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 {
9525daf0 622 fd->buffer->valid = false;
fbd2eda1
GM
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
9525daf0 662static void ConnectToUnix (FIO_File f, bool towrite, bool newfile)
fbd2eda1
GM
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
705static 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 */
9525daf0 733 nBytes = 0; /* reduce the amount for future direct */
fbd2eda1
GM
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 {
9525daf0 768 fd->buffer->valid = false;
fbd2eda1
GM
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 {
9525daf0 785 fd->buffer->valid = false;
fbd2eda1
GM
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
815static int BufferedRead (FIO_File f, unsigned int nBytes, void * a)
816{
817 typedef unsigned char *BufferedRead__T3;
818
819 void * t;
fbd2eda1
GM
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. */
9525daf0 870 fd->buffer->valid = true;
fbd2eda1
GM
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 {
9525daf0 885 fd->buffer->valid = false;
fbd2eda1
GM
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
909static 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
951static 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
978static 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
1080static 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
1096static 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
1119static 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
9525daf0 1144static void CheckAccess (FIO_File f, FIO_FileUsage use, bool towrite)
fbd2eda1
GM
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
1214static void SetEndOfLine (FIO_File f, char ch)
1215{
1216 FIO_FileDescriptor fd;
1217
9525daf0 1218 CheckAccess (f, FIO_openedforread, false);
fbd2eda1
GM
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
1242static int BufferedWrite (FIO_File f, unsigned int nBytes, void * a)
1243{
1244 typedef unsigned char *BufferedWrite__T5;
1245
1246 void * t;
fbd2eda1
GM
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
9525daf0 1312static 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)
fbd2eda1
GM
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
1354static void Init (void)
1355{
1356 FileInfo = Indexing_InitIndex (0);
1357 Error = 0;
9525daf0 1358 PreInitialize (Error, (const char *) "error", 5, FIO_toomanyfilesopen, FIO_unused, false, -1, 0);
fbd2eda1 1359 FIO_StdIn = 1;
9525daf0 1360 PreInitialize (FIO_StdIn, (const char *) "<stdin>", 7, FIO_successful, FIO_openedforread, false, 0, MaxBufferLength);
fbd2eda1 1361 FIO_StdOut = 2;
9525daf0 1362 PreInitialize (FIO_StdOut, (const char *) "<stdout>", 8, FIO_successful, FIO_openedforwrite, true, 1, MaxBufferLength);
fbd2eda1 1363 FIO_StdErr = 3;
9525daf0 1364 PreInitialize (FIO_StdErr, (const char *) "<stderr>", 8, FIO_successful, FIO_openedforwrite, true, 2, MaxBufferLength);
fbd2eda1
GM
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
9525daf0 1377extern "C" bool FIO_IsNoError (FIO_File f)
fbd2eda1
GM
1378{
1379 FIO_FileDescriptor fd;
1380
1381 if (f == Error)
1382 {
9525daf0 1383 return false;
fbd2eda1
GM
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
9525daf0 1399extern "C" bool FIO_IsActive (FIO_File f)
fbd2eda1
GM
1400{
1401 if (f == Error)
1402 {
9525daf0 1403 return false;
fbd2eda1
GM
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
9525daf0 1413extern "C" bool FIO_Exists (const char *fname_, unsigned int _fname_high)
fbd2eda1
GM
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
1428extern "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
1440extern "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
9525daf0 1452extern "C" FIO_File FIO_OpenForRandom (const char *fname_, unsigned int _fname_high, bool towrite, bool newfile)
fbd2eda1
GM
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
1471extern "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
9525daf0 1516extern "C" bool FIO_exists (void * fname, unsigned int flength)
fbd2eda1
GM
1517{
1518 FIO_File f;
1519
1520 f = FIO_openToRead (fname, flength);
1521 if (FIO_IsNoError (f))
1522 {
1523 FIO_Close (f);
9525daf0 1524 return true;
fbd2eda1
GM
1525 }
1526 else
1527 {
1528 FIO_Close (f);
9525daf0 1529 return false;
fbd2eda1
GM
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
1543extern "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 {
9525daf0
GM
1554 f = InitializeFile (f, fname, flength, FIO_successful, FIO_openedforread, false, MaxBufferLength);
1555 ConnectToUnix (f, false, false);
fbd2eda1
GM
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
1570extern "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 {
9525daf0
GM
1581 f = InitializeFile (f, fname, flength, FIO_successful, FIO_openedforwrite, true, MaxBufferLength);
1582 ConnectToUnix (f, true, true);
fbd2eda1
GM
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
9525daf0 1599extern "C" FIO_File FIO_openForRandom (void * fname, unsigned int flength, bool towrite, bool newfile)
fbd2eda1
GM
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
1623extern "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
1659extern "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 {
9525daf0 1668 CheckAccess (f, FIO_openedforread, false);
fbd2eda1
GM
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
1697extern "C" void FIO_ReadAny (FIO_File f, unsigned char *a, unsigned int _a_high)
1698{
9525daf0 1699 CheckAccess (f, FIO_openedforread, false);
fbd2eda1
GM
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
1715extern "C" unsigned int FIO_WriteNBytes (FIO_File f, unsigned int nBytes, void * src)
1716{
1717 int total;
1718 FIO_FileDescriptor fd;
1719
9525daf0 1720 CheckAccess (f, FIO_openedforwrite, true);
fbd2eda1
GM
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
1756extern "C" void FIO_WriteAny (FIO_File f, unsigned char *a, unsigned int _a_high)
1757{
9525daf0 1758 CheckAccess (f, FIO_openedforwrite, true);
fbd2eda1
GM
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
1768extern "C" void FIO_WriteChar (FIO_File f, char ch)
1769{
9525daf0 1770 CheckAccess (f, FIO_openedforwrite, true);
fbd2eda1
GM
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
9525daf0 1780extern "C" bool FIO_EOF (FIO_File f)
fbd2eda1
GM
1781{
1782 FIO_FileDescriptor fd;
1783
9525daf0 1784 CheckAccess (f, FIO_openedforread, false);
fbd2eda1
GM
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 }
9525daf0 1793 return true;
fbd2eda1
GM
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
9525daf0 1804extern "C" bool FIO_EOLN (FIO_File f)
fbd2eda1
GM
1805{
1806 char ch;
1807 FIO_FileDescriptor fd;
1808
9525daf0 1809 CheckAccess (f, FIO_openedforread, false);
fbd2eda1
GM
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 }
9525daf0 1830 return false;
fbd2eda1
GM
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
9525daf0 1840extern "C" bool FIO_WasEOLN (FIO_File f)
fbd2eda1
GM
1841{
1842 FIO_FileDescriptor fd;
1843
9525daf0 1844 CheckAccess (f, FIO_openedforread, false);
fbd2eda1
GM
1845 if (f == Error)
1846 {
9525daf0 1847 return false;
fbd2eda1
GM
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
1865extern "C" char FIO_ReadChar (FIO_File f)
1866{
1867 char ch;
1868
9525daf0 1869 CheckAccess (f, FIO_openedforread, false);
fbd2eda1
GM
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
1895extern "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
9525daf0 1902 CheckAccess (f, FIO_openedforread, false);
fbd2eda1
GM
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
1956extern "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
1966extern "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
1986extern "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
9525daf0 1992 CheckAccess (f, FIO_openedforread, false);
fbd2eda1
GM
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
2021extern "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
2033extern "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
2048extern "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
2071extern "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. */
9525daf0 2083 if ((fd->abspos != pos) || true)
fbd2eda1
GM
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 {
9525daf0 2111 fd->buffer->valid = false;
fbd2eda1
GM
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
2124extern "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 {
9525daf0 2161 fd->buffer->valid = false;
fbd2eda1
GM
2162 fd->buffer->bufstart = offset;
2163 }
2164 }
2165 }
2166}
2167
2168
2169/*
2170 FindPosition - returns the current absolute position in file, f.
2171*/
2172
2173extern "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
2202extern "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
2245extern "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
2273extern "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
2304extern "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
2316extern "C" void _M2_FIO_init (__attribute__((unused)) int argc,__attribute__((unused)) char *argv[],__attribute__((unused)) char *envp[])
2317{
2318 Init ();
2319}
2320
2321extern "C" void _M2_FIO_fini (__attribute__((unused)) int argc,__attribute__((unused)) char *argv[],__attribute__((unused)) char *envp[])
2322{
2323 FIO_FlushOutErr ();
2324}