static void decodeNull( bsd_ctx_t *ctx, bsd_data_t *x) { struct bsd_stackframe_t * f = topframe( ctx); if( BS_FZLIST == f->kind || (BS_FZMAP == f->kind && f->content.map.even)) { x->kind = BSD_CLOSE; x->content.cont_type = bsd_typeFromFrameKind( f->kind); ctx->stacksize--; } else { x->kind = BSD_NULL; } }
/* stack-debug.c 732a */ void stack_trace_current_value(Value v, Env rho, Stack s) { if (trace_countp && *trace_countp != 0) { (*trace_countp)--; vtick++; fprint(stderr, "val %d = %v\n", vtick, v); fprint(stderr, "env %R\n", rho); if (topframe(s)) fprint(stderr, "stack\n%S\n", s); else fprint(stderr, " (final answer from stack-based eval)\n"); } }
/* Adds a frame to the decoding stack. */ static bsd_status_t openContainer( bsd_ctx_t *ctx, bs_stackframekind_t kind, bs_ctxid_t ctxid, int missing, union bsd_stackframecontent_t **c) { struct bsd_stackframe_t *f; if( (BSD_STACK_SIZE-1) == ctx->stacksize) return BSD_ETOODEEP; ctx->stacksize++; f = topframe( ctx); f->kind = kind; f->ctxid = ctxid; f->missing = missing; // both key and value count for maps if( BS_FMAP == kind || BS_FZMAP == kind) { f->missing *= 2; f->content.map.even = 1; /* will be inverted */ } if( c) *c = &f->content; return BSD_EOK; }
void bsd_dump( bsd_ctx_t *ctx, FILE *output, const uint8_t *buffer, int length) { const uint8_t *begin = buffer; const uint8_t *end = buffer + length; fputs("Byte\tOpcode\tContext\tType\tValue\tAdditional bytes\tAdditional info\n", output); while( buffer < end || ctx->stacksize > 0) { bsd_data_t x; struct bsd_stackframe_t *f = topframe( ctx); // we need context in which the value is decoded, so we catch now rather than after the read bs_ctxid_t ctxid = getctxid( f); int r = bsd_read( ctx, &x, buffer, length); if( 0 == r && BSD_ERROR == x.kind) { fprintf( output, "Error %d at byte %td.\n", x.content.error, buffer - begin); break; } else if( r < 0) { fprintf( output, "Error: %d bytes missing.\n", r); break; } else { int opcode_len = 0; fprintf( output, "%td\t", buffer - begin); if( r == 0) fputs( "N/A\tN/A\t", output); else { switch( ctxid) { case BS_CTXID_CHUNKED: opcode_len = 2; break; case BS_CTXID_FLOAT: case BS_CTXID_INT32: opcode_len = 4; break; case BS_CTXID_DOUBLE: opcode_len = 8; break; default: opcode_len = 1; break; } hexdump( output, buffer, opcode_len); fputc('\t', output); switch( ctxid) { #define CASE(x) case BS_CTXID_##x: fputs( #x"\t", output); break CASE(GLOBAL); CASE(UNSIGNED_OR_STRING); CASE(NUMBER); CASE(INT32); CASE(FLOAT); CASE(DOUBLE); CASE(LIST_OR_MAP); default: printf("%d\t", ctxid); break; #undef CASE } } switch( x.kind) { #define CASE(x) case BSD_##x: fputs( #x"\t", output) CASE(CLOSE); fputs( "N/A\t", output); break; CASE(NULL); fputs( "N/A\t", output); break; CASE(INT); fprintf( output, "%" PRId64 "\t", x.content.i); break; CASE(BOOL); fputs( x.content.boolean ? "true\t" : "false\t", output); break; CASE(DOUBLE); fprintf( output, "%f\t", x.content.d); break; CASE(STRING); fprintf( output, "length: %zu\t", x.content.string.length); break; CASE(CHUNKED_STRING); fputs( "N/A\t", output); break; CASE(CHUNK); fprintf( output, "length: %zu\t", x.content.chunk.length); break; CASE(LIST); fprintf( output, "length: %zu, ctx: %d\t", x.content.length, topframe( ctx)->ctxid); break; CASE(ZLIST); fprintf( output, "ctx: %d\t", topframe( ctx)->ctxid); break; CASE(MAP); fprintf( output, "length: %zu, ctx: %d\t", x.content.length, topframe( ctx)->ctxid); break; CASE(ZMAP); fprintf( output, "ctx: %d\t", topframe( ctx)->ctxid); break; CASE(OBJECT); if( NULL == x.content.classdef->classname) fprintf( output, "class: %d\t", x.content.classdef->classid); else fprintf( output, "class: %s\t", x.content.classdef->classname); break; CASE(CLASSDEF); if( NULL == x.content.classdef->classname) fprintf( output, "class: %d\t", x.content.classdef->classid); else fprintf( output, "class: %s\t", x.content.classdef->classname); break; default: fprintf(output, "%d\tN/A\t", x.kind); #undef CASE } int additional = r - opcode_len; if( 0 < additional && additional <= 10) hexdump( output, buffer+opcode_len, additional); else if( additional > 10) { hexdump( output, buffer+opcode_len, 3); fputs( "...", output); hexdump( output, buffer+r-3, 3); } else fputs( "N/A", output); fputs( "\t", output); // additional infos if( BSD_KOBJFIELD == x._internalContext && x.fieldname != NULL) { fprintf( output, "field: %s\t", x.fieldname); } else { fputs( "N/A\t", output); } fputs( "\n", output); } buffer += r; length -= r; } }
int bsd_read( bsd_ctx_t *ctx, bsd_data_t *x, const uint8_t *buffer, int length) { int nread = 0; struct bsd_stackframe_t *f = topframe( ctx); x->kind = BSD_NULL; // if x is already of type error, it will confuse error checking // check stack (fixed length terminated containers) if( f->missing == 0) { x->kind = BSD_CLOSE; x->content.cont_type = bsd_typeFromFrameKind( f->kind); ctx->stacksize--; /* the other properties depends on the frame below the closed one */ f = topframe( ctx); x->_internalContext = bsd_getFrameDataKind( f); /* set field name for objects */ if( BSD_KOBJFIELD == x->_internalContext) { const bs_class_t *classdef = f->content.object.classdef; x->fieldname = classdef->fields[classdef->nfields - (f->missing + 1)].name; } return 0; } switch( getctxid( f)) { case BS_CTXID_GLOBAL: nread = bsd_global( ctx, x, buffer, length); break; case BS_CTXID_UNSIGNED_OR_STRING: nread = bsd_uis( ctx, x, buffer, length); break; case BS_CTXID_NUMBER: nread = bsd_number( ctx, x, buffer, length); break; case BS_CTXID_INT32: nread = bsd_int32( ctx, x, buffer, length); break; case BS_CTXID_FLOAT: nread = bsd_float( ctx, x, buffer, length); break; case BS_CTXID_DOUBLE: nread = bsd_double( ctx, x, buffer, length); break; case BS_CTXID_LIST_OR_MAP: nread = bsd_listmap( ctx, x, buffer, length); break; case BS_CTXID_CHUNKED: nread = bsd_chunked( ctx, x, buffer, length); break; // case BS_CTXID_OBJECT: // case BS_CTXID_CLASSDEF: // case BS_CTXID_NAMEDCLASSDEF: // case BS_CTXID_INTERNALCLASSDEF: default: return bsd_error( x, BSD_EBADCONTEXT); } // stop any further action in case of error if( nread < 0 || BSD_ERROR == x->kind) return nread; /* class definition does not count as value */ if( BSD_CLASSDEF != x->kind) { // decrement counter (for fixed containers) if( f->missing > 0) { f->missing--; } // map key/value decoding if( BS_FMAP == f->kind || BS_FZMAP == f->kind) { f->content.map.even ^= 1; } } // top frame may have changed if( topframe( ctx) > f) { x->_internalContext = BSD_KNEWCONTAINER; } else { f = topframe( ctx); x->_internalContext = bsd_getFrameDataKind( f); /* set field name for objects */ if( BSD_KOBJFIELD == x->_internalContext) { const bs_class_t *classdef = f->content.object.classdef; x->fieldname = classdef->fields[classdef->nfields - (f->missing + 1)].name; } } ctx->read += nread; return nread; }