/** @brief If DEBUG_TREE is defined prints debug info to dump file, else does nothing @param tree_p Pointer to node about which we want to know @param dump_file File that may contain debug info @param level Relative depth of node in tree @return 0 always */ int Node_dump(Node_t* tree_p, FILE* dump_file, int level) { #ifdef DEBUG_TREE assert(dump_file); assert(tree_p); for(int i = 0; i < level; i++) { fprintf(dump_file, "\t"); } fprintf(dump_file,"(\"%s\" [%p], lft: [%p], rgt: [%p]---->", tree_p->data, (void*)tree_p, (void*)tree_p->lft, (void*)tree_p->rgt); if(Node_ok(tree_p, dump_file)) { fprintf(dump_file, "[ok]"); } else { fprintf(dump_file, "%s" , Node_strerror()); } fprintf(dump_file, "\n"); if(tree_p->lft) Node_dump(tree_p->lft, dump_file, level+1); if(tree_p->rgt) Node_dump(tree_p->rgt, dump_file, level+1); fprintf(dump_file, ")\n"); #endif // DEBUG_TREE return 0; }
void Proxy_error(Proxy *conn, UtuMendicantErrorCode code, bstring message) { Node *err = Node_cons("[nbw", (uint64_t)code, message, "err"); Node_dump(err, ' ', 1); // don't use Proxy_listener_send since that could be causing a write error // just try writing, and ignore the write if it failed writenodes(conn->client.write_fd, err, NULL); Node_destroy(err); }
int Node_decons(Node *root, int copy, const char *format, ...) { const char *cur = format; va_list args; va_start (args, format); Node *cur_node = root; assert_not(root, NULL); assert_not(format, NULL); #define UP() { cur_node = cur_node->parent; if(cur_node == NULL) break; } #define NEXT() { if(cur_node->sibling) cur_node = cur_node->sibling; if(cur_node == NULL) break; } for(; *cur != '\0'; cur++) { if(cur_node == NULL) { log(ERROR, "deconstruct ran out at char #%jd (%c) in the spec: %s", (intmax_t)(cur-format), *cur, format); break; } switch(*cur) { case '[': cur_node = cur_node->child; break; case 'n': { uint64_t *number = va_arg(args, uint64_t *); check_type(number, NUMBER, cur_node); *number = cur_node->value.number; NEXT(); break; } case 'f': { double *floating = va_arg(args, double *); *floating = cur_node->value.floating; check_type(floating, FLOAT, cur_node); NEXT(); break; } case 's': { bstring *str = va_arg(args, bstring *); check_type(str, STRING, cur_node); if(copy) *str = bstrcpy(cur_node->value.string); else *str = cur_node->value.string; NEXT(); break; } case 'b': { bstring *blob = va_arg(args, bstring *); check_type(blob, BLOB, cur_node); if(copy) *blob = bstrcpy(cur_node->value.string); else *blob = cur_node->value.string; NEXT(); break; } case ']': { UP(); NEXT(); break; } case '@': { const char *attr = va_arg(args, const char *); check(attr != NULL, "NULL for given for ATTR name"); check_then(cur_node->name && biseqcstr(cur_node->name, attr), "wrong attribute name at:", Node_dump(cur_node, ' ', 1)); // just confirm but don't go to the next one break; } case 'w': { UP(); const char *word = va_arg(args, const char *); check(word != NULL, "NULL given for word"); check_then(cur_node->name && biseqcstr(cur_node->name, word), "wrong word name at:", Node_dump(cur_node, ' ', 1)); NEXT(); break; } case 'G': { Node **group = va_arg(args, Node **); check(group != NULL, "NULL given for group"); check(*group == NULL, "Output var wasn't NULL, must be NULL."); *group = cur_node; NEXT(); break; } case '.': NEXT(); break; default: { fail("invalid char in spec"); break; } } } va_end(args); check(*cur == '\0', "didn't process whole specification"); return 1; on_fail(return 0); }