take into account writes inside macro statements during evaluation
[pet.git] / loc.c
blob598d1d321a8f3cc902f0bda92792d413b708f84e
1 /*
2 * Copyright 2011 Leiden University. All rights reserved.
3 * Copyright 2014 Ecole Normale Superieure. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials provided
15 * with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY LEIDEN UNIVERSITY ''AS IS'' AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL LEIDEN UNIVERSITY OR
21 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
24 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 * The views and conclusions contained in the software and documentation
30 * are those of the authors and should not be interpreted as
31 * representing official policies, either expressed or implied, of
32 * Leiden University.
35 #include <string.h>
37 #include "loc.h"
39 /* A pet_loc object represents a region of the input file.
40 * The "start" and "end" fields contain the offsets in the input file
41 * of the region, where end points to the first character after the region.
42 * "line" is the line number of a line inside the region.
43 * "indentation" is (a reasonable guess at) the indentation of the region.
45 * A special pet_loc_dummy instance is used to indicate that
46 * no offset information is available (yet).
48 struct pet_loc {
49 int ref;
50 isl_ctx *ctx;
52 unsigned start;
53 unsigned end;
54 int line;
55 char *indent;
58 /* A special pet_loc object that is used to indicate that
59 * no region information is available yet.
61 * This special pet_loc object cannot be changed.
62 * In particular, it is not allowed to call pet_loc_cow on this object.
64 pet_loc pet_loc_dummy = {
65 .ref = -1,
66 .ctx = NULL,
67 .start = 0,
68 .end = 0,
69 .line = -1,
70 .indent = ""
73 /* Allocate a pet_loc with the given start, end, line number and indentation.
75 __isl_give pet_loc *pet_loc_alloc(isl_ctx *ctx,
76 unsigned start, unsigned end, int line, __isl_take char *indent)
78 pet_loc *loc;
80 if (!indent)
81 return NULL;
83 loc = isl_alloc_type(ctx, struct pet_loc);
84 if (!loc)
85 goto error;
87 loc->ctx = ctx;
88 isl_ctx_ref(ctx);
89 loc->ref = 1;
91 loc->start = start;
92 loc->end = end;
93 loc->line = line;
94 loc->indent = indent;
96 return loc;
97 error:
98 free(indent);
99 return NULL;
102 /* Return a pet_loc that is equal to "loc" and that has only one reference.
104 * It is not allowed to call pet_loc_cow on pet_loc_dummy.
105 * We cannot raise an error in this case because pet_loc_dummy does
106 * not have a reference to a valid isl_ctx.
108 __isl_give pet_loc *pet_loc_cow(__isl_take pet_loc *loc)
110 if (loc == &pet_loc_dummy)
111 return NULL;
112 if (!loc)
113 return NULL;
115 if (loc->ref == 1)
116 return loc;
117 loc->ref--;
118 return pet_loc_alloc(loc->ctx, loc->start, loc->end, loc->line,
119 strdup(loc->indent));
122 /* Return an extra reference to "loc".
124 * The special pet_loc_dummy object is not reference counted.
126 __isl_give pet_loc *pet_loc_copy(__isl_keep pet_loc *loc)
128 if (loc == &pet_loc_dummy)
129 return loc;
131 if (!loc)
132 return NULL;
134 loc->ref++;
135 return loc;
138 /* Free a reference to "loc" and return NULL.
140 * The special pet_loc_dummy object is not reference counted.
142 __isl_null pet_loc *pet_loc_free(__isl_take pet_loc *loc)
144 if (loc == &pet_loc_dummy)
145 return NULL;
146 if (!loc)
147 return NULL;
148 if (--loc->ref > 0)
149 return NULL;
151 free(loc->indent);
152 isl_ctx_deref(loc->ctx);
153 free(loc);
154 return NULL;
157 /* Return the offset in the input file of the start of "loc".
159 unsigned pet_loc_get_start(__isl_keep pet_loc *loc)
161 return loc ? loc->start : 0;
164 /* Return the offset in the input file of the character after "loc".
166 unsigned pet_loc_get_end(__isl_keep pet_loc *loc)
168 return loc ? loc->end : 0;
171 /* Return the line number of a line within the "loc" region.
173 int pet_loc_get_line(__isl_keep pet_loc *loc)
175 return loc ? loc->line : -1;
178 /* Return the indentation of the "loc" region.
180 __isl_keep const char *pet_loc_get_indent(__isl_keep pet_loc *loc)
182 return loc ? loc->indent : NULL;
185 /* Update loc->start and loc->end to include the region from "start"
186 * to "end".
188 * Since we may be modifying "loc", it should be different from
189 * pet_loc_dummy.
191 __isl_give pet_loc *pet_loc_update_start_end(__isl_take pet_loc *loc,
192 unsigned start, unsigned end)
194 loc = pet_loc_cow(loc);
195 if (!loc)
196 return NULL;
198 if (start < loc->start)
199 loc->start = start;
200 if (end > loc->end)
201 loc->end = end;
203 return loc;
206 /* Update loc->start and loc->end to include the region of "loc2".
208 * "loc" may be pet_loc_dummy, in which case we return a copy of "loc2".
209 * Similarly, if "loc2" is pet_loc_dummy, then we leave "loc" untouched.
211 __isl_give pet_loc *pet_loc_update_start_end_from_loc(__isl_take pet_loc *loc,
212 __isl_keep pet_loc *loc2)
214 if (!loc2)
215 return pet_loc_free(loc);
216 if (loc == &pet_loc_dummy)
217 return pet_loc_copy(loc2);
218 if (loc2 == &pet_loc_dummy)
219 return loc;
220 return pet_loc_update_start_end(loc, loc2->start, loc2->end);
223 /* Replace the indentation of "loc" by "indent".
225 __isl_give pet_loc *pet_loc_set_indent(__isl_take pet_loc *loc,
226 __isl_take char *indent)
228 if (!loc || !indent)
229 goto error;
231 free(loc->indent);
232 loc->indent = indent;
233 return loc;
234 error:
235 free(indent);
236 return pet_loc_free(loc);