/******************************************************************************* * GenBoap.cc Boap output * T.Barnaby, BEAM Ltd, 2/5/03 ******************************************************************************* */ #define DEBUG 1 #define DODATA 0 #include <stdio.h> #include <stdarg.h> #include <strings.h> #include <GenBoap.h> #include <bidl.h> void GenBoap::produceIntC(Node* n){ BIter i; BString s; BString c; BList<Node*>* nl; switch(n->nodeType()){ case Node::TMODULE: omodule = n->name(); ofileIntC.writeLine(BString("namespace ") + omodule + " {\n"); ofileIntC.indentMore(); ofileIntC.writeLine(BString("const BUInt32 apiVersion = ") + oapiVersion + ";\n\n"); for(n->nodes().start(i); !n->nodes().isEnd(i); n->nodes().next(i)){ produceIntC(n->nodes()[i]); } ofileIntC.indentLess(); ofileIntC.writeLine("}\n"); break; case Node::TINTERFACE: ointerface = n->name(); // Client ofileIntC.writeLine(BString("class ") + ointerface + " : public BoapClientObject {\n"); ofileIntC.writeLine("public:\n"); ofileIntC.indentMore(); ofileIntC.writeLine(BString("\t") + ointerface + "(BString name = \"\");\n"); for(n->nodes().start(i); !n->nodes().isEnd(i); n->nodes().next(i)){ produceIntC(n->nodes()[i]); } ofileIntC.indentLess(); ofileIntC.writeLine("private:\n"); ofileIntC.writeLine("};\n"); break; case Node::TLIST: for(n->nodes().start(i); !n->nodes().isEnd(i); n->nodes().next(i)){ produceIntC(n->nodes()[i]); } break; #if DODATA case Node::TSTRUCT: if((n->nodes().number() == 2) && n->node(1)){ ofileIntC.writeLine(BString("struct ") + n->name() + " : public " + n->node(1)->name() + " {\n"); } else { ofileIntC.writeLine(BString("struct ") + n->name() + " {\n"); } ofileIntC.indentMore(); nl = &n->node(0)->nodes(); for(nl->start(i); !nl->isEnd(i); nl->next(i)){ s = getTypeName(nl->get(i)->node(0)) + "\t"; s = s + nl->get(i)->node(1)->name(); if(nl->get(i)->node(2) && nl->get(i)->node(2)->nodeType() == Node::TCOMMENT) c = BString("\t//") + nl->get(i)->node(2)->name(); else c = ""; ofileIntC.writeLine(s + c + ";\n"); } ofileIntC.indentLess(); ofileIntC.writeLine("};\n\n"); break; #endif case Node::TFUNC: s = s + getTypeName(n->node(0)) + " "; s = s + n->name() + "("; nl = &n->node(1)->nodes(); for(nl->start(i); !nl->isEnd(i); nl->next(i)){ if(i != nl->begin()) s = s + ", "; if(nl->get(i)->node(0)->name() == "in"){ s = s + getTypeName(nl->get(i)->node(1)) + " "; } else if(nl->get(i)->node(0)->name() == "inref"){ s = s + "const " + getTypeName(nl->get(i)->node(1)) + "& "; } else { s = s + getTypeName(nl->get(i)->node(1)) + "& "; } s = s + nl->get(i)->node(2)->name(); } s = s + ");"; if(n->node(2) && n->node(2)->nodeType() == Node::TCOMMENT) s = s + "\t//" + n->node(2)->name(); ofileIntC.writeLine(s + "\n"); break; case Node::TCOMMENT: s = BString("//") + n->name() + "\n"; ofileIntC.writeLine(s); break; case Node::TAPIVERSION: oapiVersion = n->name().retInt(); break; default: break; } } void GenBoap::produceIntS(Node* n){ BIter i; BString s; BString sa; BList<Node*>* nl; switch(n->nodeType()){ case Node::TMODULE: omodule = n->name(); ofileIntS.writeLine(BString("namespace ") + omodule + " {\n"); ofileIntS.indentMore(); for(n->nodes().start(i); !n->nodes().isEnd(i); n->nodes().next(i)){ produceIntS(n->nodes()[i]); } ofileIntS.indentLess(); ofileIntS.writeLine("}\n"); break; case Node::TINTERFACE: ointerface = n->name(); // Server ofileIntS.writeLine(BString("class ") + ointerface + "Service : public BoapServiceObject {\n"); ofileIntS.writeLine("public:\n"); ofileIntS.indentMore(); ofileIntS.writeLine(BString("\t") + ointerface + "Service(BoapServer& server, BString name);\n"); for(n->nodes().start(i); !n->nodes().isEnd(i); n->nodes().next(i)){ produceIntS(n->nodes()[i]); } ofileIntS.indentLess(); ofileIntS.writeLine("};\n"); break; case Node::TLIST: for(n->nodes().start(i); !n->nodes().isEnd(i); n->nodes().next(i)){ produceIntS(n->nodes()[i]); } break; case Node::TSTRUCT: break; case Node::TFUNC: s = BString("BError do") + n->name() + "(BoapServerConnection* conn, BoapPacket& rx, BoapPacket& tx);\n"; ofileIntS.writeLine(s); s = "virtual "; s = s + getTypeName(n->node(0)) + " "; s = s + n->name() + "("; if(ooptions.hasKey("connectionClass")){ sa = sa + ooptions["connectionClass"] + "* conn"; } nl = &n->node(1)->nodes(); for(nl->start(i); !nl->isEnd(i); nl->next(i)){ if(sa.len()) sa = sa + ", "; if(nl->get(i)->node(0)->name() == "in"){ sa = sa + getTypeName(nl->get(i)->node(1)) + " "; } else if(nl->get(i)->node(0)->name() == "inref"){ sa = sa + "const " + getTypeName(nl->get(i)->node(1)) + "& "; } else { sa = sa + getTypeName(nl->get(i)->node(1)) + "& "; } sa = sa + nl->get(i)->node(2)->name(); } s = s + sa + ") = 0;\n"; ofileIntS.writeLine(s); break; default: break; } } void GenBoap::produceIntT(Node* n){ BIter i; BString s; BString sa; BList<Node*>* nl; switch(n->nodeType()){ case Node::TMODULE: omodule = n->name(); ofileIntT.writeLine(BString("using namespace ") + omodule + ";\n\n"); for(n->nodes().start(i); !n->nodes().isEnd(i); n->nodes().next(i)){ produceIntT(n->nodes()[i]); } break; case Node::TINTERFACE: ointerface = n->name(); // Server ofileIntT.writeLine(BString("class ") + ointerface + "Server : public " + omodule + "::" + ointerface + "Service {\n"); ofileIntT.writeLine("public:\n"); ofileIntT.indentMore(); if(ooptions.hasKey("serverControl")) ofileIntT.writeLine(BString("\t") + ointerface + "Server(Control& control, BoapServer& server, BString name);\n"); else ofileIntT.writeLine(BString("\t") + ointerface + "Server(BoapServer& server, BString name);\n"); for(n->nodes().start(i); !n->nodes().isEnd(i); n->nodes().next(i)){ produceIntT(n->nodes()[i]); } ofileIntT.indentLess(); if(ooptions.hasKey("serverControl")){ ofileIntT.writeLine("private:\n"); ofileIntT.indentMore(); ofileIntT.writeLine("Control&\tocontrol;\n"); ofileIntT.indentLess(); } ofileIntT.writeLine("};\n\n"); break; case Node::TLIST: for(n->nodes().start(i); !n->nodes().isEnd(i); n->nodes().next(i)){ produceIntT(n->nodes()[i]); } break; case Node::TSTRUCT: break; case Node::TFUNC: s = ""; s = s + getTypeName(n->node(0)) + " "; s = s + n->name() + "("; if(ooptions.hasKey("connectionClass")){ sa = sa + ooptions["connectionClass"] + "* conn"; } nl = &n->node(1)->nodes(); for(nl->start(i); !nl->isEnd(i); nl->next(i)){ if(sa.len()) sa = sa + ", "; if(nl->get(i)->node(0)->name() == "in"){ sa = sa + getTypeName(nl->get(i)->node(1)) + " "; } else if(nl->get(i)->node(0)->name() == "inref"){ sa = sa + "const " + getTypeName(nl->get(i)->node(1)) + "& "; } else { sa = sa + getTypeName(nl->get(i)->node(1)) + "& "; } sa = sa + nl->get(i)->node(2)->name(); } s = s + sa + ");\n"; ofileIntT.writeLine(s); break; default: break; } } void GenBoap::produceImpT(Node* n){ BString s; BString sa; BIter i; BList<Node*>* nl; switch(n->nodeType()){ case Node::TMODULE: omodule = n->name(); ofileImpT.writeLine(BString("using namespace ") + omodule + ";\n\n"); for(n->nodes().start(i); !n->nodes().isEnd(i); n->nodes().next(i)){ produceImpT(n->nodes()[i]); } break; case Node::TINTERFACE: ointerface = n->name(); if(ooptions.hasKey("serverControl")) ofileImpT.writeLine(ointerface + "Server::" + ointerface + "Server(Control& control, BoapServer& server, BString name) : " + ointerface + "Service(server, name), ocontrol(control){\n"); else ofileImpT.writeLine(ointerface + "Server::" + ointerface + "Server(BoapServer& server, BString name) : " + ointerface + "Service(server, name){\n"); ofileImpT.writeLine("}\n\n"); for(n->nodes().start(i); !n->nodes().isEnd(i); n->nodes().next(i)){ produceImpT(n->nodes()[i]); } break; case Node::TLIST: for(n->nodes().start(i); !n->nodes().isEnd(i); n->nodes().next(i)){ produceImpT(n->nodes()[i]); } break; case Node::TFUNC: s = ""; s = s + getTypeName(n->node(0)) + " "; s = s + ointerface + "Server::" + n->name() + "("; if(ooptions.hasKey("connectionClass")){ sa = sa + ooptions["connectionClass"] + "* conn"; } nl = &n->node(1)->nodes(); for(nl->start(i); !nl->isEnd(i); nl->next(i)){ if(sa.len()) sa = sa + ", "; if(nl->get(i)->node(0)->name() == "in"){ sa = sa + getTypeName(nl->get(i)->node(1)) + " "; } else if(nl->get(i)->node(0)->name() == "inref"){ sa = sa + "const " + getTypeName(nl->get(i)->node(1)) + "& "; } else { sa = sa + getTypeName(nl->get(i)->node(1)) + "& "; } sa = sa + nl->get(i)->node(2)->name(); } s = s + sa + "){\n"; ofileImpT.writeLine(s); ofileImpT.indentMore(); if(ooptions.hasKey("serverControl")){ s = "return ocontrol."; s += n->name() + "("; if(ooptions.hasKey("connectionClass")){ s += "conn"; if(nl->number()) s += ", "; } nl = &n->node(1)->nodes(); for(nl->start(i); !nl->isEnd(i); nl->next(i)){ if(i != nl->begin()) s = s + ", "; s = s + nl->get(i)->node(2)->name(); } s = s + ");\n"; ofileImpT.writeLine(s); } else { if(getTypeName(n->node(0)) == "BError"){ s = getTypeName(n->node(0)) + "\terr;\n\n"; ofileImpT.writeLine(s); s = "return err;\n"; ofileImpT.writeLine(s); } else { s = getTypeName(n->node(0)) + "\tret;\n\n"; ofileImpT.writeLine(s); s = "return ret;\n"; ofileImpT.writeLine(s); } } ofileImpT.indentLess(); ofileImpT.writeLine("}\n\n"); break; default: break; } } void GenBoap::pushPopVar(FileIndent& file, int push, BString func, Node* type, BString name){ BIter i; BList<Node*>* nl; Type* t; Type* dt; BString s; BString swapType; // printf("GenBoap::pushPopVar: Func(%s) Type(%s) Name(%s)\n", func.retStr(), type->name().retStr(), name.retStr()); if(t = gtypelist.search(type->name())){ // printf("DoType: %p Name(%s) Derived(%p)\n", type->name().retStr(), type, t->derived()); if(dt = t->derived()){ nl = &dt->node()->nodes(); for(nl->start(i); !nl->isEnd(i); nl->next(i)){ pushPopVar(file, push, func, nl->get(i)->node(0), name + "." + nl->get(i)->node(1)->name()); } } // printf("Node: %s %s\n", t->node()->name().retStr(), Node::nodeTypeName(t->node()->nodeType()).retStr()); if(t->node()->name() == "enumeratorList"){ if(push) file.writeLine(func + "(int(" + name + "));\n"); else file.writeLine(func + "((int&)" + name + ");\n"); } else { nl = &t->node()->nodes(); for(nl->start(i); !nl->isEnd(i); nl->next(i)){ pushPopVar(file, push, func, nl->get(i)->node(0), name + "." + nl->get(i)->node(1)->name()); } } // printf("DoType: %p Derived(%p): Done\n", type, t->derived()); } else if(type->nodeType() == Node::TTYPELIST){ if(push){ file.writeLine("{\n"); file.indentMore(); file.writeLine(BString("BIter i") + opushPopDepth + ";\n"); file.writeLine(func + "(" + name + ".number());\n"); s = BString("for(") + name + ".start(i" + opushPopDepth + "); !" + name + ".isEnd(i" + opushPopDepth + "); " + name + ".next(i" + opushPopDepth + ")){\n"; file.writeLine(s); file.indentMore(); pushPopVar(file, push, func, type->node(0), name + "[i" + opushPopDepth++ + "]"); opushPopDepth--; file.indentLess(); file.writeLine("}\n"); file.indentLess(); file.writeLine("}\n"); } else { file.writeLine("{\n"); file.indentMore(); file.writeLine(BString("BUInt32 n") + opushPopDepth + ";\n"); s = getTypeName(type->node(0)) + " v" + opushPopDepth + ";\n"; file.writeLine(s); file.writeLine(name + ".clear();\n"); file.writeLine(func + "(n" + opushPopDepth + ");\n"); file.writeLine(BString("while(n") + opushPopDepth + "--){\n"); file.indentMore(); pushPopVar(file, push, func, type->node(0), BString("v") + opushPopDepth++); opushPopDepth--; file.writeLine(name + ".append(v" + opushPopDepth + ");\n"); file.indentLess(); file.writeLine("}\n"); file.indentLess(); file.writeLine("}\n"); } } else if(type->nodeType() == Node::TTYPEDICT){ BString typeName = getTypeName(type->node(0)); if(push){ file.writeLine("{\n"); file.indentMore(); file.writeLine(BString("BDict<") + typeName + ">::iterator i" + opushPopDepth + ";\n"); file.writeLine(func + "(BUInt32(" + name + ".size()));\n"); s = BString("for(") + name + ".start(i" + opushPopDepth + "); !" + name + ".isEnd(i" + opushPopDepth + "); " + name + ".next(i" + opushPopDepth + ")){\n"; file.writeLine(s); file.indentMore(); file.writeLine(func + "(" + name + ".key(i" + opushPopDepth + "));\n"); pushPopVar(file, push, func, type->node(0), name + "[i" + opushPopDepth++ + "]"); opushPopDepth--; file.indentLess(); file.writeLine("}\n"); file.indentLess(); file.writeLine("}\n"); } else { file.writeLine("{\n"); file.indentMore(); file.writeLine(BString("BUInt32 n") + opushPopDepth + ";\n"); file.writeLine(BString("BString k") + opushPopDepth + ";\n"); s = getTypeName(type->node(0)) + " v" + opushPopDepth + ";\n"; file.writeLine(s); file.writeLine(name + ".clear();\n"); file.writeLine(func + "(n" + opushPopDepth + ");\n"); file.writeLine(BString("while(n") + opushPopDepth + "--){\n"); file.indentMore(); file.writeLine(func + "(k" + opushPopDepth + ");\n"); pushPopVar(file, push, func, type->node(0), BString("v") + opushPopDepth++); opushPopDepth--; file.writeLine(name + "[k" + opushPopDepth + "] = v" + opushPopDepth + ";\n"); file.indentLess(); file.writeLine("}\n"); file.indentLess(); file.writeLine("}\n"); } } else if(type->nodeType() == Node::TTYPEARRAY){ // Check if raw data copy can be used #ifdef ZAP printf("GenBoap::Checking For Raw Type: %s\n", getTypeName(type->node(0)).retStr()); printf("GenBoap::IsRawType: %d\n", isRawType(type->node(0))); printf("\n"); #endif if(isRawType(type->node(0))){ #ifdef ZAP printf("Push raw array of type: %s (%s)\n", getTypeName(type->node(0)).retStr(), getTypeSwapList(type->node(0)).retStr()); #endif swapType = getTypeSwapList(type->node(0)); if(push){ file.writeLine("{\n"); file.indentMore(); file.writeLine(func + "(BUInt32(" + name + ".size()));\n"); file.writeLine(func + "(" + name + ".size() * sizeof(" + getTypeName(type->node(0)) + "), " + name + ".data(), \"" + swapType + "\");\n"); file.indentLess(); file.writeLine("}\n"); } else { file.writeLine("{\n"); file.indentMore(); file.writeLine(BString("BUInt32 n") + opushPopDepth + ";\n"); file.writeLine(func + "(n" + opushPopDepth + ");\n"); file.writeLine(name + ".resize(n" + opushPopDepth + ");\n"); file.writeLine(func + "(n" + opushPopDepth + " * sizeof(" + getTypeName(type->node(0)) + "), " + name + ".data(), \"" + swapType + "\");\n"); file.indentLess(); file.writeLine("}\n"); } } else { if(push){ file.writeLine("{\n"); file.indentMore(); file.writeLine(BString("BUInt32 i") + opushPopDepth + ";\n"); file.writeLine(func + "(BUInt32(" + name + ".size()));\n"); s = BString("for(i") + opushPopDepth + " = 0; i" + opushPopDepth + " < " + name + ".size(); i" + opushPopDepth + "++){\n"; file.writeLine(s); file.indentMore(); pushPopVar(file, push, func, type->node(0), name + "[i" + opushPopDepth++ + "]"); opushPopDepth--; file.indentLess(); file.writeLine("}\n"); file.indentLess(); file.writeLine("}\n"); } else { file.writeLine("{\n"); file.indentMore(); file.writeLine(BString("BUInt32 n") + opushPopDepth + ";\n"); s = getTypeName(type->node(0)) + " v" + opushPopDepth + ";\n"; file.writeLine(s); file.writeLine(func + "(n" + opushPopDepth + ");\n"); file.writeLine(name + ".resize(n" + opushPopDepth + ");\n"); file.writeLine(BString("for(BUInt32 i = 0; i < n") + opushPopDepth + "; i++){\n"); file.indentMore(); pushPopVar(file, push, func, type->node(0), BString("v") + opushPopDepth++); opushPopDepth--; file.writeLine(name + "[i] = v" + opushPopDepth + ";\n"); file.indentLess(); file.writeLine("}\n"); file.indentLess(); file.writeLine("}\n"); } } } else { file.writeLine(func + "(" + name + ");\n"); } } void GenBoap::produceFuncC(Node* n){ BIter i; BString s; BList<Node*>* nl; BString retType; retType = getTypeName(n->node(0)); ofileImpC.writeLine("BError\terr;\n"); ofileImpC.writeLine(retType + "\tret;\n"); ofileImpC.writeLine("BoapPacketHead\ttxhead;\n"); ofileImpC.writeLine("BoapPacketHead\trxhead;\n"); ofileImpC.writeLine("\n"); ofileImpC.writeLine("olock.lock();\n"); ofileImpC.writeLine(BString("if(err = connectService(oname)){\n")); ofileImpC.indentMore(); ofileImpC.writeLine("olock.unlock();\n"); ofileImpC.writeLine(BString("return err;\n")); ofileImpC.indentLess(); ofileImpC.writeLine("}\n"); ofileImpC.writeLine("\n"); ofileImpC.writeLine(BString("txhead.type = BoapMagic | BoapTypeRpc;\n")); ofileImpC.writeLine(BString("txhead.service = oservice;\n")); ofileImpC.writeLine(BString("txhead.cmd = ") + ofuncNum + ";\n"); ofileImpC.writeLine("otx.pushHead(txhead);\n"); nl = &n->node(1)->nodes(); for(nl->start(i); !nl->isEnd(i); nl->next(i)){ if((nl->get(i)->node(0)->name() == "in") || (nl->get(i)->node(0)->name() == "inout")) pushPopVar(ofileImpC, 1, "otx.push", nl->get(i)->node(1), nl->get(i)->node(2)->name()); } ofileImpC.writeLine("if(err = performCall(otx, orx)){\n"); ofileImpC.indentMore(); ofileImpC.writeLine("olock.unlock();\n"); if(retType == "BError") ofileImpC.writeLine("return err;\n"); else ofileImpC.writeLine("throw err;\n"); ofileImpC.indentLess(); ofileImpC.writeLine("}\n"); ofileImpC.writeLine("orx.popHead(rxhead);\n"); ofileImpC.writeLine("orx.pop(ret);\n"); ofileImpC.writeLine("if((rxhead.type & 0xFF) == BoapTypeRpcReply){\n"); ofileImpC.indentMore(); nl = &n->node(1)->nodes(); for(nl->start(i); !nl->isEnd(i); nl->next(i)){ if((nl->get(i)->node(0)->name() == "out") || (nl->get(i)->node(0)->name() == "inout")) pushPopVar(ofileImpC, 0, "orx.pop", nl->get(i)->node(1), nl->get(i)->node(2)->name()); } ofileImpC.indentLess(); ofileImpC.writeLine("}\n"); ofileImpC.writeLine("olock.unlock();\n"); ofileImpC.writeLine("return ret;\n"); } void GenBoap::produceImpC(Node* n){ BString s; BIter i; BList<Node*>* nl; switch(n->nodeType()){ case Node::TMODULE: omodule = n->name(); ofileImpC.writeLine(BString("namespace ") + omodule + " {\n"); ofileImpC.indentMore(); for(n->nodes().start(i); !n->nodes().isEnd(i); n->nodes().next(i)){ produceImpC(n->nodes()[i]); } ofileImpC.indentLess(); ofileImpC.writeLine("}\n"); break; case Node::TINTERFACE: ointerface = n->name(); ofuncNum = 16; ofileImpC.writeLine(ointerface + "::" + ointerface + "(BString name) : BoapClientObject(name){\n"); ofileImpC.indentMore(); ofileImpC.writeLine(BString("oapiVersion = ") + oapiVersion + ";\n"); ofileImpC.indentLess(); ofileImpC.writeLine("}\n"); for(n->nodes().start(i); !n->nodes().isEnd(i); n->nodes().next(i)){ produceImpC(n->nodes()[i]); } break; case Node::TLIST: for(n->nodes().start(i); !n->nodes().isEnd(i); n->nodes().next(i)){ produceImpC(n->nodes()[i]); } break; case Node::TFUNC: s = s + getTypeName(n->node(0)) + " "; s = s + ointerface + "::" + n->name() + "("; nl = &n->node(1)->nodes(); for(nl->start(i); !nl->isEnd(i); nl->next(i)){ if(i != nl->begin()) s = s + ", "; if(nl->get(i)->node(0)->name() == "in"){ s = s + getTypeName(nl->get(i)->node(1)) + " "; } else if(nl->get(i)->node(0)->name() == "inref"){ s = s + "const " + getTypeName(nl->get(i)->node(1)) + "& "; } else { s = s + getTypeName(nl->get(i)->node(1)) + "& "; } s = s + nl->get(i)->node(2)->name(); } s = s + "){\n"; ofileImpC.writeLine(s); ofileImpC.indentMore(); produceFuncC(n); ofileImpC.indentLess(); ofileImpC.writeLine("}\n\n"); ofuncNum++; break; case Node::TAPIVERSION: oapiVersion = n->name().retInt(); break; default: break; } } BString GenBoap::getTypeInitialiser(BString typeName){ if(typeName == "BInt32"){ return " = 0"; } else if(typeName == "BUInt32"){ return " = 0"; } else return ""; } void GenBoap::produceFuncS(Node* n){ BIter i; BString s; BString sa; BList<Node*>* nl; BString typeName; BString retType; retType = getTypeName(n->node(0)); ofileImpS.writeLine("BError\terr;\n"); ofileImpS.writeLine("BoapPacketHead\trxhead;\n"); ofileImpS.writeLine("BoapPacketHead\ttxhead;\n"); ofileImpS.writeLine(retType + "\tret;\n"); nl = &n->node(1)->nodes(); for(nl->start(i); !nl->isEnd(i); nl->next(i)){ typeName = getTypeName(nl->get(i)->node(1)); s = typeName + "\t"; s = s + nl->get(i)->node(2)->name() + getTypeInitialiser(typeName) + ";\n"; ofileImpS.writeLine(s); } ofileImpS.writeLine("\n"); ofileImpS.writeLine("rx.popHead(rxhead);\n"); nl = &n->node(1)->nodes(); for(nl->start(i); !nl->isEnd(i); nl->next(i)){ if((nl->get(i)->node(0)->name() == "in") || (nl->get(i)->node(0)->name() == "inout")) pushPopVar(ofileImpS, 0, "rx.pop", nl->get(i)->node(1), nl->get(i)->node(2)->name()); } s = BString("ret = ") + n->name() + "("; if(ooptions.hasKey("connectionClass")){ sa = sa + "(" + ooptions["connectionClass"] + "*)conn"; } nl = &n->node(1)->nodes(); for(nl->start(i); !nl->isEnd(i); nl->next(i)){ if(sa.len()) sa = sa + ", "; sa = sa + nl->get(i)->node(2)->name(); } s = s + sa + ");\n"; ofileImpS.writeLine(s); ofileImpS.writeLine("txhead.type = BoapMagic | BoapTypeRpcReply;\n"); ofileImpS.writeLine("txhead.service = rxhead.service;\n"); ofileImpS.writeLine("txhead.cmd = rxhead.cmd;\n"); ofileImpS.writeLine("tx.pushHead(txhead);\n"); ofileImpS.writeLine("tx.push(ret);\n"); nl = &n->node(1)->nodes(); for(nl->start(i); !nl->isEnd(i); nl->next(i)){ if((nl->get(i)->node(0)->name() == "out") || (nl->get(i)->node(0)->name() == "inout")) pushPopVar(ofileImpS, 1, "tx.push", nl->get(i)->node(1), nl->get(i)->node(2)->name()); } ofileImpS.writeLine("return err;\n"); } void GenBoap::produceFuncAdd(Node* n){ BString s; BIter i; switch(n->nodeType()){ case Node::TLIST: for(n->nodes().start(i); !n->nodes().isEnd(i); n->nodes().next(i)){ produceFuncAdd(n->nodes()[i]); } break; case Node::TFUNC: s = s + "ofuncList.append(BoapFuncEntry(" + ofuncNum + ", "; s = s + "(BoapFunc)&" + ointerface + "Service::do" + n->name() + "));\n"; ofileImpS.writeLine(s); ofuncNum++; break; default: break; } } void GenBoap::produceImpS(Node* n){ BString s; BIter i; switch(n->nodeType()){ case Node::TMODULE: omodule = n->name(); ofileImpS.writeLine(BString("namespace ") + omodule + " {\n"); ofileImpS.indentMore(); for(n->nodes().start(i); !n->nodes().isEnd(i); n->nodes().next(i)){ produceImpS(n->nodes()[i]); } ofileImpS.indentLess(); ofileImpS.writeLine("}\n"); break; case Node::TINTERFACE: ointerface = n->name(); ofuncNum = 16; ofileImpS.writeLine(ointerface + "Service::" + ointerface + "Service(BoapServer& server, BString name) : BoapServiceObject(server, name){\n"); ofileImpS.indentMore(); ofileImpS.writeLine(BString("oapiVersion = ") + oapiVersion + ";\n"); for(n->nodes().start(i); !n->nodes().isEnd(i); n->nodes().next(i)){ produceFuncAdd(n->nodes()[i]); } ofileImpS.indentLess(); ofileImpS.writeLine("}\n"); ofuncNum = 16; for(n->nodes().start(i); !n->nodes().isEnd(i); n->nodes().next(i)){ produceImpS(n->nodes()[i]); } break; case Node::TLIST: for(n->nodes().start(i); !n->nodes().isEnd(i); n->nodes().next(i)){ produceImpS(n->nodes()[i]); } break; case Node::TFUNC: s = "BError "; s = s + ointerface + "Service::do" + n->name(); s = s + "(BoapServerConnection* conn, BoapPacket& rx, BoapPacket& tx){\n"; ofileImpS.writeLine(s); ofileImpS.indentMore(); produceFuncS(n); ofileImpS.indentLess(); ofileImpS.writeLine("}\n\n"); ofuncNum++; break; case Node::TAPIVERSION: oapiVersion = n->name().retInt(); break; default: break; } } BError GenBoap::produceHeaderIntC(){ BError err; BString fileName = ofileName + "C.h"; BString fileNameUpper = ofileName + "C_H"; fileNameUpper.toUpper(); ofileIntC.printf("/*******************************************************************************\n"); ofileIntC.printf(" *\t%s\tProduced by Bidl\n", fileName.retStr()); ofileIntC.printf(" *******************************************************************************\n"); ofileIntC.printf(" */\n"); ofileIntC.printf("\n"); ofileIntC.printf("#ifndef %s\n", fileNameUpper.retStr()); ofileIntC.printf("#define %s 1\n\n", fileNameUpper.retStr()); ofileIntC.printf("#include <stdlib.h>\n"); ofileIntC.printf("#include <stdint.h>\n"); ofileIntC.printf("#include <Boap.h>\n"); ofileIntC.printf("#include <BString.h>\n"); ofileIntC.printf("#include <BList.h>\n"); ofileIntC.printf("#include <BArray.h>\n"); #ifdef ZAP1 ofileIntC.printf("#include <BObjDate.h>\n"); ofileIntC.printf("#include <BObjData.h>\n"); #endif #if !DODATA ofileIntC.printf("#include <%s>\n\n", (ofileName + "D.h").retStr()); #endif ofileIntC.printf("\n"); return err; } BError GenBoap::produceHeaderIntS(){ BError err; BString fileName = ofileName + "S.h"; BString fileNameUpper = ofileName + "S_H"; fileNameUpper.toUpper(); ofileIntS.printf("/*******************************************************************************\n"); ofileIntS.printf(" *\t%s\tProduced by Bidl\n", fileName.retStr()); ofileIntS.printf(" *******************************************************************************\n"); ofileIntS.printf(" */\n"); ofileIntS.printf("\n"); ofileIntS.printf("#ifndef %s\n", fileNameUpper.retStr()); ofileIntS.printf("#define %s 1\n\n", fileNameUpper.retStr()); ofileIntS.printf("#include <stdint.h>\n"); ofileIntS.printf("#include <Boap.h>\n"); ofileIntS.printf("#include <BString.h>\n\n"); ofileIntS.printf("#include <%sC.h>\n", ofileName.retStr()); ofileIntS.printf("\n"); if(ooptions.hasKey("connectionClass")){ ofileIntS.printf("class %s;\n\n", ooptions["connectionClass"].retStr()); } return err; } BError GenBoap::produceHeaderIntT(){ BError err; BString fileName = ofileName + "T.h"; BString fileNameUpper = ofileName + "T_H"; fileNameUpper.toUpper(); ofileIntT.printf("/*******************************************************************************\n"); ofileIntT.printf(" *\t%s\tProduced by Bidl\n", fileName.retStr()); ofileIntT.printf(" *******************************************************************************\n"); ofileIntT.printf(" */\n"); ofileIntT.printf("\n"); ofileIntT.printf("#ifndef %s\n", fileNameUpper.retStr()); ofileIntT.printf("#define %s 1\n\n", fileNameUpper.retStr()); ofileIntT.printf("#include <BString.h>\n"); ofileIntT.printf("#include <BList.h>\n"); ofileIntT.printf("#include <BArray.h>\n"); ofileIntT.printf("#include <%s>\n", (ofileName + "S.h").retStr()); ofileIntT.printf("\n"); if(ooptions.hasKey("serverControl")){ ofileIntT.printf("class Control;\n\n"); } return err; } BError GenBoap::produceHeaderImpT(){ BError err; BString fileName = ofileName + "T.cc"; BString fileNameUpper = ofileName + "T_H"; fileNameUpper.toUpper(); ofileImpT.printf("/*******************************************************************************\n"); ofileImpT.printf(" *\t%s\tProduced by Bidl\n", fileName.retStr()); ofileImpT.printf(" *******************************************************************************\n"); ofileImpT.printf(" */\n"); ofileImpT.printf("\n"); ofileImpT.printf("#include <stdlib.h>\n"); ofileImpT.printf("#include <stdint.h>\n"); ofileImpT.printf("#include <%s>\n", (ofileName + "T.h").retStr()); if(ooptions.hasKey("serverControl")){ ofileImpT.printf("#include <Control.h>\n"); } ofileImpT.printf("\n"); return err; } BError GenBoap::produceTrailerInt(){ BError err; ofileIntC.printf("#endif\n"); ofileIntS.printf("#endif\n"); ofileIntT.printf("#endif\n"); return err; } BError GenBoap::produceHeaderImpC(){ BError err; ofileImpC.printf("/*******************************************************************************\n"); ofileImpC.printf(" *\t%s\tProduced by Bidl\n", (ofileName + ".cc").retStr()); ofileImpC.printf(" *******************************************************************************\n"); ofileImpC.printf(" */\n"); ofileImpC.printf("\n"); ofileImpC.printf("#include <%s>\n", (ofileName + "C.h").retStr()); ofileImpC.printf("\n"); return err; } BError GenBoap::produceHeaderImpS(){ BError err; ofileImpS.printf("/*******************************************************************************\n"); ofileImpS.printf(" *\t%s\tProduced by Bidl\n", (ofileName + ".cc").retStr()); ofileImpS.printf(" *******************************************************************************\n"); ofileImpS.printf(" */\n"); ofileImpS.printf("\n"); ofileImpS.printf("#include <%s>\n", (ofileName + "C.h").retStr()); ofileImpS.printf("#include <%s>\n", (ofileName + "S.h").retStr()); ofileImpS.printf("\n"); return err; } BString GenBoap::getTypeSwapList(Node* n){ BString typeName; Type* t; BIter i; BString typeList; typeName = n->name(); // printf("isRawType: %d %s\n", n->nodeType(), typeName.retStr()); if(n->nodeType() == Node::TTYPEARRAY){ return ""; } else if(n->nodeType() == Node::TTYPEDICT){ return ""; } else if(n->nodeType() == Node::TTYPE){ if(typeName == "Int8") return "1"; else if(typeName == "UInt8") return "1"; else if(typeName == "Int16") return "2"; else if(typeName == "UInt16") return "2"; else if(typeName == "Int32") return "4"; else if(typeName == "UInt32") return "4"; else if(typeName == "Bool") return "4"; else if(typeName == "String") return ""; else if(typeName == "Error") return ""; else if(typeName == "Date") return ""; else if(typeName == "DateTime") return ""; else if(typeName == "Id") return ""; else if(typeName == "ObjData") return ""; else if(typeName == "TimeStamp") return ""; else if(typeName == "Complex") return ""; else { if(t = gtypelist.search(typeName)){ if(t->node()){ return getTypeSwapList(t->node()); } } else return ""; } } else if(n->nodes().number()){ for(n->nodes().start(i); !n->nodes().isEnd(i); n->nodes().next(i)){ typeList += getTypeSwapList(n->nodes()[i]); } return typeList; } return ""; } GenBoap::GenBoap(){ ofuncNum = 0; opushPopDepth = 0; oapiVersion = 0; setUseBObjects(0); } GenBoap::~GenBoap(){ } BError GenBoap::produce(Node* n, BString fileName){ BError err; // dprintf("GenBoap::produce: %x\n", n); ofileName = fileName; ofileIntC.open(fileName + "C.h", "w"); ofileIntS.open(fileName + "S.h", "w"); ofileImpC.open(fileName + "C.cc", "w"); ofileImpS.open(fileName + "S.cc", "w"); ofileIntT.open(fileName + "T.h", "w"); ofileImpT.open(fileName + "T.cc", "w"); // File Headers produceHeaderIntC(); produceHeaderIntS(); produceHeaderImpC(); produceHeaderImpS(); produceHeaderIntT(); produceHeaderImpT(); // Generate code produceIntC(n); produceIntS(n); produceImpC(n); produceImpS(n); // Generate Base produceIntT(n); produceImpT(n); // Generate trailers produceTrailerInt(); ofileImpS.close(); ofileImpC.close(); ofileIntS.close(); ofileIntC.close(); ofileIntT.close(); ofileImpT.close(); return err; }