xref: /freebsd/contrib/bc/include/file.h (revision a970610a3af63b3f4df5b69d91c6b4093a00ed8f)
1252884aeSStefan Eßer /*
2252884aeSStefan Eßer  * *****************************************************************************
3252884aeSStefan Eßer  *
43aa99676SStefan Eßer  * SPDX-License-Identifier: BSD-2-Clause
5252884aeSStefan Eßer  *
6*a970610aSStefan Eßer  * Copyright (c) 2018-2024 Gavin D. Howard and contributors.
7252884aeSStefan Eßer  *
8252884aeSStefan Eßer  * Redistribution and use in source and binary forms, with or without
9252884aeSStefan Eßer  * modification, are permitted provided that the following conditions are met:
10252884aeSStefan Eßer  *
11252884aeSStefan Eßer  * * Redistributions of source code must retain the above copyright notice, this
12252884aeSStefan Eßer  *   list of conditions and the following disclaimer.
13252884aeSStefan Eßer  *
14252884aeSStefan Eßer  * * Redistributions in binary form must reproduce the above copyright notice,
15252884aeSStefan Eßer  *   this list of conditions and the following disclaimer in the documentation
16252884aeSStefan Eßer  *   and/or other materials provided with the distribution.
17252884aeSStefan Eßer  *
18252884aeSStefan Eßer  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19252884aeSStefan Eßer  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20252884aeSStefan Eßer  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21252884aeSStefan Eßer  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22252884aeSStefan Eßer  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23252884aeSStefan Eßer  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24252884aeSStefan Eßer  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25252884aeSStefan Eßer  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26252884aeSStefan Eßer  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27252884aeSStefan Eßer  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28252884aeSStefan Eßer  * POSSIBILITY OF SUCH DAMAGE.
29252884aeSStefan Eßer  *
30252884aeSStefan Eßer  * *****************************************************************************
31252884aeSStefan Eßer  *
32252884aeSStefan Eßer  * Definitions for implementing buffered I/O on my own terms.
33252884aeSStefan Eßer  *
34252884aeSStefan Eßer  */
35252884aeSStefan Eßer 
36252884aeSStefan Eßer #ifndef BC_FILE_H
37252884aeSStefan Eßer #define BC_FILE_H
38252884aeSStefan Eßer 
39252884aeSStefan Eßer #include <stdarg.h>
40252884aeSStefan Eßer 
4178bc019dSStefan Eßer #include <history.h>
42252884aeSStefan Eßer #include <vector.h>
43252884aeSStefan Eßer 
44252884aeSStefan Eßer #define BC_FILE_ULL_LENGTH (21)
45252884aeSStefan Eßer 
4678bc019dSStefan Eßer #if BC_ENABLE_LINE_LIB
47252884aeSStefan Eßer 
4878bc019dSStefan Eßer #include <stdio.h>
4978bc019dSStefan Eßer 
5078bc019dSStefan Eßer /// The file struct.
5178bc019dSStefan Eßer typedef struct BcFile
5278bc019dSStefan Eßer {
5378bc019dSStefan Eßer 	// The file. This is here simply to make the line lib code as compatible
5478bc019dSStefan Eßer 	// with the existing code as possible.
5578bc019dSStefan Eßer 	FILE* f;
5678bc019dSStefan Eßer 
57*a970610aSStefan Eßer 	// True if errors should be fatal, false otherwise.
58*a970610aSStefan Eßer 	bool errors_fatal;
59*a970610aSStefan Eßer 
6078bc019dSStefan Eßer } BcFile;
6178bc019dSStefan Eßer 
6278bc019dSStefan Eßer #else // BC_ENABLE_LINE_LIB
6378bc019dSStefan Eßer 
6478bc019dSStefan Eßer /// The file struct.
6578bc019dSStefan Eßer typedef struct BcFile
6678bc019dSStefan Eßer {
6744d4804dSStefan Eßer 	// The actual file descriptor.
68252884aeSStefan Eßer 	int fd;
6944d4804dSStefan Eßer 
70*a970610aSStefan Eßer 	// True if errors should be fatal, false otherwise.
71*a970610aSStefan Eßer 	bool errors_fatal;
72*a970610aSStefan Eßer 
7344d4804dSStefan Eßer 	// The buffer for the file.
74252884aeSStefan Eßer 	char* buf;
7544d4804dSStefan Eßer 
7644d4804dSStefan Eßer 	// The length (number of actual chars) in the buffer.
77252884aeSStefan Eßer 	size_t len;
7844d4804dSStefan Eßer 
7944d4804dSStefan Eßer 	// The capacity (max number of chars) of the buffer.
80252884aeSStefan Eßer 	size_t cap;
81252884aeSStefan Eßer 
82252884aeSStefan Eßer } BcFile;
83252884aeSStefan Eßer 
8478bc019dSStefan Eßer #endif // BC_ENABLE_LINE_LIB
8578bc019dSStefan Eßer 
8678bc019dSStefan Eßer #if BC_ENABLE_HISTORY && !BC_ENABLE_LINE_LIB
8744d4804dSStefan Eßer 
8844d4804dSStefan Eßer /// Types of flushing. These are important because of history and printing
8944d4804dSStefan Eßer /// strings without newlines, something that users could use as their own
9044d4804dSStefan Eßer /// prompts.
9178bc019dSStefan Eßer typedef enum BcFlushType
9278bc019dSStefan Eßer {
9344d4804dSStefan Eßer 	/// Do not clear the stored partial line, but don't add to it.
947e5c51e5SStefan Eßer 	BC_FLUSH_NO_EXTRAS_NO_CLEAR,
9544d4804dSStefan Eßer 
9644d4804dSStefan Eßer 	/// Do not clear the stored partial line and add to it.
977e5c51e5SStefan Eßer 	BC_FLUSH_SAVE_EXTRAS_NO_CLEAR,
9844d4804dSStefan Eßer 
9944d4804dSStefan Eßer 	/// Clear the stored partial line and do not save the new stuff either.
1007e5c51e5SStefan Eßer 	BC_FLUSH_NO_EXTRAS_CLEAR,
10144d4804dSStefan Eßer 
10244d4804dSStefan Eßer 	/// Clear the stored partial line, but save the new stuff.
1037e5c51e5SStefan Eßer 	BC_FLUSH_SAVE_EXTRAS_CLEAR,
1047e5c51e5SStefan Eßer 
1057e5c51e5SStefan Eßer } BcFlushType;
10644d4804dSStefan Eßer 
107d101cdd6SStefan Eßer // These are here to satisfy a clang warning about recursive macros.
108d101cdd6SStefan Eßer 
109d101cdd6SStefan Eßer #define bc_file_putchar(f, t, c) bc_file_putchar_impl(f, t, c)
110d101cdd6SStefan Eßer #define bc_file_flushErr(f, t) bc_file_flushErr_impl(f, t)
111d101cdd6SStefan Eßer #define bc_file_flush(f, t) bc_file_flush_impl(f, t)
112d101cdd6SStefan Eßer #define bc_file_write(f, t, b, n) bc_file_write_impl(f, t, b, n)
113d101cdd6SStefan Eßer #define bc_file_puts(f, t, s) bc_file_puts_impl(f, t, s)
114d101cdd6SStefan Eßer 
11578bc019dSStefan Eßer #else // BC_ENABLE_HISTORY && !BC_ENABLE_LINE_LIB
11644d4804dSStefan Eßer 
11744d4804dSStefan Eßer // These make sure that the BcFlushType parameter disappears if history is not
11878bc019dSStefan Eßer // used, editline is used, or readline is used.
11944d4804dSStefan Eßer 
120d101cdd6SStefan Eßer #define bc_file_putchar(f, t, c) bc_file_putchar_impl(f, c)
121d101cdd6SStefan Eßer #define bc_file_flushErr(f, t) bc_file_flushErr_impl(f)
122d101cdd6SStefan Eßer #define bc_file_flush(f, t) bc_file_flush_impl(f)
123d101cdd6SStefan Eßer #define bc_file_write(f, t, b, n) bc_file_write_impl(f, b, n)
124d101cdd6SStefan Eßer #define bc_file_puts(f, t, s) bc_file_puts_impl(f, s)
12544d4804dSStefan Eßer 
12678bc019dSStefan Eßer #endif // BC_ENABLE_HISTORY && !BC_ENABLE_LINE_LIB
12778bc019dSStefan Eßer 
12878bc019dSStefan Eßer #if BC_ENABLE_LINE_LIB
12978bc019dSStefan Eßer 
13078bc019dSStefan Eßer /**
13178bc019dSStefan Eßer  * Initialize a file.
13278bc019dSStefan Eßer  * @param f             The file to initialize.
13378bc019dSStefan Eßer  * @param file          The stdio file.
134*a970610aSStefan Eßer  * @param errors_fatal  True if errors should be fatal, false otherwise.
13578bc019dSStefan Eßer  */
13678bc019dSStefan Eßer void
137*a970610aSStefan Eßer bc_file_init(BcFile* f, FILE* file, bool errors_fatal);
13878bc019dSStefan Eßer 
13978bc019dSStefan Eßer #else // BC_ENABLE_LINE_LIB
1407e5c51e5SStefan Eßer 
14144d4804dSStefan Eßer /**
14244d4804dSStefan Eßer  * Initialize a file.
14344d4804dSStefan Eßer  * @param f             The file to initialize.
14444d4804dSStefan Eßer  * @param fd            The file descriptor.
14544d4804dSStefan Eßer  * @param buf           The buffer for the file.
14644d4804dSStefan Eßer  * @param cap           The capacity of the buffer.
147*a970610aSStefan Eßer  * @param errors_fatal  True if errors should be fatal, false otherwise.
14844d4804dSStefan Eßer  */
14978bc019dSStefan Eßer void
150*a970610aSStefan Eßer bc_file_init(BcFile* f, int fd, char* buf, size_t cap, bool errors_fatal);
15178bc019dSStefan Eßer 
15278bc019dSStefan Eßer #endif // BC_ENABLE_LINE_LIB
15344d4804dSStefan Eßer 
15444d4804dSStefan Eßer /**
15544d4804dSStefan Eßer  * Frees a file, including flushing it.
15644d4804dSStefan Eßer  * @param f  The file to free.
15744d4804dSStefan Eßer  */
15878bc019dSStefan Eßer void
15978bc019dSStefan Eßer bc_file_free(BcFile* f);
160252884aeSStefan Eßer 
16144d4804dSStefan Eßer /**
16244d4804dSStefan Eßer  * Print a char into the file.
16344d4804dSStefan Eßer  * @param f     The file to print to.
16444d4804dSStefan Eßer  * @param type  The flush type.
16544d4804dSStefan Eßer  * @param c     The character to write.
16644d4804dSStefan Eßer  */
16778bc019dSStefan Eßer void
16878bc019dSStefan Eßer bc_file_putchar(BcFile* restrict f, BcFlushType type, uchar c);
16944d4804dSStefan Eßer 
17044d4804dSStefan Eßer /**
17144d4804dSStefan Eßer  * Flush and return an error if it failed. This is meant to be used when needing
17244d4804dSStefan Eßer  * to flush in error situations when an error is already in flight. It would be
17344d4804dSStefan Eßer  * a very bad deal to throw another error.
17444d4804dSStefan Eßer  * @param f     The file to flush.
17544d4804dSStefan Eßer  * @param type  The flush type.
17644d4804dSStefan Eßer  * @return      A status indicating if an error occurred.
17744d4804dSStefan Eßer  */
17878bc019dSStefan Eßer BcStatus
17978bc019dSStefan Eßer bc_file_flushErr(BcFile* restrict f, BcFlushType type);
18044d4804dSStefan Eßer 
18144d4804dSStefan Eßer /**
18244d4804dSStefan Eßer  * Flush and throw an error on failure.
18344d4804dSStefan Eßer  * @param f     The file to flush.
18444d4804dSStefan Eßer  * @param type  The flush type.
18544d4804dSStefan Eßer  */
18678bc019dSStefan Eßer void
18778bc019dSStefan Eßer bc_file_flush(BcFile* restrict f, BcFlushType type);
18844d4804dSStefan Eßer 
18944d4804dSStefan Eßer /**
19044d4804dSStefan Eßer  * Write the contents of buf to the file.
19144d4804dSStefan Eßer  * @param f     The file to flush.
19244d4804dSStefan Eßer  * @param type  The flush type.
19344d4804dSStefan Eßer  * @param buf   The buffer whose contents will be written to the file.
19444d4804dSStefan Eßer  * @param n     The length of buf.
19544d4804dSStefan Eßer  */
19678bc019dSStefan Eßer void
19778bc019dSStefan Eßer bc_file_write(BcFile* restrict f, BcFlushType type, const char* buf, size_t n);
19844d4804dSStefan Eßer 
19944d4804dSStefan Eßer /**
20044d4804dSStefan Eßer  * Write to the file like fprintf would. This is very rudimentary.
20144d4804dSStefan Eßer  * @param f    The file to flush.
20244d4804dSStefan Eßer  * @param fmt  The format string.
20344d4804dSStefan Eßer  */
20478bc019dSStefan Eßer void
20578bc019dSStefan Eßer bc_file_printf(BcFile* restrict f, const char* fmt, ...);
20644d4804dSStefan Eßer 
20744d4804dSStefan Eßer /**
20844d4804dSStefan Eßer  * Write to the file like vfprintf would. This is very rudimentary.
20944d4804dSStefan Eßer  * @param f    The file to flush.
21044d4804dSStefan Eßer  * @param fmt  The format string.
21144d4804dSStefan Eßer  */
21278bc019dSStefan Eßer void
21378bc019dSStefan Eßer bc_file_vprintf(BcFile* restrict f, const char* fmt, va_list args);
21444d4804dSStefan Eßer 
21544d4804dSStefan Eßer /**
21644d4804dSStefan Eßer  * Write str to the file.
21744d4804dSStefan Eßer  * @param f     The file to flush.
21844d4804dSStefan Eßer  * @param type  The flush type.
21944d4804dSStefan Eßer  * @param str   The string to write to the file.
22044d4804dSStefan Eßer  */
22178bc019dSStefan Eßer void
22278bc019dSStefan Eßer bc_file_puts(BcFile* restrict f, BcFlushType type, const char* str);
2237e5c51e5SStefan Eßer 
22478bc019dSStefan Eßer #if BC_ENABLE_HISTORY && !BC_ENABLE_LINE_LIB
22544d4804dSStefan Eßer 
22644d4804dSStefan Eßer // Some constant flush types for ease of use.
2277e5c51e5SStefan Eßer extern const BcFlushType bc_flush_none;
2287e5c51e5SStefan Eßer extern const BcFlushType bc_flush_err;
2297e5c51e5SStefan Eßer extern const BcFlushType bc_flush_save;
23044d4804dSStefan Eßer 
23178bc019dSStefan Eßer #endif // BC_ENABLE_HISTORY && !BC_ENABLE_LINE_LIB
232252884aeSStefan Eßer 
233252884aeSStefan Eßer #endif // BC_FILE_H
234