bool check_constraints(ast_t* orig, ast_t* typeparams, ast_t* typeargs, bool report_errors, pass_opt_t* opt) { ast_t* typeparam = ast_child(typeparams); ast_t* typearg = ast_child(typeargs); while(typeparam != NULL) { if(ast_id(typearg) == TK_TYPEPARAMREF) { ast_t* def = (ast_t*)ast_data(typearg); if(def == typeparam) { typeparam = ast_sibling(typeparam); typearg = ast_sibling(typearg); continue; } } // Reify the constraint. ast_t* constraint = ast_childidx(typeparam, 1); ast_t* bind_constraint = bind_type(constraint); ast_t* r_constraint = reify(bind_constraint, typeparams, typeargs, opt); if(bind_constraint != r_constraint) ast_free_unattached(bind_constraint); // A bound type must be a subtype of the constraint. errorframe_t info = NULL; if(!is_subtype(typearg, r_constraint, report_errors ? &info : NULL, opt)) { if(report_errors) { ast_error(opt->check.errors, orig, "type argument is outside its constraint"); ast_error_continue(opt->check.errors, typearg, "argument: %s", ast_print_type(typearg)); ast_error_continue(opt->check.errors, typeparam, "constraint: %s", ast_print_type(r_constraint)); } ast_free_unattached(r_constraint); return false; } ast_free_unattached(r_constraint); // A constructable constraint can only be fulfilled by a concrete typearg. if(is_constructable(constraint) && !is_concrete(typearg)) { if(report_errors) { ast_error(opt->check.errors, orig, "a constructable constraint can " "only be fulfilled by a concrete type argument"); ast_error_continue(opt->check.errors, typearg, "argument: %s", ast_print_type(typearg)); ast_error_continue(opt->check.errors, typeparam, "constraint: %s", ast_print_type(constraint)); } return false; } typeparam = ast_sibling(typeparam); typearg = ast_sibling(typearg); } assert(typeparam == NULL); assert(typearg == NULL); return true; }
/** * Pivot the rows, creating a new resultset * * Call dbpivot() immediately after dbresults(). It calls dbnextrow() as long as * it returns REG_ROW, transforming the results into a cross-tab report. * dbpivot() modifies the metadata such that DB-Library can be used tranparently: * retrieve the rows as usual with dbnumcols(), dbnextrow(), etc. * * @dbproc, our old friend * @nkeys the number of left-edge columns to group by * @keys an array of left-edge columns to group by * @ncols the number of top-edge columns to group by * @cols an array of top-edge columns to group by * @func the aggregation function to use * @val the number of the column to which @func is applied * * @returns the return code from the final call to dbnextrow(). * Success is normally indicated by NO_MORE_ROWS. */ RETCODE dbpivot(DBPROCESS *dbproc, int nkeys, int *keys, int ncols, int *cols, DBPIVOT_FUNC func, int val) { enum { logalot = 1 }; struct pivot_t P, *pp; struct agg_t input, *pout = NULL; struct key_t *pacross; struct metadata_t *metadata, *pmeta; size_t i, nmeta = 0; tdsdump_log(TDS_DBG_FUNC, "dbpivot(%p, %d,%p, %d,%p, %p, %d)\n", dbproc, nkeys, keys, ncols, cols, func, val); if (logalot) { char buffer[1024] = {'\0'}, *s = buffer; const static char *names[2] = { "\tkeys (down)", "\n\tcols (across)" }; int *p = keys, *pend = p + nkeys; for (i=0; i < 2; i++) { const char *sep = ""; s += sprintf(s, "%s: ", names[i]); for ( ; p < pend; p++) { s += sprintf(s, "%s%d", sep, *p); sep = ", "; } p = cols; pend = p + ncols; assert(s < buffer + sizeof(buffer)); } tdsdump_log(TDS_DBG_FUNC, "%s\n", buffer); } memset(&input, 0, sizeof(input)); P.dbproc = dbproc; if ((pp = tds_find(&P, pivots, npivots, sizeof(*pivots), pivot_key_equal)) == NULL ) { pp = realloc(pivots, (1 + npivots) * sizeof(*pivots)); if (!pp) return FAIL; pivots = pp; pp += npivots++; } else { agg_free(pp->output); key_free(pp->across); } memset(pp, 0, sizeof(*pp)); if ((input.row_key.keys = calloc(nkeys, sizeof(*input.row_key.keys))) == NULL) return FAIL; input.row_key.nkeys = nkeys; for (i=0; i < nkeys; i++) { int type = dbcoltype(dbproc, keys[i]); int len = dbcollen(dbproc, keys[i]); assert(type && len); col_init(input.row_key.keys+i, type, len); if (FAIL == dbbind(dbproc, keys[i], bind_type(type), input.row_key.keys[i].len, col_buffer(input.row_key.keys+i))) return FAIL; if (FAIL == dbnullbind(dbproc, keys[i], &input.row_key.keys[i].null_indicator)) return FAIL; } if ((input.col_key.keys = calloc(ncols, sizeof(*input.col_key.keys))) == NULL) return FAIL; input.col_key.nkeys = ncols; for (i=0; i < ncols; i++) { int type = dbcoltype(dbproc, cols[i]); int len = dbcollen(dbproc, cols[i]); assert(type && len); col_init(input.col_key.keys+i, type, len); if (FAIL == dbbind(dbproc, cols[i], bind_type(type), input.col_key.keys[i].len, col_buffer(input.col_key.keys+i))) return FAIL; if (FAIL == dbnullbind(dbproc, cols[i], &input.col_key.keys[i].null_indicator)) return FAIL; } /* value */ { int type = dbcoltype(dbproc, val); int len = dbcollen(dbproc, val); assert(type && len); col_init(&input.value, type, len); if (FAIL == dbbind(dbproc, val, bind_type(type), input.value.len, col_buffer(&input.value))) return FAIL; if (FAIL == dbnullbind(dbproc, val, &input.value.null_indicator)) return FAIL; } while ((pp->status = dbnextrow(dbproc)) == REG_ROW) { /* add to unique list of crosstab columns */ if ((pacross = tds_find(&input.col_key, pp->across, pp->nacross, sizeof(*pp->across), key_equal)) == NULL ) { pacross = realloc(pp->across, (1 + pp->nacross) * sizeof(*pp->across)); if (!pacross) return FAIL; pp->across = pacross; pacross += pp->nacross++; key_cpy(pacross, &input.col_key); } assert(pp->across); if ((pout = tds_find(&input, pp->output, pp->nout, sizeof(*pp->output), agg_equal)) == NULL ) { pout = realloc(pp->output, (1 + pp->nout) * sizeof(*pp->output)); if (!pout) return FAIL; pp->output = pout; pout += pp->nout++; if ((pout->row_key.keys = calloc(input.row_key.nkeys, sizeof(*pout->row_key.keys))) == NULL) return FAIL; key_cpy(&pout->row_key, &input.row_key); if ((pout->col_key.keys = calloc(input.col_key.nkeys, sizeof(*pout->col_key.keys))) == NULL) return FAIL; key_cpy(&pout->col_key, &input.col_key); col_init(&pout->value, input.value.type, input.value.len); } func(&pout->value, &input.value); } /* Mark this proc as pivoted, so that dbnextrow() sees it when the application calls it */ pp->dbproc = dbproc; pp->dbresults_state = dbproc->dbresults_state; dbproc->dbresults_state = pp->output < pout? _DB_RES_RESULTSET_ROWS : _DB_RES_RESULTSET_EMPTY; /* * Initialize new metadata */ nmeta = input.row_key.nkeys + pp->nacross; metadata = calloc(nmeta, sizeof(*metadata)); assert(pp->across || pp->nacross == 0); /* key columns are passed through as-is, verbatim */ for (i=0; i < input.row_key.nkeys; i++) { assert(i < nkeys); metadata[i].name = strdup(dbcolname(dbproc, keys[i])); metadata[i].pacross = NULL; col_cpy(&metadata[i].col, input.row_key.keys+i); } /* pivoted columms are found in the "across" data */ for (i=0, pmeta = metadata + input.row_key.nkeys; i < pp->nacross; i++) { struct col_t col; col_init(&col, SYBFLT8, sizeof(double)); assert(pmeta + i < metadata + nmeta); pmeta[i].name = make_col_name(pp->across+i); assert(pp->across); pmeta[i].pacross = pp->across + i; col_cpy(&pmeta[i].col, pp->nout? &pp->output[0].value : &col); } if (!reinit_results(dbproc->tds_socket, nmeta, metadata)) { return FAIL; } return SUCCEED; #if 0 for (pp->pout=pp->output; pp->pout < pp->output + pp->nout; pp->pout++) { char name[256] = {0}; assert(pp->pout->col_key.keys[0].len < sizeof(name)); memset(name, '\0', sizeof(name)); memcpy(name, pp->pout->col_key.keys[0].s, pp->pout->col_key.keys[0].len), printf("%5d %-30s %5d\n", pp->pout->row_key.keys[0].i, name, pp->pout->value.i ); } exit(1); #endif }
static bool lc_dump_dyld_bind_info(uint32_t offset, uint32_t size, char *img, lambchop_logger *logger) { char *bind_info = img + offset; char *p = bind_info; if (!size) { return true; } while (p < (bind_info + size)) { uint8_t opcode = *p & BIND_OPCODE_MASK; uint8_t immediate = *p & BIND_IMMEDIATE_MASK; const char *type; int64_t sleb; uint64_t uleb, uleb2; p++; switch(opcode) { case BIND_OPCODE_DONE: return true; case BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: lambchop_info(logger, "bind_info: op=BIND_OPCODE_SET_DYLIB_ORDINAL_IMM ordinal=%d\n", immediate); break; case BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: uleb = parse_uleb128(&p); lambchop_info(logger, "bind_info: op=BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB ordinal=%d\n", uleb); break; case BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: lambchop_info(logger, "bind_info: op=BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM flags=0x%x, symbol = %s\n", immediate, p); p += strlen(p) + 1; break; case BIND_OPCODE_SET_TYPE_IMM: type = bind_type(immediate); if (!type) { lambchop_err(logger, "unsupported bind type 0x%x\n", immediate); return false; } lambchop_info(logger, "bind_info: op=BIND_OPCODE_SET_TYPE_IMM type=%s\n", type); break; case BIND_OPCODE_SET_ADDEND_SLEB: sleb = parse_sleb128(&p); lambchop_info(logger, "bind_info: op=BIND_OPCODE_SET_ADDEND_SLEB addend=%lld\n", sleb); break; case BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: uleb = parse_uleb128(&p); lambchop_info(logger, "bind_info: op=BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB segment=%d offset=0x%x\n", immediate, uleb); break; case BIND_OPCODE_ADD_ADDR_ULEB: uleb = parse_uleb128(&p); lambchop_info(logger, "bind_info: op=BIND_OPCODE_ADD_ADDR_ULEB offset=0x%x\n", uleb); break; case BIND_OPCODE_DO_BIND: lambchop_info(logger, "bind_info: op=BIND_OPCODE_DO_BIND\n"); break; case BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: uleb = parse_uleb128(&p); lambchop_info(logger, "bind_info: op=BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB offset=0x%x\n", uleb); break; case BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: lambchop_info(logger, "bind_info: op=BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED offset=0x%x\n", immediate); break; case BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: uleb = parse_uleb128(&p); uleb2 = parse_uleb128(&p); lambchop_info(logger, "bind_info: op=BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB, times=%d, offset=0x%x\n", uleb, uleb2); break; default: lambchop_err(logger, "unsupported bind info opcode 0x%x\n", opcode); return false; } } lambchop_err(logger, "BIND_OPCODE_DONE not found\n"); return false; }
bool check_constraints(ast_t* orig, ast_t* typeparams, ast_t* typeargs, bool report_errors) { ast_t* typeparam = ast_child(typeparams); ast_t* typearg = ast_child(typeargs); while(typeparam != NULL) { // Reify the constraint. ast_t* constraint = ast_childidx(typeparam, 1); ast_t* bind_constraint = bind_type(constraint); ast_t* r_constraint = reify(bind_constraint, typeparams, typeargs); if(bind_constraint != r_constraint) ast_free_unattached(bind_constraint); // A bound type must be a subtype of the constraint. errorframe_t info = NULL; if(!is_subtype(typearg, r_constraint, report_errors ? &info : NULL)) { if(report_errors) { errorframe_t frame = NULL; ast_error_frame(&frame, orig, "type argument is outside its constraint"); ast_error_frame(&frame, typearg, "argument: %s", ast_print_type(typearg)); ast_error_frame(&frame, typeparam, "constraint: %s", ast_print_type(r_constraint)); errorframe_append(&frame, &info); errorframe_report(&frame); } ast_free_unattached(r_constraint); return false; } ast_free_unattached(r_constraint); // A constructable constraint can only be fulfilled by a concrete typearg. if(is_constructable(constraint) && !is_concrete(typearg)) { if(report_errors) { ast_error(orig, "a constructable constraint can only be fulfilled " "by a concrete type argument"); ast_error(typearg, "argument: %s", ast_print_type(typearg)); ast_error(typeparam, "constraint: %s", ast_print_type(constraint)); } return false; } typeparam = ast_sibling(typeparam); typearg = ast_sibling(typearg); } assert(typeparam == NULL); assert(typearg == NULL); return true; }
bool check_constraints(ast_t* orig, ast_t* typeparams, ast_t* typeargs, bool report_errors) { // Reify the type parameters with the typeargs. ast_t* r_typeparams = reify(orig, typeparams, typeparams, typeargs); if(r_typeparams == NULL) return false; ast_t* r_typeparam = ast_child(r_typeparams); ast_t* typeparam = ast_child(typeparams); ast_t* typearg = ast_child(typeargs); while(r_typeparam != NULL) { // Use the reified constraint. ast_t* r_constraint = ast_childidx(r_typeparam, 1); r_constraint = bind_type(r_constraint); // A bound type must be a subtype of the constraint. if(!is_subtype(typearg, r_constraint)) { if(report_errors) { ast_error(orig, "type argument is outside its constraint"); ast_error(typearg, "argument: %s", ast_print_type(typearg)); ast_error(typeparam, "constraint: %s", ast_print_type(r_constraint)); } ast_free_unattached(r_typeparams); ast_free_unattached(r_constraint); return false; } ast_free_unattached(r_constraint); // A constructable constraint can only be fulfilled by a concrete typearg. ast_t* constraint = ast_childidx(typeparam, 1); if(is_constructable(constraint) && !is_concrete(typearg)) { if(report_errors) { ast_error(orig, "a constructable constraint can only be fulfilled " "by a concrete type argument"); ast_error(typearg, "argument: %s", ast_print_type(typearg)); ast_error(typeparam, "constraint: %s", ast_print_type(constraint)); } ast_free_unattached(r_typeparams); return false; } r_typeparam = ast_sibling(r_typeparam); typeparam = ast_sibling(typeparam); typearg = ast_sibling(typearg); } assert(r_typeparam == NULL); assert(typearg == NULL); ast_free_unattached(r_typeparams); return true; }