Build a JSON list of a node's non-null property keys: keys(n). */
| 3195 | |
| 3196 | /* Build a JSON list of a node's non-null property keys: keys(n). */ |
| 3197 | static const char *node_keys_list(const cbm_node_t *n, char *buf, size_t buf_sz) { |
| 3198 | const struct { |
| 3199 | const char *k; |
| 3200 | bool present; |
| 3201 | } ks[] = { |
| 3202 | {"name", n->name && n->name[0]}, |
| 3203 | {"qualified_name", n->qualified_name && n->qualified_name[0]}, |
| 3204 | {"label", n->label && n->label[0]}, |
| 3205 | {"file_path", n->file_path && n->file_path[0]}, |
| 3206 | {"start_line", n->start_line > 0}, |
| 3207 | {"end_line", n->end_line > 0}, |
| 3208 | }; |
| 3209 | size_t pos = 0; |
| 3210 | bool first = true; |
| 3211 | if (pos < buf_sz - SKIP_ONE) { |
| 3212 | buf[pos++] = '['; |
| 3213 | } |
| 3214 | for (size_t i = 0; i < sizeof(ks) / sizeof(ks[0]) && pos < buf_sz - SKIP_ONE; i++) { |
| 3215 | if (!ks[i].present) { |
| 3216 | continue; |
| 3217 | } |
| 3218 | int w = snprintf(buf + pos, buf_sz - pos, "%s\"%s\"", first ? "" : ",", ks[i].k); |
| 3219 | if (w < 0 || (size_t)w >= buf_sz - pos) { |
| 3220 | break; |
| 3221 | } |
| 3222 | pos += (size_t)w; |
| 3223 | first = false; |
| 3224 | } |
| 3225 | if (pos < buf_sz - SKIP_ONE) { |
| 3226 | buf[pos++] = ']'; |
| 3227 | } |
| 3228 | buf[pos] = '\0'; |
| 3229 | return buf; |
| 3230 | } |
| 3231 | |
| 3232 | /* Resolve a function argument to its string value (literal or var.prop). */ |
| 3233 | static const char *eval_func_arg(binding_t *b, const cbm_func_arg_t *a) { |