4 #include <isl/id_to_id.h>
5 #include <isl_printer_private.h>
7 static __isl_give isl_printer
*file_start_line(__isl_take isl_printer
*p
)
9 fprintf(p
->file
, "%s%*s%s", p
->indent_prefix
? p
->indent_prefix
: "",
10 p
->indent
, "", p
->prefix
? p
->prefix
: "");
14 static __isl_give isl_printer
*file_end_line(__isl_take isl_printer
*p
)
16 fprintf(p
->file
, "%s\n", p
->suffix
? p
->suffix
: "");
20 static __isl_give isl_printer
*file_flush(__isl_take isl_printer
*p
)
26 static __isl_give isl_printer
*file_print_str(__isl_take isl_printer
*p
,
29 fprintf(p
->file
, "%s", s
);
33 static __isl_give isl_printer
*file_print_double(__isl_take isl_printer
*p
,
36 fprintf(p
->file
, "%g", d
);
40 static __isl_give isl_printer
*file_print_int(__isl_take isl_printer
*p
, int i
)
42 fprintf(p
->file
, "%d", i
);
46 static __isl_give isl_printer
*file_print_isl_int(__isl_take isl_printer
*p
, isl_int i
)
48 isl_int_print(p
->file
, i
, p
->width
);
52 static int grow_buf(__isl_keep isl_printer
*p
, int extra
)
60 new_size
= ((p
->buf_n
+ extra
+ 1) * 3) / 2;
61 new_buf
= isl_realloc_array(p
->ctx
, p
->buf
, char, new_size
);
67 p
->buf_size
= new_size
;
72 static __isl_give isl_printer
*str_print(__isl_take isl_printer
*p
,
73 const char *s
, int len
)
75 if (p
->buf_n
+ len
+ 1 >= p
->buf_size
&& grow_buf(p
, len
))
77 memcpy(p
->buf
+ p
->buf_n
, s
, len
);
80 p
->buf
[p
->buf_n
] = '\0';
87 static __isl_give isl_printer
*str_print_indent(__isl_take isl_printer
*p
,
92 if (p
->buf_n
+ indent
+ 1 >= p
->buf_size
&& grow_buf(p
, indent
))
94 for (i
= 0; i
< indent
; ++i
)
95 p
->buf
[p
->buf_n
++] = ' ';
96 p
->buf
[p
->buf_n
] = '\0';
103 static __isl_give isl_printer
*str_start_line(__isl_take isl_printer
*p
)
105 if (p
->indent_prefix
)
106 p
= str_print(p
, p
->indent_prefix
, strlen(p
->indent_prefix
));
107 p
= str_print_indent(p
, p
->indent
);
109 p
= str_print(p
, p
->prefix
, strlen(p
->prefix
));
113 static __isl_give isl_printer
*str_end_line(__isl_take isl_printer
*p
)
116 p
= str_print(p
, p
->suffix
, strlen(p
->suffix
));
117 p
= str_print(p
, "\n", strlen("\n"));
121 static __isl_give isl_printer
*str_flush(__isl_take isl_printer
*p
)
124 p
->buf
[p
->buf_n
] = '\0';
128 static __isl_give isl_printer
*str_print_str(__isl_take isl_printer
*p
,
131 return str_print(p
, s
, strlen(s
));
134 static __isl_give isl_printer
*str_print_double(__isl_take isl_printer
*p
,
137 int left
= p
->buf_size
- p
->buf_n
;
138 int need
= snprintf(p
->buf
+ p
->buf_n
, left
, "%g", d
);
140 if (grow_buf(p
, need
))
142 left
= p
->buf_size
- p
->buf_n
;
143 need
= snprintf(p
->buf
+ p
->buf_n
, left
, "%g", d
);
152 static __isl_give isl_printer
*str_print_int(__isl_take isl_printer
*p
, int i
)
154 int left
= p
->buf_size
- p
->buf_n
;
155 int need
= snprintf(p
->buf
+ p
->buf_n
, left
, "%d", i
);
157 if (grow_buf(p
, need
))
159 left
= p
->buf_size
- p
->buf_n
;
160 need
= snprintf(p
->buf
+ p
->buf_n
, left
, "%d", i
);
169 static __isl_give isl_printer
*str_print_isl_int(__isl_take isl_printer
*p
,
175 s
= isl_int_get_str(i
);
178 p
= str_print_indent(p
, p
->width
- len
);
179 p
= str_print(p
, s
, len
);
184 struct isl_printer_ops
{
185 __isl_give isl_printer
*(*start_line
)(__isl_take isl_printer
*p
);
186 __isl_give isl_printer
*(*end_line
)(__isl_take isl_printer
*p
);
187 __isl_give isl_printer
*(*print_double
)(__isl_take isl_printer
*p
,
189 __isl_give isl_printer
*(*print_int
)(__isl_take isl_printer
*p
, int i
);
190 __isl_give isl_printer
*(*print_isl_int
)(__isl_take isl_printer
*p
,
192 __isl_give isl_printer
*(*print_str
)(__isl_take isl_printer
*p
,
194 __isl_give isl_printer
*(*flush
)(__isl_take isl_printer
*p
);
197 static struct isl_printer_ops file_ops
= {
207 static struct isl_printer_ops str_ops
= {
217 __isl_give isl_printer
*isl_printer_to_file(isl_ctx
*ctx
, FILE *file
)
219 struct isl_printer
*p
= isl_calloc_type(ctx
, struct isl_printer
);
230 p
->output_format
= ISL_FORMAT_ISL
;
231 p
->indent_prefix
= NULL
;
235 p
->yaml_style
= ISL_YAML_STYLE_FLOW
;
240 __isl_give isl_printer
*isl_printer_to_str(isl_ctx
*ctx
)
242 struct isl_printer
*p
= isl_calloc_type(ctx
, struct isl_printer
);
249 p
->buf
= isl_alloc_array(ctx
, char, 256);
256 p
->output_format
= ISL_FORMAT_ISL
;
257 p
->indent_prefix
= NULL
;
261 p
->yaml_style
= ISL_YAML_STYLE_FLOW
;
269 __isl_null isl_printer
*isl_printer_free(__isl_take isl_printer
*p
)
274 free(p
->indent_prefix
);
278 isl_id_to_id_free(p
->notes
);
279 isl_ctx_deref(p
->ctx
);
285 isl_ctx
*isl_printer_get_ctx(__isl_keep isl_printer
*printer
)
287 return printer
? printer
->ctx
: NULL
;
290 FILE *isl_printer_get_file(__isl_keep isl_printer
*printer
)
295 isl_die(isl_printer_get_ctx(printer
), isl_error_invalid
,
296 "not a file printer", return NULL
);
297 return printer
->file
;
300 __isl_give isl_printer
*isl_printer_set_isl_int_width(__isl_take isl_printer
*p
,
311 __isl_give isl_printer
*isl_printer_set_indent(__isl_take isl_printer
*p
,
322 __isl_give isl_printer
*isl_printer_indent(__isl_take isl_printer
*p
,
335 /* Replace the indent prefix of "p" by "prefix".
337 __isl_give isl_printer
*isl_printer_set_indent_prefix(__isl_take isl_printer
*p
,
343 free(p
->indent_prefix
);
344 p
->indent_prefix
= prefix
? strdup(prefix
) : NULL
;
349 __isl_give isl_printer
*isl_printer_set_prefix(__isl_take isl_printer
*p
,
356 p
->prefix
= prefix
? strdup(prefix
) : NULL
;
361 __isl_give isl_printer
*isl_printer_set_suffix(__isl_take isl_printer
*p
,
368 p
->suffix
= suffix
? strdup(suffix
) : NULL
;
373 __isl_give isl_printer
*isl_printer_set_output_format(__isl_take isl_printer
*p
,
379 p
->output_format
= output_format
;
384 int isl_printer_get_output_format(__isl_keep isl_printer
*p
)
388 return p
->output_format
;
391 /* Does "p" have a note with identifier "id"?
393 isl_bool
isl_printer_has_note(__isl_keep isl_printer
*p
,
394 __isl_keep isl_id
*id
)
397 return isl_bool_error
;
399 return isl_bool_false
;
400 return isl_id_to_id_has(p
->notes
, id
);
403 /* Retrieve the note identified by "id" from "p".
404 * The note is assumed to exist.
406 __isl_give isl_id
*isl_printer_get_note(__isl_keep isl_printer
*p
,
407 __isl_take isl_id
*id
)
411 has_note
= isl_printer_has_note(p
, id
);
415 isl_die(isl_printer_get_ctx(p
), isl_error_invalid
,
416 "no such note", goto error
);
418 return isl_id_to_id_get(p
->notes
, id
);
424 /* Associate "note" to the identifier "id" in "p",
425 * replacing the previous note associated to the identifier, if any.
427 __isl_give isl_printer
*isl_printer_set_note(__isl_take isl_printer
*p
,
428 __isl_take isl_id
*id
, __isl_take isl_id
*note
)
430 if (!p
|| !id
|| !note
)
433 p
->notes
= isl_id_to_id_alloc(isl_printer_get_ctx(p
), 1);
437 p
->notes
= isl_id_to_id_set(p
->notes
, id
, note
);
439 return isl_printer_free(p
);
448 /* Keep track of whether the printing to "p" is being performed from
449 * an isl_*_dump function as specified by "dump".
451 __isl_give isl_printer
*isl_printer_set_dump(__isl_take isl_printer
*p
,
462 /* Set the YAML style of "p" to "yaml_style" and return the updated printer.
464 __isl_give isl_printer
*isl_printer_set_yaml_style(__isl_take isl_printer
*p
,
470 p
->yaml_style
= yaml_style
;
475 /* Return the YAML style of "p" or -1 on error.
477 int isl_printer_get_yaml_style(__isl_keep isl_printer
*p
)
481 return p
->yaml_style
;
484 /* Push "state" onto the stack of currently active YAML elements and
485 * return the updated printer.
487 static __isl_give isl_printer
*push_state(__isl_take isl_printer
*p
,
488 enum isl_yaml_state state
)
493 if (p
->yaml_size
< p
->yaml_depth
+ 1) {
494 enum isl_yaml_state
*state
;
495 state
= isl_realloc_array(p
->ctx
, p
->yaml_state
,
496 enum isl_yaml_state
, p
->yaml_depth
+ 1);
498 return isl_printer_free(p
);
499 p
->yaml_state
= state
;
500 p
->yaml_size
= p
->yaml_depth
+ 1;
503 p
->yaml_state
[p
->yaml_depth
] = state
;
509 /* Remove the innermost active YAML element from the stack and
510 * return the updated printer.
512 static __isl_give isl_printer
*pop_state(__isl_take isl_printer
*p
)
520 /* Set the state of the innermost active YAML element to "state" and
521 * return the updated printer.
523 static __isl_give isl_printer
*update_state(__isl_take isl_printer
*p
,
524 enum isl_yaml_state state
)
528 if (p
->yaml_depth
< 1)
529 isl_die(isl_printer_get_ctx(p
), isl_error_invalid
,
530 "not in YAML construct", return isl_printer_free(p
));
532 p
->yaml_state
[p
->yaml_depth
- 1] = state
;
537 /* Return the state of the innermost active YAML element.
538 * Return isl_yaml_none if we are not inside any YAML element.
540 static enum isl_yaml_state
current_state(__isl_keep isl_printer
*p
)
543 return isl_yaml_none
;
544 if (p
->yaml_depth
< 1)
545 return isl_yaml_none
;
546 return p
->yaml_state
[p
->yaml_depth
- 1];
549 /* If we are printing a YAML document and we are at the start of an element,
550 * print whatever is needed before we can print the actual element and
551 * keep track of the fact that we are now printing the element.
552 * If "eol" is set, then whatever we print is going to be the last
553 * thing that gets printed on this line.
555 * If we are about the print the first key of a mapping, then nothing
556 * extra needs to be printed. For any other key, however, we need
557 * to either move to the next line (in block format) or print a comma
559 * Before printing a value in a mapping, we need to print a colon.
561 * For sequences, in flow format, we only need to print a comma
562 * for each element except the first.
563 * In block format, before the first element in the sequence,
564 * we move to a new line, print a dash and increase the indentation.
565 * Before any other element, we print a dash on a new line,
566 * temporarily moving the indentation back.
568 static __isl_give isl_printer
*enter_state(__isl_take isl_printer
*p
,
571 enum isl_yaml_state state
;
576 state
= current_state(p
);
577 if (state
== isl_yaml_mapping_val_start
) {
579 p
= p
->ops
->print_str(p
, ":");
581 p
= p
->ops
->print_str(p
, ": ");
582 p
= update_state(p
, isl_yaml_mapping_val
);
583 } else if (state
== isl_yaml_mapping_first_key_start
) {
584 p
= update_state(p
, isl_yaml_mapping_key
);
585 } else if (state
== isl_yaml_mapping_key_start
) {
586 if (p
->yaml_style
== ISL_YAML_STYLE_FLOW
)
587 p
= p
->ops
->print_str(p
, ", ");
589 p
= p
->ops
->end_line(p
);
590 p
= p
->ops
->start_line(p
);
592 p
= update_state(p
, isl_yaml_mapping_key
);
593 } else if (state
== isl_yaml_sequence_first_start
) {
594 if (p
->yaml_style
!= ISL_YAML_STYLE_FLOW
) {
595 p
= p
->ops
->end_line(p
);
596 p
= p
->ops
->start_line(p
);
597 p
= p
->ops
->print_str(p
, "- ");
598 p
= isl_printer_indent(p
, 2);
600 p
= update_state(p
, isl_yaml_sequence
);
601 } else if (state
== isl_yaml_sequence_start
) {
602 if (p
->yaml_style
== ISL_YAML_STYLE_FLOW
)
603 p
= p
->ops
->print_str(p
, ", ");
605 p
= p
->ops
->end_line(p
);
606 p
= isl_printer_indent(p
, -2);
607 p
= p
->ops
->start_line(p
);
608 p
= p
->ops
->print_str(p
, "- ");
609 p
= isl_printer_indent(p
, 2);
611 p
= update_state(p
, isl_yaml_sequence
);
617 __isl_give isl_printer
*isl_printer_print_str(__isl_take isl_printer
*p
,
623 return isl_printer_free(p
);
624 p
= enter_state(p
, 0);
627 return p
->ops
->print_str(p
, s
);
630 __isl_give isl_printer
*isl_printer_print_double(__isl_take isl_printer
*p
,
633 p
= enter_state(p
, 0);
637 return p
->ops
->print_double(p
, d
);
640 __isl_give isl_printer
*isl_printer_print_int(__isl_take isl_printer
*p
, int i
)
642 p
= enter_state(p
, 0);
646 return p
->ops
->print_int(p
, i
);
649 __isl_give isl_printer
*isl_printer_print_isl_int(__isl_take isl_printer
*p
,
652 p
= enter_state(p
, 0);
656 return p
->ops
->print_isl_int(p
, i
);
659 __isl_give isl_printer
*isl_printer_start_line(__isl_take isl_printer
*p
)
664 return p
->ops
->start_line(p
);
667 __isl_give isl_printer
*isl_printer_end_line(__isl_take isl_printer
*p
)
672 return p
->ops
->end_line(p
);
675 /* Return a copy of the string constructed by the string printer "printer".
677 __isl_give
char *isl_printer_get_str(__isl_keep isl_printer
*printer
)
681 if (printer
->ops
!= &str_ops
)
682 isl_die(isl_printer_get_ctx(printer
), isl_error_invalid
,
683 "isl_printer_get_str can only be called on a string "
684 "printer", return NULL
);
687 return strdup(printer
->buf
);
690 __isl_give isl_printer
*isl_printer_flush(__isl_take isl_printer
*p
)
695 return p
->ops
->flush(p
);
698 /* Start a YAML mapping and push a new state to reflect that we
699 * are about to print the first key in a mapping.
701 * In flow style, print the opening brace.
702 * In block style, move to the next line with an increased indentation,
703 * except if this is the outer mapping or if we are inside a sequence
704 * (in which case we have already increased the indentation and we want
705 * to print the first key on the same line as the dash).
707 __isl_give isl_printer
*isl_printer_yaml_start_mapping(
708 __isl_take isl_printer
*p
)
710 enum isl_yaml_state state
;
714 p
= enter_state(p
, p
->yaml_style
== ISL_YAML_STYLE_BLOCK
);
717 state
= current_state(p
);
718 if (p
->yaml_style
== ISL_YAML_STYLE_FLOW
)
719 p
= p
->ops
->print_str(p
, "{ ");
720 else if (state
!= isl_yaml_none
&& state
!= isl_yaml_sequence
) {
721 p
= p
->ops
->end_line(p
);
722 p
= isl_printer_indent(p
, 2);
723 p
= p
->ops
->start_line(p
);
725 p
= push_state(p
, isl_yaml_mapping_first_key_start
);
729 /* Finish a YAML mapping and pop it from the state stack.
731 * In flow style, print the closing brace.
733 * In block style, first check if we are still in the
734 * isl_yaml_mapping_first_key_start state. If so, we have not printed
735 * anything yet, so print "{}" to indicate an empty mapping.
736 * If we increased the indentation in isl_printer_yaml_start_mapping,
737 * then decrease it again.
738 * If this is the outer mapping then print a newline.
740 __isl_give isl_printer
*isl_printer_yaml_end_mapping(
741 __isl_take isl_printer
*p
)
743 enum isl_yaml_state state
;
745 state
= current_state(p
);
749 if (p
->yaml_style
== ISL_YAML_STYLE_FLOW
)
750 return p
->ops
->print_str(p
, " }");
751 if (state
== isl_yaml_mapping_first_key_start
)
752 p
= p
->ops
->print_str(p
, "{}");
755 state
= current_state(p
);
756 if (state
!= isl_yaml_none
&& state
!= isl_yaml_sequence
)
757 p
= isl_printer_indent(p
, -2);
758 if (state
== isl_yaml_none
)
759 p
= p
->ops
->end_line(p
);
763 /* Start a YAML sequence and push a new state to reflect that we
764 * are about to print the first element in a sequence.
766 * In flow style, print the opening bracket.
768 __isl_give isl_printer
*isl_printer_yaml_start_sequence(
769 __isl_take isl_printer
*p
)
773 p
= enter_state(p
, p
->yaml_style
== ISL_YAML_STYLE_BLOCK
);
774 p
= push_state(p
, isl_yaml_sequence_first_start
);
777 if (p
->yaml_style
== ISL_YAML_STYLE_FLOW
)
778 p
= p
->ops
->print_str(p
, "[ ");
782 /* Finish a YAML sequence and pop it from the state stack.
784 * In flow style, print the closing bracket.
786 * In block style, check if we are still in the
787 * isl_yaml_sequence_first_start state. If so, we have not printed
788 * anything yet, so print "[]" or " []" to indicate an empty sequence.
789 * We print the extra space when we instructed enter_state not
790 * to print a space at the end of the line.
791 * Otherwise, undo the increase in indentation performed by
792 * enter_state when moving away from the isl_yaml_sequence_first_start
794 * If this is the outer sequence then print a newline.
796 __isl_give isl_printer
*isl_printer_yaml_end_sequence(
797 __isl_take isl_printer
*p
)
799 enum isl_yaml_state state
, up
;
801 state
= current_state(p
);
805 if (p
->yaml_style
== ISL_YAML_STYLE_FLOW
)
806 return p
->ops
->print_str(p
, " ]");
807 up
= current_state(p
);
808 if (state
== isl_yaml_sequence_first_start
) {
809 if (up
== isl_yaml_mapping_val
)
810 p
= p
->ops
->print_str(p
, " []");
812 p
= p
->ops
->print_str(p
, "[]");
814 p
= isl_printer_indent(p
, -2);
818 state
= current_state(p
);
819 if (state
== isl_yaml_none
)
820 p
= p
->ops
->end_line(p
);
824 /* Mark the fact that the current element is finished and that
825 * the next output belongs to the next element.
826 * In particular, if we are printing a key, then prepare for
827 * printing the subsequent value. If we are printing a value,
828 * prepare for printing the next key. If we are printing an
829 * element in a sequence, prepare for printing the next element.
831 __isl_give isl_printer
*isl_printer_yaml_next(__isl_take isl_printer
*p
)
833 enum isl_yaml_state state
;
837 if (p
->yaml_depth
< 1)
838 isl_die(isl_printer_get_ctx(p
), isl_error_invalid
,
839 "not in YAML construct", return isl_printer_free(p
));
841 state
= current_state(p
);
842 if (state
== isl_yaml_mapping_key
)
843 state
= isl_yaml_mapping_val_start
;
844 else if (state
== isl_yaml_mapping_val
)
845 state
= isl_yaml_mapping_key_start
;
846 else if (state
== isl_yaml_sequence
)
847 state
= isl_yaml_sequence_start
;
848 p
= update_state(p
, state
);