int ApiGen::genDecoderHeader(const std::string &filename) { FILE *fp = fopen(filename.c_str(), "wt"); if (fp == NULL) { perror(filename.c_str()); return -1; } printHeader(fp); std::string classname = m_basename + "_decoder_context_t"; fprintf(fp, "\n#ifndef GUARD_%s\n", classname.c_str()); fprintf(fp, "#define GUARD_%s\n\n", classname.c_str()); fprintf(fp, "#include \"IOStream.h\" \n"); fprintf(fp, "#include \"%s_%s_context.h\"\n\n\n", m_basename.c_str(), sideString(SERVER_SIDE)); for (size_t i = 0; i < m_decoderHeaders.size(); i++) { fprintf(fp, "#include %s\n", m_decoderHeaders[i].c_str()); } fprintf(fp, "\n"); fprintf(fp, "struct %s : public %s_%s_context_t {\n\n", classname.c_str(), m_basename.c_str(), sideString(SERVER_SIDE)); fprintf(fp, "\tsize_t decode(void *buf, size_t bufsize, IOStream *stream);\n"); fprintf(fp, "\n};\n\n"); fprintf(fp, "#endif // GUARD_%s\n", classname.c_str()); fclose(fp); return 0; }
int ApiGen::genContextImpl(const std::string &filename, SideType side) { FILE *fp = fopen(filename.c_str(), "wt"); if (fp == NULL) { perror(filename.c_str()); return -1; } printHeader(fp); std::string classname = m_basename + "_" + sideString(side) + "_context_t"; size_t n = size(); fprintf(fp, "\n\n#include <string.h>\n"); fprintf(fp, "#include \"%s_%s_context.h\"\n\n\n", m_basename.c_str(), sideString(side)); fprintf(fp, "#include <stdio.h>\n\n"); // init function; fprintf(fp, "int %s::initDispatchByName(void *(*getProc)(const char *, void *userData), void *userData)\n{\n", classname.c_str()); for (size_t i = 0; i < n; i++) { EntryPoint *e = &at(i); fprintf(fp, "\t%s = (%s_%s_proc_t) getProc(\"%s\", userData);\n", e->name().c_str(), e->name().c_str(), sideString(side), e->name().c_str()); } fprintf(fp, "\treturn 0;\n"); fprintf(fp, "}\n\n"); fclose(fp); return 0; }
int ApiGen::genFuncTable(const std::string &filename, SideType side) { FILE *fp = fopen(filename.c_str(), "wt"); if (fp == NULL) { perror(filename.c_str()); return -1; } printHeader(fp); fprintf(fp, "#ifndef __%s_%s_ftable_t_h\n", m_basename.c_str(), sideString(side)); fprintf(fp, "#define __%s_%s_ftable_t_h\n", m_basename.c_str(), sideString(side)); fprintf(fp, "\n\n"); fprintf(fp, "static const struct _%s_funcs_by_name {\n", m_basename.c_str()); fprintf(fp, "\tconst char *name;\n" \ "\tvoid *proc;\n" \ "} %s_funcs_by_name[] = {\n", m_basename.c_str()); for (size_t i = 0; i < size(); i++) { EntryPoint *e = &at(i); if (e->notApi()) continue; fprintf(fp, "\t{\"%s\", (void*)%s},\n", e->name().c_str(), e->name().c_str()); } fprintf(fp, "};\n"); fprintf(fp, "static const int %s_num_funcs = sizeof(%s_funcs_by_name) / sizeof(struct _%s_funcs_by_name);\n", m_basename.c_str(), m_basename.c_str(), m_basename.c_str()); fprintf(fp, "\n\n#endif\n"); return 0; }
int ApiGen::genProcTypes(const std::string &filename, SideType side) { FILE *fp = fopen(filename.c_str(), "wt"); if (fp == NULL) { perror(filename.c_str()); return -1; } printHeader(fp); const char* basename = m_basename.c_str(); fprintf(fp, "#ifndef __%s_%s_proc_t_h\n", basename, sideString(side)); fprintf(fp, "#define __%s_%s_proc_t_h\n", basename, sideString(side)); fprintf(fp, "\n\n"); fprintf(fp, "\n#include \"%s_types.h\"\n",basename); fprintf(fp, "#ifndef %s_APIENTRY\n",basename); fprintf(fp, "#define %s_APIENTRY \n",basename); fprintf(fp, "#endif\n"); for (size_t i = 0; i < size(); i++) { EntryPoint *e = &at(i); fprintf(fp, "typedef "); e->retval().printType(fp); fprintf(fp, " (%s_APIENTRY *%s_%s_proc_t) (", basename, e->name().c_str(), sideString(side)); if (side == CLIENT_SIDE) { fprintf(fp, "void * ctx"); } if (e->customDecoder() && side == SERVER_SIDE) { fprintf(fp, "void *ctx"); } VarsArray & evars = e->vars(); size_t n = evars.size(); for (size_t j = 0; j < n; j++) { if (!evars[j].isVoid()) { if (j != 0 || side == CLIENT_SIDE || (side == SERVER_SIDE && e->customDecoder())) fprintf(fp, ", "); evars[j].printType(fp); } } fprintf(fp, ");\n"); } fprintf(fp, "\n\n#endif\n"); return 0; }
/// Add BC_PRESSURE boundary conditions to all faces on a given side. /// The grid must have a logical cartesian structure, and grid /// faces must be tagged (i.e. grid.cell_facetag must be /// non-null). Only the set of faces adjacent to cells with /// minimum/maximum I/J/K coordinate (depending on side) are /// considered. void FlowBCManager::pressureSide(const UnstructuredGrid& grid, const Side side, const double pressure) { std::vector<int> faces; findSideFaces(grid, side, faces); int ok = flow_conditions_append_multi(BC_PRESSURE, faces.size(), &faces[0], pressure, bc_); if (!ok) { THROW("Failed to append pressure boundary conditions for side " << sideString(side)); } }
int ApiGen::genContext(const std::string & filename, SideType side) { FILE *fp = fopen(filename.c_str(), "wt"); if (fp == NULL) { perror(filename.c_str()); return -1; } printHeader(fp); fprintf(fp, "#ifndef __%s_%s_context_t_h\n", m_basename.c_str(), sideString(side)); fprintf(fp, "#define __%s_%s_context_t_h\n", m_basename.c_str(), sideString(side)); // fprintf(fp, "\n#include \"%s_types.h\"\n", m_basename.c_str()); fprintf(fp, "\n#include \"%s_%s_proc.h\"\n", m_basename.c_str(), sideString(side)); StringVec & contextHeaders = side == CLIENT_SIDE ? m_clientContextHeaders : m_serverContextHeaders; for (size_t i = 0; i < contextHeaders.size(); i++) { fprintf(fp, "#include %s\n", contextHeaders[i].c_str()); } fprintf(fp, "\n"); fprintf(fp, "\nstruct %s_%s_context_t {\n\n", m_basename.c_str(), sideString(side)); for (size_t i = 0; i < size(); i++) { EntryPoint *e = &at(i); fprintf(fp, "\t%s_%s_proc_t %s;\n", e->name().c_str(), sideString(side), e->name().c_str()); } // virtual destructor fprintf(fp, "\t virtual ~%s_%s_context_t() {}\n", m_basename.c_str(), sideString(side)); // accessor if (side == CLIENT_SIDE || side == WRAPPER_SIDE) { fprintf(fp, "\n\ttypedef %s_%s_context_t *CONTEXT_ACCESSOR_TYPE(void);\n", m_basename.c_str(), sideString(side)); fprintf(fp, "\tstatic void setContextAccessor(CONTEXT_ACCESSOR_TYPE *f);\n"); } // init function fprintf(fp, "\tint initDispatchByName( void *(*getProc)(const char *name, void *userData), void *userData);\n"); //client site set error virtual func if (side == CLIENT_SIDE) { fprintf(fp, "\tvirtual void setError(unsigned int error){ (void)error; };\n"); fprintf(fp, "\tvirtual unsigned int getError(){ return 0; };\n"); } fprintf(fp, "};\n"); fprintf(fp, "\n#endif\n"); fclose(fp); return 0; }
/// Add BC_FLUX_TOTVOL boundary conditions to all faces on a given side. /// The grid must have a logical cartesian structure, and grid /// faces must be tagged (i.e. grid.cell_facetag must be /// non-null). Only the set of faces adjacent to cells with /// minimum/maximum I/J/K coordinate (depending on side) are /// considered. /// The flux specified is taken to be the total flux through /// the side, each individual face receiving a part of the /// total flux in proportion to its area, so that all faces /// will have identical normal velocities. void FlowBCManager::fluxSide(const UnstructuredGrid& grid, const Side side, const double flux) { // Find side faces. std::vector<int> faces; findSideFaces(grid, side, faces); // Compute total area of faces. double tot_area = 0.0; for (int fi = 0; fi < int(faces.size()); ++fi) { tot_area += grid.face_areas[faces[fi]]; } // Append flux conditions for all the faces individually. for (int fi = 0; fi < int(faces.size()); ++fi) { const double face_flux = flux * grid.face_areas[faces[fi]] / tot_area; int ok = flow_conditions_append(BC_FLUX_TOTVOL, faces[fi], face_flux, bc_); if (!ok) { THROW("Failed to append flux boundary conditions for face " << faces[fi] << " on side " << sideString(side)); } } }
int ApiGen::genEncoderImpl(const std::string &filename) { FILE *fp = fopen(filename.c_str(), "wt"); if (fp == NULL) { perror(filename.c_str()); return -1; } printHeader(fp); fprintf(fp, "\n\n#include <string.h>\n"); fprintf(fp, "#include \"%s_opcodes.h\"\n\n", m_basename.c_str()); fprintf(fp, "#include \"%s_enc.h\"\n\n\n", m_basename.c_str()); fprintf(fp, "#include <stdio.h>\n\n"); fprintf(fp, "namespace {\n\n"); // unsupport printout fprintf(fp, "void enc_unsupported()\n" "{\n" "\tALOGE(\"Function is unsupported\\n\");\n" "}\n\n"); // entry points; std::string classname = m_basename + "_encoder_context_t"; size_t n = size(); for (size_t i = 0; i < n; i++) { EntryPoint *e = &at(i); if (e->unsupported()) continue; e->print(fp, true, "_enc", /* classname + "::" */"", "void *self"); fprintf(fp, "{\n"); // fprintf(fp, "\n\tDBG(\">>>> %s\\n\");\n", e->name().c_str()); fprintf(fp, "\n\t%s *ctx = (%s *)self;\n", classname.c_str(), classname.c_str()); fprintf(fp, "\tIOStream *stream = ctx->m_stream;\n\n"); VarsArray & evars = e->vars(); size_t maxvars = evars.size(); size_t j; char buff[256]; // Define the __size_XXX variables that contain the size of data // associated with pointers. for (j = 0; j < maxvars; j++) { Var& var = evars[j]; if (!var.isPointer()) continue; const char* varname = var.name().c_str(); fprintf(fp, "\tconst unsigned int __size_%s = ", varname); getVarEncodingSizeExpression(var, e, buff, sizeof(buff)); fprintf(fp, "%s;\n", buff); } #if WITH_LARGE_SUPPORT // We need to take care of 'isLarge' variable in a special way // Anything before an isLarge variable can be packed into a single // buffer, which is then commited. Each isLarge variable is a pointer // to data that can be written to directly through the pipe, which // will be instant when using a QEMU pipe size_t nvars = 0; size_t npointers = 0; // First, compute the total size, 8 bytes for the opcode + payload size fprintf(fp, "\t unsigned char *ptr;\n"); fprintf(fp, "\t const size_t packetSize = 8"); for (j = 0; j < maxvars; j++) { fprintf(fp, " + "); npointers += writeVarEncodingSize(evars[j], fp); } if (npointers > 0) { fprintf(fp, " + %zu*4", npointers); } fprintf(fp, ";\n"); // We need to divide the packet into fragments. Each fragment contains // either copied arguments to a temporary buffer, or direct writes for // large variables. // // The first fragment must also contain the opcode+payload_size // nvars = 0; while (nvars < maxvars || maxvars == 0) { // Skip over non-large fields for (j = nvars; j < maxvars; j++) { if (evars[j].isLarge()) break; } // Write a fragment if needed. if (nvars == 0 || j > nvars) { const char* plus = ""; if (nvars == 0 && j == maxvars) { // Simple shortcut for the common case where we don't have large variables; fprintf(fp, "\tptr = stream->alloc(packetSize);\n"); } else { // allocate buffer from the stream until the first large variable fprintf(fp, "\tptr = stream->alloc("); plus = ""; if (nvars == 0) { fprintf(fp,"8"); plus = " + "; } if (j > nvars) { npointers = 0; for (j = nvars; j < maxvars && !evars[j].isLarge(); j++) { fprintf(fp, "%s", plus); plus = " + "; npointers += writeVarEncodingSize(evars[j], fp); } if (npointers > 0) { fprintf(fp, "%s%zu*4", plus, npointers); plus = " + "; } } fprintf(fp,");\n"); } // encode packet header if needed. if (nvars == 0) { fprintf(fp, "\tint tmp = OP_%s;memcpy(ptr, &tmp, 4); ptr += 4;\n", e->name().c_str()); fprintf(fp, "\tmemcpy(ptr, &packetSize, 4); ptr += 4;\n\n"); } if (maxvars == 0) break; // encode non-large fields in this fragment for (j = nvars; j < maxvars && !evars[j].isLarge(); j++) { writeVarEncodingExpression(evars[j],fp); } // Ensure the fragment is commited if it is followed by a large variable if (j < maxvars) { fprintf(fp, "\tstream->flush();\n"); } } // If we have one or more large variables, write them directly. // As size + data for ( ; j < maxvars && evars[j].isLarge(); j++) { writeVarLargeEncodingExpression(evars[j], fp); } nvars = j; } #else /* !WITH_LARGE_SUPPORT */ size_t nvars = evars.size(); size_t npointers = 0; fprintf(fp, "\t const size_t packetSize = 8"); for (size_t j = 0; j < nvars; j++) { npointers += getVarEncodingSizeExpression(evars[j],e,buff,sizeof(buff)); fprintf(fp, " + %s", buff); } fprintf(fp, " + %u * 4;\n", (unsigned int) npointers); // allocate buffer from the stream; fprintf(fp, "\t unsigned char *ptr = stream->alloc(packetSize);\n\n"); // encode into the stream; fprintf(fp, "\tint tmp = OP_%s; memcpy(ptr, &tmp, 4); ptr += 4;\n", e->name().c_str()); fprintf(fp, "\tmemcpy(ptr, &packetSize, 4); ptr += 4;\n\n"); // out variables for (size_t j = 0; j < nvars; j++) { writeVarEncodingExpression(evars[j], fp); } #endif /* !WITH_LARGE_SUPPORT */ // in variables; for (size_t j = 0; j < nvars; j++) { if (evars[j].isPointer()) { Var::PointerDir dir = evars[j].pointerDir(); if (dir == Var::POINTER_INOUT || dir == Var::POINTER_OUT) { const char* varname = evars[j].name().c_str(); if (evars[j].nullAllowed()) { fprintf(fp, "\tif (%s != NULL) ",varname); } else { fprintf(fp, "\t"); } fprintf(fp, "stream->readback(%s, __size_%s);\n", varname, varname); } } } //XXX fprintf(fp, "\n\tDBG(\"<<<< %s\\n\");\n", e->name().c_str()); // todo - return value for pointers if (e->retval().isPointer()) { fprintf(stderr, "WARNING: %s : return value of pointer is unsupported\n", e->name().c_str()); if (e->flushOnEncode()) { fprintf(fp, "\tstream->flush();\n"); } fprintf(fp, "\t return NULL;\n"); } else if (e->retval().type()->name() != "void") { fprintf(fp, "\n\t%s retval;\n", e->retval().type()->name().c_str()); fprintf(fp, "\tstream->readback(&retval, %u);\n",(unsigned) e->retval().type()->bytes()); fprintf(fp, "\treturn retval;\n"); } else if (e->flushOnEncode()) { fprintf(fp, "\tstream->flush();\n"); } fprintf(fp, "}\n\n"); } fprintf(fp, "} // namespace\n\n"); // constructor fprintf(fp, "%s::%s(IOStream *stream)\n{\n", classname.c_str(), classname.c_str()); fprintf(fp, "\tm_stream = stream;\n\n"); for (size_t i = 0; i < n; i++) { EntryPoint *e = &at(i); if (e->unsupported()) { fprintf(fp, "\tthis->%s = (%s_%s_proc_t) &enc_unsupported;\n", e->name().c_str(), e->name().c_str(), sideString(CLIENT_SIDE)); } else { fprintf(fp, "\tthis->%s = &%s_enc;\n", e->name().c_str(), e->name().c_str()); } } fprintf(fp, "}\n\n"); fclose(fp); return 0; }
int ApiGen::genEntryPoints(const std::string & filename, SideType side) { if (side != CLIENT_SIDE && side != WRAPPER_SIDE) { fprintf(stderr, "Entry points are only defined for Client and Wrapper components\n"); return -999; } FILE *fp = fopen(filename.c_str(), "wt"); if (fp == NULL) { perror(filename.c_str()); return errno; } printHeader(fp); fprintf(fp, "#include <stdio.h>\n"); fprintf(fp, "#include <stdlib.h>\n"); fprintf(fp, "#include \"%s_%s_context.h\"\n", m_basename.c_str(), sideString(side)); fprintf(fp, "\n"); fprintf(fp, "#ifndef GL_TRUE\n"); fprintf(fp, "extern \"C\" {\n"); for (size_t i = 0; i < size(); i++) { fprintf(fp, "\t"); at(i).print(fp, false); fprintf(fp, ";\n"); } fprintf(fp, "};\n\n"); fprintf(fp, "#endif\n"); fprintf(fp, "#ifndef GET_CONTEXT\n"); fprintf(fp, "static %s_%s_context_t::CONTEXT_ACCESSOR_TYPE *getCurrentContext = NULL;\n", m_basename.c_str(), sideString(side)); fprintf(fp, "void %s_%s_context_t::setContextAccessor(CONTEXT_ACCESSOR_TYPE *f) { getCurrentContext = f; }\n", m_basename.c_str(), sideString(side)); fprintf(fp, "#define GET_CONTEXT %s_%s_context_t * ctx = getCurrentContext()\n", m_basename.c_str(), sideString(side)); fprintf(fp, "#endif\n\n"); for (size_t i = 0; i < size(); i++) { EntryPoint *e = &at(i); e->print(fp); fprintf(fp, "{\n"); fprintf(fp, "\tGET_CONTEXT;\n"); bool shouldReturn = !e->retval().isVoid(); bool shouldCallWithContext = (side == CLIENT_SIDE); //param check if (shouldCallWithContext) { for (size_t j=0; j<e->vars().size(); j++) { if (e->vars()[j].paramCheckExpression() != "") fprintf(fp, "\t%s\n", e->vars()[j].paramCheckExpression().c_str()); } } fprintf(fp, "\t%sctx->%s(%s", shouldReturn ? "return " : "", e->name().c_str(), shouldCallWithContext ? "ctx" : ""); size_t nvars = e->vars().size(); for (size_t j = 0; j < nvars; j++) { if (!e->vars()[j].isVoid()) { fprintf(fp, "%s %s", j != 0 || shouldCallWithContext ? "," : "", e->vars()[j].name().c_str()); } } fprintf(fp, ");\n"); fprintf(fp, "}\n\n"); } fclose(fp); return 0; }