Line data Source code
1 : #include <string.h>
2 : #include <isl_int.h>
3 : #include <isl/id.h>
4 : #include <isl/id_to_id.h>
5 : #include <isl_printer_private.h>
6 :
7 0 : static __isl_give isl_printer *file_start_line(__isl_take isl_printer *p)
8 : {
9 0 : fprintf(p->file, "%s%*s%s", p->indent_prefix ? p->indent_prefix : "",
10 0 : p->indent, "", p->prefix ? p->prefix : "");
11 0 : return p;
12 : }
13 :
14 225912 : static __isl_give isl_printer *file_end_line(__isl_take isl_printer *p)
15 : {
16 225912 : fprintf(p->file, "%s\n", p->suffix ? p->suffix : "");
17 225912 : return p;
18 : }
19 :
20 0 : static __isl_give isl_printer *file_flush(__isl_take isl_printer *p)
21 : {
22 0 : fflush(p->file);
23 0 : return p;
24 : }
25 :
26 51591874 : static __isl_give isl_printer *file_print_str(__isl_take isl_printer *p,
27 : const char *s)
28 : {
29 51591874 : fprintf(p->file, "%s", s);
30 51591874 : return p;
31 : }
32 :
33 0 : static __isl_give isl_printer *file_print_double(__isl_take isl_printer *p,
34 : double d)
35 : {
36 0 : fprintf(p->file, "%g", d);
37 0 : return p;
38 : }
39 :
40 0 : static __isl_give isl_printer *file_print_int(__isl_take isl_printer *p, int i)
41 : {
42 0 : fprintf(p->file, "%d", i);
43 0 : return p;
44 : }
45 :
46 10274463 : static __isl_give isl_printer *file_print_isl_int(__isl_take isl_printer *p, isl_int i)
47 : {
48 10274463 : isl_int_print(p->file, i, p->width);
49 10274463 : return p;
50 : }
51 :
52 0 : static int grow_buf(__isl_keep isl_printer *p, int extra)
53 : {
54 : int new_size;
55 : char *new_buf;
56 :
57 0 : if (p->buf_size == 0)
58 0 : return -1;
59 :
60 0 : new_size = ((p->buf_n + extra + 1) * 3) / 2;
61 0 : new_buf = isl_realloc_array(p->ctx, p->buf, char, new_size);
62 0 : if (!new_buf) {
63 0 : p->buf_size = 0;
64 0 : return -1;
65 : }
66 0 : p->buf = new_buf;
67 0 : p->buf_size = new_size;
68 :
69 0 : return 0;
70 : }
71 :
72 0 : static __isl_give isl_printer *str_print(__isl_take isl_printer *p,
73 : const char *s, int len)
74 : {
75 0 : if (p->buf_n + len + 1 >= p->buf_size && grow_buf(p, len))
76 0 : goto error;
77 0 : memcpy(p->buf + p->buf_n, s, len);
78 0 : p->buf_n += len;
79 :
80 0 : p->buf[p->buf_n] = '\0';
81 0 : return p;
82 : error:
83 0 : isl_printer_free(p);
84 0 : return NULL;
85 : }
86 :
87 0 : static __isl_give isl_printer *str_print_indent(__isl_take isl_printer *p,
88 : int indent)
89 : {
90 : int i;
91 :
92 0 : if (p->buf_n + indent + 1 >= p->buf_size && grow_buf(p, indent))
93 0 : goto error;
94 0 : for (i = 0; i < indent; ++i)
95 0 : p->buf[p->buf_n++] = ' ';
96 0 : return p;
97 : error:
98 0 : isl_printer_free(p);
99 0 : return NULL;
100 : }
101 :
102 0 : static __isl_give isl_printer *str_start_line(__isl_take isl_printer *p)
103 : {
104 0 : if (p->indent_prefix)
105 0 : p = str_print(p, p->indent_prefix, strlen(p->indent_prefix));
106 0 : p = str_print_indent(p, p->indent);
107 0 : if (p->prefix)
108 0 : p = str_print(p, p->prefix, strlen(p->prefix));
109 0 : return p;
110 : }
111 :
112 0 : static __isl_give isl_printer *str_end_line(__isl_take isl_printer *p)
113 : {
114 0 : if (p->suffix)
115 0 : p = str_print(p, p->suffix, strlen(p->suffix));
116 0 : p = str_print(p, "\n", strlen("\n"));
117 0 : return p;
118 : }
119 :
120 0 : static __isl_give isl_printer *str_flush(__isl_take isl_printer *p)
121 : {
122 0 : p->buf_n = 0;
123 0 : p->buf[p->buf_n] = '\0';
124 0 : return p;
125 : }
126 :
127 0 : static __isl_give isl_printer *str_print_str(__isl_take isl_printer *p,
128 : const char *s)
129 : {
130 0 : return str_print(p, s, strlen(s));
131 : }
132 :
133 0 : static __isl_give isl_printer *str_print_double(__isl_take isl_printer *p,
134 : double d)
135 : {
136 0 : int left = p->buf_size - p->buf_n;
137 0 : int need = snprintf(p->buf + p->buf_n, left, "%g", d);
138 0 : if (need >= left) {
139 0 : if (grow_buf(p, need))
140 0 : goto error;
141 0 : left = p->buf_size - p->buf_n;
142 0 : need = snprintf(p->buf + p->buf_n, left, "%g", d);
143 : }
144 0 : p->buf_n += need;
145 0 : return p;
146 : error:
147 0 : isl_printer_free(p);
148 0 : return NULL;
149 : }
150 :
151 0 : static __isl_give isl_printer *str_print_int(__isl_take isl_printer *p, int i)
152 : {
153 0 : int left = p->buf_size - p->buf_n;
154 0 : int need = snprintf(p->buf + p->buf_n, left, "%d", i);
155 0 : if (need >= left) {
156 0 : if (grow_buf(p, need))
157 0 : goto error;
158 0 : left = p->buf_size - p->buf_n;
159 0 : need = snprintf(p->buf + p->buf_n, left, "%d", i);
160 : }
161 0 : p->buf_n += need;
162 0 : return p;
163 : error:
164 0 : isl_printer_free(p);
165 0 : return NULL;
166 : }
167 :
168 0 : static __isl_give isl_printer *str_print_isl_int(__isl_take isl_printer *p,
169 : isl_int i)
170 : {
171 : char *s;
172 : int len;
173 :
174 0 : s = isl_int_get_str(i);
175 0 : len = strlen(s);
176 0 : if (len < p->width)
177 0 : p = str_print_indent(p, p->width - len);
178 0 : p = str_print(p, s, len);
179 0 : isl_int_free_str(s);
180 0 : return p;
181 : }
182 :
183 : struct isl_printer_ops {
184 : __isl_give isl_printer *(*start_line)(__isl_take isl_printer *p);
185 : __isl_give isl_printer *(*end_line)(__isl_take isl_printer *p);
186 : __isl_give isl_printer *(*print_double)(__isl_take isl_printer *p,
187 : double d);
188 : __isl_give isl_printer *(*print_int)(__isl_take isl_printer *p, int i);
189 : __isl_give isl_printer *(*print_isl_int)(__isl_take isl_printer *p,
190 : isl_int i);
191 : __isl_give isl_printer *(*print_str)(__isl_take isl_printer *p,
192 : const char *s);
193 : __isl_give isl_printer *(*flush)(__isl_take isl_printer *p);
194 : };
195 :
196 : static struct isl_printer_ops file_ops = {
197 : file_start_line,
198 : file_end_line,
199 : file_print_double,
200 : file_print_int,
201 : file_print_isl_int,
202 : file_print_str,
203 : file_flush
204 : };
205 :
206 : static struct isl_printer_ops str_ops = {
207 : str_start_line,
208 : str_end_line,
209 : str_print_double,
210 : str_print_int,
211 : str_print_isl_int,
212 : str_print_str,
213 : str_flush
214 : };
215 :
216 225912 : __isl_give isl_printer *isl_printer_to_file(isl_ctx *ctx, FILE *file)
217 : {
218 225912 : struct isl_printer *p = isl_calloc_type(ctx, struct isl_printer);
219 225912 : if (!p)
220 0 : return NULL;
221 225912 : p->ctx = ctx;
222 225912 : isl_ctx_ref(p->ctx);
223 225912 : p->ops = &file_ops;
224 225912 : p->file = file;
225 225912 : p->buf = NULL;
226 225912 : p->buf_n = 0;
227 225912 : p->buf_size = 0;
228 225912 : p->indent = 0;
229 225912 : p->output_format = ISL_FORMAT_ISL;
230 225912 : p->indent_prefix = NULL;
231 225912 : p->prefix = NULL;
232 225912 : p->suffix = NULL;
233 225912 : p->width = 0;
234 225912 : p->yaml_style = ISL_YAML_STYLE_FLOW;
235 :
236 225912 : return p;
237 : }
238 :
239 0 : __isl_give isl_printer *isl_printer_to_str(isl_ctx *ctx)
240 : {
241 0 : struct isl_printer *p = isl_calloc_type(ctx, struct isl_printer);
242 0 : if (!p)
243 0 : return NULL;
244 0 : p->ctx = ctx;
245 0 : isl_ctx_ref(p->ctx);
246 0 : p->ops = &str_ops;
247 0 : p->file = NULL;
248 0 : p->buf = isl_alloc_array(ctx, char, 256);
249 0 : if (!p->buf)
250 0 : goto error;
251 0 : p->buf_n = 0;
252 0 : p->buf[0] = '\0';
253 0 : p->buf_size = 256;
254 0 : p->indent = 0;
255 0 : p->output_format = ISL_FORMAT_ISL;
256 0 : p->indent_prefix = NULL;
257 0 : p->prefix = NULL;
258 0 : p->suffix = NULL;
259 0 : p->width = 0;
260 0 : p->yaml_style = ISL_YAML_STYLE_FLOW;
261 :
262 0 : return p;
263 : error:
264 0 : isl_printer_free(p);
265 0 : return NULL;
266 : }
267 :
268 225912 : __isl_null isl_printer *isl_printer_free(__isl_take isl_printer *p)
269 : {
270 225912 : if (!p)
271 0 : return NULL;
272 225912 : free(p->buf);
273 225912 : free(p->indent_prefix);
274 225912 : free(p->prefix);
275 225912 : free(p->suffix);
276 225912 : free(p->yaml_state);
277 225912 : isl_id_to_id_free(p->notes);
278 225912 : isl_ctx_deref(p->ctx);
279 225912 : free(p);
280 :
281 225912 : return NULL;
282 : }
283 :
284 0 : isl_ctx *isl_printer_get_ctx(__isl_keep isl_printer *printer)
285 : {
286 0 : return printer ? printer->ctx : NULL;
287 : }
288 :
289 0 : FILE *isl_printer_get_file(__isl_keep isl_printer *printer)
290 : {
291 0 : if (!printer)
292 0 : return NULL;
293 0 : if (!printer->file)
294 0 : isl_die(isl_printer_get_ctx(printer), isl_error_invalid,
295 : "not a file printer", return NULL);
296 0 : return printer->file;
297 : }
298 :
299 0 : __isl_give isl_printer *isl_printer_set_isl_int_width(__isl_take isl_printer *p,
300 : int width)
301 : {
302 0 : if (!p)
303 0 : return NULL;
304 :
305 0 : p->width = width;
306 :
307 0 : return p;
308 : }
309 :
310 0 : __isl_give isl_printer *isl_printer_set_indent(__isl_take isl_printer *p,
311 : int indent)
312 : {
313 0 : if (!p)
314 0 : return NULL;
315 :
316 0 : p->indent = indent;
317 :
318 0 : return p;
319 : }
320 :
321 0 : __isl_give isl_printer *isl_printer_indent(__isl_take isl_printer *p,
322 : int indent)
323 : {
324 0 : if (!p)
325 0 : return NULL;
326 :
327 0 : p->indent += indent;
328 0 : if (p->indent < 0)
329 0 : p->indent = 0;
330 :
331 0 : return p;
332 : }
333 :
334 : /* Replace the indent prefix of "p" by "prefix".
335 : */
336 0 : __isl_give isl_printer *isl_printer_set_indent_prefix(__isl_take isl_printer *p,
337 : const char *prefix)
338 : {
339 0 : if (!p)
340 0 : return NULL;
341 :
342 0 : free(p->indent_prefix);
343 0 : p->indent_prefix = prefix ? strdup(prefix) : NULL;
344 :
345 0 : return p;
346 : }
347 :
348 0 : __isl_give isl_printer *isl_printer_set_prefix(__isl_take isl_printer *p,
349 : const char *prefix)
350 : {
351 0 : if (!p)
352 0 : return NULL;
353 :
354 0 : free(p->prefix);
355 0 : p->prefix = prefix ? strdup(prefix) : NULL;
356 :
357 0 : return p;
358 : }
359 :
360 0 : __isl_give isl_printer *isl_printer_set_suffix(__isl_take isl_printer *p,
361 : const char *suffix)
362 : {
363 0 : if (!p)
364 0 : return NULL;
365 :
366 0 : free(p->suffix);
367 0 : p->suffix = suffix ? strdup(suffix) : NULL;
368 :
369 0 : return p;
370 : }
371 :
372 0 : __isl_give isl_printer *isl_printer_set_output_format(__isl_take isl_printer *p,
373 : int output_format)
374 : {
375 0 : if (!p)
376 0 : return NULL;
377 :
378 0 : p->output_format = output_format;
379 :
380 0 : return p;
381 : }
382 :
383 0 : int isl_printer_get_output_format(__isl_keep isl_printer *p)
384 : {
385 0 : if (!p)
386 0 : return -1;
387 0 : return p->output_format;
388 : }
389 :
390 : /* Does "p" have a note with identifier "id"?
391 : */
392 0 : isl_bool isl_printer_has_note(__isl_keep isl_printer *p,
393 : __isl_keep isl_id *id)
394 : {
395 0 : if (!p || !id)
396 0 : return isl_bool_error;
397 0 : if (!p->notes)
398 0 : return isl_bool_false;
399 0 : return isl_id_to_id_has(p->notes, id);
400 : }
401 :
402 : /* Retrieve the note identified by "id" from "p".
403 : * The note is assumed to exist.
404 : */
405 0 : __isl_give isl_id *isl_printer_get_note(__isl_keep isl_printer *p,
406 : __isl_take isl_id *id)
407 : {
408 : isl_bool has_note;
409 :
410 0 : has_note = isl_printer_has_note(p, id);
411 0 : if (has_note < 0)
412 0 : goto error;
413 0 : if (!has_note)
414 0 : isl_die(isl_printer_get_ctx(p), isl_error_invalid,
415 : "no such note", goto error);
416 :
417 0 : return isl_id_to_id_get(p->notes, id);
418 : error:
419 0 : isl_id_free(id);
420 0 : return NULL;
421 : }
422 :
423 : /* Associate "note" to the identifier "id" in "p",
424 : * replacing the previous note associated to the identifier, if any.
425 : */
426 0 : __isl_give isl_printer *isl_printer_set_note(__isl_take isl_printer *p,
427 : __isl_take isl_id *id, __isl_take isl_id *note)
428 : {
429 0 : if (!p || !id || !note)
430 : goto error;
431 0 : if (!p->notes) {
432 0 : p->notes = isl_id_to_id_alloc(isl_printer_get_ctx(p), 1);
433 0 : if (!p->notes)
434 0 : goto error;
435 : }
436 0 : p->notes = isl_id_to_id_set(p->notes, id, note);
437 0 : if (!p->notes)
438 0 : return isl_printer_free(p);
439 0 : return p;
440 : error:
441 0 : isl_printer_free(p);
442 0 : isl_id_free(id);
443 0 : isl_id_free(note);
444 0 : return NULL;
445 : }
446 :
447 : /* Keep track of whether the printing to "p" is being performed from
448 : * an isl_*_dump function as specified by "dump".
449 : */
450 225912 : __isl_give isl_printer *isl_printer_set_dump(__isl_take isl_printer *p,
451 : int dump)
452 : {
453 225912 : if (!p)
454 0 : return NULL;
455 :
456 225912 : p->dump = dump;
457 :
458 225912 : return p;
459 : }
460 :
461 : /* Set the YAML style of "p" to "yaml_style" and return the updated printer.
462 : */
463 0 : __isl_give isl_printer *isl_printer_set_yaml_style(__isl_take isl_printer *p,
464 : int yaml_style)
465 : {
466 0 : if (!p)
467 0 : return NULL;
468 :
469 0 : p->yaml_style = yaml_style;
470 :
471 0 : return p;
472 : }
473 :
474 : /* Return the YAML style of "p" or -1 on error.
475 : */
476 0 : int isl_printer_get_yaml_style(__isl_keep isl_printer *p)
477 : {
478 0 : if (!p)
479 0 : return -1;
480 0 : return p->yaml_style;
481 : }
482 :
483 : /* Push "state" onto the stack of currently active YAML elements and
484 : * return the updated printer.
485 : */
486 0 : static __isl_give isl_printer *push_state(__isl_take isl_printer *p,
487 : enum isl_yaml_state state)
488 : {
489 0 : if (!p)
490 0 : return NULL;
491 :
492 0 : if (p->yaml_size < p->yaml_depth + 1) {
493 : enum isl_yaml_state *state;
494 0 : state = isl_realloc_array(p->ctx, p->yaml_state,
495 : enum isl_yaml_state, p->yaml_depth + 1);
496 0 : if (!state)
497 0 : return isl_printer_free(p);
498 0 : p->yaml_state = state;
499 0 : p->yaml_size = p->yaml_depth + 1;
500 : }
501 :
502 0 : p->yaml_state[p->yaml_depth] = state;
503 0 : p->yaml_depth++;
504 :
505 0 : return p;
506 : }
507 :
508 : /* Remove the innermost active YAML element from the stack and
509 : * return the updated printer.
510 : */
511 0 : static __isl_give isl_printer *pop_state(__isl_take isl_printer *p)
512 : {
513 0 : if (!p)
514 0 : return NULL;
515 0 : p->yaml_depth--;
516 0 : return p;
517 : }
518 :
519 : /* Set the state of the innermost active YAML element to "state" and
520 : * return the updated printer.
521 : */
522 0 : static __isl_give isl_printer *update_state(__isl_take isl_printer *p,
523 : enum isl_yaml_state state)
524 : {
525 0 : if (!p)
526 0 : return NULL;
527 0 : if (p->yaml_depth < 1)
528 0 : isl_die(isl_printer_get_ctx(p), isl_error_invalid,
529 : "not in YAML construct", return isl_printer_free(p));
530 :
531 0 : p->yaml_state[p->yaml_depth - 1] = state;
532 :
533 0 : return p;
534 : }
535 :
536 : /* Return the state of the innermost active YAML element.
537 : * Return isl_yaml_none if we are not inside any YAML element.
538 : */
539 61866337 : static enum isl_yaml_state current_state(__isl_keep isl_printer *p)
540 : {
541 61866337 : if (!p)
542 0 : return isl_yaml_none;
543 61866337 : if (p->yaml_depth < 1)
544 61866337 : return isl_yaml_none;
545 0 : return p->yaml_state[p->yaml_depth - 1];
546 : }
547 :
548 : /* If we are printing a YAML document and we are at the start of an element,
549 : * print whatever is needed before we can print the actual element and
550 : * keep track of the fact that we are now printing the element.
551 : * If "eol" is set, then whatever we print is going to be the last
552 : * thing that gets printed on this line.
553 : *
554 : * If we are about the print the first key of a mapping, then nothing
555 : * extra needs to be printed. For any other key, however, we need
556 : * to either move to the next line (in block format) or print a comma
557 : * (in flow format).
558 : * Before printing a value in a mapping, we need to print a colon.
559 : *
560 : * For sequences, in flow format, we only need to print a comma
561 : * for each element except the first.
562 : * In block format, before the first element in the sequence,
563 : * we move to a new line, print a dash and increase the indentation.
564 : * Before any other element, we print a dash on a new line,
565 : * temporarily moving the indentation back.
566 : */
567 61866337 : static __isl_give isl_printer *enter_state(__isl_take isl_printer *p,
568 : int eol)
569 : {
570 : enum isl_yaml_state state;
571 :
572 61866337 : if (!p)
573 0 : return NULL;
574 :
575 61866337 : state = current_state(p);
576 61866337 : if (state == isl_yaml_mapping_val_start) {
577 0 : if (eol)
578 0 : p = p->ops->print_str(p, ":");
579 : else
580 0 : p = p->ops->print_str(p, ": ");
581 0 : p = update_state(p, isl_yaml_mapping_val);
582 61866337 : } else if (state == isl_yaml_mapping_first_key_start) {
583 0 : p = update_state(p, isl_yaml_mapping_key);
584 61866337 : } else if (state == isl_yaml_mapping_key_start) {
585 0 : if (p->yaml_style == ISL_YAML_STYLE_FLOW)
586 0 : p = p->ops->print_str(p, ", ");
587 : else {
588 0 : p = p->ops->end_line(p);
589 0 : p = p->ops->start_line(p);
590 : }
591 0 : p = update_state(p, isl_yaml_mapping_key);
592 61866337 : } else if (state == isl_yaml_sequence_first_start) {
593 0 : if (p->yaml_style != ISL_YAML_STYLE_FLOW) {
594 0 : p = p->ops->end_line(p);
595 0 : p = p->ops->start_line(p);
596 0 : p = p->ops->print_str(p, "- ");
597 0 : p = isl_printer_indent(p, 2);
598 : }
599 0 : p = update_state(p, isl_yaml_sequence);
600 61866337 : } else if (state == isl_yaml_sequence_start) {
601 0 : if (p->yaml_style == ISL_YAML_STYLE_FLOW)
602 0 : p = p->ops->print_str(p, ", ");
603 : else {
604 0 : p = p->ops->end_line(p);
605 0 : p = isl_printer_indent(p, -2);
606 0 : p = p->ops->start_line(p);
607 0 : p = p->ops->print_str(p, "- ");
608 0 : p = isl_printer_indent(p, 2);
609 : }
610 0 : p = update_state(p, isl_yaml_sequence);
611 : }
612 :
613 61866337 : return p;
614 : }
615 :
616 51591874 : __isl_give isl_printer *isl_printer_print_str(__isl_take isl_printer *p,
617 : const char *s)
618 : {
619 51591874 : if (!p)
620 0 : return NULL;
621 51591874 : if (!s)
622 0 : return isl_printer_free(p);
623 51591874 : p = enter_state(p, 0);
624 51591874 : if (!p)
625 0 : return NULL;
626 51591874 : return p->ops->print_str(p, s);
627 : }
628 :
629 0 : __isl_give isl_printer *isl_printer_print_double(__isl_take isl_printer *p,
630 : double d)
631 : {
632 0 : p = enter_state(p, 0);
633 0 : if (!p)
634 0 : return NULL;
635 :
636 0 : return p->ops->print_double(p, d);
637 : }
638 :
639 0 : __isl_give isl_printer *isl_printer_print_int(__isl_take isl_printer *p, int i)
640 : {
641 0 : p = enter_state(p, 0);
642 0 : if (!p)
643 0 : return NULL;
644 :
645 0 : return p->ops->print_int(p, i);
646 : }
647 :
648 10274463 : __isl_give isl_printer *isl_printer_print_isl_int(__isl_take isl_printer *p,
649 : isl_int i)
650 : {
651 10274463 : p = enter_state(p, 0);
652 10274463 : if (!p)
653 0 : return NULL;
654 :
655 10274463 : return p->ops->print_isl_int(p, i);
656 : }
657 :
658 0 : __isl_give isl_printer *isl_printer_start_line(__isl_take isl_printer *p)
659 : {
660 0 : if (!p)
661 0 : return NULL;
662 :
663 0 : return p->ops->start_line(p);
664 : }
665 :
666 225912 : __isl_give isl_printer *isl_printer_end_line(__isl_take isl_printer *p)
667 : {
668 225912 : if (!p)
669 0 : return NULL;
670 :
671 225912 : return p->ops->end_line(p);
672 : }
673 :
674 : /* Return a copy of the string constructed by the string printer "printer".
675 : */
676 0 : __isl_give char *isl_printer_get_str(__isl_keep isl_printer *printer)
677 : {
678 0 : if (!printer)
679 0 : return NULL;
680 0 : if (printer->ops != &str_ops)
681 0 : isl_die(isl_printer_get_ctx(printer), isl_error_invalid,
682 : "isl_printer_get_str can only be called on a string "
683 : "printer", return NULL);
684 0 : if (!printer->buf)
685 0 : return NULL;
686 0 : return strdup(printer->buf);
687 : }
688 :
689 0 : __isl_give isl_printer *isl_printer_flush(__isl_take isl_printer *p)
690 : {
691 0 : if (!p)
692 0 : return NULL;
693 :
694 0 : return p->ops->flush(p);
695 : }
696 :
697 : /* Start a YAML mapping and push a new state to reflect that we
698 : * are about to print the first key in a mapping.
699 : *
700 : * In flow style, print the opening brace.
701 : * In block style, move to the next line with an increased indentation,
702 : * except if this is the outer mapping or if we are inside a sequence
703 : * (in which case we have already increased the indentation and we want
704 : * to print the first key on the same line as the dash).
705 : */
706 0 : __isl_give isl_printer *isl_printer_yaml_start_mapping(
707 : __isl_take isl_printer *p)
708 : {
709 : enum isl_yaml_state state;
710 :
711 0 : if (!p)
712 0 : return NULL;
713 0 : p = enter_state(p, p->yaml_style == ISL_YAML_STYLE_BLOCK);
714 0 : if (!p)
715 0 : return NULL;
716 0 : state = current_state(p);
717 0 : if (p->yaml_style == ISL_YAML_STYLE_FLOW)
718 0 : p = p->ops->print_str(p, "{ ");
719 0 : else if (state != isl_yaml_none && state != isl_yaml_sequence) {
720 0 : p = p->ops->end_line(p);
721 0 : p = isl_printer_indent(p, 2);
722 0 : p = p->ops->start_line(p);
723 : }
724 0 : p = push_state(p, isl_yaml_mapping_first_key_start);
725 0 : return p;
726 : }
727 :
728 : /* Finish a YAML mapping and pop it from the state stack.
729 : *
730 : * In flow style, print the closing brace.
731 : *
732 : * In block style, first check if we are still in the
733 : * isl_yaml_mapping_first_key_start state. If so, we have not printed
734 : * anything yet, so print "{}" to indicate an empty mapping.
735 : * If we increased the indentation in isl_printer_yaml_start_mapping,
736 : * then decrease it again.
737 : * If this is the outer mapping then print a newline.
738 : */
739 0 : __isl_give isl_printer *isl_printer_yaml_end_mapping(
740 : __isl_take isl_printer *p)
741 : {
742 : enum isl_yaml_state state;
743 :
744 0 : state = current_state(p);
745 0 : p = pop_state(p);
746 0 : if (!p)
747 0 : return NULL;
748 0 : if (p->yaml_style == ISL_YAML_STYLE_FLOW)
749 0 : return p->ops->print_str(p, " }");
750 0 : if (state == isl_yaml_mapping_first_key_start)
751 0 : p = p->ops->print_str(p, "{}");
752 0 : if (!p)
753 0 : return NULL;
754 0 : state = current_state(p);
755 0 : if (state != isl_yaml_none && state != isl_yaml_sequence)
756 0 : p = isl_printer_indent(p, -2);
757 0 : if (state == isl_yaml_none)
758 0 : p = p->ops->end_line(p);
759 0 : return p;
760 : }
761 :
762 : /* Start a YAML sequence and push a new state to reflect that we
763 : * are about to print the first element in a sequence.
764 : *
765 : * In flow style, print the opening bracket.
766 : */
767 0 : __isl_give isl_printer *isl_printer_yaml_start_sequence(
768 : __isl_take isl_printer *p)
769 : {
770 0 : if (!p)
771 0 : return NULL;
772 0 : p = enter_state(p, p->yaml_style == ISL_YAML_STYLE_BLOCK);
773 0 : p = push_state(p, isl_yaml_sequence_first_start);
774 0 : if (!p)
775 0 : return NULL;
776 0 : if (p->yaml_style == ISL_YAML_STYLE_FLOW)
777 0 : p = p->ops->print_str(p, "[ ");
778 0 : return p;
779 : }
780 :
781 : /* Finish a YAML sequence and pop it from the state stack.
782 : *
783 : * In flow style, print the closing bracket.
784 : *
785 : * In block style, check if we are still in the
786 : * isl_yaml_sequence_first_start state. If so, we have not printed
787 : * anything yet, so print "[]" or " []" to indicate an empty sequence.
788 : * We print the extra space when we instructed enter_state not
789 : * to print a space at the end of the line.
790 : * Otherwise, undo the increase in indentation performed by
791 : * enter_state when moving away from the isl_yaml_sequence_first_start
792 : * state.
793 : * If this is the outer sequence then print a newline.
794 : */
795 0 : __isl_give isl_printer *isl_printer_yaml_end_sequence(
796 : __isl_take isl_printer *p)
797 : {
798 : enum isl_yaml_state state, up;
799 :
800 0 : state = current_state(p);
801 0 : p = pop_state(p);
802 0 : if (!p)
803 0 : return NULL;
804 0 : if (p->yaml_style == ISL_YAML_STYLE_FLOW)
805 0 : return p->ops->print_str(p, " ]");
806 0 : up = current_state(p);
807 0 : if (state == isl_yaml_sequence_first_start) {
808 0 : if (up == isl_yaml_mapping_val)
809 0 : p = p->ops->print_str(p, " []");
810 : else
811 0 : p = p->ops->print_str(p, "[]");
812 : } else {
813 0 : p = isl_printer_indent(p, -2);
814 : }
815 0 : if (!p)
816 0 : return NULL;
817 0 : state = current_state(p);
818 0 : if (state == isl_yaml_none)
819 0 : p = p->ops->end_line(p);
820 0 : return p;
821 : }
822 :
823 : /* Mark the fact that the current element is finished and that
824 : * the next output belongs to the next element.
825 : * In particular, if we are printing a key, then prepare for
826 : * printing the subsequent value. If we are printing a value,
827 : * prepare for printing the next key. If we are printing an
828 : * element in a sequence, prepare for printing the next element.
829 : */
830 0 : __isl_give isl_printer *isl_printer_yaml_next(__isl_take isl_printer *p)
831 : {
832 : enum isl_yaml_state state;
833 :
834 0 : if (!p)
835 0 : return NULL;
836 0 : if (p->yaml_depth < 1)
837 0 : isl_die(isl_printer_get_ctx(p), isl_error_invalid,
838 : "not in YAML construct", return isl_printer_free(p));
839 :
840 0 : state = current_state(p);
841 0 : if (state == isl_yaml_mapping_key)
842 0 : state = isl_yaml_mapping_val_start;
843 0 : else if (state == isl_yaml_mapping_val)
844 0 : state = isl_yaml_mapping_key_start;
845 0 : else if (state == isl_yaml_sequence)
846 0 : state = isl_yaml_sequence_start;
847 0 : p = update_state(p, state);
848 :
849 0 : return p;
850 : }
|