예제 #1
0
파일: ApiGen.cpp 프로젝트: lcweik/emulator
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());
        }
    }
}
예제 #2
0
파일: ApiGen.cpp 프로젝트: lcweik/emulator
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;
}
예제 #3
0
파일: ApiGen.cpp 프로젝트: lcweik/emulator
// 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;
}
예제 #4
0
파일: ApiGen.cpp 프로젝트: lcweik/emulator
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";
                }