| /* do not edit automatically generated by mc from mcStream. */ |
| /* mcStream.mod provides an interface to create a file from fragments. |
| |
| Copyright (C) 2015-2025 Free Software Foundation, Inc. |
| Contributed by Gaius Mulley <gaius@glam.ac.uk>. |
| |
| This file is part of GNU Modula-2. |
| |
| GNU Modula-2 is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 3, or (at your option) |
| any later version. |
| |
| GNU Modula-2 is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with GNU Modula-2; see the file COPYING3. If not see |
| <http://www.gnu.org/licenses/>. */ |
| |
| #include "config.h" |
| #include "system.h" |
| #include <stdbool.h> |
| # if !defined (PROC_D) |
| # define PROC_D |
| typedef void (*PROC_t) (void); |
| typedef struct { PROC_t proc; } PROC; |
| # endif |
| |
| # if !defined (TRUE) |
| # define TRUE (1==1) |
| # endif |
| |
| # if !defined (FALSE) |
| # define FALSE (1==0) |
| # endif |
| |
| # include "GStorage.h" |
| #if defined(__cplusplus) |
| # undef NULL |
| # define NULL 0 |
| #endif |
| #define _mcStream_C |
| |
| #include "GmcStream.h" |
| # include "GFIO.h" |
| # include "Glibc.h" |
| # include "GIndexing.h" |
| # include "GDynamicStrings.h" |
| # include "GFormatStrings.h" |
| # include "GSYSTEM.h" |
| # include "GStorage.h" |
| # include "Galists.h" |
| # include "GSFIO.h" |
| # include "GM2RTS.h" |
| |
| typedef FIO_File *mcStream_ptrToFile; |
| |
| # define maxBuffer 4096 |
| static alists_alist listOfFiles; |
| static Indexing_Index frag; |
| static FIO_File destFile; |
| static bool seenDest; |
| |
| /* |
| openFrag - create and open fragment, id, and return the file. |
| The file should not be closed by the user. |
| */ |
| |
| extern "C" FIO_File mcStream_openFrag (unsigned int id); |
| |
| /* |
| setDest - informs the stream module and all fragments must be copied |
| info, f. |
| */ |
| |
| extern "C" void mcStream_setDest (FIO_File f); |
| |
| /* |
| combine - closes all fragments and then writes them in |
| order to the destination file. The dest file |
| is returned. |
| */ |
| |
| extern "C" FIO_File mcStream_combine (void); |
| |
| /* |
| removeFiles - remove any fragment. |
| */ |
| |
| extern "C" void mcStream_removeFiles (void); |
| |
| /* |
| removeLater - |
| */ |
| |
| static DynamicStrings_String removeLater (DynamicStrings_String filename); |
| |
| /* |
| removeNow - removes a single file, s. |
| */ |
| |
| static void removeNow (DynamicStrings_String s); |
| |
| /* |
| createTemporaryFile - |
| */ |
| |
| static FIO_File createTemporaryFile (unsigned int id); |
| |
| /* |
| copy - copies contents of f to the destination file. |
| */ |
| |
| static void copy (mcStream_ptrToFile p); |
| |
| |
| /* |
| removeLater - |
| */ |
| |
| static DynamicStrings_String removeLater (DynamicStrings_String filename) |
| { |
| alists_includeItemIntoList (listOfFiles, reinterpret_cast <void *> (filename)); |
| return filename; |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| removeNow - removes a single file, s. |
| */ |
| |
| static void removeNow (DynamicStrings_String s) |
| { |
| if ((libc_unlink (DynamicStrings_string (s))) != 0) |
| {} /* empty. */ |
| } |
| |
| |
| /* |
| createTemporaryFile - |
| */ |
| |
| static FIO_File createTemporaryFile (unsigned int id) |
| { |
| DynamicStrings_String s; |
| FIO_File f; |
| int p; |
| |
| s = DynamicStrings_InitString ((const char *) "/tmp/frag-%d-%d.frag", 20); |
| p = libc_getpid (); |
| s = removeLater (FormatStrings_Sprintf2 (s, (const unsigned char *) &p, (sizeof (p)-1), (const unsigned char *) &id, (sizeof (id)-1))); |
| f = SFIO_OpenToWrite (s); |
| return f; |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| copy - copies contents of f to the destination file. |
| */ |
| |
| static void copy (mcStream_ptrToFile p) |
| { |
| typedef struct copy__T1_a copy__T1; |
| |
| struct copy__T1_a { char array[maxBuffer+1]; }; |
| copy__T1 buffer; |
| unsigned int b; |
| DynamicStrings_String s; |
| FIO_File f; |
| |
| if (p != NULL) |
| { |
| f = (*p); |
| s = DynamicStrings_InitStringCharStar (FIO_getFileName (f)); |
| FIO_Close (f); |
| f = SFIO_OpenToRead (s); |
| while ((! (FIO_EOF (f))) && (FIO_IsNoError (f))) |
| { |
| b = FIO_ReadNBytes (f, maxBuffer, &buffer); |
| if (FIO_IsNoError (f)) |
| { |
| b = FIO_WriteNBytes (destFile, b, &buffer); |
| } |
| else if (! (FIO_EOF (f))) |
| { |
| /* avoid dangling else. */ |
| libc_printf ((const char *) "mcStream.mod:copy: error seen when reading file fragment: %s\\n", 62, DynamicStrings_string (s)); |
| libc_exit (1); |
| } |
| } |
| FIO_Close (f); |
| } |
| } |
| |
| |
| /* |
| openFrag - create and open fragment, id, and return the file. |
| The file should not be closed by the user. |
| */ |
| |
| extern "C" FIO_File mcStream_openFrag (unsigned int id) |
| { |
| FIO_File f; |
| mcStream_ptrToFile p; |
| |
| f = createTemporaryFile (id); |
| Storage_ALLOCATE ((void **) &p, sizeof (FIO_File)); |
| (*p) = f; |
| Indexing_PutIndice (frag, id, reinterpret_cast <void *> (p)); |
| return f; |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| setDest - informs the stream module and all fragments must be copied |
| info, f. |
| */ |
| |
| extern "C" void mcStream_setDest (FIO_File f) |
| { |
| seenDest = true; |
| destFile = f; |
| } |
| |
| |
| /* |
| combine - closes all fragments and then writes them in |
| order to the destination file. The dest file |
| is returned. |
| */ |
| |
| extern "C" FIO_File mcStream_combine (void) |
| { |
| if (! seenDest) |
| { |
| M2RTS_HALT (-1); |
| __builtin_unreachable (); |
| } |
| Indexing_ForeachIndiceInIndexDo (frag, (Indexing_IndexProcedure) {(Indexing_IndexProcedure_t) copy}); |
| mcStream_removeFiles (); |
| return destFile; |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| removeFiles - remove any fragment. |
| */ |
| |
| extern "C" void mcStream_removeFiles (void) |
| { |
| alists_foreachItemInListDo (listOfFiles, (alists_performOperation) {(alists_performOperation_t) removeNow}); |
| alists_killList (&listOfFiles); |
| listOfFiles = alists_initList (); |
| } |
| |
| extern "C" void _M2_mcStream_init (__attribute__((unused)) int argc, __attribute__((unused)) char *argv[], __attribute__((unused)) char *envp[]) |
| { |
| listOfFiles = alists_initList (); |
| seenDest = false; |
| frag = Indexing_InitIndex (1); |
| } |
| |
| extern "C" void _M2_mcStream_fini (__attribute__((unused)) int argc, __attribute__((unused)) char *argv[], __attribute__((unused)) char *envp[]) |
| { |
| } |