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 #include <assert.h>
20 #include <errno.h>
21
22 #include "writer.h"
23
24 /*
25 * Initialize for the given filename
26 * - tries to open the file with mode "w"
27 * - returns -1 if the file can't be opened.
28 * set print_failed to true and store the errno
29 * - returns 0 otherwise (print_failed is false and errno is 0)
30 */
init_file_writer(writer_t * writer,const char * filename)31 int32_t init_file_writer(writer_t *writer, const char *filename) {
32 FILE *f;
33 int32_t code;
34
35 f = fopen(filename, "w");
36 writer->output.stream = f;
37 writer->is_stream = true;
38 if (f == NULL) {
39 writer->print_failed = true;
40 writer->print_errno = errno;
41 code = -1;
42 } else {
43 writer->print_failed = false;
44 writer->print_errno = 0;
45 code = 0;
46 }
47
48 return code;
49 }
50
51
52 /*
53 * Initialize with an open stream f
54 * - f must be open and writable
55 */
init_stream_writer(writer_t * writer,FILE * f)56 void init_stream_writer(writer_t *writer, FILE *f) {
57 writer->output.stream = f;
58 writer->is_stream = true;
59 writer->print_failed = false;
60 writer->print_errno = 0;
61 }
62
63
64 /*
65 * Initialize for a string buffer
66 */
init_string_writer(writer_t * writer)67 void init_string_writer(writer_t *writer) {
68 init_string_buffer(&writer->output.buffer, 1024);
69 writer->is_stream = false;
70 writer->print_failed = false;
71 writer->print_errno = 0;
72 }
73
74
75
76 /*
77 * Close:
78 * - for a stream writer: close the stream
79 * - for a string writer: add a '\0' at the end of the string buffer
80 * return code = EOF if fclose fails, 0 otherwise
81 */
close_writer(writer_t * writer)82 int close_writer(writer_t *writer) {
83 int code;
84
85 if (writer->is_stream) {
86 // try to close even if writer->print_failed is true
87 // update the flags if fclose fails
88 code = fclose(writer->output.stream);
89 if (code == EOF && !writer->print_failed) {
90 writer->print_failed = true;
91 writer->print_errno = errno;
92 }
93 } else {
94 string_buffer_close(&writer->output.buffer);
95 code = 0;
96 }
97
98 return code;
99 }
100
101
102 /*
103 * Extract the string constructed by writer
104 * - this must be a string writer
105 * - function close_writer must be called first
106 * - the returned string is '\0' terminated
107 * - the length of the string 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 */
writer_get_string(writer_t * writer,uint32_t * len)112 char *writer_get_string(writer_t *writer, uint32_t *len) {
113 assert(!writer->is_stream);
114 return string_buffer_export(&writer->output.buffer, len);
115 }
116
117
118
119 /*
120 * Delete: free the buffer if any otherwise do nothing
121 */
delete_writer(writer_t * writer)122 void delete_writer(writer_t *writer) {
123 if (!writer->is_stream) {
124 delete_string_buffer(&writer->output.buffer);
125 }
126 }
127
128 /*
129 * Print a character, a string, flush
130 * - if writer->print_failed is true, these functions do nothing and exit
131 * - otherwise, they perform the IO operation. If this fails, writer->print_failed
132 * is set to true and errno is stored in writer->print_errno.
133 */
writer_putc(writer_t * writer,char c)134 void writer_putc(writer_t *writer, char c) {
135 int x;
136
137 if (writer->is_stream) {
138 if (!writer->print_failed) {
139 x = fputc(c, writer->output.stream);
140 if (x == EOF) {
141 writer->print_failed = true;
142 writer->print_errno = errno;
143 }
144 }
145 } else {
146 string_buffer_append_char(&writer->output.buffer, c);
147 }
148 }
149
writer_puts(writer_t * writer,const char * s)150 void writer_puts(writer_t *writer, const char *s) {
151 int x;
152
153 if (writer->is_stream) {
154 if (!writer->print_failed) {
155 x = fputs(s, writer->output.stream);
156 if (x == EOF) {
157 writer->print_failed = true;
158 writer->print_errno = errno;
159 }
160 }
161 } else {
162 string_buffer_append_string(&writer->output.buffer, s);
163 }
164 }
165
writer_flush(writer_t * writer)166 void writer_flush(writer_t *writer) {
167 int x;
168
169 if (writer->is_stream) {
170 if (!writer->print_failed) {
171 x = fflush(writer->output.stream);
172 if (x == EOF) {
173 writer->print_failed = true;
174 writer->print_errno = errno;
175 }
176 }
177 }
178 }
179
180
181