emugen: generate wrapper library files
Add functionality to generate a wrapper library. A wrapper library includes: 1. entry points 2. dispatch table (accessed from the library entry points) 3. dispatch table accessor callback 4. dispatch table initialization function Note that the dispatch table initialization function used to be part of the decoder. This change moves it to be part of the dispatch table layer where it belongs. Change-Id: Ide6764a17cc029056f9946e778a513cdc2a49003
This commit is contained in:
committed by
David 'Digit' Turner
parent
139308015e
commit
ea3a3584f5
@@ -31,7 +31,7 @@ LOCAL_STATIC_LIBRARIES := \
|
|||||||
LOCAL_LDLIBS := -ldl
|
LOCAL_LDLIBS := -ldl
|
||||||
|
|
||||||
|
|
||||||
GEN := $(intermediates)/gl_dec.cpp $(intermediates)/gl_dec.h
|
GEN := $(intermediates)/gl_server_context.cpp $(intermediates)/gl_dec.cpp $(intermediates)/gl_dec.h
|
||||||
|
|
||||||
$(GEN) : PRIVATE_PATH := $(LOCAL_PATH)
|
$(GEN) : PRIVATE_PATH := $(LOCAL_PATH)
|
||||||
$(GEN) : PRIVATE_CUSTOM_TOOL := $(EMUGEN) -D $(intermediates) -i $(emulatorOpengl)/system/GLESv1_enc gl
|
$(GEN) : PRIVATE_CUSTOM_TOOL := $(EMUGEN) -D $(intermediates) -i $(emulatorOpengl)/system/GLESv1_enc gl
|
||||||
|
|||||||
@@ -21,7 +21,6 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
|
||||||
EntryPoint * ApiGen::findEntryByName(const std::string & name)
|
EntryPoint * ApiGen::findEntryByName(const std::string & name)
|
||||||
{
|
{
|
||||||
EntryPoint * entry = NULL;
|
EntryPoint * entry = NULL;
|
||||||
@@ -119,12 +118,15 @@ int ApiGen::genContext(const std::string & filename, SideType side)
|
|||||||
// virtual destructor
|
// virtual destructor
|
||||||
fprintf(fp, "\t virtual ~%s_%s_context_t() {}\n", m_basename.c_str(), sideString(side));
|
fprintf(fp, "\t virtual ~%s_%s_context_t() {}\n", m_basename.c_str(), sideString(side));
|
||||||
// accessor
|
// accessor
|
||||||
if (side == CLIENT_SIDE) {
|
if (side == CLIENT_SIDE || side == WRAPPER_SIDE) {
|
||||||
fprintf(fp, "\n\ttypedef %s_%s_context_t *CONTEXT_ACCESSOR_TYPE(void);\n",
|
fprintf(fp, "\n\ttypedef %s_%s_context_t *CONTEXT_ACCESSOR_TYPE(void);\n",
|
||||||
m_basename.c_str(), sideString(side));
|
m_basename.c_str(), sideString(side));
|
||||||
fprintf(fp, "\tvoid setContextAccessor(CONTEXT_ACCESSOR_TYPE *f);\n");
|
fprintf(fp, "\tvoid setContextAccessor(CONTEXT_ACCESSOR_TYPE *f);\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// init function
|
||||||
|
fprintf(fp, "\tint initDispatchByName( void *(*getProc)(const char *name, void *userData), void *userData);\n");
|
||||||
|
|
||||||
fprintf(fp, "};\n");
|
fprintf(fp, "};\n");
|
||||||
|
|
||||||
fprintf(fp, "\n#endif\n");
|
fprintf(fp, "\n#endif\n");
|
||||||
@@ -132,8 +134,15 @@ int ApiGen::genContext(const std::string & filename, SideType side)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ApiGen::genClientEntryPoints(const std::string & filename)
|
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");
|
FILE *fp = fopen(filename.c_str(), "wt");
|
||||||
if (fp == NULL) {
|
if (fp == NULL) {
|
||||||
perror(filename.c_str());
|
perror(filename.c_str());
|
||||||
@@ -143,7 +152,7 @@ int ApiGen::genClientEntryPoints(const std::string & filename)
|
|||||||
printHeader(fp);
|
printHeader(fp);
|
||||||
fprintf(fp, "#include <stdio.h>\n");
|
fprintf(fp, "#include <stdio.h>\n");
|
||||||
fprintf(fp, "#include <stdlib.h>\n");
|
fprintf(fp, "#include <stdlib.h>\n");
|
||||||
fprintf(fp, "#include \"%s_%s_context.h\"\n", m_basename.c_str(), sideString(CLIENT_SIDE));
|
fprintf(fp, "#include \"%s_%s_context.h\"\n", m_basename.c_str(), sideString(side));
|
||||||
fprintf(fp, "\n");
|
fprintf(fp, "\n");
|
||||||
|
|
||||||
fprintf(fp, "extern \"C\" {\n");
|
fprintf(fp, "extern \"C\" {\n");
|
||||||
@@ -154,11 +163,11 @@ int ApiGen::genClientEntryPoints(const std::string & filename)
|
|||||||
fprintf(fp, "};\n\n");
|
fprintf(fp, "};\n\n");
|
||||||
|
|
||||||
fprintf(fp, "static %s_%s_context_t::CONTEXT_ACCESSOR_TYPE *getCurrentContext = NULL;\n",
|
fprintf(fp, "static %s_%s_context_t::CONTEXT_ACCESSOR_TYPE *getCurrentContext = NULL;\n",
|
||||||
m_basename.c_str(), sideString(CLIENT_SIDE));
|
m_basename.c_str(), sideString(side));
|
||||||
|
|
||||||
fprintf(fp,
|
fprintf(fp,
|
||||||
"void %s_%s_context_t::setContextAccessor(CONTEXT_ACCESSOR_TYPE *f) { getCurrentContext = f; }\n\n",
|
"void %s_%s_context_t::setContextAccessor(CONTEXT_ACCESSOR_TYPE *f) { getCurrentContext = f; }\n\n",
|
||||||
m_basename.c_str(), sideString(CLIENT_SIDE));
|
m_basename.c_str(), sideString(side));
|
||||||
|
|
||||||
|
|
||||||
for (size_t i = 0; i < size(); i++) {
|
for (size_t i = 0; i < size(); i++) {
|
||||||
@@ -166,18 +175,21 @@ int ApiGen::genClientEntryPoints(const std::string & filename)
|
|||||||
e->print(fp);
|
e->print(fp);
|
||||||
fprintf(fp, "{\n");
|
fprintf(fp, "{\n");
|
||||||
fprintf(fp, "\t %s_%s_context_t * ctx = getCurrentContext(); \n",
|
fprintf(fp, "\t %s_%s_context_t * ctx = getCurrentContext(); \n",
|
||||||
m_basename.c_str(), sideString(CLIENT_SIDE));
|
m_basename.c_str(), sideString(side));
|
||||||
|
|
||||||
bool shouldReturn = !e->retval().isVoid();
|
bool shouldReturn = !e->retval().isVoid();
|
||||||
|
bool shouldCallWithContext = (side == CLIENT_SIDE);
|
||||||
fprintf(fp, "\t %sctx->%s(ctx",
|
fprintf(fp, "\t %sctx->%s(%s",
|
||||||
shouldReturn ? "return " : "",
|
shouldReturn ? "return " : "",
|
||||||
e->name().c_str());
|
e->name().c_str(),
|
||||||
|
shouldCallWithContext ? "ctx" : "");
|
||||||
size_t nvars = e->vars().size();
|
size_t nvars = e->vars().size();
|
||||||
|
|
||||||
for (size_t j = 0; j < nvars; j++) {
|
for (size_t j = 0; j < nvars; j++) {
|
||||||
if (!e->vars()[j].isVoid()) {
|
if (!e->vars()[j].isVoid()) {
|
||||||
fprintf(fp, ", %s", e->vars()[j].name().c_str());
|
fprintf(fp, "%s %s",
|
||||||
|
j != 0 || shouldCallWithContext ? "," : "",
|
||||||
|
e->vars()[j].name().c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fprintf(fp, ");\n");
|
fprintf(fp, ");\n");
|
||||||
@@ -467,7 +479,6 @@ int ApiGen::genDecoderHeader(const std::string &filename)
|
|||||||
fprintf(fp, "struct %s : public %s_%s_context_t {\n\n",
|
fprintf(fp, "struct %s : public %s_%s_context_t {\n\n",
|
||||||
classname.c_str(), m_basename.c_str(), sideString(SERVER_SIDE));
|
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, "\tsize_t decode(void *buf, size_t bufsize, IOStream *stream);\n");
|
||||||
fprintf(fp, "\tint initDispatchByName( void *(*getProc)(const char *name, void *userData), void *userData);\n");
|
|
||||||
fprintf(fp, "\n};\n\n");
|
fprintf(fp, "\n};\n\n");
|
||||||
fprintf(fp, "#endif");
|
fprintf(fp, "#endif");
|
||||||
|
|
||||||
@@ -475,6 +486,39 @@ int ApiGen::genDecoderHeader(const std::string &filename)
|
|||||||
return 0;
|
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());
|
||||||
|
fprintf(fp, "\tvoid *ptr;\n\n");
|
||||||
|
for (size_t i = 0; i < n; i++) {
|
||||||
|
EntryPoint *e = &at(i);
|
||||||
|
fprintf(fp, "\tptr = getProc(\"%s\", userData); set_%s((%s_%s_proc_t)ptr);\n",
|
||||||
|
e->name().c_str(),
|
||||||
|
e->name().c_str(),
|
||||||
|
e->name().c_str(),
|
||||||
|
sideString(SERVER_SIDE));
|
||||||
|
|
||||||
|
}
|
||||||
|
fprintf(fp, "\treturn 0;\n");
|
||||||
|
fprintf(fp, "}\n\n");
|
||||||
|
fclose(fp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int ApiGen::genDecoderImpl(const std::string &filename)
|
int ApiGen::genDecoderImpl(const std::string &filename)
|
||||||
{
|
{
|
||||||
FILE *fp = fopen(filename.c_str(), "wt");
|
FILE *fp = fopen(filename.c_str(), "wt");
|
||||||
@@ -492,22 +536,7 @@ int ApiGen::genDecoderImpl(const std::string &filename)
|
|||||||
fprintf(fp, "\n\n#include <string.h>\n");
|
fprintf(fp, "\n\n#include <string.h>\n");
|
||||||
fprintf(fp, "#include \"%s_opcodes.h\"\n\n", m_basename.c_str());
|
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 \"%s_dec.h\"\n\n\n", m_basename.c_str());
|
||||||
fprintf(fp, "#include <stdio.h>\n");
|
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());
|
|
||||||
fprintf(fp, "\tvoid *ptr;\n\n");
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
EntryPoint *e = &at(i);
|
|
||||||
fprintf(fp, "\tptr = getProc(\"%s\", userData); set_%s((%s_%s_proc_t)ptr);\n",
|
|
||||||
e->name().c_str(),
|
|
||||||
e->name().c_str(),
|
|
||||||
e->name().c_str(),
|
|
||||||
sideString(SERVER_SIDE));
|
|
||||||
|
|
||||||
}
|
|
||||||
fprintf(fp, "\treturn 0;\n");
|
|
||||||
fprintf(fp, "}\n\n");
|
|
||||||
|
|
||||||
// decoder switch;
|
// decoder switch;
|
||||||
fprintf(fp, "size_t %s::decode(void *buf, size_t len, IOStream *stream)\n{\n", classname.c_str());
|
fprintf(fp, "size_t %s::decode(void *buf, size_t len, IOStream *stream)\n{\n", classname.c_str());
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ class ApiGen : public std::vector<EntryPoint> {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
typedef std::vector<std::string> StringVec;
|
typedef std::vector<std::string> StringVec;
|
||||||
typedef enum { CLIENT_SIDE, SERVER_SIDE } SideType;
|
typedef enum { CLIENT_SIDE, SERVER_SIDE, WRAPPER_SIDE } SideType;
|
||||||
|
|
||||||
ApiGen(const std::string & basename) :
|
ApiGen(const std::string & basename) :
|
||||||
m_basename(basename),
|
m_basename(basename),
|
||||||
@@ -42,7 +42,21 @@ public:
|
|||||||
int baseOpcode() { return m_baseOpcode; }
|
int baseOpcode() { return m_baseOpcode; }
|
||||||
void setBaseOpcode(int base) { m_baseOpcode = base; }
|
void setBaseOpcode(int base) { m_baseOpcode = base; }
|
||||||
|
|
||||||
const char *sideString(SideType side) { return (side == CLIENT_SIDE) ? "client" : "server"; }
|
const char *sideString(SideType side) {
|
||||||
|
const char *retval;
|
||||||
|
switch(side) {
|
||||||
|
case CLIENT_SIDE:
|
||||||
|
retval = "client";
|
||||||
|
break;
|
||||||
|
case SERVER_SIDE:
|
||||||
|
retval = "server";
|
||||||
|
break;
|
||||||
|
case WRAPPER_SIDE:
|
||||||
|
retval = "wrapper";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
StringVec & clientContextHeaders() { return m_clientContextHeaders; }
|
StringVec & clientContextHeaders() { return m_clientContextHeaders; }
|
||||||
StringVec & encoderHeaders() { return m_encoderHeaders; }
|
StringVec & encoderHeaders() { return m_encoderHeaders; }
|
||||||
@@ -55,7 +69,9 @@ public:
|
|||||||
int genProcTypes(const std::string &filename, SideType side);
|
int genProcTypes(const std::string &filename, SideType side);
|
||||||
|
|
||||||
int genContext(const std::string &filename, SideType side);
|
int genContext(const std::string &filename, SideType side);
|
||||||
int genClientEntryPoints(const std::string &filename);
|
int genContextImpl(const std::string &filename, SideType side);
|
||||||
|
|
||||||
|
int genEntryPoints(const std::string &filename, SideType side);
|
||||||
|
|
||||||
int genEncoderHeader(const std::string &filename);
|
int genEncoderHeader(const std::string &filename);
|
||||||
int genEncoderImpl(const std::string &filename);
|
int genEncoderImpl(const std::string &filename);
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
Introduction:
|
Introduction:
|
||||||
|
-------------
|
||||||
The emugen tool is a tool to generate a wire protocol implementation
|
The emugen tool is a tool to generate a wire protocol implementation
|
||||||
based on provided API. The tool generates c++ encoder code that takes
|
based on provided API. The tool generates c++ encoder code that takes
|
||||||
API calls and encodes them into the wire and decoder code that decodes
|
API calls and encodes them into the wire and decoder code that decodes
|
||||||
the wire stream and calls server matching API.
|
the wire stream and calls server matching API.
|
||||||
|
The emugen tool includes additional functionality that enables to
|
||||||
|
generate an wrapper library. The wrapper library provides entry points
|
||||||
|
for the specified API, where each entry routes the call via a dispatch
|
||||||
|
table. The dispatch table may be initialized as required by a specific application.
|
||||||
|
|
||||||
The following paragraphs includes the following:
|
The following paragraphs includes the following:
|
||||||
* Wire Protocol Description
|
* Wire Protocol Description
|
||||||
@@ -18,7 +22,7 @@ are used interchangeably by the context.
|
|||||||
|
|
||||||
|
|
||||||
Wire Protocol packet structure:
|
Wire Protocol packet structure:
|
||||||
|
-------------------------------
|
||||||
A general Encoder->Decoder packet is structured as following:
|
A general Encoder->Decoder packet is structured as following:
|
||||||
struct Packet {
|
struct Packet {
|
||||||
unsigned int opcode;
|
unsigned int opcode;
|
||||||
@@ -52,7 +56,7 @@ Since ‘foo’ returns value, the caller is expected to read back the return pa
|
|||||||
|
|
||||||
|
|
||||||
Pointer decoding:
|
Pointer decoding:
|
||||||
|
----------------
|
||||||
The wire protocol also allows exchanging of pointer data
|
The wire protocol also allows exchanging of pointer data
|
||||||
(arrays). Pointers are defined with directions:
|
(arrays). Pointers are defined with directions:
|
||||||
|
|
||||||
@@ -92,7 +96,7 @@ The return packet is;
|
|||||||
}
|
}
|
||||||
|
|
||||||
Endianess
|
Endianess
|
||||||
|
---------
|
||||||
The Wire protocol is designed to impose minimum overhead on the client
|
The Wire protocol is designed to impose minimum overhead on the client
|
||||||
side. Thus, the data endianness that is sent across the wire is
|
side. Thus, the data endianness that is sent across the wire is
|
||||||
determined by the ‘client’ side. It is up to the server side to
|
determined by the ‘client’ side. It is up to the server side to
|
||||||
@@ -101,7 +105,7 @@ determine the client endianess and marshal the packets as required.
|
|||||||
|
|
||||||
|
|
||||||
Emugen input files - protocol specification
|
Emugen input files - protocol specification
|
||||||
|
-------------------------------------------
|
||||||
The protocol generated by emugen consists of two input files:
|
The protocol generated by emugen consists of two input files:
|
||||||
|
|
||||||
1. basename.in - A sepcification of the protocol RPC procedures. This
|
1. basename.in - A sepcification of the protocol RPC procedures. This
|
||||||
@@ -135,17 +139,22 @@ tree. The format of the .attrib file is described below.
|
|||||||
|
|
||||||
This files describes the types that are described by the API. A type
|
This files describes the types that are described by the API. A type
|
||||||
is defined as follows:
|
is defined as follows:
|
||||||
<type name> <size in bits> <print format string>
|
<type name> <size in bits> <print format string> <is a pointer? true|false>
|
||||||
where:
|
where:
|
||||||
<type name> is the name of the type as described in the API
|
<type name> is the name of the type as described in the API
|
||||||
<size in bits> 0, 8, 16, 32 sizes are accepted
|
<size in bits> 0, 8, 16, 32 sizes are accepted
|
||||||
<print format string> a string to format the value of the type, as acceted by printf(3)
|
<print format string> a string to format the value of the type, as
|
||||||
|
acceted by printf(3)
|
||||||
|
<is pointer?> true or false string species whether the type should be
|
||||||
|
treated as a pointer.
|
||||||
|
|
||||||
example:
|
example:
|
||||||
GLint 32 %d
|
GLint 32 %d false
|
||||||
|
GLint* 32 %p true
|
||||||
|
GLptr 32 %p true
|
||||||
|
|
||||||
Encoder generated code files
|
Encoder generated code files
|
||||||
|
----------------------------
|
||||||
In order to generate the encoder files, one should run the ‘emugen’
|
In order to generate the encoder files, one should run the ‘emugen’
|
||||||
tool as follows:
|
tool as follows:
|
||||||
|
|
||||||
@@ -174,6 +183,9 @@ structure that stores the encoding functions. This data structure also
|
|||||||
includes ‘accessors’ methods such that library user can override
|
includes ‘accessors’ methods such that library user can override
|
||||||
default entries for special case handling.
|
default entries for special case handling.
|
||||||
|
|
||||||
|
api_client_context.cpp - defines an initialization function for
|
||||||
|
dispatch table
|
||||||
|
|
||||||
api_enc.h - This header file defines the encoder data strcuture. The
|
api_enc.h - This header file defines the encoder data strcuture. The
|
||||||
encoder data structure inherits its functionality from the
|
encoder data structure inherits its functionality from the
|
||||||
‘client_context’ class above and adds encoding and streaming
|
‘client_context’ class above and adds encoding and streaming
|
||||||
@@ -181,7 +193,8 @@ functionality.
|
|||||||
|
|
||||||
api_enc.cpp - Encoder implementation.
|
api_enc.cpp - Encoder implementation.
|
||||||
|
|
||||||
5.1.2.2 Decoder generated files
|
Decoder generated files
|
||||||
|
-----------------------
|
||||||
In order to generate the decoder files, one should run the ‘emugen’
|
In order to generate the decoder files, one should run the ‘emugen’
|
||||||
tool as follows:
|
tool as follows:
|
||||||
emugen -i <input directory> -D <decoder files output directory> basename
|
emugen -i <input directory> -D <decoder files output directory> basename
|
||||||
@@ -197,8 +210,9 @@ api_opcodes.h - Protocol opcodes
|
|||||||
|
|
||||||
api_server_proc.h - type definitions for the server side procedures
|
api_server_proc.h - type definitions for the server side procedures
|
||||||
|
|
||||||
api_server_context.h - dispatch table the encoder functions
|
api_server_context.h - dispatch table the decoder functions
|
||||||
|
|
||||||
|
api_server_context.cpp - dispatch table initialization function
|
||||||
api_dec.h - Decoder header file
|
api_dec.h - Decoder header file
|
||||||
|
|
||||||
api_dec.cpp - Decoder implementation. In addtion, this file includes
|
api_dec.cpp - Decoder implementation. In addtion, this file includes
|
||||||
@@ -207,8 +221,30 @@ initialize the API server implementation. An example for such
|
|||||||
initialization is loading a set of functions from a shared library
|
initialization is loading a set of functions from a shared library
|
||||||
module.
|
module.
|
||||||
|
|
||||||
.attrib file format description:
|
Wrapper generated files
|
||||||
|
-----------------------
|
||||||
|
In order to generate a wrapper library files, one should run the
|
||||||
|
'emugen' tool as follows:
|
||||||
|
|
||||||
|
emugen -i <input directory> -W <wrapper files output directory> basename
|
||||||
|
where:
|
||||||
|
<input directory> containes the api specification files (basename.in + basename.attrib)
|
||||||
|
<wrapper directory> - a directory name to generate the wrapper output files
|
||||||
|
basename - The basename for the api.
|
||||||
|
|
||||||
|
With resepct to the example above, Emugen will generate the following
|
||||||
|
files:
|
||||||
|
|
||||||
|
api_wrapper_proc.h - type definitions for the wrapper procedures
|
||||||
|
|
||||||
|
api_wrapper_context.h - dispatch table the wrapper functions
|
||||||
|
|
||||||
|
api_wrapper_context.cpp - dispatch table initialization function
|
||||||
|
api_wrapper_entry.cpp - entry points for the API
|
||||||
|
|
||||||
|
|
||||||
|
.attrib file format description:
|
||||||
|
-------------------------------
|
||||||
The .attrib file is an input file to emugen and is used to provide
|
The .attrib file is an input file to emugen and is used to provide
|
||||||
additional information that is required for the code generation.
|
additional information that is required for the code generation.
|
||||||
The file format is as follows:
|
The file format is as follows:
|
||||||
|
|||||||
@@ -34,18 +34,23 @@ void usage(const char *filename)
|
|||||||
fprintf(stderr, "\t-D <dir>: generate decoder into dir\n");
|
fprintf(stderr, "\t-D <dir>: generate decoder into dir\n");
|
||||||
fprintf(stderr, "\t-i: input dir, local directory by default\n");
|
fprintf(stderr, "\t-i: input dir, local directory by default\n");
|
||||||
fprintf(stderr, "\t-T : generate attribute template into the input directory\n\t\tno other files are generated\n");
|
fprintf(stderr, "\t-T : generate attribute template into the input directory\n\t\tno other files are generated\n");
|
||||||
|
fprintf(stderr, "\t-W : generate wrapper into dir\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
std::string encoderDir = "";
|
std::string encoderDir = "";
|
||||||
std::string decoderDir = "";
|
std::string decoderDir = "";
|
||||||
|
std::string wrapperDir = "";
|
||||||
std::string inDir = ".";
|
std::string inDir = ".";
|
||||||
bool generateAttributesTemplate = false;
|
bool generateAttributesTemplate = false;
|
||||||
|
|
||||||
int c;
|
int c;
|
||||||
while((c = getopt(argc, argv, "TE:D:i:h")) != -1) {
|
while((c = getopt(argc, argv, "TE:D:i:hW:")) != -1) {
|
||||||
switch(c) {
|
switch(c) {
|
||||||
|
case 'W':
|
||||||
|
wrapperDir = std::string(optarg);
|
||||||
|
break;
|
||||||
case 'T':
|
case 'T':
|
||||||
generateAttributesTemplate = true;
|
generateAttributesTemplate = true;
|
||||||
break;
|
break;
|
||||||
@@ -76,7 +81,10 @@ int main(int argc, char *argv[])
|
|||||||
return BAD_USAGE;
|
return BAD_USAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (encoderDir.size() == 0 && decoderDir.size() == 0 && generateAttributesTemplate == false) {
|
if (encoderDir.size() == 0 &&
|
||||||
|
decoderDir.size() == 0 &&
|
||||||
|
generateAttributesTemplate == false &&
|
||||||
|
wrapperDir.size() == 0) {
|
||||||
fprintf(stderr, "No output specified - aborting\n");
|
fprintf(stderr, "No output specified - aborting\n");
|
||||||
return BAD_USAGE;
|
return BAD_USAGE;
|
||||||
}
|
}
|
||||||
@@ -114,23 +122,31 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
apiEntries.genOpcodes(encoderDir + "/" + baseName + "_opcodes.h");
|
apiEntries.genOpcodes(encoderDir + "/" + baseName + "_opcodes.h");
|
||||||
apiEntries.genContext(encoderDir + "/" + baseName + "_client_context.h", ApiGen::CLIENT_SIDE);
|
apiEntries.genContext(encoderDir + "/" + baseName + "_client_context.h", ApiGen::CLIENT_SIDE);
|
||||||
|
apiEntries.genContextImpl(encoderDir + "/" + baseName + "_client_context.cpp", ApiGen::CLIENT_SIDE);
|
||||||
|
|
||||||
apiEntries.genProcTypes(encoderDir + "/" + baseName + "_client_proc.h", ApiGen::CLIENT_SIDE);
|
apiEntries.genProcTypes(encoderDir + "/" + baseName + "_client_proc.h", ApiGen::CLIENT_SIDE);
|
||||||
|
|
||||||
apiEntries.genClientEntryPoints(encoderDir + "/" + baseName + "_entry.cpp");
|
apiEntries.genEntryPoints(encoderDir + "/" + baseName + "_entry.cpp", ApiGen::CLIENT_SIDE);
|
||||||
apiEntries.genEncoderHeader(encoderDir + "/" + baseName + "_enc.h");
|
apiEntries.genEncoderHeader(encoderDir + "/" + baseName + "_enc.h");
|
||||||
apiEntries.genEncoderImpl(encoderDir + "/" + baseName + "_enc.cpp");
|
apiEntries.genEncoderImpl(encoderDir + "/" + baseName + "_enc.cpp");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (decoderDir.size() != 0) {
|
if (decoderDir.size() != 0) {
|
||||||
//apiEntries.genEntryPoints(decoderDir + "/" + baseName + "_entry.cpp", baseName);
|
|
||||||
apiEntries.genOpcodes(decoderDir + "/" + baseName + "_opcodes.h");
|
apiEntries.genOpcodes(decoderDir + "/" + baseName + "_opcodes.h");
|
||||||
apiEntries.genProcTypes(decoderDir + "/" + baseName + "_server_proc.h", ApiGen::SERVER_SIDE);
|
apiEntries.genProcTypes(decoderDir + "/" + baseName + "_server_proc.h", ApiGen::SERVER_SIDE);
|
||||||
apiEntries.genContext(decoderDir + "/" + baseName + "_server_context.h", ApiGen::SERVER_SIDE);
|
apiEntries.genContext(decoderDir + "/" + baseName + "_server_context.h", ApiGen::SERVER_SIDE);
|
||||||
|
apiEntries.genContextImpl(decoderDir + "/" + baseName + "_server_context.cpp", ApiGen::SERVER_SIDE);
|
||||||
apiEntries.genDecoderHeader(decoderDir + "/" + baseName + "_dec.h");
|
apiEntries.genDecoderHeader(decoderDir + "/" + baseName + "_dec.h");
|
||||||
apiEntries.genDecoderImpl(decoderDir + "/" + baseName + "_dec.cpp");
|
apiEntries.genDecoderImpl(decoderDir + "/" + baseName + "_dec.cpp");
|
||||||
// generate the encoder type;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (wrapperDir.size() != 0) {
|
||||||
|
apiEntries.genProcTypes(wrapperDir + "/" + baseName + "_wrapper_proc.h", ApiGen::WRAPPER_SIDE);
|
||||||
|
apiEntries.genContext(wrapperDir + "/" + baseName + "_wrapper_context.h", ApiGen::WRAPPER_SIDE);
|
||||||
|
apiEntries.genContextImpl(wrapperDir + "/" + baseName + "_wrapper_context.cpp", ApiGen::WRAPPER_SIDE);
|
||||||
|
apiEntries.genEntryPoints(wrapperDir + "/" + baseName + "_wrapper_entry.cpp", ApiGen::WRAPPER_SIDE);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_DUMP
|
#ifdef DEBUG_DUMP
|
||||||
int withPointers = 0;
|
int withPointers = 0;
|
||||||
printf("%d functions found\n", int(apiEntries.size()));
|
printf("%d functions found\n", int(apiEntries.size()));
|
||||||
|
|||||||
Reference in New Issue
Block a user