brintos

brintos / llvm-project-archived public Read only

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