1/*
2 * Copyright 2008-2009 Katholieke Universiteit Leuven
3 *
4 * Use of this software is governed by the MIT license
5 *
6 * Written by Sven Verdoolaege, K.U.Leuven, Departement
7 * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
8 */
9
10#include <isl_ctx_private.h>
11#include <isl/vec.h>
12#include <isl_options_private.h>
13
14#define __isl_calloc(type,size)		((type *)calloc(1, size))
15#define __isl_calloc_type(type)		__isl_calloc(type,sizeof(type))
16
17void isl_handle_error(isl_ctx *ctx, enum isl_error error, const char *msg,
18	const char *file, int line)
19{
20	if (!ctx)
21		return;
22
23	isl_ctx_set_error(ctx, error);
24
25	switch (ctx->opt->on_error) {
26	case ISL_ON_ERROR_WARN:
27		fprintf(stderr, "%s:%d: %s\n", file, line, msg);
28		return;
29	case ISL_ON_ERROR_CONTINUE:
30		return;
31	case ISL_ON_ERROR_ABORT:
32		fprintf(stderr, "%s:%d: %s\n", file, line, msg);
33		abort();
34		return;
35	}
36}
37
38static struct isl_options *find_nested_options(struct isl_args *args,
39	void *opt, struct isl_args *wanted)
40{
41	int i;
42	struct isl_options *options;
43
44	if (args == wanted)
45		return opt;
46
47	for (i = 0; args->args[i].type != isl_arg_end; ++i) {
48		struct isl_arg *arg = &args->args[i];
49		void *child;
50
51		if (arg->type != isl_arg_child)
52			continue;
53
54		if (arg->offset == (size_t) -1)
55			child = opt;
56		else
57			child = *(void **)(((char *)opt) + arg->offset);
58
59		options = find_nested_options(arg->u.child.child,
60						child, wanted);
61		if (options)
62			return options;
63	}
64
65	return NULL;
66}
67
68static struct isl_options *find_nested_isl_options(struct isl_args *args,
69	void *opt)
70{
71	return find_nested_options(args, opt, &isl_options_args);
72}
73
74void *isl_ctx_peek_options(isl_ctx *ctx, struct isl_args *args)
75{
76	if (!ctx)
77		return NULL;
78	if (args == &isl_options_args)
79		return ctx->opt;
80	return find_nested_options(ctx->user_args, ctx->user_opt, args);
81}
82
83isl_ctx *isl_ctx_alloc_with_options(struct isl_args *args, void *user_opt)
84{
85	struct isl_ctx *ctx = NULL;
86	struct isl_options *opt = NULL;
87	int opt_allocated = 0;
88
89	if (!user_opt)
90		return NULL;
91
92	opt = find_nested_isl_options(args, user_opt);
93	if (!opt) {
94		opt = isl_options_new_with_defaults();
95		if (!opt)
96			goto error;
97		opt_allocated = 1;
98	}
99
100	ctx = __isl_calloc_type(struct isl_ctx);
101	if (!ctx)
102		goto error;
103
104	if (isl_hash_table_init(ctx, &ctx->id_table, 0))
105		goto error;
106
107	ctx->stats = isl_calloc_type(ctx, struct isl_stats);
108	if (!ctx->stats)
109		goto error;
110
111	ctx->user_args = args;
112	ctx->user_opt = user_opt;
113	ctx->opt_allocated = opt_allocated;
114	ctx->opt = opt;
115	ctx->ref = 0;
116
117	isl_int_init(ctx->zero);
118	isl_int_set_si(ctx->zero, 0);
119
120	isl_int_init(ctx->one);
121	isl_int_set_si(ctx->one, 1);
122
123	isl_int_init(ctx->two);
124	isl_int_set_si(ctx->two, 2);
125
126	isl_int_init(ctx->negone);
127	isl_int_set_si(ctx->negone, -1);
128
129	isl_int_init(ctx->normalize_gcd);
130
131	ctx->n_cached = 0;
132	ctx->n_miss = 0;
133
134	ctx->error = isl_error_none;
135
136	return ctx;
137error:
138	isl_args_free(args, user_opt);
139	if (opt_allocated)
140		isl_options_free(opt);
141	free(ctx);
142	return NULL;
143}
144
145struct isl_ctx *isl_ctx_alloc()
146{
147	struct isl_options *opt;
148
149	opt = isl_options_new_with_defaults();
150
151	return isl_ctx_alloc_with_options(&isl_options_args, opt);
152}
153
154void isl_ctx_ref(struct isl_ctx *ctx)
155{
156	ctx->ref++;
157}
158
159void isl_ctx_deref(struct isl_ctx *ctx)
160{
161	isl_assert(ctx, ctx->ref > 0, return);
162	ctx->ref--;
163}
164
165void isl_ctx_free(struct isl_ctx *ctx)
166{
167	if (!ctx)
168		return;
169	if (ctx->ref != 0)
170		isl_die(ctx, isl_error_invalid,
171			"isl_ctx freed, but some objects still reference it",
172			return);
173
174	isl_hash_table_clear(&ctx->id_table);
175	isl_blk_clear_cache(ctx);
176	isl_int_clear(ctx->zero);
177	isl_int_clear(ctx->one);
178	isl_int_clear(ctx->two);
179	isl_int_clear(ctx->negone);
180	isl_int_clear(ctx->normalize_gcd);
181	isl_args_free(ctx->user_args, ctx->user_opt);
182	if (ctx->opt_allocated)
183		isl_options_free(ctx->opt);
184	free(ctx->stats);
185	free(ctx);
186}
187
188struct isl_options *isl_ctx_options(isl_ctx *ctx)
189{
190	if (!ctx)
191		return NULL;
192	return ctx->opt;
193}
194
195enum isl_error isl_ctx_last_error(isl_ctx *ctx)
196{
197	return ctx->error;
198}
199
200void isl_ctx_reset_error(isl_ctx *ctx)
201{
202	ctx->error = isl_error_none;
203}
204
205void isl_ctx_set_error(isl_ctx *ctx, enum isl_error error)
206{
207	if (ctx)
208		ctx->error = error;
209}
210
211void isl_ctx_abort(isl_ctx *ctx)
212{
213	if (ctx)
214		ctx->abort = 1;
215}
216
217void isl_ctx_resume(isl_ctx *ctx)
218{
219	if (ctx)
220		ctx->abort = 0;
221}
222
223int isl_ctx_aborted(isl_ctx *ctx)
224{
225	return ctx ? ctx->abort : -1;
226}
227
228int isl_ctx_parse_options(isl_ctx *ctx, int argc, char **argv, unsigned flags)
229{
230	if (!ctx)
231		return -1;
232	return isl_args_parse(ctx->user_args, argc, argv, ctx->user_opt, flags);
233}
234