aboutsummaryrefslogtreecommitdiffstats
path: root/emulator/opengl/host/tools/emugen/ApiGen.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'emulator/opengl/host/tools/emugen/ApiGen.cpp')
-rw-r--r--emulator/opengl/host/tools/emugen/ApiGen.cpp1232
1 files changed, 0 insertions, 1232 deletions
diff --git a/emulator/opengl/host/tools/emugen/ApiGen.cpp b/emulator/opengl/host/tools/emugen/ApiGen.cpp
deleted file mode 100644
index 8be0270..0000000
--- a/emulator/opengl/host/tools/emugen/ApiGen.cpp
+++ /dev/null
@@ -1,1232 +0,0 @@
-/*
-* Copyright (C) 2011 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
-#include "ApiGen.h"
-#include "EntryPoint.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include "strUtils.h"
-#include <errno.h>
-#include <sys/types.h>
-
-/* Define this to 1 to enable support for the 'isLarge' variable flag
- * that instructs the encoder to send large data buffers by a direct
- * write through the pipe (i.e. without copying it into a temporary
- * buffer. This has definite performance benefits when using a QEMU Pipe.
- *
- * Set to 0 otherwise.
- */
-#define WITH_LARGE_SUPPORT 1
-
-// Set to 1 to ensure buffers passed to/from EGL/GL are properly aligned.
-// This prevents crashes with certain backends (e.g. OSMesa).
-#define USE_ALIGNED_BUFFERS 1
-
-EntryPoint * ApiGen::findEntryByName(const std::string & name)
-{
- EntryPoint * entry = NULL;
-
- size_t n = this->size();
- for (size_t i = 0; i < n; i++) {
- if (at(i).name() == name) {
- entry = &(at(i));
- break;
- }
- }
- return entry;
-}
-
-void ApiGen::printHeader(FILE *fp) const
-{
- fprintf(fp, "// Generated Code - DO NOT EDIT !!\n");
- fprintf(fp, "// generated by 'emugen'\n");
-}
-
-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;
-}
-
-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::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;
-}
-
-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;
-}
-
-
-int ApiGen::genOpcodes(const std::string &filename)
-{
- FILE *fp = fopen(filename.c_str(), "wt");
- if (fp == NULL) {
- perror(filename.c_str());
- return errno;
- }
-
- printHeader(fp);
- fprintf(fp, "#ifndef __GUARD_%s_opcodes_h_\n", m_basename.c_str());
- fprintf(fp, "#define __GUARD_%s_opcodes_h_\n\n", m_basename.c_str());
- for (size_t i = 0; i < size(); i++) {
- fprintf(fp, "#define OP_%s \t\t\t\t\t%u\n", at(i).name().c_str(), (unsigned int)i + m_baseOpcode);
- }
- fprintf(fp, "#define OP_last \t\t\t\t\t%u\n", (unsigned int)size() + m_baseOpcode);
- fprintf(fp,"\n\n#endif\n");
- fclose(fp);
- return 0;
-
-}
-int ApiGen::genAttributesTemplate(const std::string &filename )
-{
- FILE *fp = fopen(filename.c_str(), "wt");
- if (fp == NULL) {
- perror(filename.c_str());
- return -1;
- }
-
- for (size_t i = 0; i < size(); i++) {
- if (at(i).hasPointers()) {
- fprintf(fp, "#");
- at(i).print(fp);
- fprintf(fp, "%s\n\n", at(i).name().c_str());
- }
- }
- fclose(fp);
- return 0;
-}
-
-int ApiGen::genEncoderHeader(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 + "_encoder_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(CLIENT_SIDE));
-
- for (size_t i = 0; i < m_encoderHeaders.size(); i++) {
- fprintf(fp, "#include %s\n", m_encoderHeaders[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(CLIENT_SIDE));
- fprintf(fp, "\tIOStream *m_stream;\n\n");
-
- fprintf(fp, "\t%s(IOStream *stream);\n", classname.c_str());
- fprintf(fp, "};\n\n");
-
- fprintf(fp, "#endif // GUARD_%s", classname.c_str());
-
- fclose(fp);
- return 0;
-}
-
-// Format the byte length expression for a given variable into a user-provided buffer
-// If the variable type is not a pointer, this is simply its size as a decimal constant
-// If the variable is a pointer, this will be an expression provided by the .attrib file
-// through the 'len' attribute.
-//
-// Returns 1 if the variable is a pointer, 0 otherwise
-//
-static int getVarEncodingSizeExpression(Var& var, EntryPoint* e, char* buff, size_t bufflen)
-{
- int ret = 0;
- if (!var.isPointer()) {
- snprintf(buff, bufflen, "%u", (unsigned int) var.type()->bytes());
- } else {
- ret = 1;
- const char* lenExpr = var.lenExpression().c_str();
- const char* varname = var.name().c_str();
- if (e != NULL && lenExpr[0] == '\0') {
- fprintf(stderr, "%s: data len is undefined for '%s'\n",
- e->name().c_str(), varname);
- }
- if (var.nullAllowed()) {
- snprintf(buff, bufflen, "((%s != NULL) ? %s : 0)", varname, lenExpr);
- } else {
- snprintf(buff, bufflen, "%s", lenExpr);
- }
- }
- return ret;
-}
-
-static int writeVarEncodingSize(Var& var, FILE* fp)
-{
- int ret = 0;
- if (!var.isPointer()) {
- fprintf(fp, "%u", (unsigned int) var.type()->bytes());
- } else {
- ret = 1;
- fprintf(fp, "__size_%s", var.name().c_str());
- }
- return ret;
-}
-
-
-
-static void writeVarEncodingExpression(Var& var, FILE* fp)
-{
- const char* varname = var.name().c_str();
-
- if (var.isPointer()) {
- // encode a pointer header
- fprintf(fp, "\t*(unsigned int *)(ptr) = __size_%s; ptr += 4;\n", varname);
-
- Var::PointerDir dir = var.pointerDir();
- if (dir == Var::POINTER_INOUT || dir == Var::POINTER_IN) {
- if (var.nullAllowed()) {
- fprintf(fp, "\tif (%s != NULL) ", varname);
- } else {
- fprintf(fp, "\t");
- }
-
- if (var.packExpression().size() != 0) {
- fprintf(fp, "%s;", var.packExpression().c_str());
- } else {
- fprintf(fp, "memcpy(ptr, %s, __size_%s);",
- varname, varname);
- }
-
- fprintf(fp, "ptr += __size_%s;\n", varname);
- }
- } else {
- // encode a non pointer variable
- if (!var.isVoid()) {
- fprintf(fp, "\t\tmemcpy(ptr, &%s, %u); ptr += %u;\n",
- varname,
- (unsigned) var.type()->bytes(),
- (unsigned) var.type()->bytes());
- }
- }
-}
-
-#if WITH_LARGE_SUPPORT
-static void writeVarLargeEncodingExpression(Var& var, FILE* fp)
-{
- const char* varname = var.name().c_str();
-
- fprintf(fp, "\tstream->writeFully(&__size_%s,4);\n", varname);
- if (var.nullAllowed()) {
- fprintf(fp, "\tif (%s != NULL) ", varname);
- } else {
- fprintf(fp, "\t");
- }
- if (var.writeExpression() != "") {
- fprintf(fp, "%s", var.writeExpression().c_str());
- } else {
- fprintf(fp, "stream->writeFully(%s, __size_%s)", varname, varname);
- }
- fprintf(fp, ";\n");
-}
-#endif /* WITH_LARGE_SUPPORT */
-
-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::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::genDecoderImpl(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";
-
- size_t n = size();
-
- fprintf(fp, "\n\n#include <string.h>\n");
- fprintf(fp, "#include \"%s_opcodes.h\"\n\n", m_basename.c_str());
- fprintf(fp, "#include \"%s_dec.h\"\n\n\n", m_basename.c_str());
- fprintf(fp, "#include \"ProtocolUtils.h\"\n\n");
- fprintf(fp, "#include <stdio.h>\n\n");
- fprintf(fp, "typedef unsigned int tsize_t; // Target \"size_t\", which is 32-bit for now. It may or may not be the same as host's size_t when emugen is compiled.\n\n");
-
- // helper macros
- fprintf(fp,
- "#ifdef DEBUG_PRINTOUT\n"
- "# define DEBUG(...) fprintf(stderr, __VA_ARGS__)\n"
- "#else\n"
- "# define DEBUG(...) ((void)0)\n"
- "#endif\n\n");
-
- fprintf(fp,
- "#ifdef CHECK_GLERROR\n"
- "# define SET_LASTCALL(name) sprintf(lastCall, #name)\n"
- "#else\n"
- "# define SET_LASTCALL(name) ((void)0)\n"
- "#endif\n\n");
-
- // helper templates
- fprintf(fp, "using namespace emugl;\n\n");
-
- // decoder switch;
- fprintf(fp, "size_t %s::decode(void *buf, size_t len, IOStream *stream)\n{\n", classname.c_str());
- fprintf(fp,
- " \n\
-\tsize_t pos = 0;\n\
-\tif (len < 8) return pos; \n\
-\tunsigned char *ptr = (unsigned char *)buf;\n\
-\tbool unknownOpcode = false; \n\
-#ifdef CHECK_GL_ERROR \n\
-\tchar lastCall[256] = {0}; \n\
-#endif \n\
-\twhile ((len - pos >= 8) && !unknownOpcode) { \n\
-\t\tuint32_t opcode = *(uint32_t *)ptr; \n\
-\t\tsize_t packetLen = *(uint32_t *)(ptr + 4);\n\
-\t\tif (len - pos < packetLen) return pos; \n\
-\t\tswitch(opcode) {\n");
-
- for (size_t f = 0; f < n; f++) {
- enum Pass_t {
- PASS_FIRST = 0,
- PASS_VariableDeclarations = PASS_FIRST,
- PASS_TmpBuffAlloc,
- PASS_MemAlloc,
- PASS_DebugPrint,
- PASS_FunctionCall,
- PASS_FlushOutput,
- PASS_Epilog,
- PASS_LAST };
- EntryPoint *e = &at(f);
-
- // construct a printout string;
- std::string printString = "";
- for (size_t i = 0; i < e->vars().size(); i++) {
- Var *v = &e->vars()[i];
- if (!v->isVoid()) printString += (v->isPointer() ? "%p(%u)" : v->type()->printFormat()) + " ";
- }
- printString += "";
- // TODO - add for return value;
-
- fprintf(fp, "\t\tcase OP_%s: {\n", e->name().c_str());
-
- bool totalTmpBuffExist = false;
- std::string totalTmpBuffOffset = "0";
- std::string *tmpBufOffset = new std::string[e->vars().size()];
-
- // construct retval type string
- std::string retvalType;
- if (!e->retval().isVoid()) {
- retvalType = e->retval().type()->name();
- }
-
- for (int pass = PASS_FIRST; pass < PASS_LAST; pass++) {
- if (pass == PASS_FunctionCall &&
- !e->retval().isVoid() &&
- !e->retval().isPointer()) {
- fprintf(fp, "\t\t\t*(%s *)(&tmpBuf[%s]) = ", retvalType.c_str(),
- totalTmpBuffOffset.c_str());
- }
-
-
- if (pass == PASS_FunctionCall) {
- fprintf(fp, "\t\t\tthis->%s(", e->name().c_str());
- if (e->customDecoder()) {
- fprintf(fp, "this"); // add a context to the call
- }
- } else if (pass == PASS_DebugPrint) {
- fprintf(fp,
- "\t\t\tDEBUG(\"%s(%%p): %s(%s)\\n\", stream",
- m_basename.c_str(),
- e->name().c_str(),
- printString.c_str());
- if (e->vars().size() > 0 && !e->vars()[0].isVoid()) {
- fprintf(fp, ",");
- }
- }
-
- std::string varoffset = "8"; // skip the header
- VarsArray & evars = e->vars();
- // allocate memory for out pointers;
- for (size_t j = 0; j < evars.size(); j++) {
- Var *v = & evars[j];
- if (v->isVoid()) {
- continue;
- }
- const char* var_name = v->name().c_str();
- const char* var_type_name = v->type()->name().c_str();
- const unsigned var_type_bytes = v->type()->bytes();
-
- if ((pass == PASS_FunctionCall) &&
- (j != 0 || e->customDecoder())) {
- fprintf(fp, ", ");
- }
- if (pass == PASS_DebugPrint && j != 0) {
- fprintf(fp, ", ");
- }
-
- if (!v->isPointer()) {
- if (pass == PASS_VariableDeclarations) {
- fprintf(fp,
- "\t\t\t%s var_%s = Unpack<%s,uint%u_t>(ptr + %s);\n",
- var_type_name,
- var_name,
- var_type_name,
- var_type_bytes * 8U,
- varoffset.c_str());
- }
-
- if (pass == PASS_FunctionCall ||
- pass == PASS_DebugPrint) {
- fprintf(fp, "var_%s", var_name);
- }
- varoffset += " + " + toString(var_type_bytes);
- continue;
- }
-
- if (pass == PASS_VariableDeclarations) {
- fprintf(fp,
- "\t\t\tuint32_t size_%s __attribute__((unused)) = Unpack<uint32_t,uint32_t>(ptr + %s);\n",
- var_name,
- varoffset.c_str());
- }
-
- if (v->pointerDir() == Var::POINTER_IN ||
- v->pointerDir() == Var::POINTER_INOUT) {
- if (pass == PASS_VariableDeclarations) {
-#if USE_ALIGNED_BUFFERS
- fprintf(fp,
- "\t\t\tInputBuffer inptr_%s(ptr + %s + 4, size_%s);\n",
- var_name,
- varoffset.c_str(),
- var_name);
- }
- if (pass == PASS_FunctionCall) {
- if (v->nullAllowed()) {
- fprintf(fp,
- "size_%s == 0 ? NULL : (%s)(inptr_%s.get())",
- var_name,
- var_type_name,
- var_name);
- } else {
- fprintf(fp,
- "(%s)(inptr_%s.get())",
- var_type_name,
- var_name);
- }
- } else if (pass == PASS_DebugPrint) {
- fprintf(fp,
- "(%s)(inptr_%s.get()), size_%s",
- var_type_name,
- var_name,
- var_name);
- }
-#else // !USE_ALIGNED_BUFFERS
- fprintf(fp,
- "unsigned char *inptr_%s = (ptr + %s + 4);\n",
- var_name,
- varoffset.c_str());
- }
- if (pass == PASS_FunctionCall) {
- if (v->nullAllowed()) {
- fprintf(fp,
- "size_%s == 0 ? NULL : (%s)(inptr_%s)",
- var_name,
- var_type_name,
- var_name);
- } else {
- fprintf(fp,
- "(%s)(inptr_%s)",
- var_type_name,
- var_name);
- }
- } else if (pass == PASS_DebugPrint) {
- fprintf(fp,
- "(%s)(inptr_%s), size_%s",
- var_type_name,
- var_name,
- var_name);
- }
-#endif // !USE_ALIGNED_BUFFERS
- varoffset += " + 4 + size_";
- varoffset += var_name;
- } else { // out pointer;
- if (pass == PASS_TmpBuffAlloc) {
- if (!totalTmpBuffExist) {
- fprintf(fp,
- "\t\t\tsize_t totalTmpSize = size_%s;\n",
- var_name);
- } else {
- fprintf(fp,
- "\t\t\ttotalTmpSize += size_%s;\n",
- var_name);
- }
- tmpBufOffset[j] = totalTmpBuffOffset;
- totalTmpBuffOffset += " + size_";
- totalTmpBuffOffset += var_name;
- totalTmpBuffExist = true;
- } else if (pass == PASS_MemAlloc) {
-#if USE_ALIGNED_BUFFERS
- fprintf(fp,
- "\t\t\tOutputBuffer outptr_%s(&tmpBuf[%s], size_%s);\n",
- var_name,
- tmpBufOffset[j].c_str(),
- var_name);
- } else if (pass == PASS_FunctionCall) {
- if (v->nullAllowed()) {
- fprintf(fp,
- "size_%s == 0 ? NULL : (%s)(outptr_%s.get())",
- var_name,
- var_type_name,
- var_name);
- } else {
- fprintf(fp,
- "(%s)(outptr_%s.get())",
- var_type_name,
- var_name);
- }
- } else if (pass == PASS_DebugPrint) {
- fprintf(fp,
- "(%s)(outptr_%s.get()), size_%s",
- var_type_name,
- var_name,
- var_name);
- }
- if (pass == PASS_FlushOutput) {
- fprintf(fp,
- "\t\t\toutptr_%s.flush();\n",
- var_name);
- }
-#else // !USE_ALIGNED_BUFFERS
- fprintf(fp,
- "\t\t\tunsigned char *outptr_%s = &tmpBuf[%s];\n",
- var_name,
- tmpBufOffset[j].c_str());
- fprintf(fp,
- "\t\t\tmemset(outptr_%s, 0, %s);\n",
- var_name,
- toString(v->type()->bytes()).c_str());
- } else if (pass == PASS_FunctionCall) {
- if (v->nullAllowed()) {
- fprintf(fp,
- "size_%s == 0 ? NULL : (%s)(outptr_%s)",
- var_name,
- var_type_name,
- var_name);
- } else {
- fprintf(fp,
- "(%s)(outptr_%s)",
- var_type_name,
- var_name);
- }
- } else if (pass == PASS_DebugPrint) {
- fprintf(fp,
- "(%s)(outptr_%s), size_%s",
- var_type_name,
- var_name,
- varoffset.c_str());
- }
-#endif // !USE_ALIGNED_BUFFERS
- varoffset += " + 4";
- }
- }
-
- if (pass == PASS_FunctionCall ||
- pass == PASS_DebugPrint) {
- fprintf(fp, ");\n");
- }
-
- if (pass == PASS_TmpBuffAlloc) {
- if (!e->retval().isVoid() && !e->retval().isPointer()) {
- if (!totalTmpBuffExist)
- fprintf(fp,
- "\t\t\tsize_t totalTmpSize = sizeof(%s);\n",
- retvalType.c_str());
- else
- fprintf(fp,
- "\t\t\ttotalTmpSize += sizeof(%s);\n",
- retvalType.c_str());
-
- totalTmpBuffExist = true;
- }
- if (totalTmpBuffExist) {
- fprintf(fp,
- "\t\t\tunsigned char *tmpBuf = stream->alloc(totalTmpSize);\n");
- }
- }
-
- if (pass == PASS_Epilog) {
- // send back out pointers data as well as retval
- if (totalTmpBuffExist) {
- fprintf(fp, "\t\t\tstream->flush();\n");
- }
- }
-
- } // pass;
- fprintf(fp, "\t\t\tSET_LASTCALL(\"%s\");\n", e->name().c_str());
- fprintf(fp, "\t\t\tbreak;\n");
- fprintf(fp, "\t\t}\n");
-
- delete [] tmpBufOffset;
- }
- fprintf(fp, "\t\t\tdefault:\n");
- fprintf(fp, "\t\t\t\tunknownOpcode = true;\n");
- fprintf(fp, "\t\t} //switch\n");
- if (strstr(m_basename.c_str(), "gl")) {
- fprintf(fp, "#ifdef CHECK_GL_ERROR\n");
- fprintf(fp, "\tint err = lastCall[0] ? this->glGetError() : GL_NO_ERROR;\n");
- fprintf(fp, "\tif (err) fprintf(stderr, \"%s Error: 0x%%X in %%s\\n\", err, lastCall);\n", m_basename.c_str());
- fprintf(fp, "#endif\n");
- }
-
- fprintf(fp, "\t\tif (!unknownOpcode) {\n");
- fprintf(fp, "\t\t\tpos += packetLen;\n");
- fprintf(fp, "\t\t\tptr += packetLen;\n");
- fprintf(fp, "\t\t}\n");
- fprintf(fp, "\t} // while\n");
- fprintf(fp, "\treturn pos;\n");
- fprintf(fp, "}\n");
-
- fclose(fp);
- return 0;
-}
-
-int ApiGen::readSpec(const std::string & filename)
-{
- FILE *specfp = fopen(filename.c_str(), "rt");
- if (specfp == NULL) {
- return -1;
- }
-
- char line[1000];
- unsigned int lc = 0;
- while (fgets(line, sizeof(line), specfp) != NULL) {
- lc++;
- EntryPoint ref;
- if (ref.parse(lc, std::string(line))) {
- push_back(ref);
- updateMaxEntryPointsParams(ref.vars().size());
- }
- }
- fclose(specfp);
- return 0;
-}
-
-int ApiGen::readAttributes(const std::string & attribFilename)
-{
- enum { ST_NAME, ST_ATT } state;
-
- FILE *fp = fopen(attribFilename.c_str(), "rt");
- if (fp == NULL) {
- perror(attribFilename.c_str());
- return -1;
- }
- char buf[1000];
-
- state = ST_NAME;
- EntryPoint *currentEntry = NULL;
- size_t lc = 0;
- bool globalAttributes = false;
- while (fgets(buf, sizeof(buf), fp) != NULL) {
- lc++;
- std::string line(buf);
- if (line.size() == 0) continue; // could that happen?
-
- if (line.at(0) == '#') continue; // comment
-
- size_t first = line.find_first_not_of(" \t\n");
- if (state == ST_ATT && (first == std::string::npos || first == 0)) state = ST_NAME;
-
- line = trim(line);
- if (line.size() == 0 || line.at(0) == '#') continue;
-
- switch(state) {
- case ST_NAME:
- if (line == "GLOBAL") {
- globalAttributes = true;
- } else {
- globalAttributes = false;
- currentEntry = findEntryByName(line);
- if (currentEntry == NULL) {
- fprintf(stderr, "WARNING: %u: attribute of non existant entry point %s\n", (unsigned int)lc, line.c_str());
- }
- }
- state = ST_ATT;
- break;
- case ST_ATT:
- if (globalAttributes) {
- setGlobalAttribute(line, lc);
- } else if (currentEntry != NULL) {
- currentEntry->setAttribute(line, lc);
- }
- break;
- }
- }
- return 0;
-}
-
-
-int ApiGen::setGlobalAttribute(const std::string & line, size_t lc)
-{
- size_t pos = 0;
- size_t last;
- std::string token = getNextToken(line, pos, &last, WHITESPACE);
- pos = last;
-
- if (token == "base_opcode") {
- std::string str = getNextToken(line, pos, &last, WHITESPACE);
- if (str.size() == 0) {
- fprintf(stderr, "line %u: missing value for base_opcode\n", (unsigned) lc);
- } else {
- setBaseOpcode(atoi(str.c_str()));
- }
- } else if (token == "encoder_headers") {
- std::string str = getNextToken(line, pos, &last, WHITESPACE);
- pos = last;
- while (str.size() != 0) {
- encoderHeaders().push_back(str);
- str = getNextToken(line, pos, &last, WHITESPACE);
- pos = last;
- }
- } else if (token == "client_context_headers") {
- std::string str = getNextToken(line, pos, &last, WHITESPACE);
- pos = last;
- while (str.size() != 0) {
- clientContextHeaders().push_back(str);
- str = getNextToken(line, pos, &last, WHITESPACE);
- pos = last;
- }
- } else if (token == "server_context_headers") {
- std::string str = getNextToken(line, pos, &last, WHITESPACE);
- pos = last;
- while (str.size() != 0) {
- serverContextHeaders().push_back(str);
- str = getNextToken(line, pos, &last, WHITESPACE);
- pos = last;
- }
- } else if (token == "decoder_headers") {
- std::string str = getNextToken(line, pos, &last, WHITESPACE);
- pos = last;
- while (str.size() != 0) {
- decoderHeaders().push_back(str);
- str = getNextToken(line, pos, &last, WHITESPACE);
- pos = last;
- }
- }
- else {
- fprintf(stderr, "WARNING: %u : unknown global attribute %s\n", (unsigned int)lc, line.c_str());
- }
-
- return 0;
-}
-