static void ayadavar(autobuf_t *buf, yadac_param_t param, char *name) { switch(param) { case(YADAC_INT): if(name) aprintf(buf, "int %s", name); else acopy(buf, "int"); break; case(YADAC_FLOAT): if(name) aprintf(buf, "double %s", name); else acopy(buf, "double"); break; case(YADAC_LONG): if(name) aprintf(buf, "long long %s", name); else acopy(buf, "long long"); break; case(YADAC_BINARY): case(YADAC_STRING): if(name) aprintf(buf, "char *%s", name); else acopy(buf, "char*"); break; case(YADAC_INTP): if(name) aprintf(buf, "int *%s", name); else acopy(buf, "int*"); break; case(YADAC_FLOATP): if(name) aprintf(buf, "double *%s", name); else acopy(buf, "double*"); break; case(YADAC_LONGP): if(name) aprintf(buf, "long long *%s", name); else acopy(buf, "long long*"); break; case(YADAC_BINARYP): case(YADAC_STRINGP): if(name) aprintf(buf, "char *%s", name); else acopy(buf, "char*"); break; } }
static void ayadatypes(autobuf_t *buf, yadac_param_t *param, int params) { int loop; for(loop=0; loop<params; param++, loop++) { switch(*param) { case(YADAC_INT): acopy(buf, "?d"); break; case(YADAC_FLOAT): acopy(buf, "?f"); break; case(YADAC_LONG): acopy(buf, "?l"); break; case(YADAC_BINARY): acopy(buf, "?b"); break; case(YADAC_STRING): acopy(buf, "?s"); break; case(YADAC_INTP): acopy(buf, "?pd"); break; case(YADAC_FLOATP): acopy(buf, "?pf"); break; case(YADAC_LONGP): acopy(buf, "?pl"); break; case(YADAC_BINARYP): acopy(buf, "?pb"); break; case(YADAC_STRINGP): acopy(buf, "?ps"); break; } } /* foreach(param) */ }
void preserves_input(dofft_closure *k, aconstrain constrain, int n, C *inA, C *inB, C *outB, int rounds) { int j; int recopy_input = k->recopy_input; k->recopy_input = 1; for (j = 0; j < rounds; ++j) { arand(inA, n); if (constrain) constrain(inA, n); acopy(inB, inA, n); k->apply(k, inB, outB); acmp(inB, inA, n, "preserves_input", 0.0); } k->recopy_input = recopy_input; }
static inline void aiproto(autobuf_t *buf, yadac_binding_t *binding) { int idx; /* input struct bound, use it */ if(binding->istruct) { aprintf(buf, ", %s *in", binding->istruct->type); return; } /* no input variables needed */ if(!binding->iparams) return; /* loop through input paramters making variables */ for(idx=0; idx<binding->iparams; idx++) { acopy(buf, ", "); ayadavar(buf, binding->iparam[idx], "in"); aprintf(buf, "%u", (idx + 1)); } }
void access(Array& A, const const_array_tag&) { typedef boost::multi_array<int,3> array3; array3 acopy(A); BOOST_CHECK(equal(acopy,A)); ++tests_run; }
void test_block_solver () { if (!process_messenger) process_messenger.reset (new mpi::messenger ()); int timesteps = 1; int id = process_messenger->get_id (); int np = process_messenger->get_np (); int n = 10, nrhs = 10, ntop = 0, nbot = 0; if (id != 0) { ntop = 1; } if (id != np - 1) { nbot = 1; } int lda = n + ntop + nbot, ldx = 0, ldb = lda; std::vector <int> ns (process_messenger->get_np ()); process_messenger->gather <int> (1, &ntop, &ns [0]); if (process_messenger->get_id () == 0) { for (int i = 0; i < process_messenger->get_np (); ++i) { ldx += ns [i]; } } else { ldx = ntop + nbot; } std::vector <double> bufftop (ntop * nrhs), buffbot (nbot * nrhs), rbufftop (ntop * nrhs), rbuffbot (nbot * nrhs); std::vector <double> a (lda * lda), acopy (lda * lda); std::vector <double> b (lda * nrhs), bcopy (lda * nrhs); std::vector <int> ipiv (lda); std::vector <double> x (ldx * ldx); std::vector <int> xipiv (ldx); int info; srand (2); for (int i = 0; i < lda; ++i) { for (int j = 0; j < lda; ++j) { a [j * lda + i] = rand () % 100; } for (int j = 0; j < nrhs; ++j) { b [j * ldb + i] = rand () % 100; bcopy [j * ldb + i] = b [j * ldb + i]; } } linalg::matrix_copy (lda, lda, &a [0], &acopy [0], lda, lda); // clock_t corig_begin, corig_end; // std::chrono::time_point <std::chrono::system_clock> orig_begin, orig_end; // corig_begin = clock (); // orig_begin = std::chrono::system_clock::now (); linalg::matrix_factorize (n, n, &a [0], &ipiv [0], &info, lda); linalg::matrix_solve (n, &a [0], &ipiv [0], &b [0], &info, nrhs, lda, ldb); // corig_end = clock (); // orig_end = std::chrono::system_clock::now (); // std::chrono::duration <double> orig_total = orig_end - orig_begin; // printf ("[%i] Orig CPU Time: %f\n", id, ((double) (corig_end - corig_begin))/CLOCKS_PER_SEC); // printf ("[%i] Orig Wall Time: %f\n", id, (double) orig_total.count ()); // clock_t cbegin, cmid, cend; // std::chrono::time_point <std::chrono::system_clock> begin, mid, end; // std::chrono::duration <double> mb, em, eb; // double cmb = 0.0, cem = 0.0, ceb = 0.0; for (int i = 0; i < timesteps; ++i) { for (int i = 0; i < lda; ++i) { for (int j = 0; j < lda; ++j) { a [j * lda + i] = rand () % 100; acopy [j * lda + i] = a [j * lda + i]; } for (int j = 0; j < nrhs; ++j) { b [j * ldb + i] = rand () % 100; bcopy [j * ldb + i] = b [j * ldb + i]; } } // cbegin = clock (); // begin = std::chrono::system_clock::now (); linalg::block::matrix_factorize (process_messenger->get_id (), process_messenger->get_np (), n, ntop, nbot, &a [0], &ipiv [0], &x [0], &xipiv [0], &ns [0], &info, lda, ldx); // cmid = clock (); // mid = std::chrono::system_clock::now (); // mb += mid - begin; // cmb += cmid - cbegin; linalg::block::matrix_solve (process_messenger->get_id (), process_messenger->get_np (), n, ntop, nbot, &a [0], &ipiv [0], &b [0], &x [0], &xipiv [0], &ns [0], &info, nrhs, lda, ldx, ldb); // cend = clock (); // end = std::chrono::system_clock::now (); // em += end - mid; // eb += end - begin; // cem += cend - cmid; // ceb += cend - cbegin; linalg::matrix_matrix_multiply (n + ntop + nbot, nrhs, n + ntop + nbot, 1.0, &acopy [0], &b [0], -1.0, &bcopy [0]); if (id != 0) { linalg::matrix_copy (ntop, nrhs, &bcopy [0], &bufftop [0], ldb, ntop); process_messenger->send (ntop * nrhs, &bufftop [0], id - 1, 0); } if (id != np - 1) { linalg::matrix_copy (nbot, nrhs, &bcopy [n + ntop], &buffbot [0], ldb, nbot); process_messenger->recv (nbot * nrhs, &rbuffbot [0], id + 1, 0); process_messenger->send (nbot * nrhs, &buffbot [0], id + 1, 1); linalg::matrix_add_scaled (nbot, nrhs, 1.0, &rbuffbot [0], &bcopy [n + ntop], nbot, ldb); } if (id != 0) { process_messenger->recv (ntop * nrhs, &rbufftop [0], id - 1, 1); linalg::matrix_add_scaled (ntop, nrhs, 1.0, &rbufftop [0], &bcopy [0], ntop, ldb); } for (int i = 0; i < n + ntop + nbot; ++i) { for (int j = 0; j < nrhs; ++j) { TSM_ASSERT_DELTA ("Block solver failure", bcopy [j * ldb + i], 0.0, TEST_TINY); } } } // printf ("[%i] Avg CPU Time: %f + %f = %f\n", id, ((double) (cmb))/CLOCKS_PER_SEC/timesteps, ((double) (cem))/CLOCKS_PER_SEC/timesteps, ((double) (ceb))/CLOCKS_PER_SEC/timesteps); // printf ("[%i] Avg Wall Time: %f + %f = %f\n", id, (double) mb.count ()/timesteps, (double) em.count ()/timesteps, (double) eb.count ()/timesteps); }
//------------------------------------------------------------------------ // Test exceptions safety (from allocator and items constructors) //------------------------------------------------------------------------ void TestExceptions() { typedef static_counting_allocator<debug_allocator<FooWithAssign>, std::size_t> allocator_t; typedef tbb::concurrent_vector<FooWithAssign, allocator_t> vector_t; enum methods { zero_method = 0, ctor_copy, ctor_size, assign_nt, assign_ir, op_equ, reserve, compact, grow, all_methods }; ASSERT( !FooCount, NULL ); try { vector_t src(FooIterator(0), FooIterator(N)); // original data for(int t = 0; t < 2; ++t) // exception type for(int m = zero_method+1; m < all_methods; ++m) { ASSERT( FooCount == N, "Previous iteration miss some Foo's de-/initialization" ); allocator_t::init_counters(); if(t) MaxFooCount = FooCount + N/4; else allocator_t::set_limits(N/4); vector_t victim; try { switch(m) { case ctor_copy: { vector_t acopy(src); } break; // auto destruction after exception is checked by ~Foo case ctor_size: { vector_t sized(N); } break; // auto destruction after exception is checked by ~Foo // Do not test assignment constructor due to reusing of same methods as below case assign_nt: { victim.assign(N, FooWithAssign()); } break; case assign_ir: { victim.assign(FooIterator(0), FooIterator(N)); } break; case op_equ: { victim.reserve(2); victim = src; // fragmented assignment } break; case reserve: { try { victim.reserve(victim.max_size()+1); } catch(std::length_error &) { } catch(...) { KNOWN_ISSUE("ERROR: unrecognized exception - known compiler issue\n"); } victim.reserve(N); } break; case compact: { if(t) MaxFooCount = 0; else allocator_t::set_limits(); // reset limits victim.reserve(2); victim = src; // fragmented assignment if(t) MaxFooCount = FooCount + 10; else allocator_t::set_limits(1, false); // block any allocation, check NULL return from allocator victim.shrink_to_fit(); // should start defragmenting first segment } break; case grow: { tbb::task_scheduler_init init(2); if(t) MaxFooCount = FooCount + 31; // these numbers help to reproduce the live lock for versions < TBB2.2 try { tbb::parallel_for( tbb::blocked_range<int>(0, N, 70), GrowBy<vector_t>(victim) ); } catch(...) { #if TBB_USE_CAPTURED_EXCEPTION throw tbb::bad_last_alloc(); #else throw; #endif } } break; default:; } if(!t || m != reserve) ASSERT(false, "should throw an exception"); } catch(std::bad_alloc &e) { allocator_t::set_limits(); MaxFooCount = 0; size_t capacity = victim.capacity(); size_t size = victim.size(); #if TBB_DEPRECATED size_t req_size = victim.grow_by(0); #else size_t req_size = victim.grow_by(0) - victim.begin(); #endif ASSERT( size <= capacity, NULL); ASSERT( req_size >= size, NULL); switch(m) { case reserve: if(t) ASSERT(false, NULL); case assign_nt: case assign_ir: if(!t) { ASSERT(capacity < N/2, "unexpected capacity"); ASSERT(size == 0, "unexpected size"); break; } else { ASSERT(size == N, "unexpected size"); ASSERT(capacity >= N, "unexpected capacity"); int i; for(i = 1; ; ++i) if(!victim[i].zero_bar()) break; else ASSERT(victim[i].bar() == (m == assign_ir)? i : initial_value_of_bar, NULL); for(; size_t(i) < size; ++i) ASSERT(!victim[i].zero_bar(), NULL); ASSERT(size_t(i) == size, NULL); break; } case grow: case op_equ: if(!t) { ASSERT(capacity > 0, NULL); ASSERT(capacity < N, "unexpected capacity"); } { vector_t copy_of_victim(victim); ASSERT(copy_of_victim.size() > 0, NULL); for(int i = 0; ; ++i) { try { FooWithAssign &foo = victim.at(i); if( !foo.is_valid_or_zero() ) { std::printf("i: %d size: %u req_size: %u state: %d\n", i, unsigned(size), unsigned(req_size), foo.state); } int bar = foo.zero_bar(); if(m != grow) ASSERT( bar == i || (t && bar == 0), NULL); if(size_t(i) < copy_of_victim.size()) ASSERT( copy_of_victim[i].bar() == bar, NULL); } catch(std::range_error &) { // skip broken segment ASSERT( size_t(i) < req_size, NULL ); if(m == op_equ) break; } catch(std::out_of_range &){ ASSERT( i > 0, NULL ); break; } catch(...) { KNOWN_ISSUE("ERROR: unrecognized exception - known compiler issue\n"); break; } } vector_t copy_of_victim2(10); copy_of_victim2 = victim; ASSERT(copy_of_victim == copy_of_victim2, "assignment doesn't match copying"); if(m == op_equ) { try { victim = copy_of_victim2; } catch(tbb::bad_last_alloc &) { break; } catch(...) { KNOWN_ISSUE("ERROR: unrecognized exception - known compiler issue\n"); break; } ASSERT(t, NULL); } } break; case compact: ASSERT(capacity > 0, "unexpected capacity"); ASSERT(victim == src, "shrink_to_fit() is broken"); break; default:; // nothing to check here } REMARK("Exception %d: %s\t- ok\n", m, e.what()); } } } catch(...) { ASSERT(false, "unexpected exception"); } }
void TestExceptions() { typedef local_counting_allocator<tbb::tbb_allocator<MyData2> > allocator_t; typedef tbb::concurrent_hash_map<MyKey,MyData2,MyHashCompare,allocator_t> ThrowingTable; enum methods { zero_method = 0, ctor_copy, op_assign, op_insert, all_methods }; REMARK("testing exception-safety guarantees\n"); ThrowingTable src; FillTable( src, 1000 ); ASSERT( MyDataCount==1000, NULL ); try { for(int t = 0; t < 2; t++) // exception type for(int m = zero_method+1; m < all_methods; m++) { allocator_t a; if(t) MyDataCountLimit = 101; else a.set_limits(101); ThrowingTable victim(a); MyDataCount = 0; try { switch(m) { case ctor_copy: { ThrowingTable acopy(src, a); } break; case op_assign: { victim = src; } break; case op_insert: { FillTable( victim, 1000 ); } break; default:; } ASSERT(false, "should throw an exception"); } catch(std::bad_alloc &e) { MyDataCountLimit = 0; size_t size = victim.size(); switch(m) { case op_assign: ASSERT( MyDataCount==100, "data leak?" ); ASSERT( size>=100, NULL ); CheckAllocator(victim, 100+t, t); case ctor_copy: CheckTable(src, 1000); break; case op_insert: ASSERT( size==size_t(100-t), NULL ); ASSERT( MyDataCount==100-t, "data leak?" ); CheckTable(victim, 100-t); CheckAllocator(victim, 100, t); break; default:; // nothing to check here } REMARK("Exception %d: %s\t- ok ()\n", m, e.what()); } catch ( ... ) { ASSERT ( __TBB_EXCEPTION_TYPE_INFO_BROKEN, "Unrecognized exception" ); } } } catch(...) { ASSERT(false, "unexpected exception"); } src.clear(); MyDataCount = 0; }
static char* gen_header(yadac_t *tree, int *siz, char *src_fname, char *fname, char *prefix) { char tag[32]; char *ptr, *in, *out; int loop, idx; yadac_binding_t *binding; autobuf_t *buf; /* convert prefix to caps */ snprintf(tag, sizeof(tag), "%s", prefix); for(ptr=tag; *ptr; ptr++) *ptr = toupper(*ptr); /* remove path from source filename */ in = strrchr(src_fname, '/'); in = (in ? (in + 1) : src_fname); /* remove path from output filename */ out = strrchr(fname, '/'); out = (out ? (out + 1) : fname); /* allocate new autobuf */ if(!(buf = calloc(1, sizeof(autobuf_t)))) return(NULL); acopy(buf, "\n/*******************************************************"); acopy(buf, "***********************\n ********************************"); acopy(buf, "**********************************************/\n\n"); aprintf(buf, "/** \\file %s\n", out); aprintf(buf, " * automatically generated from: %s\n */\n\n", in); aprintf(buf, "#ifndef __YADAC_%s_H__\n", tag); aprintf(buf, "#define __YADAC_%s_H__\n\n", tag); acopy(buf, "/*********************************************************"); acopy(buf, "*********************\n * I N C L U D E S ****************"); acopy(buf, "********************************************\n ***********"); acopy(buf, "**********************************************************"); acopy(buf, "*********/\n\n"); acopy(buf, "#include <yada.h>\n\n"); /* list included files */ if(tree->incs) { for(loop=0; loop<tree->incs; loop++) aprintf(buf, "#include \"%s\"\n", tree->inc[loop]); acopy(buf, "\n"); } acopy(buf, "/*********************************************************"); acopy(buf, "*********************\n * T Y P E D E F S ****************"); acopy(buf, "********************************************\n ***********"); acopy(buf, "**********************************************************"); acopy(buf, "*********/\n\n"); acopy(buf, "#ifndef __YADAC_T_\n"); acopy(buf, "#define __YADAC_T_\n\n"); acopy(buf, "typedef struct\n{\n"); acopy(buf, " yada_t *db;\n"); acopy(buf, " int sz;\n int rcs;\n"); acopy(buf, " yada_rc_t **rc;\n"); acopy(buf, "} yadac_t;\n\n"); acopy(buf, "#endif\n\n"); acopy(buf, "/*********************************************************"); acopy(buf, "*********************\n * P R O T O T Y P E S ************"); acopy(buf, "********************************************\n ***********"); acopy(buf, "**********************************************************"); acopy(buf, "*********/\n\n"); aprintf(buf, "/* init / destroy %s functions */\n", prefix); aprintf(buf, "yadac_t* %s_init(yadac_t *db, ...);\n", prefix); aprintf(buf, "void %s_free(yadac_t *yc);\n\n", prefix); aprintf(buf, "void %s_destroy(yadac_t *yc);\n\n", prefix); /* output prototypes */ acopy(buf, "/* compiled queries */\n"); for(loop=0, binding=tree->bind; loop<tree->binds; binding++, loop++) { switch(binding->rtype) { /************************************************/ case(YADAC_STATUS): /************************************************/ aprintf(buf, "int %s_%s(yadac_t *yc", prefix, binding->name); aiproto(buf, binding); acopy(buf, ");\n\n"); break; /************************************************/ case(YADAC_SIMPLE): /************************************************/ ayadavar(buf, *binding->oparam, NULL); aprintf(buf, " %s_%s(yadac_t *yc, ", prefix, binding->name); ayadavar(buf, *binding->oparam, "errval"); aiproto(buf, binding); acopy(buf, ");\n\n"); break; /************************************************/ case(YADAC_SINGLE): /************************************************/ aprintf(buf, "int %s_%s(yadac_t *yc", prefix, binding->name); aiproto(buf, binding); for(idx=0; idx<binding->oparams; idx++) { acopy(buf, ", "); if(binding->oparam[idx] == YADAC_STRING) ayadavar(buf, binding->oparam[idx], "out"); else ayadavar(buf, binding->oparam[idx], "*out"); aprintf(buf, "%u", (idx + 1)); } acopy(buf, ");\n\n"); break; /************************************************/ case(YADAC_STRUCT): /************************************************/ aprintf(buf, "int %s_%s(yadac_t *yc", prefix, binding->name); aiproto(buf, binding); aprintf(buf, ", %s *out);\n\n", binding->ostruct->type); break; /************************************************/ case(YADAC_MULTIROW): /************************************************/ aprintf(buf, "int %s_%s(yadac_t *yc", prefix, binding->name); aiproto(buf, binding); for(idx=0; idx<binding->oparams; idx++) { acopy(buf, ", "); if(binding->oparam[idx] == YADAC_STRING) ayadavar(buf, binding->oparam[idx], "out"); else ayadavar(buf, binding->oparam[idx], "*out"); aprintf(buf, "%u", (idx + 1)); } acopy(buf, ");\n"); aprintf(buf, "int %s_%s_fetch(yadac_t *yc);\n", prefix, binding->name); break; /************************************************/ case(YADAC_MULTISTRUCT): /************************************************/ aprintf(buf, "int %s_%s(yadac_t *yc", prefix, binding->name); aiproto(buf, binding); aprintf(buf, ", %s *out);\n\n", binding->ostruct->type); aprintf(buf, "int %s_%s_fetch(yadac_t *yc);\n", prefix, binding->name); break; /************************************************/ } /* switch(rtype) */ } /* foreach(binding) */ acopy(buf, "/*********************************************************"); acopy(buf, "*********************/\n\n"); aprintf(buf, "#endif /* end __YADAC_%s_H__ */\n\n", tag); acopy(buf, "/*********************************************************"); acopy(buf, "*********************\n **********************************"); acopy(buf, "********************************************/\n\n"); /* check if any errors occured */ if(buf->errs) { free(buf->ptr); free(buf); return(NULL); } /* set size if needed */ if(siz) *siz = buf->siz; /* shrink and return buffer */ ptr = realloc(buf->ptr, buf->siz); free(buf); return(ptr); }
static char* gen_source(yadac_t *tree, int *siz, char *src_fname, char *fname, char *hdr_fname, char *prefix) { char tag[32]; char *ptr, *in, *out, *hdr; int loop, idx; autobuf_t *buf; yadac_binding_t *binding; /* convert prefix to caps */ snprintf(tag, sizeof(tag), "%s", prefix); for(ptr=tag; *ptr; ptr++) *ptr = toupper(*ptr); /* remove path from source filename */ in = strrchr(src_fname, '/'); in = (in ? (in + 1) : src_fname); /* remove path from output filename */ out = strrchr(fname, '/'); out = (out ? (out + 1) : fname); /* remove path from header filename */ hdr = strrchr(hdr_fname, '/'); hdr = (hdr ? (hdr + 1) : hdr_fname); /* allocate new autobuf */ if(!(buf = calloc(1, sizeof(autobuf_t)))) return(NULL); acopy(buf, "\n/*******************************************************"); acopy(buf, "***********************\n ********************************"); acopy(buf, "**********************************************/\n\n"); aprintf(buf, "/** \\file %s\n", out); aprintf(buf, " * automatically generated from: %s\n */\n\n", in); acopy(buf, "/*********************************************************"); acopy(buf, "*********************\n * D E F I N E S ******************"); acopy(buf, "********************************************\n ***********"); acopy(buf, "**********************************************************"); acopy(buf, "*********/\n\n"); aprintf(buf, "#define __YADAC_%s_LIBSRC_\n", tag); aprintf(buf, "#define YADAC_%s_CHUNK_SZ 8\n\n", tag); acopy(buf, "/*********************************************************"); acopy(buf, "*********************\n * I N C L U D E S ****************"); acopy(buf, "********************************************\n ***********"); acopy(buf, "**********************************************************"); acopy(buf, "*********/\n\n"); acopy(buf, "#include <stdarg.h>\n\n"); acopy(buf, "#include <stdlib.h>\n\n"); acopy(buf, "#include <yada.h>\n\n"); aprintf(buf, "#include \"%s\"\n\n", hdr); acopy(buf, "/*********************************************************"); acopy(buf, "*********************\n * S Q L **************************"); acopy(buf, "********************************************\n ***********"); acopy(buf, "**********************************************************"); acopy(buf, "*********/\n\n"); /* output SQL for each query */ for(loop=0, binding=tree->bind; loop<tree->binds; binding++, loop++) { aprintf(buf, "#define SQL_%s \\\n", binding->upper); for(idx=0; idx<binding->lines; idx++) { aindent(buf, binding->line[idx].indent); if((idx + 1) < binding->lines) aprintf(buf, "\"%s \"\\\n", binding->line[idx].text); else aprintf(buf, "\"%s\"\n", binding->line[idx].text); } acopy(buf, "\n"); } acopy(buf, "/*********************************************************"); acopy(buf, "*********************\n * G L O B A L S ******************"); acopy(buf, "********************************************\n ***********"); acopy(buf, "**********************************************************"); acopy(buf, "*********/\n\n"); acopy(buf, "/* saved database pointer */\n"); acopy(buf, "static yadac_t *yadac;\n\n"); /* output statement pointer for each query */ aprintf(buf, "/* %s statements */\n", prefix); for(loop=0, binding=tree->bind; loop<tree->binds; binding++, loop++) aprintf(buf, "static yada_rc_t *stmt_%s = NULL;\n", binding->name); acopy(buf, "\n"); acopy(buf, "/*********************************************************"); acopy(buf, "*********************\n * F U N C T I O N S **************"); acopy(buf, "********************************************\n ***********"); acopy(buf, "**********************************************************"); acopy(buf, "*********/\n\n"); acopy(buf, "/*********************************************************"); acopy(buf, "*********************/\n"); aprintf(buf, "/** prepare %s statements\n", prefix); acopy(buf, " * @param yc yadac_t to use\n"); acopy(buf, " * @param yada_t* db if yc is null, alloc new and use this db\n"); acopy(buf, " * @return yadac_t* on success, NULL on error\n */\n"); aprintf(buf, "\nyadac_t* %s_init(yadac_t *yc, ...)\n{\n", prefix); acopy(buf, " int err = 0;\n va_list ap;\n yada_t *db;\n\n\n"); /* create yadac */ acopy(buf, " if(!yc)\n {\n"); acopy(buf, " if(!(yadac = calloc(1, sizeof(yadac_t))) || "); aprintf(buf, "!(yadac->rc = malloc(YADAC_%s_CHUNK_SZ * ", tag); acopy(buf, "sizeof(yadac_t*))))\n {\n free(yadac);\n"); aprintf(buf, " return(NULL);\n }\n", prefix); acopy(buf, " va_start(ap, yc);\n yadac->db = va_arg(ap, yada_t*);\n"); acopy(buf, " va_end(ap);\n"); aprintf(buf, " yadac->sz = YADAC_%s_CHUNK_SZ;\n }\n", tag); acopy(buf, " else\n yadac = yc;\n\n"); acopy(buf, " db = yadac->db;\n\n"); /* code to prepare statements */ aprintf(buf, " /* prepare %s statements */\n", prefix); for(loop=0, binding=tree->bind; loop<tree->binds; binding++, loop++) aprintf(buf, " err |= !(stmt_%s = db->%s(db, SQL_%s, 0));\n", binding->name, (binding->ptype ? "yprepare" : "prepare"), binding->upper); acopy(buf, "\n"); /* output error check */ acopy(buf, " /* check for errors */\n"); acopy(buf, " if(err)\n {\n"); aprintf(buf, " %s_destroy(yadac);\n return(NULL);\n }\n\n", prefix); acopy(buf, " return(yadac);\n}\n\n"); acopy(buf, "/*********************************************************"); acopy(buf, "*********************/\n"); aprintf(buf, "/** free %s queries and bindsets\n */\n", prefix); aprintf(buf, "\nvoid %s_free(yadac_t *yc)\n{\n", prefix); /* make sure yadac instance was specified */ acopy(buf, " if(!yc)\n yc = yadac;\n\n"); acopy(buf, " if(!yc->rcs)\n return;\n\n"); acopy(buf, " while(yc->rcs--)\n"); acopy(buf, " yc->db->free(yc->db, yc->rc[yc->rcs]);\n\n"); acopy(buf, " yc->rcs = 0;\n}\n\n"); acopy(buf, "/*********************************************************"); acopy(buf, "*********************/\n"); aprintf(buf, "/** destroy %s statements\n */\n", prefix); aprintf(buf, "\nvoid %s_destroy(yadac_t *yc)\n{\n", prefix); acopy(buf, " yada_t *db;\n\n\n"); /* make sure yadac instance was specified */ acopy(buf, " if(!yc)\n yc = yadac;\n"); acopy(buf, " db = yc->db;\n\n"); /* cleanup each statement */ for(loop=0, binding=tree->bind; loop<tree->binds; binding++, loop++) { aprintf(buf, " if(stmt_%s)\n", binding->name); aprintf(buf, " db->free(db, stmt_%s);\n", binding->name); aprintf(buf, " stmt_%s = NULL;\n\n", binding->name); } /* cleanup results and free yadac */ aprintf(buf, " %s_free(yc);\n free(yc->rc);\n free(yc);\n", prefix); acopy(buf, " if(yc == yadac)\n yadac = NULL;\n"); acopy(buf, "}\n\n"); acopy(buf, "/*********************************************************"); acopy(buf, "*********************/\n"); aprintf(buf, "/** push rcs onto yadac\n", prefix); acopy(buf, " * @return 0 on success, -1 on error\n */\n"); acopy(buf, "\ninline static int _yadac_push(yadac_t *yc, "); acopy(buf, "yada_rc_t *query, yada_rc_t *bs)\n{\n"); acopy(buf, " yada_rc_t **tmp;\n\n\n"); /* grow yadac rc array if needed */ acopy(buf, " if(yc->rcs + 1 >= yc->sz)\n {\n"); acopy(buf, " if(!(tmp = realloc(yc->rc, sizeof(yada_rc_t*) * (yc->sz + "); aprintf(buf, "YADAC_%s_CHUNK_SZ))))\n return(-1);\n", tag); aprintf(buf, " yc->rc = tmp;\n yc->sz += YADAC_%s_CHUNK_SZ;\n }\n\n", tag); /* set rcs */ acopy(buf, " yc->rc[yc->rcs++] = query;\n yc->rc[yc->rcs++] = bs;\n"); acopy(buf, " return(0);\n}\n\n"); /* actual statement functions */ for(loop=0, binding=tree->bind; loop<tree->binds; binding++, loop++) { acopy(buf, "/*********************************************************"); acopy(buf, "*********************/\n"); switch(binding->rtype) { /************************************************/ case(YADAC_STATUS): /************************************************/ aprintf(buf, "/** %s (STATUS operation)\n", binding->name); acopy(buf, " * @return num rows affected on success, "); acopy(buf, "-1 on error\n */\n\n"); aprintf(buf, "int %s_%s(yadac_t *yc", prefix, binding->name); /* add input variables */ aiproto(buf, binding); acopy(buf, ")\n{\n yada_t *db;\n\n\n"); /* make sure yadac instance was specified */ acopy(buf, " if(!yc)\n yc = yadac;\n"); acopy(buf, " db = yc->db;\n\n"); acopy(buf, " /* execute statement */\n"); aprintf(buf, " return(db->execute(db, stmt_%s", binding->name); aivars(buf, binding); acopy(buf, "));\n}\n\n"); break; /************************************************/ case(YADAC_SIMPLE): /************************************************/ aprintf(buf, "/** %s (SIMPLE operation)\n", binding->name); acopy(buf, " * @param errval value to return on error\n"); acopy(buf, " * @return value on success, errval on error\n */\n\n"); ayadavar(buf, *binding->oparam, NULL); aprintf(buf, " %s_%s(yadac_t *yc, ", prefix, binding->name); ayadavar(buf, *binding->oparam, "errval"); aiproto(buf, binding); acopy(buf, ")\n{\n "); ayadavar(buf, *binding->oparam, "out"); acopy(buf, ";\n int rval;\n"); acopy(buf, " yada_t *db;\n yada_rc_t *bs, *query;\n\n\n"); /* make sure yadac instance was specified */ acopy(buf, " if(!yc)\n yc = yadac;\n"); acopy(buf, " db = yc->db;\n\n"); acopy(buf, " /* bind output variables */\n"); acopy(buf, " if(!(bs = db->bind(db, \""); ayadatypes(buf, binding->oparam, binding->oparams); acopy(buf, "\", &out)))\n return(errval);\n\n"); acopy(buf, " /* perform query */\n"); aprintf(buf, " if(!(query = db->query(db, stmt_%s", binding->name); aivars(buf, binding); acopy(buf, ")))\n {\n"); acopy(buf, " db->free(db, bs);\n"); acopy(buf, " return(errval);\n"); acopy(buf, " }\n\n"); acopy(buf, " /* fetch result */\n"); acopy(buf, " rval = db->fetch(db, query, bs);\n"); acopy(buf, " if(!rval || db->error || _yadac_push(yc, query, bs))\n"); acopy(buf, " {\n db->free(db, query);\n db->free(db, bs);\n"); acopy(buf, " return(errval);\n }\n\n"); acopy(buf, " return(out);\n}\n\n"); break; /************************************************/ case(YADAC_SINGLE): /************************************************/ aprintf(buf, "/** %s (SINGLE operation)\n", binding->name); acopy(buf, " * @return 0 on success, -1 on error\n */\n\n"); aprintf(buf, "int %s_%s(yadac_t *yc", prefix, binding->name); aiproto(buf, binding); for(idx=0; idx<binding->oparams; idx++) { acopy(buf, ", "); if(binding->oparam[idx] == YADAC_STRING) ayadavar(buf, binding->oparam[idx], "out"); else ayadavar(buf, binding->oparam[idx], "*out"); aprintf(buf, "%u", (idx + 1)); } acopy(buf, ")\n{\n"); acopy(buf, " int rval;\n"); acopy(buf, " yada_t *db;\n yada_rc_t *bs, *query;\n\n\n"); /* make sure yadac instance was specified */ acopy(buf, " if(!yc)\n yc = yadac;\n"); acopy(buf, " db = yc->db;\n\n"); acopy(buf, " /* bind output variables */\n"); acopy(buf, " if(!(bs = db->bind(db, \""); ayadatypes(buf, binding->oparam, binding->oparams); acopy(buf, "\""); for(idx=0; idx<binding->oparams; idx++) aprintf(buf, ", out%u", (idx + 1)); acopy(buf, ")))\n return(-1);\n\n"); acopy(buf, " /* perform query */\n"); aprintf(buf, " if(!(query = db->query(db, stmt_%s", binding->name); aivars(buf, binding); acopy(buf, ")))\n {\n"); acopy(buf, " db->free(db, bs);\n"); acopy(buf, " return(-1);\n"); acopy(buf, " }\n\n"); acopy(buf, " /* fetch result */\n"); acopy(buf, " rval = db->fetch(db, query, bs);\n"); acopy(buf, " if(!rval || db->error || _yadac_push(yc, query, bs))\n"); acopy(buf, " {\n db->free(db, query);\n db->free(db, bs);\n"); acopy(buf, " return(db->error ? -1 : 1);\n }\n\n"); acopy(buf, " return(0);\n}\n\n"); break; /************************************************/ case(YADAC_STRUCT): /************************************************/ aprintf(buf, "/** %s (%s STRUCT operation)\n", binding->name, binding->ostruct->type); acopy(buf, " * @return 0 on success, -1 on error, 1 no results\n */\n\n"); aprintf(buf, "int %s_%s(yadac_t *yc", prefix, binding->name); aiproto(buf, binding); aprintf(buf, ", %s *out)\n{\n", binding->ostruct->type); acopy(buf, " int rval;\n"); acopy(buf, " yada_t *db;\n yada_rc_t *bs, *query;\n\n\n"); /* make sure yadac instance was specified */ acopy(buf, " if(!yc)\n yc = yadac;\n"); acopy(buf, " db = yc->db;\n\n"); acopy(buf, " /* bind output variables */\n"); acopy(buf, " if(!(bs = db->bind(db, \""); ayadatypes(buf, binding->oparam, binding->oparams); acopy(buf, "\""); for(idx=0; idx<binding->ostruct->list->tokens; idx++) if(*binding->ostruct->list->token[idx] < 0x2b) aprintf(buf, ", %cout->%s", binding->ostruct->list->token[idx][0], &binding->ostruct->list->token[idx][1]); else aprintf(buf, ", out->%s", binding->ostruct->list->token[idx]); acopy(buf, ")))\n return(-1);\n\n"); acopy(buf, " /* perform query */\n"); aprintf(buf, " if(!(query = db->query(db, stmt_%s", binding->name); aivars(buf, binding); acopy(buf, ")))\n {\n"); acopy(buf, " db->free(db, bs);\n"); acopy(buf, " return(-1);\n"); acopy(buf, " }\n\n"); acopy(buf, " /* fetch result */\n"); acopy(buf, " rval = db->fetch(db, query, bs);\n"); acopy(buf, " if(!rval || db->error || _yadac_push(yc, query, bs))\n"); acopy(buf, " {\n db->free(db, query);\n db->free(db, bs);\n"); acopy(buf, " return(db->error ? -1 : 1);\n }\n\n"); acopy(buf, " return(0);\n}\n\n"); break; /************************************************/ case(YADAC_MULTIROW): /************************************************/ aprintf(buf, "/** %s (MULTIROW operation)\n", binding->name); acopy(buf, " * @return 0 on success, -1 on error\n */\n\n"); aprintf(buf, "int %s_%s(yadac_t *yc", prefix, binding->name); aiproto(buf, binding); for(idx=0; idx<binding->oparams; idx++) { acopy(buf, ", "); if(binding->oparam[idx] == YADAC_STRING) ayadavar(buf, binding->oparam[idx], "out"); else ayadavar(buf, binding->oparam[idx], "*out"); aprintf(buf, "%u", (idx + 1)); } acopy(buf, ")\n{\n"); acopy(buf, " yada_t *db;\n yada_rc_t *bs, *query;\n\n\n"); /* make sure yadac instance was specified */ acopy(buf, " if(!yc)\n yc = yadac;\n"); acopy(buf, " db = yc->db;\n\n"); acopy(buf, " /* bind output variables */\n"); acopy(buf, " if(!(bs = db->bind(db, \""); ayadatypes(buf, binding->oparam, binding->oparams); acopy(buf, "\""); for(idx=0; idx<binding->oparams; idx++) aprintf(buf, ", out%u", (idx + 1)); acopy(buf, ")))\n return(-1);\n\n"); acopy(buf, " /* perform query */\n"); aprintf(buf, " if(!(query = db->query(db, stmt_%s", binding->name); aivars(buf, binding); acopy(buf, ")))\n {\n"); acopy(buf, " db->free(db, bs);\n"); acopy(buf, " return(-1);\n }\n\n"); acopy(buf, " if(_yadac_push(yc, query, bs))\n"); acopy(buf, " {\n db->free(db, query);\n db->free(db, bs);\n"); acopy(buf, " return(-1);\n }\n\n"); acopy(buf, " return(0);\n}\n\n"); acopy(buf, "/*******************************************************"); acopy(buf, "***********************/\n"); aprintf(buf, "/** %s (MULTIROW operation) fetch routine\n", binding->name); acopy(buf, " * @return 0 on completion, 1 if incomplete, "\ "-1 on error\n */\n\n"); aprintf(buf, "int %s_%s_fetch(yadac_t *yc)\n{\n", prefix, binding->name); /* make sure yadac instance was specified */ acopy(buf, " if(!yc)\n yc = yadac;\n\n"); acopy(buf, " /* fetch result */\n"); acopy(buf, " if(yc->db->fetch(yc->db, "); acopy(buf, "yc->rc[yc->rcs - 2], yc->rc[yc->rcs - 1]))\n"); acopy(buf, " return(1);\n\n"); acopy(buf, " /* check for errors */\n"); acopy(buf, " return(yc->db->error ? -1 : 0);\n}\n\n"); break; /************************************************/ case(YADAC_MULTISTRUCT): /************************************************/ aprintf(buf, "/** %s (%s MULTISTRUCT operation)\n", binding->name, binding->ostruct->type); acopy(buf, " * @return 0 on success, -1 on error, 1 no results\n */\n\n"); aprintf(buf, "int %s_%s(yadac_t *yc", prefix, binding->name); aiproto(buf, binding); aprintf(buf, ", %s *out)\n{\n", binding->ostruct->type); acopy(buf, " yada_t *db;\n yada_rc_t *bs, *query;\n\n\n"); /* make sure yadac instance was specified */ acopy(buf, " if(!yc)\n yc = yadac;\n"); acopy(buf, " db = yc->db;\n\n"); acopy(buf, " /* bind output variables */\n"); acopy(buf, " if(!(bs = db->bind(db, \""); ayadatypes(buf, binding->oparam, binding->oparams); acopy(buf, "\""); for(idx=0; idx<binding->ostruct->list->tokens; idx++) if(*binding->ostruct->list->token[idx] < 0x2b) aprintf(buf, ", %cout->%s", binding->ostruct->list->token[idx][0], &binding->ostruct->list->token[idx][1]); else aprintf(buf, ", out->%s", binding->ostruct->list->token[idx]); acopy(buf, ")))\n return(-1);\n\n"); acopy(buf, " /* perform query */\n"); aprintf(buf, " if(!(query = db->query(db, stmt_%s", binding->name); aivars(buf, binding); acopy(buf, ")))\n {\n"); acopy(buf, " db->free(db, bs);\n"); acopy(buf, " return(-1);\n"); acopy(buf, " }\n\n"); acopy(buf, " if(_yadac_push(yc, query, bs))\n"); acopy(buf, " {\n db->free(db, query);\n db->free(db, bs);\n"); acopy(buf, " return(-1);\n }\n\n"); acopy(buf, " return(0);\n}\n\n"); acopy(buf, "/*******************************************************"); acopy(buf, "***********************/\n"); aprintf(buf, "/** %s (MULTISTRUCT operation) fetch routine\n", binding->name); acopy(buf, " * @return 0 on completion, 1 if incomplete, "\ "-1 on error\n */\n\n"); aprintf(buf, "int %s_%s_fetch(yadac_t *yc)\n{\n", prefix, binding->name); /* make sure yadac instance was specified */ acopy(buf, " if(!yc)\n yc = yadac;\n\n"); acopy(buf, " /* fetch result */\n"); acopy(buf, " if(yc->db->fetch(yc->db, "); acopy(buf, "yc->rc[yc->rcs - 2], yc->rc[yc->rcs - 1]))\n"); acopy(buf, " return(1);\n\n"); acopy(buf, " /* check for errors */\n"); acopy(buf, " return(yc->db->error ? -1 : 0);\n}\n\n"); break; /************************************************/ } /* switch(rtype) */ } /* foreach(binding) */ acopy(buf, "/*********************************************************"); acopy(buf, "*********************\n **********************************"); acopy(buf, "********************************************/\n\n"); /* check if any errors occured */ if(buf->errs) { free(buf->ptr); free(buf); return(NULL); } /* set size if needed */ if(siz) *siz = buf->siz; /* shrink and return buffer */ ptr = realloc(buf->ptr, buf->siz); free(buf); return(ptr); }