/*******************************************************************************
* GenData.cc BEAM Data output
* T.Barnaby, BEAM Ltd, 12/9/03
*******************************************************************************
*/
#define DEBUG 1
#include <stdio.h>
#include <stdarg.h>
#include <strings.h>
#include <GenData.h>
#include <bidl.h>
void GenData::produceInt(Node* n){
BIter i;
BString s;
BList<Node*>* nl;
BString typeName;
switch(n->nodeType()){
case Node::TMODULE:
omodule = n->name();
ofileInt.writeLine(BString("namespace ") + omodule + " {\n");
ofileInt.indentMore();
for(n->nodes().start(i); !n->nodes().isEnd(i); n->nodes().next(i)){
produceInt(n->nodes()[i]);
}
ofileInt.indentLess();
ofileInt.writeLine("}\n");
break;
case Node::TLIST:
for(n->nodes().start(i); !n->nodes().isEnd(i); n->nodes().next(i)){
produceInt(n->nodes()[i]);
}
break;
case Node::TSTRUCT:
typeName = BString("") + n->name();
if((n->nodes().number() == 2) && n->node(1)){
ofileInt.writeLine(BString("class ") + typeName + " : public " + getTypeName(n->node(1), 1) + " {\n");
}
else {
ofileInt.writeLine(BString("class ") + typeName + " {\n");
}
ofileInt.writeLine(BString("class ") + typeName + " {\n");
ofileInt.writeLine("public:\n");
ofileInt.indentMore();
ofileInt.writeLine(typeName + "();\n");
ofileInt.indentLess();
ofileInt.writeLine("public:\n");
ofileInt.indentMore();
nl = &n->node(0)->nodes();
for(nl->start(i); !nl->isEnd(i); nl->next(i)){
s = getTypeName(nl->get(i)->node(0), 1) + "\t";
s = s + nl->get(i)->node(1)->name();
ofileInt.writeLine(s + ";\n");
}
ofileInt.indentLess();
ofileInt.writeLine("};\n\n");
break;
case Node::TENUM:
s = "";
if(n->node(0)){
s = s + n->node(0)->name() + " ";
}
nl = &n->node(1)->nodes();
for(nl->start(i); !nl->isEnd(i); nl->next(i)){
if(s.len())
s += ", ";
s += nl->get(i)->name();
}
ofileInt.writeLine(BString("enum { " + s + "};\n");
break;
default:
break;
}
}
void GenData::produceImp(Node* n){
BString s;
BIter i;
BList<Node*>* nl;
BString typeName;
BString parentTypeName;
switch(n->nodeType()){
case Node::TMODULE:
omodule = n->name();
ofileImp.writeLine(BString("namespace ") + omodule + " {\n");
ofileImp.indentMore();
for(n->nodes().start(i); !n->nodes().isEnd(i); n->nodes().next(i)){
produceImp(n->nodes()[i]);
}
ofileImp.indentLess();
ofileImp.writeLine("}\n");
break;
case Node::TLIST:
for(n->nodes().start(i); !n->nodes().isEnd(i); n->nodes().next(i)){
produceImp(n->nodes()[i]);
}
break;
case Node::TTYPEDOMAIN:
otypeDomain = atoi(n->name());
break;
case Node::TSTRUCT:
typeName = BString("") + n->name();
parentTypeName = "";
if((n->nodes().number() == 2) && n->node(1)){
parentTypeName = getTypeName(n->node(1), 1);
}
ofileImp.writeLine("\n");
ofileImp.writeLine(BString("// ") + typeName + " Object Implementation\n");
if((n->nodes().number() == 2) && n->node(1)){
ofileImp.writeLine(typeName + "::" + typeName + "(){\n");
}
else {
ofileImp.writeLine(typeName + "::" + typeName + "(){\n");
}
ofileImp.indentMore();
ofileImp.indentLess();
ofileImp.writeLine("}\n");
otypeNum++;
break;
default:
break;
}
}
BError GenData::produceHeaderInt(){
BError err;
BString fileName = ofileName + "D.h";
BString fileNameUpper = ofileName + "D_H";
fileNameUpper.toUpper();
ofileInt.printf("/*******************************************************************************\n");
ofileInt.printf(" *\t%s\tProduced by Bidl\n", fileName.retStr());
ofileInt.printf(" *******************************************************************************\n");
ofileInt.printf(" */\n");
ofileInt.printf("\n");
ofileInt.printf("#ifndef %s\n", fileNameUpper.retStr());
ofileInt.printf("#define %s 1\n\n", fileNameUpper.retStr());
ofileInt.printf("#include <Boap.h>\n\n");
#ifdef ZAP1
ofileInt.printf("#include <BObjData.h>\n");
ofileInt.printf("#include <BObjInt.h>\n");
ofileInt.printf("#include <BObjString.h>\n");
ofileInt.printf("#include <BObjDate.h>\n");
ofileInt.printf("#include <BObjDateTime.h>\n");
ofileInt.printf("#include <BObjListVar.h>\n");
#endif
ofileInt.printf("\n");
return err;
}
BError GenData::produceTrailerInt(){
BError err;
ofileInt.printf("#endif\n");
return err;
}
BError GenData::produceHeaderImp(){
BError err;
ofileImp.printf("/*******************************************************************************\n");
ofileImp.printf(" *\t%s\tProduced by Bidl\n", (ofileName + ".cc").retStr());
ofileImp.printf(" *******************************************************************************\n");
ofileImp.printf(" */\n");
ofileImp.printf("\n");
ofileImp.printf("#include <%s>\n", (ofileName + "D.h").retStr());
ofileImp.printf("#include <BType.h>\n");
ofileImp.printf("\n");
return err;
}
BError GenData::produceTrailerImp(){
BError err;
// Produce Python Init
ofileImp.writeLine("\n// Python module init\n");
ofileImp.writeLine("#include <Python.h>\n");
ofileImp.writeLine("\n");
ofileImp.writeLine("static PyMethodDef methods[] = {\n");
ofileImp.indentMore();
ofileImp.writeLine("{NULL, NULL}\n");
ofileImp.indentLess();
ofileImp.writeLine("};\n");
ofileImp.writeLine(BString("extern \"C\" void initlib") + omodule + "(){\n");
ofileImp.indentMore();
ofileImp.writeLine(BString("Py_InitModule(\"lib") + omodule + "\", methods);\n");
ofileImp.indentLess();
ofileImp.writeLine("}\n");
return err;
}
GenData::GenData(){
otypeDomain = 0;
otypeNum = 1;
}
GenData::~GenData(){
}
BError GenData::produce(Node* n, BString fileName){
BError err;
// dprintf("GenData::produce: %p\n", n);
ofileName = fileName;
ofileInt.open(ofileName + "D.h", "w");
ofileImp.open(ofileName + "D.cc", "w");
// File Headers
produceHeaderInt();
produceHeaderImp();
// Generate code
produceInt(n);
produceImp(n);
// Generate trailers
produceTrailerInt();
produceTrailerImp();
ofileImp.close();
ofileInt.close();
return err;
}