Branch data Line data Source code
1 : : /*
2 : : * (c) Thomas Pornin 1999 - 2002
3 : : *
4 : : * Redistribution and use in source and binary forms, with or without
5 : : * modification, are permitted provided that the following conditions
6 : : * are met:
7 : : * 1. Redistributions of source code must retain the above copyright
8 : : * notice, this list of conditions and the following disclaimer.
9 : : * 2. Redistributions in binary form must reproduce the above copyright
10 : : * notice, this list of conditions and the following disclaimer in the
11 : : * documentation and/or other materials provided with the distribution.
12 : : * 4. The name of the authors may not be used to endorse or promote
13 : : * products derived from this software without specific prior written
14 : : * permission.
15 : : *
16 : : * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17 : : * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 : : * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 : : * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
20 : : * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 : : * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
22 : : * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 : : * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 : : * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 : : * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
26 : : * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 : : *
28 : : */
29 : :
30 : : #include "tune.h"
31 : : #include <stdio.h>
32 : : #include <string.h>
33 : : #include <stddef.h>
34 : : #include <limits.h>
35 : : #include <time.h>
36 : : #include "ucppi.h"
37 : : #include "mem.h"
38 : : #include "nhash.h"
39 : :
40 : : /*
41 : : * Assertion support. Each assertion is indexed by its predicate, and
42 : : * the list of 'questions' which yield a true answer.
43 : : */
44 : :
45 : : static HTT assertions;
46 : : static int assertions_init_done = 0;
47 : :
48 : 0 : static struct assert *new_assertion(void)
49 : : {
50 : 0 : struct assert *a = getmem(sizeof(struct assert));
51 : :
52 : 0 : a->nbval = 0;
53 : 0 : return a;
54 : : }
55 : :
56 : 0 : static void del_token_fifo(struct token_fifo *tf)
57 : : {
58 : : size_t i;
59 : :
60 [ # # ]: 0 : for (i = 0; i < tf->nt; i ++)
61 [ # # ][ # # ]: 0 : if (S_TOKEN(tf->t[i].type)) freemem(tf->t[i].name);
62 [ # # ]: 0 : if (tf->nt) freemem(tf->t);
63 : 0 : }
64 : :
65 : 0 : static void del_assertion(void *va)
66 : : {
67 : 0 : struct assert *a = va;
68 : : size_t i;
69 : :
70 [ # # ]: 0 : for (i = 0; i < a->nbval; i ++) del_token_fifo(a->val + i);
71 [ # # ]: 0 : if (a->nbval) freemem(a->val);
72 : 0 : freemem(a);
73 : 0 : }
74 : :
75 : : /*
76 : : * print the contents of a token list
77 : : */
78 : 0 : static void print_token_fifo(struct token_fifo *tf)
79 : : {
80 : : size_t i;
81 : :
82 [ # # ]: 0 : for (i = 0; i < tf->nt; i ++)
83 [ # # ][ # # ]: 0 : if (ttMWS(tf->t[i].type)) fputc(' ', emit_output);
[ # # ]
84 : 0 : else fputs(token_name(tf->t + i), emit_output);
85 : 0 : }
86 : :
87 : : /*
88 : : * print all assertions related to a given name
89 : : */
90 : 0 : static void print_assert(void *va)
91 : : {
92 : 0 : struct assert *a = va;
93 : : size_t i;
94 : :
95 [ # # ]: 0 : for (i = 0; i < a->nbval; i ++) {
96 : 0 : fprintf(emit_output, "#assert %s(", HASH_ITEM_NAME(a));
97 : 0 : print_token_fifo(a->val + i);
98 : 0 : fprintf(emit_output, ")\n");
99 : : }
100 : 0 : }
101 : :
102 : : /*
103 : : * compare two token_fifo, return 0 if they are identical, 1 otherwise.
104 : : * All whitespace tokens are considered identical, but sequences of
105 : : * whitespace are not shrinked.
106 : : */
107 : 0 : int cmp_token_list(struct token_fifo *f1, struct token_fifo *f2)
108 : : {
109 : : size_t i;
110 : :
111 [ # # ]: 0 : if (f1->nt != f2->nt) return 1;
112 [ # # ]: 0 : for (i = 0; i < f1->nt; i ++) {
113 [ # # ][ # # ]: 0 : if (ttMWS(f1->t[i].type) && ttMWS(f2->t[i].type)) continue;
[ # # ][ # # ]
[ # # ][ # # ]
114 [ # # ]: 0 : if (f1->t[i].type != f2->t[i].type) return 1;
115 [ # # ]: 0 : if (f1->t[i].type == MACROARG
116 [ # # ]: 0 : && f1->t[i].line != f2->t[i].line) return 1;
117 [ # # ][ # # ]: 0 : if (S_TOKEN(f1->t[i].type)
118 [ # # ]: 0 : && strcmp(f1->t[i].name, f2->t[i].name)) return 1;
119 : : }
120 : 0 : return 0;
121 : : }
122 : :
123 : : /*
124 : : * for #assert
125 : : * Assertions are not part of the ISO-C89 standard, but they are sometimes
126 : : * encountered, for instance in Solaris standard include files.
127 : : */
128 : 0 : int handle_assert(struct lexer_state *ls)
129 : : {
130 : 0 : int ina = 0, ltww;
131 : : struct token t;
132 : 0 : struct token_fifo *atl = 0;
133 : : struct assert *a;
134 : : char *aname;
135 : 0 : int ret = -1;
136 : 0 : long l = ls->line;
137 : : int nnp;
138 : : size_t i;
139 : :
140 [ # # ]: 0 : while (!next_token(ls)) {
141 [ # # ]: 0 : if (ls->ctok->type == NEWLINE) break;
142 [ # # ][ # # ]: 0 : if (ttMWS(ls->ctok->type)) continue;
[ # # ]
143 [ # # ]: 0 : if (ls->ctok->type == NAME) {
144 [ # # ]: 0 : if (!(a = HTT_get(&assertions, ls->ctok->name))) {
145 : 0 : a = new_assertion();
146 : 0 : aname = sdup(ls->ctok->name);
147 : 0 : ina = 1;
148 : : }
149 : 0 : goto handle_assert_next;
150 : : }
151 : 0 : error(l, "illegal assertion name for #assert");
152 : 0 : goto handle_assert_warp_ign;
153 : : }
154 : 0 : goto handle_assert_trunc;
155 : :
156 : : handle_assert_next:
157 [ # # ]: 0 : while (!next_token(ls)) {
158 [ # # ]: 0 : if (ls->ctok->type == NEWLINE) break;
159 [ # # ][ # # ]: 0 : if (ttMWS(ls->ctok->type)) continue;
[ # # ]
160 [ # # ]: 0 : if (ls->ctok->type != LPAR) {
161 : 0 : error(l, "syntax error in #assert");
162 : 0 : goto handle_assert_warp_ign;
163 : : }
164 : 0 : goto handle_assert_next2;
165 : : }
166 : 0 : goto handle_assert_trunc;
167 : :
168 : : handle_assert_next2:
169 : 0 : atl = getmem(sizeof(struct token_fifo));
170 : 0 : atl->art = atl->nt = 0;
171 [ # # ][ # # ]: 0 : for (nnp = 1, ltww = 1; nnp && !next_token(ls);) {
172 [ # # ]: 0 : if (ls->ctok->type == NEWLINE) break;
173 [ # # ][ # # ]: 0 : if (ltww && ttMWS(ls->ctok->type)) continue;
[ # # ][ # # ]
174 [ # # ][ # # ]: 0 : ltww = ttMWS(ls->ctok->type);
[ # # ]
175 [ # # ]: 0 : if (ls->ctok->type == LPAR) nnp ++;
176 [ # # ]: 0 : else if (ls->ctok->type == RPAR) {
177 [ # # ]: 0 : if (!(-- nnp)) goto handle_assert_next3;
178 : : }
179 : 0 : t.type = ls->ctok->type;
180 [ # # ][ # # ]: 0 : if (S_TOKEN(t.type)) t.name = sdup(ls->ctok->name);
181 [ # # ][ # # ]: 0 : aol(atl->t, atl->nt, t, TOKEN_LIST_MEMG);
182 : : }
183 : 0 : goto handle_assert_trunc;
184 : :
185 : : handle_assert_next3:
186 [ # # ][ # # ]: 0 : while (!next_token(ls) && ls->ctok->type != NEWLINE) {
187 [ # # ][ # # ]: 0 : if (!ttWHI(ls->ctok->type) && (ls->flags & WARN_STANDARD)) {
[ # # ][ # # ]
[ # # ]
188 : 0 : warning(l, "trailing garbage in #assert");
189 : : }
190 : : }
191 [ # # ][ # # ]: 0 : if (atl->nt && ttMWS(atl->t[atl->nt - 1].type) && (-- atl->nt) == 0)
[ # # ][ # # ]
[ # # ]
192 : 0 : freemem(atl->t);
193 [ # # ]: 0 : if (atl->nt == 0) {
194 : 0 : error(l, "void assertion in #assert");
195 : 0 : goto handle_assert_error;
196 : : }
197 [ # # ][ # # ]: 0 : for (i = 0; i < a->nbval && cmp_token_list(atl, a->val + i); i ++);
198 [ # # ]: 0 : if (i != a->nbval) {
199 : : /* we already have it */
200 : 0 : ret = 0;
201 : 0 : goto handle_assert_error;
202 : : }
203 : :
204 : : /* This is a new assertion. Let's keep it. */
205 [ # # ][ # # ]: 0 : aol(a->val, a->nbval, *atl, TOKEN_LIST_MEMG);
206 [ # # ]: 0 : if (ina) {
207 : 0 : HTT_put(&assertions, a, aname);
208 : 0 : freemem(aname);
209 : : }
210 [ # # ]: 0 : if (emit_assertions) {
211 : 0 : fprintf(emit_output, "#assert %s(", HASH_ITEM_NAME(a));
212 : 0 : print_token_fifo(atl);
213 : 0 : fputs(")\n", emit_output);
214 : : }
215 : 0 : freemem(atl);
216 : 0 : return 0;
217 : :
218 : : handle_assert_trunc:
219 : 0 : error(l, "unfinished #assert");
220 : : handle_assert_error:
221 [ # # ]: 0 : if (atl) {
222 : 0 : del_token_fifo(atl);
223 : 0 : freemem(atl);
224 : : }
225 [ # # ]: 0 : if (ina) {
226 : 0 : freemem(aname);
227 : 0 : freemem(a);
228 : : }
229 : 0 : return ret;
230 : : handle_assert_warp_ign:
231 [ # # ][ # # ]: 0 : while (!next_token(ls) && ls->ctok->type != NEWLINE);
232 [ # # ]: 0 : if (ina) {
233 : 0 : freemem(aname);
234 : 0 : freemem(a);
235 : : }
236 : 0 : return ret;
237 : : }
238 : :
239 : : /*
240 : : * for #unassert
241 : : */
242 : 0 : int handle_unassert(struct lexer_state *ls)
243 : : {
244 : : int ltww;
245 : : struct token t;
246 : : struct token_fifo atl;
247 : : struct assert *a;
248 : 0 : int ret = -1;
249 : 0 : long l = ls->line;
250 : : int nnp;
251 : : size_t i;
252 : :
253 : 0 : atl.art = atl.nt = 0;
254 [ # # ]: 0 : while (!next_token(ls)) {
255 [ # # ]: 0 : if (ls->ctok->type == NEWLINE) break;
256 [ # # ][ # # ]: 0 : if (ttMWS(ls->ctok->type)) continue;
[ # # ]
257 [ # # ]: 0 : if (ls->ctok->type == NAME) {
258 [ # # ]: 0 : if (!(a = HTT_get(&assertions, ls->ctok->name))) {
259 : 0 : ret = 0;
260 : 0 : goto handle_unassert_warp;
261 : : }
262 : 0 : goto handle_unassert_next;
263 : : }
264 : 0 : error(l, "illegal assertion name for #unassert");
265 : 0 : goto handle_unassert_warp;
266 : : }
267 : 0 : goto handle_unassert_trunc;
268 : :
269 : : handle_unassert_next:
270 [ # # ]: 0 : while (!next_token(ls)) {
271 [ # # ]: 0 : if (ls->ctok->type == NEWLINE) break;
272 [ # # ][ # # ]: 0 : if (ttMWS(ls->ctok->type)) continue;
[ # # ]
273 [ # # ]: 0 : if (ls->ctok->type != LPAR) {
274 : 0 : error(l, "syntax error in #unassert");
275 : 0 : goto handle_unassert_warp;
276 : : }
277 : 0 : goto handle_unassert_next2;
278 : : }
279 [ # # ]: 0 : if (emit_assertions)
280 : 0 : fprintf(emit_output, "#unassert %s\n", HASH_ITEM_NAME(a));
281 : 0 : HTT_del(&assertions, HASH_ITEM_NAME(a));
282 : 0 : return 0;
283 : :
284 : : handle_unassert_next2:
285 [ # # ][ # # ]: 0 : for (nnp = 1, ltww = 1; nnp && !next_token(ls);) {
286 [ # # ]: 0 : if (ls->ctok->type == NEWLINE) break;
287 [ # # ][ # # ]: 0 : if (ltww && ttMWS(ls->ctok->type)) continue;
[ # # ][ # # ]
288 [ # # ][ # # ]: 0 : ltww = ttMWS(ls->ctok->type);
[ # # ]
289 [ # # ]: 0 : if (ls->ctok->type == LPAR) nnp ++;
290 [ # # ]: 0 : else if (ls->ctok->type == RPAR) {
291 [ # # ]: 0 : if (!(-- nnp)) goto handle_unassert_next3;
292 : : }
293 : 0 : t.type = ls->ctok->type;
294 [ # # ][ # # ]: 0 : if (S_TOKEN(t.type)) t.name = sdup(ls->ctok->name);
295 [ # # ][ # # ]: 0 : aol(atl.t, atl.nt, t, TOKEN_LIST_MEMG);
296 : : }
297 : 0 : goto handle_unassert_trunc;
298 : :
299 : : handle_unassert_next3:
300 [ # # ][ # # ]: 0 : while (!next_token(ls) && ls->ctok->type != NEWLINE) {
301 [ # # ][ # # ]: 0 : if (!ttWHI(ls->ctok->type) && (ls->flags & WARN_STANDARD)) {
[ # # ][ # # ]
[ # # ]
302 : 0 : warning(l, "trailing garbage in #unassert");
303 : : }
304 : : }
305 [ # # ][ # # ]: 0 : if (atl.nt && ttMWS(atl.t[atl.nt - 1].type) && (-- atl.nt) == 0)
[ # # ][ # # ]
[ # # ]
306 : 0 : freemem(atl.t);
307 [ # # ]: 0 : if (atl.nt == 0) {
308 : 0 : error(l, "void assertion in #unassert");
309 : 0 : return ret;
310 : : }
311 [ # # ][ # # ]: 0 : for (i = 0; i < a->nbval && cmp_token_list(&atl, a->val + i); i ++);
312 [ # # ]: 0 : if (i != a->nbval) {
313 : : /* we have it, undefine it */
314 : 0 : del_token_fifo(a->val + i);
315 [ # # ]: 0 : if (i < (a->nbval - 1))
316 : 0 : mmvwo(a->val + i, a->val + i + 1, (a->nbval - i - 1)
317 : : * sizeof(struct token_fifo));
318 [ # # ]: 0 : if ((-- a->nbval) == 0) freemem(a->val);
319 [ # # ]: 0 : if (emit_assertions) {
320 : 0 : fprintf(emit_output, "#unassert %s(",
321 : 0 : HASH_ITEM_NAME(a));
322 : 0 : print_token_fifo(&atl);
323 : 0 : fputs(")\n", emit_output);
324 : : }
325 : : }
326 : 0 : ret = 0;
327 : 0 : goto handle_unassert_finish;
328 : :
329 : : handle_unassert_trunc:
330 : 0 : error(l, "unfinished #unassert");
331 : : handle_unassert_finish:
332 [ # # ]: 0 : if (atl.nt) del_token_fifo(&atl);
333 : 0 : return ret;
334 : : handle_unassert_warp:
335 [ # # ][ # # ]: 0 : while (!next_token(ls) && ls->ctok->type != NEWLINE);
336 : 0 : return ret;
337 : : }
338 : :
339 : : /*
340 : : * Add the given assertion (as string).
341 : : */
342 : 0 : int make_assertion(char *aval)
343 : : {
344 : : struct lexer_state lls;
345 : 0 : size_t n = strlen(aval) + 1;
346 : 0 : char *c = sdup(aval);
347 : : int ret;
348 : :
349 : 0 : *(c + n - 1) = '\n';
350 : 0 : init_buf_lexer_state(&lls, 0);
351 : 0 : lls.flags = DEFAULT_LEXER_FLAGS;
352 : 0 : lls.input = 0;
353 : 0 : lls.input_string = (unsigned char *)c;
354 : 0 : lls.pbuf = 0;
355 : 0 : lls.ebuf = n;
356 : 0 : lls.line = -1;
357 : 0 : ret = handle_assert(&lls);
358 : 0 : freemem(c);
359 : 0 : free_lexer_state(&lls);
360 : 0 : return ret;
361 : : }
362 : :
363 : : /*
364 : : * Remove the given assertion (as string).
365 : : */
366 : 0 : int destroy_assertion(char *aval)
367 : : {
368 : : struct lexer_state lls;
369 : 0 : size_t n = strlen(aval) + 1;
370 : 0 : char *c = sdup(aval);
371 : : int ret;
372 : :
373 : 0 : *(c + n - 1) = '\n';
374 : 0 : init_buf_lexer_state(&lls, 0);
375 : 0 : lls.flags = DEFAULT_LEXER_FLAGS;
376 : 0 : lls.input = 0;
377 : 0 : lls.input_string = (unsigned char *)c;
378 : 0 : lls.pbuf = 0;
379 : 0 : lls.ebuf = n;
380 : 0 : lls.line = -1;
381 : 0 : ret = handle_unassert(&lls);
382 : 0 : freemem(c);
383 : 0 : free_lexer_state(&lls);
384 : 0 : return ret;
385 : : }
386 : :
387 : : /*
388 : : * erase the assertion table
389 : : */
390 : 11956 : void wipe_assertions(void)
391 : : {
392 [ + + ]: 11956 : if (assertions_init_done) HTT_kill(&assertions);
393 : 11956 : assertions_init_done = 0;
394 : 11956 : }
395 : :
396 : : /*
397 : : * initialize the assertion table
398 : : */
399 : 5978 : void init_assertions(void)
400 : : {
401 : 5978 : wipe_assertions();
402 : 5978 : HTT_init(&assertions, del_assertion);
403 : 5978 : assertions_init_done = 1;
404 : 5978 : }
405 : :
406 : : /*
407 : : * retrieve an assertion from the hash table
408 : : */
409 : 0 : struct assert *get_assertion(char *name)
410 : : {
411 : 0 : return HTT_get(&assertions, name);
412 : : }
413 : :
414 : : /*
415 : : * print already defined assertions
416 : : */
417 : 0 : void print_assertions(void)
418 : : {
419 : 0 : HTT_scan(&assertions, print_assert);
420 : 0 : }
|