1 /*
2  * This file is part of the Yices SMT Solver.
3  * Copyright (C) 2017 SRI International.
4  *
5  * Yices is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * Yices is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with Yices.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 /*
20  * Writer: wrapper that provides functions to write either to a FILE or to a string buffer.
21  * We currently support only putc, puts, and flush
22  */
23 
24 #ifndef __WRITER_H
25 #define __WRITER_H
26 
27 #include <stdio.h>
28 #include <stdbool.h>
29 
30 #include "utils/string_buffers.h"
31 
32 /*
33  * Data structure:
34  * - output = either a FILE or a string buffer
35  * - is_stream: true for FILE/false for string buffers
36  * - print_failed: true after an error
37  * - print_errno = errno when the error was detected
38  */
39 typedef struct writer_s {
40   union {
41     FILE *stream;
42     string_buffer_t buffer;
43   } output;
44   bool is_stream;
45   bool print_failed;
46   int print_errno;
47 } writer_t;
48 
49 
50 
51 /*
52  * Initialize for the given filename
53  * - tries to open the file with mode "w"
54  * - returns -1 if the file can't be opened.
55  *   set print_failed to true and store the errno
56  * - returns 0 otherwise (print_failed is false and errno is 0)
57  */
58 extern int32_t init_file_writer(writer_t *writer, const char *filename);
59 
60 /*
61  * Initialize with an open stream f
62  * - f must be open and writable
63  */
64 extern void init_stream_writer(writer_t *writer, FILE *f);
65 
66 /*
67  * Initialize for standard output or standard error
68  */
init_stdout_writer(writer_t * writer)69 static inline void init_stdout_writer(writer_t *writer) {
70   init_stream_writer(writer, stdout);
71 }
72 
init_stderr_writer(writer_t * writer)73 static inline void init_stderr_writer(writer_t *writer) {
74   init_stream_writer(writer, stderr);
75 }
76 
77 /*
78  * Initialize for a string buffer
79  */
80 extern void init_string_writer(writer_t *writer);
81 
82 
83 /*
84  * Close:
85  * - for a stream writer: close the stream
86  * - for a string writer: append '\0' to the buffer
87  * return code = EOF if fclose fails, 0 otherwise
88  */
89 extern int close_writer(writer_t *writer);
90 
91 
92 /*
93  * Check the type of writer
94  */
is_stream_writer(writer_t * writer)95 static inline bool is_stream_writer(writer_t *writer) {
96   return writer->is_stream;
97 }
98 
is_string_writer(writer_t * writer)99 static inline bool is_string_writer(writer_t *writer) {
100   return !writer->is_stream;
101 }
102 
103 /*
104  * Extract the string constructed by writer
105  * - this must be a string writer
106  * - the returned string is  '\0'-terminated
107  * - its length is returned in *len
108  *
109  * The returned string must be freed when no-longer needed (by a call
110  * to safe_free in utils/memalloc.h).
111  */
112 extern char *writer_get_string(writer_t *writer, uint32_t *len);
113 
114 
115 /*
116  * Delete:
117  * - delete the buffer (do nothing if this is a stream writer)
118  */
119 extern void delete_writer(writer_t *writer);
120 
121 
122 
123 /*
124  * Print a character, a string, flush
125  * - if writer->print_failed is true, these functions do nothing and exit
126  * - otherwise, they perform the IO operation. If this fails, writer->print_failed
127  *   is set to true and errno is stored in writer->print_errno.
128  */
129 extern void writer_putc(writer_t *writer, char c);
130 extern void writer_puts(writer_t *writer, const char *s);
131 extern void writer_flush(writer_t *writer);
132 
133 
134 /*
135  * Check error flag + errno
136  */
writer_failed(writer_t * writer)137 static inline bool writer_failed(writer_t *writer) {
138   return writer->print_failed;
139 }
140 
writer_errno(writer_t * writer)141 static inline int writer_errno(writer_t *writer) {
142   return writer->print_errno;
143 }
144 
145 
146 #endif /* __WRITER_H */
147