Build a JSON list of a node's non-null property keys: keys(n). */
| 3522 | |
| 3523 | /* Build a JSON list of a node's non-null property keys: keys(n). */ |
| 3524 | static const char *node_keys_list(const cbm_node_t *n, char *buf, size_t buf_sz) { |
| 3525 | const struct { |
| 3526 | const char *k; |
| 3527 | bool present; |
| 3528 | } ks[] = { |
| 3529 | {"name", n->name && n->name[0]}, |
| 3530 | {"qualified_name", n->qualified_name && n->qualified_name[0]}, |
| 3531 | {"label", n->label && n->label[0]}, |
| 3532 | {"file_path", n->file_path && n->file_path[0]}, |
| 3533 | {"start_line", n->start_line > 0}, |
| 3534 | {"end_line", n->end_line > 0}, |
| 3535 | }; |
| 3536 | size_t pos = 0; |
| 3537 | bool first = true; |
| 3538 | if (pos < buf_sz - SKIP_ONE) { |
| 3539 | buf[pos++] = '['; |
| 3540 | } |
| 3541 | for (size_t i = 0; i < sizeof(ks) / sizeof(ks[0]) && pos < buf_sz - SKIP_ONE; i++) { |
| 3542 | if (!ks[i].present) { |
| 3543 | continue; |
| 3544 | } |
| 3545 | int w = snprintf(buf + pos, buf_sz - pos, "%s\"%s\"", first ? "" : ",", ks[i].k); |
| 3546 | if (w < 0 || (size_t)w >= buf_sz - pos) { |
| 3547 | break; |
| 3548 | } |
| 3549 | pos += (size_t)w; |
| 3550 | first = false; |
| 3551 | } |
| 3552 | if (pos < buf_sz - SKIP_ONE) { |
| 3553 | buf[pos++] = ']'; |
| 3554 | } |
| 3555 | buf[pos] = '\0'; |
| 3556 | return buf; |
| 3557 | } |
| 3558 | |
| 3559 | /* Resolve a function argument to its string value (literal or var.prop). */ |
| 3560 | static const char *eval_func_arg(binding_t *b, const cbm_func_arg_t *a) { |