Commit | Line | Data |
---|---|---|
67905e42 MD |
1 | /* |
2 | * ctf-visitor-semantic-validator.c | |
3 | * | |
4 | * Common Trace Format Metadata Semantic Validator. | |
5 | * | |
6 | * Copyright 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> | |
7 | * | |
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy | |
9 | * of this software and associated documentation files (the "Software"), to deal | |
10 | * in the Software without restriction, including without limitation the rights | |
11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
12 | * copies of the Software, and to permit persons to whom the Software is | |
13 | * furnished to do so, subject to the following conditions: | |
14 | * | |
15 | * The above copyright notice and this permission notice shall be included in | |
16 | * all copies or substantial portions of the Software. | |
17 | */ | |
18 | ||
19 | #include <stdio.h> | |
20 | #include <unistd.h> | |
21 | #include <string.h> | |
22 | #include <stdlib.h> | |
23 | #include <assert.h> | |
24 | #include <glib.h> | |
25 | #include <inttypes.h> | |
26 | #include <errno.h> | |
c8b219a3 | 27 | #include <babeltrace/babeltrace.h> |
67905e42 MD |
28 | #include <babeltrace/list.h> |
29 | #include "ctf-scanner.h" | |
30 | #include "ctf-parser.h" | |
31 | #include "ctf-ast.h" | |
32 | ||
33 | #define _cds_list_first_entry(ptr, type, member) \ | |
34 | cds_list_entry((ptr)->next, type, member) | |
35 | ||
34f7b02c | 36 | #define fprintf_dbg(fd, fmt, args...) fprintf(fd, "%s: " fmt, __func__, ## args) |
67905e42 MD |
37 | |
38 | static | |
39 | int _ctf_visitor_semantic_check(FILE *fd, int depth, struct ctf_node *node); | |
40 | ||
41 | static | |
42 | int ctf_visitor_unary_expression(FILE *fd, int depth, struct ctf_node *node) | |
43 | { | |
44 | struct ctf_node *iter; | |
34f7b02c | 45 | int is_ctf_exp = 0, is_ctf_exp_left = 0; |
67905e42 MD |
46 | |
47 | switch (node->parent->type) { | |
48 | case NODE_CTF_EXPRESSION: | |
34f7b02c | 49 | is_ctf_exp = 1; |
67905e42 MD |
50 | cds_list_for_each_entry(iter, &node->parent->u.ctf_expression.left, |
51 | siblings) { | |
52 | if (iter == node) { | |
53 | is_ctf_exp_left = 1; | |
54 | /* | |
55 | * We are a left child of a ctf expression. | |
56 | * We are only allowed to be a string. | |
57 | */ | |
34f7b02c MD |
58 | if (node->u.unary_expression.type != UNARY_STRING) { |
59 | fprintf(fd, "[error]: semantic error (left child of a ctf expression is only allowed to be a string)\n"); | |
60 | ||
67905e42 | 61 | goto errperm; |
34f7b02c | 62 | } |
67905e42 MD |
63 | break; |
64 | } | |
65 | } | |
66 | /* Right child of a ctf expression can be any type of unary exp. */ | |
67 | break; /* OK */ | |
68 | case NODE_TYPE_DECLARATOR: | |
69 | /* | |
2b0a0f95 | 70 | * We are the length of a type declarator. |
67905e42 MD |
71 | */ |
72 | switch (node->u.unary_expression.type) { | |
73 | case UNARY_SIGNED_CONSTANT: | |
74 | case UNARY_UNSIGNED_CONSTANT: | |
75 | break; | |
76 | default: | |
34f7b02c | 77 | fprintf(fd, "[error]: semantic error (children of type declarator and enum can only be numeric constants)\n"); |
67905e42 MD |
78 | goto errperm; |
79 | } | |
80 | break; /* OK */ | |
81 | case NODE_ENUMERATOR: | |
135d0e88 | 82 | /* The enumerator's parent has validated its validity already. */ |
67905e42 MD |
83 | break; /* OK */ |
84 | ||
85 | case NODE_UNARY_EXPRESSION: | |
86 | /* | |
87 | * We disallow nested unary expressions and "sbrac" unary | |
88 | * expressions. | |
89 | */ | |
34f7b02c | 90 | fprintf(fd, "[error]: semantic error (nested unary expressions not allowed ( () and [] ))\n"); |
67905e42 MD |
91 | goto errperm; |
92 | ||
93 | case NODE_ROOT: | |
94 | case NODE_EVENT: | |
95 | case NODE_STREAM: | |
96 | case NODE_TRACE: | |
97 | case NODE_TYPEDEF: | |
98 | case NODE_TYPEALIAS_TARGET: | |
99 | case NODE_TYPEALIAS_ALIAS: | |
100 | case NODE_TYPEALIAS: | |
101 | case NODE_TYPE_SPECIFIER: | |
102 | case NODE_POINTER: | |
103 | case NODE_FLOATING_POINT: | |
104 | case NODE_INTEGER: | |
67905e42 | 105 | case NODE_STRING: |
2b0a0f95 | 106 | case NODE_ENUM: |
67905e42 MD |
107 | case NODE_STRUCT_OR_VARIANT_DECLARATION: |
108 | case NODE_VARIANT: | |
109 | case NODE_STRUCT: | |
110 | default: | |
111 | goto errinval; | |
112 | } | |
113 | ||
114 | switch (node->u.unary_expression.link) { | |
115 | case UNARY_LINK_UNKNOWN: | |
135d0e88 | 116 | /* We don't allow empty link except on the first node of the list */ |
34f7b02c | 117 | if (is_ctf_exp && _cds_list_first_entry(is_ctf_exp_left ? |
135d0e88 MD |
118 | &node->parent->u.ctf_expression.left : |
119 | &node->parent->u.ctf_expression.right, | |
120 | struct ctf_node, | |
34f7b02c MD |
121 | siblings) != node) { |
122 | fprintf(fd, "[error]: semantic error (empty link not allowed except on first node of unary expression (need to separate nodes with \".\" or \"->\")\n"); | |
135d0e88 | 123 | goto errperm; |
34f7b02c | 124 | } |
135d0e88 | 125 | break; /* OK */ |
67905e42 MD |
126 | case UNARY_DOTLINK: |
127 | case UNARY_ARROWLINK: | |
128 | /* We only allow -> and . links between children of ctf_expression. */ | |
34f7b02c MD |
129 | if (node->parent->type != NODE_CTF_EXPRESSION) { |
130 | fprintf(fd, "[error]: semantic error (links \".\" and \"->\" are only allowed as children of ctf expression)\n"); | |
135d0e88 | 131 | goto errperm; |
34f7b02c | 132 | } |
135d0e88 MD |
133 | /* |
134 | * Only strings can be separated linked by . or ->. | |
135 | * This includes "", '' and non-quoted identifiers. | |
136 | */ | |
34f7b02c MD |
137 | if (node->u.unary_expression.type != UNARY_STRING) { |
138 | fprintf(fd, "[error]: semantic error (links \".\" and \"->\" are only allowed to separate strings and identifiers)\n"); | |
139 | goto errperm; | |
140 | } | |
141 | /* We don't allow link on the first node of the list */ | |
142 | if (is_ctf_exp && _cds_list_first_entry(is_ctf_exp_left ? | |
143 | &node->parent->u.ctf_expression.left : | |
144 | &node->parent->u.ctf_expression.right, | |
145 | struct ctf_node, | |
146 | siblings) == node) { | |
147 | fprintf(fd, "[error]: semantic error (links \".\" and \"->\" are not allowed before first node of the unary expression list)\n"); | |
135d0e88 | 148 | goto errperm; |
34f7b02c | 149 | } |
67905e42 MD |
150 | break; |
151 | case UNARY_DOTDOTDOT: | |
152 | /* We only allow ... link between children of enumerator. */ | |
34f7b02c MD |
153 | if (node->parent->type != NODE_ENUMERATOR) { |
154 | fprintf(fd, "[error]: semantic error (link \"...\" is only allowed within enumerator)\n"); | |
135d0e88 | 155 | goto errperm; |
34f7b02c | 156 | } |
67905e42 MD |
157 | /* We don't allow link on the first node of the list */ |
158 | if (_cds_list_first_entry(&node->parent->u.enumerator.values, | |
159 | struct ctf_node, | |
34f7b02c MD |
160 | siblings) == node) { |
161 | fprintf(fd, "[error]: semantic error (link \"...\" is not allowed on the first node of the unary expression list)\n"); | |
162 | goto errperm; | |
163 | } | |
67905e42 MD |
164 | break; |
165 | default: | |
166 | fprintf(fd, "[error] %s: unknown expression link type %d\n", __func__, | |
167 | (int) node->u.unary_expression.link); | |
168 | return -EINVAL; | |
169 | } | |
170 | return 0; | |
171 | ||
172 | errinval: | |
34f7b02c MD |
173 | fprintf(fd, "[error] %s: incoherent parent type %s for node type %s\n", __func__, |
174 | node_type(node->parent), node_type(node)); | |
67905e42 MD |
175 | return -EINVAL; /* Incoherent structure */ |
176 | ||
177 | errperm: | |
34f7b02c MD |
178 | fprintf(fd, "[error] %s: semantic error (parent type %s for node type %s)\n", __func__, |
179 | node_type(node->parent), node_type(node)); | |
67905e42 MD |
180 | return -EPERM; /* Structure not allowed */ |
181 | } | |
182 | ||
183 | static | |
3e11b713 | 184 | int ctf_visitor_type_specifier_list(FILE *fd, int depth, struct ctf_node *node) |
67905e42 MD |
185 | { |
186 | switch (node->parent->type) { | |
187 | case NODE_CTF_EXPRESSION: | |
188 | case NODE_TYPE_DECLARATOR: | |
189 | case NODE_TYPEDEF: | |
190 | case NODE_TYPEALIAS_TARGET: | |
191 | case NODE_TYPEALIAS_ALIAS: | |
192 | case NODE_ENUM: | |
34f7b02c | 193 | case NODE_STRUCT_OR_VARIANT_DECLARATION: |
3e11b713 MD |
194 | case NODE_ROOT: |
195 | break; /* OK */ | |
196 | ||
197 | case NODE_EVENT: | |
198 | case NODE_STREAM: | |
199 | case NODE_TRACE: | |
200 | case NODE_UNARY_EXPRESSION: | |
201 | case NODE_TYPEALIAS: | |
202 | case NODE_TYPE_SPECIFIER: | |
203 | case NODE_TYPE_SPECIFIER_LIST: | |
204 | case NODE_POINTER: | |
205 | case NODE_FLOATING_POINT: | |
206 | case NODE_INTEGER: | |
207 | case NODE_STRING: | |
208 | case NODE_ENUMERATOR: | |
209 | case NODE_VARIANT: | |
210 | case NODE_STRUCT: | |
211 | default: | |
212 | goto errinval; | |
213 | } | |
214 | return 0; | |
215 | errinval: | |
216 | fprintf(fd, "[error] %s: incoherent parent type %s for node type %s\n", __func__, | |
217 | node_type(node->parent), node_type(node)); | |
218 | return -EINVAL; /* Incoherent structure */ | |
219 | } | |
220 | ||
221 | static | |
222 | int ctf_visitor_type_specifier(FILE *fd, int depth, struct ctf_node *node) | |
223 | { | |
224 | switch (node->parent->type) { | |
225 | case NODE_TYPE_SPECIFIER_LIST: | |
67905e42 MD |
226 | break; /* OK */ |
227 | ||
3e11b713 MD |
228 | case NODE_CTF_EXPRESSION: |
229 | case NODE_TYPE_DECLARATOR: | |
230 | case NODE_TYPEDEF: | |
231 | case NODE_TYPEALIAS_TARGET: | |
232 | case NODE_TYPEALIAS_ALIAS: | |
233 | case NODE_ENUM: | |
234 | case NODE_STRUCT_OR_VARIANT_DECLARATION: | |
67905e42 MD |
235 | case NODE_ROOT: |
236 | case NODE_EVENT: | |
237 | case NODE_STREAM: | |
238 | case NODE_TRACE: | |
239 | case NODE_UNARY_EXPRESSION: | |
240 | case NODE_TYPEALIAS: | |
241 | case NODE_TYPE_SPECIFIER: | |
242 | case NODE_POINTER: | |
243 | case NODE_FLOATING_POINT: | |
244 | case NODE_INTEGER: | |
245 | case NODE_STRING: | |
246 | case NODE_ENUMERATOR: | |
67905e42 MD |
247 | case NODE_VARIANT: |
248 | case NODE_STRUCT: | |
249 | default: | |
250 | goto errinval; | |
251 | } | |
252 | return 0; | |
253 | errinval: | |
34f7b02c MD |
254 | fprintf(fd, "[error] %s: incoherent parent type %s for node type %s\n", __func__, |
255 | node_type(node->parent), node_type(node)); | |
67905e42 MD |
256 | return -EINVAL; /* Incoherent structure */ |
257 | } | |
258 | ||
259 | static | |
260 | int ctf_visitor_type_declarator(FILE *fd, int depth, struct ctf_node *node) | |
261 | { | |
262 | int ret = 0; | |
263 | struct ctf_node *iter; | |
264 | ||
265 | depth++; | |
266 | ||
267 | switch (node->parent->type) { | |
268 | case NODE_TYPE_DECLARATOR: | |
269 | /* | |
270 | * A nested type declarator is not allowed to contain pointers. | |
271 | */ | |
272 | if (!cds_list_empty(&node->u.type_declarator.pointers)) | |
273 | goto errperm; | |
1ee8e81d | 274 | break; /* OK */ |
67905e42 | 275 | case NODE_TYPEALIAS_TARGET: |
1ee8e81d | 276 | break; /* OK */ |
67905e42 | 277 | case NODE_TYPEALIAS_ALIAS: |
1ee8e81d MD |
278 | /* |
279 | * Only accept alias name containing: | |
280 | * - identifier | |
281 | * - identifier * (any number of pointers) | |
282 | * NOT accepting alias names containing [] (would otherwise | |
283 | * cause semantic clash for later declarations of | |
284 | * arrays/sequences of elements, where elements could be | |
285 | * arrays/sequences themselves (if allowed in typealias). | |
286 | * NOT accepting alias with identifier. The declarator should | |
287 | * be either empty or contain pointer(s). | |
288 | */ | |
289 | if (node->u.type_declarator.type == TYPEDEC_NESTED) | |
290 | goto errperm; | |
3e11b713 MD |
291 | switch (node->u.type_declarator.type) { |
292 | case TYPESPEC_FLOATING_POINT: | |
293 | case TYPESPEC_INTEGER: | |
294 | case TYPESPEC_STRING: | |
295 | case TYPESPEC_STRUCT: | |
296 | case TYPESPEC_VARIANT: | |
297 | case TYPESPEC_ENUM: | |
298 | if (cds_list_empty(&node->u.type_declarator.pointers)) | |
299 | goto errperm; | |
300 | break; | |
301 | default: | |
302 | break; | |
303 | } | |
1ee8e81d MD |
304 | if (node->u.type_declarator.type == TYPEDEC_ID && |
305 | node->u.type_declarator.u.id != NULL) | |
306 | goto errperm; | |
307 | break; /* OK */ | |
308 | case NODE_TYPEDEF: | |
67905e42 MD |
309 | case NODE_STRUCT_OR_VARIANT_DECLARATION: |
310 | break; /* OK */ | |
311 | ||
312 | case NODE_ROOT: | |
313 | case NODE_EVENT: | |
314 | case NODE_STREAM: | |
315 | case NODE_TRACE: | |
316 | case NODE_CTF_EXPRESSION: | |
317 | case NODE_UNARY_EXPRESSION: | |
318 | case NODE_TYPEALIAS: | |
319 | case NODE_TYPE_SPECIFIER: | |
320 | case NODE_POINTER: | |
321 | case NODE_FLOATING_POINT: | |
322 | case NODE_INTEGER: | |
323 | case NODE_STRING: | |
324 | case NODE_ENUMERATOR: | |
325 | case NODE_ENUM: | |
326 | case NODE_VARIANT: | |
327 | case NODE_STRUCT: | |
328 | default: | |
329 | goto errinval; | |
330 | } | |
331 | ||
332 | if (!cds_list_empty(&node->u.type_declarator.pointers)) { | |
333 | cds_list_for_each_entry(iter, &node->u.type_declarator.pointers, | |
334 | siblings) { | |
335 | ret = _ctf_visitor_semantic_check(fd, depth + 1, iter); | |
336 | if (ret) | |
337 | return ret; | |
338 | } | |
339 | } | |
340 | ||
341 | switch (node->u.type_declarator.type) { | |
342 | case TYPEDEC_ID: | |
343 | break; | |
344 | case TYPEDEC_NESTED: | |
7d4192cb | 345 | { |
67905e42 MD |
346 | if (node->u.type_declarator.u.nested.type_declarator) { |
347 | ret = _ctf_visitor_semantic_check(fd, depth + 1, | |
348 | node->u.type_declarator.u.nested.type_declarator); | |
349 | if (ret) | |
350 | return ret; | |
351 | } | |
3e11b713 MD |
352 | ret = _ctf_visitor_semantic_check(fd, depth + 1, |
353 | node->u.type_declarator.u.nested.length); | |
354 | if (ret) | |
355 | return ret; | |
67905e42 MD |
356 | if (node->u.type_declarator.bitfield_len) { |
357 | ret = _ctf_visitor_semantic_check(fd, depth + 1, | |
358 | node->u.type_declarator.bitfield_len); | |
359 | if (ret) | |
360 | return ret; | |
361 | } | |
362 | break; | |
7d4192cb | 363 | } |
67905e42 MD |
364 | case TYPEDEC_UNKNOWN: |
365 | default: | |
366 | fprintf(fd, "[error] %s: unknown type declarator %d\n", __func__, | |
367 | (int) node->u.type_declarator.type); | |
368 | return -EINVAL; | |
369 | } | |
370 | depth--; | |
371 | return 0; | |
372 | ||
373 | errinval: | |
34f7b02c MD |
374 | fprintf(fd, "[error] %s: incoherent parent type %s for node type %s\n", __func__, |
375 | node_type(node->parent), node_type(node)); | |
67905e42 MD |
376 | return -EINVAL; /* Incoherent structure */ |
377 | ||
378 | errperm: | |
34f7b02c MD |
379 | fprintf(fd, "[error] %s: semantic error (parent type %s for node type %s)\n", __func__, |
380 | node_type(node->parent), node_type(node)); | |
67905e42 MD |
381 | return -EPERM; /* Structure not allowed */ |
382 | } | |
383 | ||
384 | static | |
385 | int _ctf_visitor_semantic_check(FILE *fd, int depth, struct ctf_node *node) | |
386 | { | |
387 | int ret = 0; | |
388 | struct ctf_node *iter; | |
389 | ||
390 | switch (node->type) { | |
391 | case NODE_ROOT: | |
3e11b713 | 392 | cds_list_for_each_entry(iter, &node->u.root.declaration_list, siblings) { |
67905e42 MD |
393 | ret = _ctf_visitor_semantic_check(fd, depth + 1, iter); |
394 | if (ret) | |
395 | return ret; | |
396 | } | |
397 | cds_list_for_each_entry(iter, &node->u.root.trace, siblings) { | |
398 | ret = _ctf_visitor_semantic_check(fd, depth + 1, iter); | |
399 | if (ret) | |
400 | return ret; | |
401 | } | |
402 | cds_list_for_each_entry(iter, &node->u.root.stream, siblings) { | |
403 | ret = _ctf_visitor_semantic_check(fd, depth + 1, iter); | |
404 | if (ret) | |
405 | return ret; | |
406 | } | |
407 | cds_list_for_each_entry(iter, &node->u.root.event, siblings) { | |
408 | ret = _ctf_visitor_semantic_check(fd, depth + 1, iter); | |
409 | if (ret) | |
410 | return ret; | |
411 | } | |
412 | break; | |
413 | ||
414 | case NODE_EVENT: | |
415 | switch (node->parent->type) { | |
416 | case NODE_ROOT: | |
417 | break; /* OK */ | |
418 | default: | |
419 | goto errinval; | |
420 | } | |
421 | ||
422 | cds_list_for_each_entry(iter, &node->u.event.declaration_list, siblings) { | |
423 | ret = _ctf_visitor_semantic_check(fd, depth + 1, iter); | |
424 | if (ret) | |
425 | return ret; | |
426 | } | |
427 | break; | |
428 | case NODE_STREAM: | |
429 | switch (node->parent->type) { | |
430 | case NODE_ROOT: | |
431 | break; /* OK */ | |
432 | default: | |
433 | goto errinval; | |
434 | } | |
435 | ||
436 | cds_list_for_each_entry(iter, &node->u.stream.declaration_list, siblings) { | |
437 | ret = _ctf_visitor_semantic_check(fd, depth + 1, iter); | |
438 | if (ret) | |
439 | return ret; | |
440 | } | |
441 | break; | |
442 | case NODE_TRACE: | |
443 | switch (node->parent->type) { | |
444 | case NODE_ROOT: | |
445 | break; /* OK */ | |
446 | default: | |
447 | goto errinval; | |
448 | } | |
449 | ||
450 | cds_list_for_each_entry(iter, &node->u.trace.declaration_list, siblings) { | |
451 | ret = _ctf_visitor_semantic_check(fd, depth + 1, iter); | |
452 | if (ret) | |
453 | return ret; | |
454 | } | |
455 | break; | |
456 | ||
457 | case NODE_CTF_EXPRESSION: | |
458 | switch (node->parent->type) { | |
459 | case NODE_ROOT: | |
460 | case NODE_EVENT: | |
461 | case NODE_STREAM: | |
462 | case NODE_TRACE: | |
463 | case NODE_FLOATING_POINT: | |
464 | case NODE_INTEGER: | |
465 | case NODE_STRING: | |
466 | break; /* OK */ | |
467 | ||
468 | case NODE_CTF_EXPRESSION: | |
469 | case NODE_UNARY_EXPRESSION: | |
470 | case NODE_TYPEDEF: | |
471 | case NODE_TYPEALIAS_TARGET: | |
472 | case NODE_TYPEALIAS_ALIAS: | |
473 | case NODE_STRUCT_OR_VARIANT_DECLARATION: | |
474 | case NODE_TYPEALIAS: | |
475 | case NODE_TYPE_SPECIFIER: | |
3e11b713 | 476 | case NODE_TYPE_SPECIFIER_LIST: |
67905e42 MD |
477 | case NODE_POINTER: |
478 | case NODE_TYPE_DECLARATOR: | |
479 | case NODE_ENUMERATOR: | |
480 | case NODE_ENUM: | |
481 | case NODE_VARIANT: | |
482 | case NODE_STRUCT: | |
483 | default: | |
484 | goto errinval; | |
485 | } | |
486 | ||
487 | depth++; | |
488 | cds_list_for_each_entry(iter, &node->u.ctf_expression.left, siblings) { | |
489 | ret = _ctf_visitor_semantic_check(fd, depth + 1, iter); | |
490 | if (ret) | |
491 | return ret; | |
492 | } | |
493 | cds_list_for_each_entry(iter, &node->u.ctf_expression.right, siblings) { | |
494 | ret = _ctf_visitor_semantic_check(fd, depth + 1, iter); | |
495 | if (ret) | |
496 | return ret; | |
497 | } | |
498 | depth--; | |
499 | break; | |
500 | case NODE_UNARY_EXPRESSION: | |
501 | return ctf_visitor_unary_expression(fd, depth, node); | |
502 | ||
503 | case NODE_TYPEDEF: | |
504 | switch (node->parent->type) { | |
505 | case NODE_ROOT: | |
506 | case NODE_EVENT: | |
507 | case NODE_STREAM: | |
508 | case NODE_TRACE: | |
509 | case NODE_VARIANT: | |
510 | case NODE_STRUCT: | |
511 | break; /* OK */ | |
512 | ||
513 | case NODE_CTF_EXPRESSION: | |
514 | case NODE_UNARY_EXPRESSION: | |
515 | case NODE_TYPEDEF: | |
516 | case NODE_TYPEALIAS_TARGET: | |
517 | case NODE_TYPEALIAS_ALIAS: | |
518 | case NODE_TYPEALIAS: | |
519 | case NODE_STRUCT_OR_VARIANT_DECLARATION: | |
520 | case NODE_TYPE_SPECIFIER: | |
3e11b713 | 521 | case NODE_TYPE_SPECIFIER_LIST: |
67905e42 MD |
522 | case NODE_POINTER: |
523 | case NODE_TYPE_DECLARATOR: | |
524 | case NODE_FLOATING_POINT: | |
525 | case NODE_INTEGER: | |
526 | case NODE_STRING: | |
527 | case NODE_ENUMERATOR: | |
528 | case NODE_ENUM: | |
529 | default: | |
530 | goto errinval; | |
531 | } | |
532 | ||
533 | depth++; | |
3e11b713 MD |
534 | ret = _ctf_visitor_semantic_check(fd, depth + 1, |
535 | node->u._typedef.type_specifier_list); | |
536 | if (ret) | |
537 | return ret; | |
67905e42 MD |
538 | cds_list_for_each_entry(iter, &node->u._typedef.type_declarators, siblings) { |
539 | ret = _ctf_visitor_semantic_check(fd, depth + 1, iter); | |
540 | if (ret) | |
541 | return ret; | |
542 | } | |
543 | depth--; | |
544 | break; | |
545 | case NODE_TYPEALIAS_TARGET: | |
1ee8e81d MD |
546 | { |
547 | int nr_declarators; | |
548 | ||
67905e42 MD |
549 | switch (node->parent->type) { |
550 | case NODE_TYPEALIAS: | |
551 | break; /* OK */ | |
552 | default: | |
553 | goto errinval; | |
554 | } | |
555 | ||
556 | depth++; | |
3e11b713 MD |
557 | ret = _ctf_visitor_semantic_check(fd, depth + 1, |
558 | node->u.typealias_target.type_specifier_list); | |
559 | if (ret) | |
560 | return ret; | |
1ee8e81d | 561 | nr_declarators = 0; |
67905e42 MD |
562 | cds_list_for_each_entry(iter, &node->u.typealias_target.type_declarators, siblings) { |
563 | ret = _ctf_visitor_semantic_check(fd, depth + 1, iter); | |
564 | if (ret) | |
565 | return ret; | |
1ee8e81d MD |
566 | nr_declarators++; |
567 | } | |
568 | if (nr_declarators > 1) { | |
569 | fprintf(fd, "[error] %s: Too many declarators in typealias alias (%d, max is 1)\n", __func__, nr_declarators); | |
570 | ||
571 | return -EINVAL; | |
67905e42 MD |
572 | } |
573 | depth--; | |
574 | break; | |
1ee8e81d | 575 | } |
67905e42 | 576 | case NODE_TYPEALIAS_ALIAS: |
1ee8e81d MD |
577 | { |
578 | int nr_declarators; | |
579 | ||
67905e42 MD |
580 | switch (node->parent->type) { |
581 | case NODE_TYPEALIAS: | |
582 | break; /* OK */ | |
583 | default: | |
584 | goto errinval; | |
585 | } | |
586 | ||
587 | depth++; | |
3e11b713 MD |
588 | ret = _ctf_visitor_semantic_check(fd, depth + 1, |
589 | node->u.typealias_alias.type_specifier_list); | |
590 | if (ret) | |
591 | return ret; | |
1ee8e81d | 592 | nr_declarators = 0; |
67905e42 MD |
593 | cds_list_for_each_entry(iter, &node->u.typealias_alias.type_declarators, siblings) { |
594 | ret = _ctf_visitor_semantic_check(fd, depth + 1, iter); | |
595 | if (ret) | |
596 | return ret; | |
1ee8e81d MD |
597 | nr_declarators++; |
598 | } | |
599 | if (nr_declarators > 1) { | |
600 | fprintf(fd, "[error] %s: Too many declarators in typealias alias (%d, max is 1)\n", __func__, nr_declarators); | |
601 | ||
602 | return -EINVAL; | |
67905e42 MD |
603 | } |
604 | depth--; | |
605 | break; | |
1ee8e81d | 606 | } |
67905e42 MD |
607 | case NODE_TYPEALIAS: |
608 | switch (node->parent->type) { | |
609 | case NODE_ROOT: | |
610 | case NODE_EVENT: | |
611 | case NODE_STREAM: | |
612 | case NODE_TRACE: | |
613 | case NODE_VARIANT: | |
614 | case NODE_STRUCT: | |
615 | break; /* OK */ | |
616 | ||
617 | case NODE_CTF_EXPRESSION: | |
618 | case NODE_UNARY_EXPRESSION: | |
619 | case NODE_TYPEDEF: | |
620 | case NODE_TYPEALIAS_TARGET: | |
621 | case NODE_TYPEALIAS_ALIAS: | |
622 | case NODE_TYPEALIAS: | |
623 | case NODE_STRUCT_OR_VARIANT_DECLARATION: | |
624 | case NODE_TYPE_SPECIFIER: | |
3e11b713 | 625 | case NODE_TYPE_SPECIFIER_LIST: |
67905e42 MD |
626 | case NODE_POINTER: |
627 | case NODE_TYPE_DECLARATOR: | |
628 | case NODE_FLOATING_POINT: | |
629 | case NODE_INTEGER: | |
630 | case NODE_STRING: | |
631 | case NODE_ENUMERATOR: | |
632 | case NODE_ENUM: | |
633 | default: | |
634 | goto errinval; | |
635 | } | |
636 | ||
637 | ret = _ctf_visitor_semantic_check(fd, depth + 1, node->u.typealias.target); | |
638 | if (ret) | |
639 | return ret; | |
640 | ret = _ctf_visitor_semantic_check(fd, depth + 1, node->u.typealias.alias); | |
641 | if (ret) | |
642 | return ret; | |
643 | break; | |
644 | ||
3e11b713 MD |
645 | case NODE_TYPE_SPECIFIER_LIST: |
646 | ret = ctf_visitor_type_specifier_list(fd, depth, node); | |
647 | if (ret) | |
648 | return ret; | |
649 | break; | |
67905e42 MD |
650 | case NODE_TYPE_SPECIFIER: |
651 | ret = ctf_visitor_type_specifier(fd, depth, node); | |
652 | if (ret) | |
653 | return ret; | |
654 | break; | |
655 | case NODE_POINTER: | |
656 | switch (node->parent->type) { | |
657 | case NODE_TYPE_DECLARATOR: | |
658 | break; /* OK */ | |
659 | default: | |
660 | goto errinval; | |
661 | } | |
662 | break; | |
663 | case NODE_TYPE_DECLARATOR: | |
664 | ret = ctf_visitor_type_declarator(fd, depth, node); | |
665 | if (ret) | |
666 | return ret; | |
667 | break; | |
668 | ||
669 | case NODE_FLOATING_POINT: | |
670 | switch (node->parent->type) { | |
67905e42 | 671 | case NODE_TYPE_SPECIFIER: |
3e11b713 | 672 | break; /* OK */ |
67905e42 MD |
673 | default: |
674 | goto errinval; | |
675 | ||
676 | case NODE_UNARY_EXPRESSION: | |
677 | goto errperm; | |
678 | } | |
679 | cds_list_for_each_entry(iter, &node->u.floating_point.expressions, siblings) { | |
680 | ret = _ctf_visitor_semantic_check(fd, depth + 1, iter); | |
681 | if (ret) | |
682 | return ret; | |
683 | } | |
684 | break; | |
685 | case NODE_INTEGER: | |
686 | switch (node->parent->type) { | |
67905e42 | 687 | case NODE_TYPE_SPECIFIER: |
3e11b713 | 688 | break; /* OK */ |
67905e42 MD |
689 | default: |
690 | goto errinval; | |
691 | ||
692 | } | |
693 | ||
694 | cds_list_for_each_entry(iter, &node->u.integer.expressions, siblings) { | |
695 | ret = _ctf_visitor_semantic_check(fd, depth + 1, iter); | |
696 | if (ret) | |
697 | return ret; | |
698 | } | |
699 | break; | |
700 | case NODE_STRING: | |
701 | switch (node->parent->type) { | |
67905e42 | 702 | case NODE_TYPE_SPECIFIER: |
3e11b713 | 703 | break; /* OK */ |
67905e42 MD |
704 | default: |
705 | goto errinval; | |
706 | ||
707 | case NODE_UNARY_EXPRESSION: | |
708 | goto errperm; | |
709 | } | |
710 | ||
711 | cds_list_for_each_entry(iter, &node->u.string.expressions, siblings) { | |
712 | ret = _ctf_visitor_semantic_check(fd, depth + 1, iter); | |
713 | if (ret) | |
714 | return ret; | |
715 | } | |
716 | break; | |
717 | case NODE_ENUMERATOR: | |
718 | switch (node->parent->type) { | |
719 | case NODE_ENUM: | |
720 | break; | |
721 | default: | |
722 | goto errinval; | |
723 | } | |
724 | /* | |
725 | * Enumerators are only allows to contain: | |
726 | * numeric unary expression | |
727 | * or num. unary exp. ... num. unary exp | |
728 | */ | |
729 | { | |
730 | int count = 0; | |
731 | ||
34f7b02c | 732 | cds_list_for_each_entry(iter, &node->u.enumerator.values, |
67905e42 MD |
733 | siblings) { |
734 | switch (count++) { | |
735 | case 0: if (iter->type != NODE_UNARY_EXPRESSION | |
736 | || (iter->u.unary_expression.type != UNARY_SIGNED_CONSTANT | |
737 | && iter->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) | |
34f7b02c MD |
738 | || iter->u.unary_expression.link != UNARY_LINK_UNKNOWN) { |
739 | fprintf(fd, "[error]: semantic error (first unary expression of enumerator is unexpected)\n"); | |
67905e42 | 740 | goto errperm; |
34f7b02c | 741 | } |
67905e42 MD |
742 | break; |
743 | case 1: if (iter->type != NODE_UNARY_EXPRESSION | |
744 | || (iter->u.unary_expression.type != UNARY_SIGNED_CONSTANT | |
745 | && iter->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) | |
34f7b02c MD |
746 | || iter->u.unary_expression.link != UNARY_DOTDOTDOT) { |
747 | fprintf(fd, "[error]: semantic error (second unary expression of enumerator is unexpected)\n"); | |
67905e42 | 748 | goto errperm; |
34f7b02c | 749 | } |
67905e42 MD |
750 | break; |
751 | default: | |
752 | goto errperm; | |
753 | } | |
754 | } | |
755 | } | |
756 | ||
757 | cds_list_for_each_entry(iter, &node->u.enumerator.values, siblings) { | |
758 | ret = _ctf_visitor_semantic_check(fd, depth + 1, iter); | |
759 | if (ret) | |
760 | return ret; | |
761 | } | |
762 | break; | |
763 | case NODE_ENUM: | |
764 | switch (node->parent->type) { | |
67905e42 | 765 | case NODE_TYPE_SPECIFIER: |
3e11b713 | 766 | break; /* OK */ |
67905e42 MD |
767 | default: |
768 | goto errinval; | |
769 | ||
770 | case NODE_UNARY_EXPRESSION: | |
771 | goto errperm; | |
772 | } | |
773 | ||
774 | depth++; | |
3e11b713 MD |
775 | ret = _ctf_visitor_semantic_check(fd, depth + 1, node->u._enum.container_type); |
776 | if (ret) | |
777 | return ret; | |
67905e42 MD |
778 | |
779 | cds_list_for_each_entry(iter, &node->u._enum.enumerator_list, siblings) { | |
780 | ret = _ctf_visitor_semantic_check(fd, depth + 1, iter); | |
781 | if (ret) | |
782 | return ret; | |
783 | } | |
784 | depth--; | |
785 | break; | |
786 | case NODE_STRUCT_OR_VARIANT_DECLARATION: | |
787 | switch (node->parent->type) { | |
788 | case NODE_STRUCT: | |
789 | case NODE_VARIANT: | |
790 | break; | |
791 | default: | |
792 | goto errinval; | |
793 | } | |
3e11b713 MD |
794 | ret = _ctf_visitor_semantic_check(fd, depth + 1, |
795 | node->u.struct_or_variant_declaration.type_specifier_list); | |
796 | if (ret) | |
797 | return ret; | |
67905e42 MD |
798 | cds_list_for_each_entry(iter, &node->u.struct_or_variant_declaration.type_declarators, siblings) { |
799 | ret = _ctf_visitor_semantic_check(fd, depth + 1, iter); | |
800 | if (ret) | |
801 | return ret; | |
802 | } | |
803 | break; | |
804 | case NODE_VARIANT: | |
805 | switch (node->parent->type) { | |
67905e42 | 806 | case NODE_TYPE_SPECIFIER: |
3e11b713 | 807 | break; /* OK */ |
67905e42 MD |
808 | default: |
809 | goto errinval; | |
810 | ||
811 | case NODE_UNARY_EXPRESSION: | |
812 | goto errperm; | |
813 | } | |
814 | cds_list_for_each_entry(iter, &node->u.variant.declaration_list, siblings) { | |
815 | ret = _ctf_visitor_semantic_check(fd, depth + 1, iter); | |
816 | if (ret) | |
817 | return ret; | |
818 | } | |
819 | break; | |
820 | ||
821 | case NODE_STRUCT: | |
822 | switch (node->parent->type) { | |
67905e42 | 823 | case NODE_TYPE_SPECIFIER: |
3e11b713 | 824 | break; /* OK */ |
67905e42 MD |
825 | default: |
826 | goto errinval; | |
827 | ||
828 | case NODE_UNARY_EXPRESSION: | |
829 | goto errperm; | |
830 | } | |
831 | cds_list_for_each_entry(iter, &node->u._struct.declaration_list, siblings) { | |
832 | ret = _ctf_visitor_semantic_check(fd, depth + 1, iter); | |
833 | if (ret) | |
834 | return ret; | |
835 | } | |
836 | break; | |
837 | ||
838 | case NODE_UNKNOWN: | |
839 | default: | |
840 | fprintf(fd, "[error] %s: unknown node type %d\n", __func__, | |
841 | (int) node->type); | |
842 | return -EINVAL; | |
843 | } | |
844 | return ret; | |
845 | ||
846 | errinval: | |
34f7b02c MD |
847 | fprintf(fd, "[error] %s: incoherent parent type %s for node type %s\n", __func__, |
848 | node_type(node->parent), node_type(node)); | |
67905e42 MD |
849 | return -EINVAL; /* Incoherent structure */ |
850 | ||
851 | errperm: | |
34f7b02c MD |
852 | fprintf(fd, "[error] %s: semantic error (parent type %s for node type %s)\n", __func__, |
853 | node_type(node->parent), node_type(node)); | |
67905e42 MD |
854 | return -EPERM; /* Structure not allowed */ |
855 | } | |
856 | ||
857 | int ctf_visitor_semantic_check(FILE *fd, int depth, struct ctf_node *node) | |
858 | { | |
859 | int ret = 0; | |
860 | ||
861 | /* | |
862 | * First make sure we create the parent links for all children. Let's | |
863 | * take the safe route and recreate them at each validation, just in | |
864 | * case the structure has changed. | |
865 | */ | |
c8b219a3 | 866 | printf_verbose("CTF visitor: parent links creation... "); |
67905e42 MD |
867 | ret = ctf_visitor_parent_links(fd, depth, node); |
868 | if (ret) | |
869 | return ret; | |
c8b219a3 MD |
870 | printf_verbose("done.\n"); |
871 | printf_verbose("CTF visitor: semantic check... "); | |
34f7b02c MD |
872 | ret = _ctf_visitor_semantic_check(fd, depth, node); |
873 | if (ret) | |
874 | return ret; | |
c8b219a3 | 875 | printf_verbose("done.\n"); |
34f7b02c | 876 | return ret; |
67905e42 | 877 | } |