• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

nickg / nvc / 15809308352

22 Jun 2025 04:57PM UTC coverage: 92.236% (-0.02%) from 92.252%
15809308352

push

github

nickg
Parse Verilog generate blocks

83 of 142 new or added lines in 5 files covered. (58.45%)

303 existing lines in 12 files now uncovered.

70258 of 76172 relevant lines covered (92.24%)

566112.73 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.21
/src/vlog/vlog-node.c
1
//
2
//  Copyright (C) 2022-2025  Nick Gasson
3
//
4
//  This program is free software: you can redistribute it and/or modify
5
//  it under the terms of the GNU General Public License as published by
6
//  the Free Software Foundation, either version 3 of the License, or
7
//  (at your option) any later version.
8
//
9
//  This program is distributed in the hope that it will be useful,
10
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
//  GNU General Public License for more details.
13
//
14
//  You should have received a copy of the GNU General Public License
15
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
//
17

18
#include "util.h"
19
#include "vlog/vlog-node.h"
20
#include "vlog/vlog-number.h"
21
#include "object.h"
22

23
#include <string.h>
24
#include <inttypes.h>
25
#include <stdlib.h>
26

27
static const imask_t has_map[V_LAST_NODE_KIND] = {
28
   // V_MODULE
29
   (I_IDENT | I_PORTS | I_STMTS | I_DECLS | I_IDENT2),
30

31
   // V_PORT_DECL
32
   (I_IDENT | I_SUBKIND | I_IDENT2 | I_REF | I_RANGES | I_TYPE),
33

34
   // V_REF
35
   (I_IDENT | I_REF),
36

37
   // V_ALWAYS
38
   (I_IDENT | I_SUBKIND | I_STMTS),
39

40
   // V_TIMING
41
   (I_VALUE | I_STMTS),
42

43
   // V_NBASSIGN
44
   (I_TARGET | I_VALUE | I_DELAY),
45

46
   // V_EVENT
47
   (I_SUBKIND | I_VALUE),
48

49
   // V_INITIAL
50
   (I_IDENT | I_STMTS),
51

52
   // V_BLOCK
53
   (I_IDENT | I_DECLS | I_STMTS),
54

55
   // V_SYS_TCALL
56
   (I_IDENT | I_PARAMS),
57

58
   // V_STRING
59
   (I_TEXT),
60

61
   // V_NUMBER
62
   (I_NUMBER),
63

64
   // V_NET_DECL
65
   (I_IDENT | I_SUBKIND | I_TYPE | I_RANGES | I_VALUE),
66

67
   // V_ASSIGN
68
   (I_TARGET | I_VALUE | I_IDENT | I_DELAY),
69

70
   // V_DIMENSION
71
   (I_SUBKIND | I_LEFT | I_RIGHT),
72

73
   // V_IF
74
   (I_CONDS),
75

76
   // V_COND
77
   (I_VALUE | I_STMTS),
78

79
   // V_VAR_DECL
80
   (I_IDENT | I_TYPE | I_RANGES | I_VALUE),
81

82
   // V_DELAY_CONTROL
83
   (I_VALUE),
84

85
   // V_BINARY
86
   (I_LEFT | I_RIGHT | I_SUBKIND),
87

88
   // V_BASSIGN
89
   (I_TARGET | I_VALUE | I_SUBKIND | I_DELAY),
90

91
   // V_UNARY
92
   (I_VALUE | I_SUBKIND),
93

94
   // V_GATE_INST
95
   (I_SUBKIND | I_PARAMS | I_IDENT | I_REF | I_TARGET),
96

97
   // V_STRENGTH
98
   (I_SUBKIND),
99

100
   // V_MOD_INST
101
   (I_IDENT | I_PARAMS),
102

103
   // V_BIT_SELECT
104
   (I_IDENT | I_REF | I_PARAMS),
105

106
   // V_SYS_FCALL
107
   (I_IDENT | I_PARAMS),
108

109
   // V_FOREVER
110
   (I_STMTS),
111

112
   // V_SPECIFY
113
   (0),
114

115
   // V_PRIMITIVE
116
   (I_IDENT | I_IDENT2 | I_PORTS | I_DECLS | I_STMTS),
117

118
   // V_UDP_TABLE
119
   (I_IDENT | I_PARAMS | I_SUBKIND | I_STMTS),
120

121
   // V_UDP_ENTRY
122
   (I_TEXT),
123

124
   // V_DATA_TYPE
125
   (I_SUBKIND | I_RANGES),
126

127
   // V_TYPE_DECL
128
   (I_IDENT | I_TYPE),
129

130
   // V_ENUM_DECL
131
   (I_IDENT | I_TYPE | I_RANGES | I_DECLS),
132

133
   // V_ENUM_NAME
134
   (I_IDENT | I_TYPE),
135

136
   // V_UNION_DECL
137
   (I_IDENT | I_DECLS),
138

139
   // V_STRUCT_DECL
140
   (I_IDENT | I_DECLS),
141

142
   // V_EVENT_CONTROL
143
   (I_PARAMS),
144

145
   // V_EMPTY
146
   (0),
147

148
   // V_REPEAT
149
   (I_VALUE | I_STMTS),
150

151
   // V_WHILE
152
   (I_VALUE | I_STMTS),
153

154
   // V_DO_WHILE
155
   (I_VALUE | I_STMTS),
156

157
   // V_TASK_DECL
158
   (I_IDENT | I_STMTS | I_DECLS),
159

160
   // V_FUNC_DECL
161
   (I_IDENT | I_STMTS | I_DECLS | I_TYPE),
162

163
   // V_WAIT
164
   (I_VALUE | I_STMTS),
165

166
   // V_PARAM_DECL
167
   (I_IDENT | I_VALUE | I_TYPE),
168

169
   // V_COND_EXPR
170
   (I_VALUE | I_LEFT | I_RIGHT),
171

172
   // V_REAL
173
   (I_DVAL),
174

175
   // V_CONCAT
176
   (I_PARAMS | I_VALUE),
177

178
   // V_FOR_LOOP
179
   (I_LEFT | I_VALUE | I_RIGHT | I_STMTS),
180

181
   // V_FOR_INIT
182
   (I_DECLS | I_STMTS),
183

184
   // V_FOR_STEP
185
   (I_STMTS),
186

187
   // V_PREFIX
188
   (I_TARGET | I_SUBKIND),
189

190
   // V_POSTFIX
191
   (I_TARGET | I_SUBKIND),
192

193
   // V_LOCALPARAM
194
   (I_IDENT | I_VALUE | I_TYPE),
195

196
   // V_CASE
197
   (I_SUBKIND | I_VALUE | I_STMTS),
198

199
   // V_CASE_ITEM
200
   (I_PARAMS | I_STMTS),
201

202
   // V_INST_LIST
203
   (I_PARAMS | I_STMTS | I_IDENT),
204

205
   // V_PARAM_ASSIGN
206
   (I_IDENT | I_VALUE),
207

208
   // V_INST_BODY
209
   (I_IDENT | I_IDENT2 | I_PORTS | I_STMTS | I_DECLS),
210

211
   // V_PORT_CONN
212
   (I_IDENT | I_VALUE),
213

214
   // V_PART_SELECT
215
   (I_SUBKIND | I_VALUE | I_LEFT | I_RIGHT),
216

217
   // V_IF_GENERATE
218
   (I_CONDS),
219
};
220

221
static const char *kind_text_map[V_LAST_NODE_KIND] = {
222
   "V_MODULE",     "V_PORT_DECL",   "V_REF",           "V_ALWAYS",
223
   "V_TIMING",     "V_NBASSIGN",    "V_EVENT",         "V_INITIAL",
224
   "V_BLOCK",      "V_SYS_TCALL",   "V_STRING",        "V_NUMBER",
225
   "V_NET_DECL",   "V_ASSIGN",      "V_DIMENSION",     "V_IF",
226
   "V_COND",       "V_VAR_DECL",    "V_DELAY_CONTROL", "V_BINARY",
227
   "V_BASSIGN",    "V_UNARY",       "V_GATE_INST",     "V_STRENGTH",
228
   "V_MOD_INST",   "V_BIT_SELECT",  "V_SYS_FCALL",     "V_FOREVER",
229
   "V_SPECIFY",    "V_PRIMITIVE",   "V_UDP_TABLE",     "V_UDP_ENTRY",
230
   "V_DATA_TYPE",  "V_TYPE_DECL",   "V_ENUM_DECL",     "V_ENUM_NAME",
231
   "V_UNION_DECL", "V_STRUCT_DECL", "V_EVENT_CONTROL", "V_EMPTY",
232
   "V_REPEAT",     "V_WHILE",       "V_DO_WHILE",      "V_TASK_DECL",
233
   "V_FUNC_DECL",  "V_WAIT",        "V_PARAM_DECL",    "V_COND_EXPR",
234
   "V_REAL",       "V_CONCAT",      "V_FOR_LOOP",      "V_FOR_INIT",
235
   "V_FOR_STEP",   "V_PREFIX",      "V_POSTFIX",       "V_LOCALPARAM",
236
   "V_CASE",       "V_CASE_ITEM",   "V_INST_LIST",     "V_PARAM_ASSIGN",
237
   "V_INST_BODY",  "V_PORT_CONN",   "V_PART_SELECT",   "V_IF_GENERATE",
238
};
239

240
static const change_allowed_t change_allowed[] = {
241
   { -1, -1 }
242
};
243

244
object_class_t vlog_object = {
245
   .name           = "vlog",
246
   .change_allowed = change_allowed,
247
   .has_map        = has_map,
248
   .kind_text_map  = kind_text_map,
249
   .tag            = OBJECT_TAG_VLOG,
250
   .last_kind      = V_LAST_NODE_KIND,
251
   .has_loc        = true,
252
   .gc_roots       = { V_MODULE, V_PRIMITIVE },
253
   .gc_num_roots   = 2
254
};
255

256
struct _vlog_node {
257
   object_t object;
258
};
259

260
static inline vlog_node_t vlog_array_nth(item_t *item, unsigned n)
13,688✔
261
{
262
   object_t *o = obj_array_nth(item->obj_array, n);
13,688✔
263
   return container_of(o, struct _vlog_node, object);
13,688✔
264
}
265

266
static inline void vlog_array_add(item_t *item, vlog_node_t v)
6,437✔
267
{
268
   obj_array_add(&(item->obj_array), &(v->object));
6,437✔
269
}
6,437✔
270

271
vlog_node_t vlog_new(vlog_kind_t kind)
9,872✔
272
{
273
   object_t *o = object_new(NULL, &vlog_object, kind);
9,872✔
274
   return container_of(o, struct _vlog_node, object);
9,872✔
275
}
276

277
vlog_kind_t vlog_kind(vlog_node_t v)
56,213✔
278
{
279
   return v->object.kind;
56,213✔
280
}
281

UNCOV
282
const char *vlog_kind_str(vlog_kind_t kind)
×
283
{
UNCOV
284
   return kind_text_map[kind];
×
285
}
286

287
ident_t vlog_ident(vlog_node_t v)
7,270✔
288
{
289
   item_t *item = lookup_item(&vlog_object, v, I_IDENT);
7,270✔
290
   assert(item->ident != NULL);
7,270✔
291
   return item->ident;
7,270✔
292
}
293

294
void vlog_set_ident(vlog_node_t v, ident_t i)
4,530✔
295
{
296
   lookup_item(&vlog_object, v, I_IDENT)->ident = i;
4,530✔
297
}
4,530✔
298

299
bool vlog_has_ident(vlog_node_t v)
54✔
300
{
301
   return lookup_item(&vlog_object, v, I_IDENT)->ident != NULL;
54✔
302
}
303

304
ident_t vlog_ident2(vlog_node_t v)
474✔
305
{
306
   item_t *item = lookup_item(&vlog_object, v, I_IDENT2);
474✔
307
   assert(item->ident != NULL);
474✔
308
   return item->ident;
474✔
309
}
310

311
void vlog_set_ident2(vlog_node_t v, ident_t i)
555✔
312
{
313
   lookup_item(&vlog_object, v, I_IDENT2)->ident = i;
555✔
314
}
555✔
315

316
const loc_t *vlog_loc(vlog_node_t v)
7,059✔
317
{
318
   assert(v != NULL);
7,059✔
319
   return &(v->object.loc);
7,059✔
320
}
321

322
void vlog_set_loc(vlog_node_t v, const loc_t *loc)
10,405✔
323
{
324
   assert(v != NULL);
10,405✔
325
   assert(loc != NULL);
10,405✔
326
   v->object.loc = *loc;
10,405✔
327
}
10,405✔
328

329
vlog_node_t vlog_ref(vlog_node_t v)
5,969✔
330
{
331
   item_t *item = lookup_item(&vlog_object, v, I_REF);
5,969✔
332
   assert(item->object != NULL);
5,969✔
333
   return container_of(item->object, struct _vlog_node, object);
5,969✔
334
}
335

336
bool vlog_has_ref(vlog_node_t v)
1,651✔
337
{
338
   return lookup_item(&vlog_object, v, I_REF)->object != NULL;
1,651✔
339
}
340

341
void vlog_set_ref(vlog_node_t v, vlog_node_t d)
2,025✔
342
{
343
   lookup_item(&vlog_object, v, I_REF)->object = &(d->object);
2,025✔
344
   object_write_barrier(&(v->object), &(d->object));
2,025✔
345
}
2,025✔
346

347
unsigned vlog_stmts(vlog_node_t v)
2,940✔
348
{
349
   item_t *item = lookup_item(&vlog_object, v, I_STMTS);
2,940✔
350
   return obj_array_count(item->obj_array);
2,940✔
351
}
352

353
vlog_node_t vlog_stmt(vlog_node_t v, unsigned n)
5,638✔
354
{
355
   item_t *item = lookup_item(&vlog_object, v, I_STMTS);
5,638✔
356
   return vlog_array_nth(item, n);
5,638✔
357
}
358

359
void vlog_add_stmt(vlog_node_t v, vlog_node_t s)
2,947✔
360
{
361
   assert(s != NULL);
2,947✔
362
   vlog_array_add(lookup_item(&vlog_object, v, I_STMTS), s);
2,947✔
363
   object_write_barrier(&(v->object), &(s->object));
2,947✔
364
}
2,947✔
365

366
unsigned vlog_ports(vlog_node_t v)
667✔
367
{
368
   item_t *item = lookup_item(&vlog_object, v, I_PORTS);
667✔
369
   return obj_array_count(item->obj_array);
667✔
370
}
371

372
vlog_node_t vlog_port(vlog_node_t v, unsigned n)
704✔
373
{
374
   item_t *item = lookup_item(&vlog_object, v, I_PORTS);
704✔
375
   return vlog_array_nth(item, n);
704✔
376
}
377

378
void vlog_add_port(vlog_node_t v, vlog_node_t p)
371✔
379
{
380
   assert(p != NULL);
371✔
381
   assert(p->object.kind == V_REF);
371✔
382
   vlog_array_add(lookup_item(&vlog_object, v, I_PORTS), p);
371✔
383
   object_write_barrier(&(v->object), &(p->object));
371✔
384
}
371✔
385

386
unsigned vlog_params(vlog_node_t v)
2,632✔
387
{
388
   item_t *item = lookup_item(&vlog_object, v, I_PARAMS);
2,632✔
389
   return obj_array_count(item->obj_array);
2,632✔
390
}
391

392
vlog_node_t vlog_param(vlog_node_t v, unsigned n)
3,376✔
393
{
394
   item_t *item = lookup_item(&vlog_object, v, I_PARAMS);
3,376✔
395
   return vlog_array_nth(item, n);
3,376✔
396
}
397

398
void vlog_add_param(vlog_node_t v, vlog_node_t p)
1,375✔
399
{
400
   assert(p != NULL);
1,375✔
401
   vlog_array_add(lookup_item(&vlog_object, v, I_PARAMS), p);
1,375✔
402
   object_write_barrier(&(v->object), &(p->object));
1,375✔
403
}
1,375✔
404

405
unsigned vlog_ranges(vlog_node_t v)
2,660✔
406
{
407
   item_t *item = lookup_item(&vlog_object, v, I_RANGES);
2,660✔
408
   return obj_array_count(item->obj_array);
2,660✔
409
}
410

411
vlog_node_t vlog_range(vlog_node_t v, unsigned n)
714✔
412
{
413
   item_t *item = lookup_item(&vlog_object, v, I_RANGES);
714✔
414
   return vlog_array_nth(item, n);
714✔
415
}
416

417
void vlog_add_range(vlog_node_t v, vlog_node_t r)
110✔
418
{
419
   assert(r != NULL);
110✔
420
   assert(r->object.kind == V_DIMENSION);
110✔
421
   vlog_array_add(lookup_item(&vlog_object, v, I_RANGES), r);
110✔
422
   object_write_barrier(&(v->object), &(r->object));
110✔
423
}
110✔
424

425
unsigned vlog_decls(vlog_node_t v)
1,008✔
426
{
427
   item_t *item = lookup_item(&vlog_object, v, I_DECLS);
1,008✔
428
   return obj_array_count(item->obj_array);
1,008✔
429
}
430

431
vlog_node_t vlog_decl(vlog_node_t v, unsigned n)
2,755✔
432
{
433
   item_t *item = lookup_item(&vlog_object, v, I_DECLS);
2,755✔
434
   return vlog_array_nth(item, n);
2,755✔
435
}
436

437
void vlog_add_decl(vlog_node_t v, vlog_node_t d)
1,374✔
438
{
439
   assert(d != NULL);
1,374✔
440
   vlog_array_add(lookup_item(&vlog_object, v, I_DECLS), d);
1,374✔
441
   object_write_barrier(&(v->object), &(d->object));
1,374✔
442
}
1,374✔
443

444
unsigned vlog_conds(vlog_node_t v)
392✔
445
{
446
   item_t *item = lookup_item(&vlog_object, v, I_CONDS);
392✔
447
   return obj_array_count(item->obj_array);
392✔
448
}
449

450
vlog_node_t vlog_cond(vlog_node_t v, unsigned n)
501✔
451
{
452
   item_t *item = lookup_item(&vlog_object, v, I_CONDS);
501✔
453
   return vlog_array_nth(item, n);
501✔
454
}
455

456
void vlog_add_cond(vlog_node_t v, vlog_node_t c)
260✔
457
{
458
   assert(c != NULL && c->object.kind == V_COND);
260✔
459
   vlog_array_add(lookup_item(&vlog_object, v, I_CONDS), c);
260✔
460
   object_write_barrier(&(v->object), &(c->object));
260✔
461
}
260✔
462

463
unsigned vlog_subkind(vlog_node_t v)
2,567✔
464
{
465
   return lookup_item(&vlog_object, v, I_SUBKIND)->ival;
2,567✔
466
}
467

468
void vlog_set_subkind(vlog_node_t v, unsigned sub)
1,946✔
469
{
470
   lookup_item(&vlog_object, v, I_SUBKIND)->ival = sub;
1,946✔
471
}
1,946✔
472

473
vlog_node_t vlog_value(vlog_node_t v)
3,729✔
474
{
475
   item_t *item = lookup_item(&vlog_object, v, I_VALUE);
3,729✔
476
   assert(item->object != NULL);
3,729✔
477
   return container_of(item->object, struct _vlog_node, object);
3,729✔
478
}
479

480
bool vlog_has_value(vlog_node_t v)
819✔
481
{
482
   return lookup_item(&vlog_object, v, I_VALUE)->object != NULL;
819✔
483
}
484

485
void vlog_set_value(vlog_node_t v, vlog_node_t e)
1,713✔
486
{
487
   lookup_item(&vlog_object, v, I_VALUE)->object = &(e->object);
1,713✔
488
   object_write_barrier(&(v->object), &(e->object));
1,713✔
489
}
1,713✔
490

491
vlog_node_t vlog_target(vlog_node_t v)
1,310✔
492
{
493
   item_t *item = lookup_item(&vlog_object, v, I_TARGET);
1,310✔
494
   assert(item->object != NULL);
1,310✔
495
   return container_of(item->object, struct _vlog_node, object);
1,310✔
496
}
497

498
void vlog_set_target(vlog_node_t v, vlog_node_t e)
617✔
499
{
500
   lookup_item(&vlog_object, v, I_TARGET)->object = &(e->object);
617✔
501
   object_write_barrier(&(v->object), &(e->object));
617✔
502
}
617✔
503

504
vlog_node_t vlog_delay(vlog_node_t v)
98✔
505
{
506
   item_t *item = lookup_item(&vlog_object, v, I_DELAY);
98✔
507
   assert(item->object != NULL);
98✔
508
   return container_of(item->object, struct _vlog_node, object);
98✔
509
}
510

511
bool vlog_has_delay(vlog_node_t v)
938✔
512
{
513
   return lookup_item(&vlog_object, v, I_DELAY)->object != NULL;
938✔
514
}
515

516
void vlog_set_delay(vlog_node_t v, vlog_node_t d)
50✔
517
{
518
   lookup_item(&vlog_object, v, I_DELAY)->object = &(d->object);
50✔
519
   object_write_barrier(&(v->object), &(d->object));
50✔
520
}
50✔
521

522
vlog_node_t vlog_type(vlog_node_t v)
2,783✔
523
{
524
   item_t *item = lookup_item(&vlog_object, v, I_TYPE);
2,783✔
525
   assert(item->object != NULL);
2,783✔
526
   return container_of(item->object, struct _vlog_node, object);
2,783✔
527
}
528

UNCOV
529
bool vlog_has_type(vlog_node_t v)
×
530
{
UNCOV
531
   return lookup_item(&vlog_object, v, I_TYPE)->object != NULL;
×
532
}
533

534
void vlog_set_type(vlog_node_t v, vlog_node_t t)
786✔
535
{
536
   lookup_item(&vlog_object, v, I_TYPE)->object = &(t->object);
786✔
537
   object_write_barrier(&(v->object), &(t->object));
786✔
538
}
786✔
539

540
const char *vlog_text(vlog_node_t v)
768✔
541
{
542
   item_t *item = lookup_item(&vlog_object, v, I_TEXT);
768✔
543
   assert(item->text != NULL);
768✔
544
   return item->text;
768✔
545
}
546

547
void vlog_set_text(vlog_node_t v, const char *text)
582✔
548
{
549
   lookup_item(&vlog_object, v, I_TEXT)->text = xstrdup(text);
582✔
550
}
582✔
551

552
number_t vlog_number(vlog_node_t v)
2,234✔
553
{
554
   return lookup_item(&vlog_object, v, I_NUMBER)->number;
2,234✔
555
}
556

557
void vlog_set_number(vlog_node_t v, number_t n)
1,331✔
558
{
559
   lookup_item(&vlog_object, v, I_NUMBER)->number = n;
1,331✔
560
}
1,331✔
561

562
vlog_node_t vlog_left(vlog_node_t v)
1,415✔
563
{
564
   item_t *item = lookup_item(&vlog_object, v, I_LEFT);
1,415✔
565
   assert(item->object != NULL);
1,415✔
566
   return container_of(item->object, struct _vlog_node, object);
1,415✔
567
}
568

569
void vlog_set_left(vlog_node_t v, vlog_node_t e)
490✔
570
{
571
   lookup_item(&vlog_object, v, I_LEFT)->object = &(e->object);
490✔
572
   object_write_barrier(&(v->object), &(e->object));
490✔
573
}
490✔
574

575
vlog_node_t vlog_right(vlog_node_t v)
1,407✔
576
{
577
   item_t *item = lookup_item(&vlog_object, v, I_RIGHT);
1,407✔
578
   assert(item->object != NULL);
1,407✔
579
   return container_of(item->object, struct _vlog_node, object);
1,407✔
580
}
581

582
void vlog_set_right(vlog_node_t v, vlog_node_t e)
490✔
583
{
584
   lookup_item(&vlog_object, v, I_RIGHT)->object = &(e->object);
490✔
585
   object_write_barrier(&(v->object), &(e->object));
490✔
586
}
490✔
587

588
double vlog_dval(vlog_node_t v)
1✔
589
{
590
   return lookup_item(&vlog_object, v, I_DVAL)->dval;
1✔
591
}
592

593
void vlog_set_dval(vlog_node_t v, double d)
17✔
594
{
595
   lookup_item(&vlog_object, v, I_DVAL)->dval = d;
17✔
596
}
17✔
597

598
void vlog_visit(vlog_node_t v, vlog_visit_fn_t fn, void *context)
268✔
599
{
600
   vlog_visit_only(v, fn, context, V_LAST_NODE_KIND);
268✔
601
}
268✔
602

603
void vlog_visit_only(vlog_node_t v, vlog_visit_fn_t fn, void *context,
268✔
604
                     vlog_kind_t kind)
605
{
606
   assert(v != NULL);
268✔
607

608
   object_visit_ctx_t ctx = {
268✔
609
      .count      = 0,
610
      .postorder  = (object_visit_fn_t)fn,
611
      .preorder   = NULL,
612
      .context    = context,
613
      .kind       = kind,
614
      .tag        = OBJECT_TAG_VLOG,
615
      .generation = object_next_generation(),
268✔
616
      .deep       = false
617
   };
618

619
   object_visit(&(v->object), &ctx);
268✔
620
}
268✔
621

622
vlog_node_t vlog_rewrite(vlog_node_t v, vlog_rewrite_fn_t fn, void *context)
295✔
623
{
624
   object_arena_t *arena = object_arena(&(v->object));
295✔
625
   if (arena_frozen(arena))
295✔
626
      return v;
627

628
   object_rewrite_ctx_t ctx = {
295✔
629
      .generation = object_next_generation(),
295✔
630
      .context    = context,
631
      .arena      = arena,
632
   };
633

634
   ctx.post_fn[OBJECT_TAG_VLOG] = (object_rewrite_post_fn_t)fn;
295✔
635

636
   object_t *result = object_rewrite(&(v->object), &ctx);
295✔
637
   free(ctx.cache);
295✔
638
   return container_of(result, struct _vlog_node, object);
295✔
639
}
640

641
vlog_node_t vlog_copy(vlog_node_t v, vlog_copy_pred_t pred, void *ctx)
150✔
642
{
643
   object_copy_ctx_t *copy LOCAL = xcalloc_flex(sizeof(object_copy_ctx_t),
150✔
644
                                                1, sizeof(object_t *));
645
   copy->generation   = object_next_generation();
150✔
646
   copy->pred_context = ctx;
150✔
647
   copy->nroots       = 1;
150✔
648
   copy->roots[0]     = &(v->object);
150✔
649

650
   copy->should_copy[OBJECT_TAG_VLOG] = (object_copy_pred_t)pred;
150✔
651

652
   object_copy(copy);
150✔
653

654
   return container_of(copy->roots[0], struct _vlog_node, object);
150✔
655
}
656

657
object_t *vlog_to_object(vlog_node_t v)
1,449✔
658
{
659
   return &(v->object);
1,449✔
660
}
661

662
vlog_node_t vlog_from_object(object_t *obj)
5,912✔
663
{
664
   if (obj != NULL && obj->tag == OBJECT_TAG_VLOG)
5,912✔
665
      return container_of(obj, struct _vlog_node, object);
666
   else
667
      return NULL;
5,515✔
668
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc