isl_basic_set_opt: avoid invalid access on error path
[platform/upstream/isl.git] / isl_printer.c
1 #include <string.h>
2 #include <isl_printer_private.h>
3
4 static __isl_give isl_printer *file_start_line(__isl_take isl_printer *p)
5 {
6         fprintf(p->file, "%*s%s", p->indent, "", p->prefix ? p->prefix : "");
7         return p;
8 }
9
10 static __isl_give isl_printer *file_end_line(__isl_take isl_printer *p)
11 {
12         fprintf(p->file, "%s\n", p->suffix ? p->suffix : "");
13         return p;
14 }
15
16 static __isl_give isl_printer *file_flush(__isl_take isl_printer *p)
17 {
18         fflush(p->file);
19         return p;
20 }
21
22 static __isl_give isl_printer *file_print_str(__isl_take isl_printer *p,
23         const char *s)
24 {
25         fprintf(p->file, "%s", s);
26         return p;
27 }
28
29 static __isl_give isl_printer *file_print_double(__isl_take isl_printer *p,
30         double d)
31 {
32         fprintf(p->file, "%g", d);
33         return p;
34 }
35
36 static __isl_give isl_printer *file_print_int(__isl_take isl_printer *p, int i)
37 {
38         fprintf(p->file, "%d", i);
39         return p;
40 }
41
42 static __isl_give isl_printer *file_print_isl_int(__isl_take isl_printer *p, isl_int i)
43 {
44         isl_int_print(p->file, i, p->width);
45         return p;
46 }
47
48 static int grow_buf(__isl_keep isl_printer *p, int extra)
49 {
50         int new_size;
51         char *new_buf;
52
53         if (p->buf_size == 0)
54                 return -1;
55
56         new_size = ((p->buf_n + extra + 1) * 3) / 2;
57         new_buf = isl_realloc_array(p->ctx, p->buf, char, new_size);
58         if (!new_buf) {
59                 p->buf_size = 0;
60                 return -1;
61         }
62         p->buf = new_buf;
63         p->buf_size = new_size;
64
65         return 0;
66 }
67
68 static __isl_give isl_printer *str_print(__isl_take isl_printer *p,
69         const char *s, int len)
70 {
71         if (p->buf_n + len + 1 >= p->buf_size && grow_buf(p, len))
72                 goto error;
73         memcpy(p->buf + p->buf_n, s, len);
74         p->buf_n += len;
75
76         p->buf[p->buf_n] = '\0';
77         return p;
78 error:
79         isl_printer_free(p);
80         return NULL;
81 }
82
83 static __isl_give isl_printer *str_print_indent(__isl_take isl_printer *p,
84         int indent)
85 {
86         int i;
87
88         if (p->buf_n + indent + 1 >= p->buf_size && grow_buf(p, indent))
89                 goto error;
90         for (i = 0; i < indent; ++i)
91                 p->buf[p->buf_n++] = ' ';
92         return p;
93 error:
94         isl_printer_free(p);
95         return NULL;
96 }
97
98 static __isl_give isl_printer *str_start_line(__isl_take isl_printer *p)
99 {
100         p = str_print_indent(p, p->indent);
101         if (p->prefix)
102                 p = str_print(p, p->prefix, strlen(p->prefix));
103         return p;
104 }
105
106 static __isl_give isl_printer *str_end_line(__isl_take isl_printer *p)
107 {
108         if (p->suffix)
109                 p = str_print(p, p->suffix, strlen(p->suffix));
110         p = str_print(p, "\n", strlen("\n"));
111         return p;
112 }
113
114 static __isl_give isl_printer *str_flush(__isl_take isl_printer *p)
115 {
116         p->buf_n = 0;
117         return p;
118 }
119
120 static __isl_give isl_printer *str_print_str(__isl_take isl_printer *p,
121         const char *s)
122 {
123         return str_print(p, s, strlen(s));
124 }
125
126 static __isl_give isl_printer *str_print_double(__isl_take isl_printer *p,
127         double d)
128 {
129         int left = p->buf_size - p->buf_n;
130         int need = snprintf(p->buf + p->buf_n, left, "%g", d);
131         if (need >= left) {
132                 if (grow_buf(p, need))
133                         goto error;
134                 left = p->buf_size - p->buf_n;
135                 need = snprintf(p->buf + p->buf_n, left, "%g", d);
136         }
137         p->buf_n += need;
138         return p;
139 error:
140         isl_printer_free(p);
141         return NULL;
142 }
143
144 static __isl_give isl_printer *str_print_int(__isl_take isl_printer *p, int i)
145 {
146         int left = p->buf_size - p->buf_n;
147         int need = snprintf(p->buf + p->buf_n, left, "%d", i);
148         if (need >= left) {
149                 if (grow_buf(p, need))
150                         goto error;
151                 left = p->buf_size - p->buf_n;
152                 need = snprintf(p->buf + p->buf_n, left, "%d", i);
153         }
154         p->buf_n += need;
155         return p;
156 error:
157         isl_printer_free(p);
158         return NULL;
159 }
160
161 static __isl_give isl_printer *str_print_isl_int(__isl_take isl_printer *p,
162         isl_int i)
163 {
164         char *s;
165         int len;
166
167         s = isl_int_get_str(i);
168         len = strlen(s);
169         if (len < p->width)
170                 p = str_print_indent(p, p->width - len);
171         p = str_print(p, s, len);
172         isl_int_free_str(s);
173         return p;
174 }
175
176 struct isl_printer_ops {
177         __isl_give isl_printer *(*start_line)(__isl_take isl_printer *p);
178         __isl_give isl_printer *(*end_line)(__isl_take isl_printer *p);
179         __isl_give isl_printer *(*print_double)(__isl_take isl_printer *p,
180                 double d);
181         __isl_give isl_printer *(*print_int)(__isl_take isl_printer *p, int i);
182         __isl_give isl_printer *(*print_isl_int)(__isl_take isl_printer *p,
183                                                 isl_int i);
184         __isl_give isl_printer *(*print_str)(__isl_take isl_printer *p,
185                                                 const char *s);
186         __isl_give isl_printer *(*flush)(__isl_take isl_printer *p);
187 };
188
189 static struct isl_printer_ops file_ops = {
190         file_start_line,
191         file_end_line,
192         file_print_double,
193         file_print_int,
194         file_print_isl_int,
195         file_print_str,
196         file_flush
197 };
198
199 static struct isl_printer_ops str_ops = {
200         str_start_line,
201         str_end_line,
202         str_print_double,
203         str_print_int,
204         str_print_isl_int,
205         str_print_str,
206         str_flush
207 };
208
209 __isl_give isl_printer *isl_printer_to_file(isl_ctx *ctx, FILE *file)
210 {
211         struct isl_printer *p = isl_alloc_type(ctx, struct isl_printer);
212         if (!p)
213                 return NULL;
214         p->ctx = ctx;
215         isl_ctx_ref(p->ctx);
216         p->ops = &file_ops;
217         p->file = file;
218         p->buf = NULL;
219         p->buf_n = 0;
220         p->buf_size = 0;
221         p->indent = 0;
222         p->output_format = ISL_FORMAT_ISL;
223         p->prefix = NULL;
224         p->suffix = NULL;
225         p->width = 0;
226
227         return p;
228 }
229
230 __isl_give isl_printer *isl_printer_to_str(isl_ctx *ctx)
231 {
232         struct isl_printer *p = isl_alloc_type(ctx, struct isl_printer);
233         if (!p)
234                 return NULL;
235         p->ctx = ctx;
236         isl_ctx_ref(p->ctx);
237         p->ops = &str_ops;
238         p->file = NULL;
239         p->buf = isl_alloc_array(ctx, char, 256);
240         if (!p->buf)
241                 goto error;
242         p->buf_n = 0;
243         p->buf[0] = '\0';
244         p->buf_size = 256;
245         p->indent = 0;
246         p->output_format = ISL_FORMAT_ISL;
247         p->prefix = NULL;
248         p->suffix = NULL;
249         p->width = 0;
250
251         return p;
252 error:
253         isl_printer_free(p);
254         return NULL;
255 }
256
257 void *isl_printer_free(__isl_take isl_printer *p)
258 {
259         if (!p)
260                 return NULL;
261         free(p->buf);
262         isl_ctx_deref(p->ctx);
263         free(p);
264
265         return NULL;
266 }
267
268 isl_ctx *isl_printer_get_ctx(__isl_keep isl_printer *printer)
269 {
270         return printer ? printer->ctx : NULL;
271 }
272
273 FILE *isl_printer_get_file(__isl_keep isl_printer *printer)
274 {
275         if (!printer)
276                 return NULL;
277         if (!printer->file)
278                 isl_die(isl_printer_get_ctx(printer), isl_error_invalid,
279                         "not a file printer", return NULL);
280         return printer->file;
281 }
282
283 __isl_give isl_printer *isl_printer_set_isl_int_width(__isl_take isl_printer *p,
284         int width)
285 {
286         if (!p)
287                 return NULL;
288
289         p->width = width;
290
291         return p;
292 }
293
294 __isl_give isl_printer *isl_printer_set_indent(__isl_take isl_printer *p,
295         int indent)
296 {
297         if (!p)
298                 return NULL;
299
300         p->indent = indent;
301
302         return p;
303 }
304
305 __isl_give isl_printer *isl_printer_indent(__isl_take isl_printer *p,
306         int indent)
307 {
308         if (!p)
309                 return NULL;
310
311         p->indent += indent;
312         if (p->indent < 0)
313                 p->indent = 0;
314
315         return p;
316 }
317
318 __isl_give isl_printer *isl_printer_set_prefix(__isl_take isl_printer *p,
319         const char *prefix)
320 {
321         if (!p)
322                 return NULL;
323
324         p->prefix = prefix;
325
326         return p;
327 }
328
329 __isl_give isl_printer *isl_printer_set_suffix(__isl_take isl_printer *p,
330         const char *suffix)
331 {
332         if (!p)
333                 return NULL;
334
335         p->suffix = suffix;
336
337         return p;
338 }
339
340 __isl_give isl_printer *isl_printer_set_output_format(__isl_take isl_printer *p,
341         int output_format)
342 {
343         if (!p)
344                 return NULL;
345
346         p->output_format = output_format;
347
348         return p;
349 }
350
351 int isl_printer_get_output_format(__isl_keep isl_printer *p)
352 {
353         if (!p)
354                 return -1;
355         return p->output_format;
356 }
357
358 __isl_give isl_printer *isl_printer_print_str(__isl_take isl_printer *p,
359         const char *s)
360 {
361         if (!p)
362                 return NULL;
363         if (!s)
364                 return isl_printer_free(p);
365
366         return p->ops->print_str(p, s);
367 }
368
369 __isl_give isl_printer *isl_printer_print_double(__isl_take isl_printer *p,
370         double d)
371 {
372         if (!p)
373                 return NULL;
374
375         return p->ops->print_double(p, d);
376 }
377
378 __isl_give isl_printer *isl_printer_print_int(__isl_take isl_printer *p, int i)
379 {
380         if (!p)
381                 return NULL;
382
383         return p->ops->print_int(p, i);
384 }
385
386 __isl_give isl_printer *isl_printer_print_isl_int(__isl_take isl_printer *p,
387         isl_int i)
388 {
389         if (!p)
390                 return NULL;
391
392         return p->ops->print_isl_int(p, i);
393 }
394
395 __isl_give isl_printer *isl_printer_start_line(__isl_take isl_printer *p)
396 {
397         if (!p)
398                 return NULL;
399
400         return p->ops->start_line(p);
401 }
402
403 __isl_give isl_printer *isl_printer_end_line(__isl_take isl_printer *p)
404 {
405         if (!p)
406                 return NULL;
407
408         return p->ops->end_line(p);
409 }
410
411 char *isl_printer_get_str(__isl_keep isl_printer *printer)
412 {
413         if (!printer || !printer->buf)
414                 return NULL;
415         return strdup(printer->buf);
416 }
417
418 __isl_give isl_printer *isl_printer_flush(__isl_take isl_printer *p)
419 {
420         if (!p)
421                 return NULL;
422
423         return p->ops->flush(p);
424 }