RSS Git Download  Clone
Raw Blame History
/*******************************************************************************
 *	GenBData.cc	BEAM Data output
 *			T.Barnaby,	BEAM Ltd,	12/9/03
 *******************************************************************************
 */
#define	DEBUG	1

#include <stdio.h>
#include <stdarg.h>
#include <strings.h>
#include <GenBData.h>
#include <bidl.h>

void GenBData::produceInt(Node* n){
	BIter		i;
	BString		s;
	BString		s1;
	BString		c;
	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:
		// Ignore internal objects
		if((n->name() == "BObjData") || (n->name() == "BObject"))
			return;
		typeName = BString("") + n->name();
		
		if((n->nodes().number() == 2) && n->node(1)){
			ofileInt.writeLine(BString("class ") + typeName + " : public " +  getTypeName(n->node(1), 1) + " {\n");
			oisBObject = 1;
		}
		else {
			ofileInt.writeLine(BString("class ") + typeName + " {\n");
			oisBObject = 0;
		}
		ofileInt.writeLine("public:\n");
		ofileInt.indentMore();
		
		if(oisBObject){
			ofileInt.writeLine(typeName + "();\n");
			ofileInt.writeLine("static BObject*	createObj();\n");
			ofileInt.writeLine("static BType	otype;\n");
			ofileInt.writeLine("BType& getType();\n");
			ofileInt.writeLine("BMemberList	getMemberList();\n");
		}
		else {
			// Add default constructor
			ofileInt.writeLine(typeName + "();\n");
			
			// Add constructer to initialise parameters
			nl = &n->node(0)->nodes();
			s = "";
			for(nl->start(i); !nl->isEnd(i); nl->next(i)){
				if(i != nl->begin())
					s = s + ", ";
				s = s + getTypeName(nl->get(i)->node(0), 0) + " p" + nl->get(i)->node(1)->name();
			}
			ofileInt.writeLine(typeName + "(" + s + ");\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), oisBObject) + "\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 = "";
			ofileInt.writeLine(s + ";" + c + "\n");
		}

		ofileInt.indentLess();
		ofileInt.writeLine("};\n\n");
		break;
	case Node::TCOMMENT:
		s = BString("//") + n->name() + "\n";
		ofileInt.writeLine(s);
		break;
	case Node::TENUM:
		s = "enum ";

		if(n->node(0)){
			s = s + n->node(0)->name() + " ";
		}
		else {
			s = s + "\t";
		}
		
		s = s + "\t{ ";
		
		s1 = "";
		nl = &n->node(1)->nodes();
		for(nl->start(i); !nl->isEnd(i); nl->next(i)){
			if(s1.len())
				s1 += ", ";
			s1 += nl->get(i)->name();
		}
		ofileInt.writeLine(s + s1 + "};\n\n");
		break;
	default:
		break;
	}
}

void GenBData::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:
		if((n->name() == "BObjData") || (n->name() == "BObject"))
			return;
		typeName = BString("") + n->name();
		parentTypeName = "";
		if((n->nodes().number() == 2) && n->node(1)){
			parentTypeName = getTypeName(n->node(1), 1);
			oisBObject = 1;
		}
		else {
			oisBObject = 0;
		}
		
		ofileImp.writeLine("\n");
		ofileImp.writeLine(BString("// ") + typeName + " Object Implementation\n");
		
		if(oisBObject){
			ofileImp.writeLine(BString("BType ") + typeName + "::otype = btypesList.appendType(BType(\"" + typeName + "\", " + BString(otypeDomain) + ", " + BString(otypeNum) + ", createObj));\n");
			ofileImp.writeLine(BString("BType& ") + typeName + "::getType(){\n");
			ofileImp.indentMore();
			ofileImp.writeLine(BString("return otype;\n"));
			ofileImp.indentLess();
			ofileImp.writeLine("}\n");

			ofileImp.writeLine(BString("BObject* ") + typeName + "::createObj(){\n");
			ofileImp.indentMore();
			ofileImp.writeLine(BString("return new ") + typeName + ";\n");
			ofileImp.indentLess();
			ofileImp.writeLine("}\n");
		}
		
		if((n->nodes().number() == 2) && n->node(1)){
			ofileImp.writeLine(typeName + "::" + typeName + "(){\n");
			ofileImp.writeLine("}\n");
		}
		else {
			// Add default constructor
			ofileImp.writeLine(typeName + "::" + typeName + "(){\n");
			ofileImp.writeLine("}\n");

			// Add constructer to initialise parameters
			nl = &n->node(0)->nodes();
			s = "";
			for(nl->start(i); !nl->isEnd(i); nl->next(i)){
				if(i != nl->begin())
					s = s + ", ";
				s = s + getTypeName(nl->get(i)->node(0), 0) + " p" + nl->get(i)->node(1)->name();
			}
			ofileImp.writeLine(typeName + "::" + typeName + "(" + s + "){\n");
			ofileImp.indentMore();
			nl = &n->node(0)->nodes();
			for(nl->start(i); !nl->isEnd(i); nl->next(i)){
				s = "";
				s = s + "" + nl->get(i)->node(1)->name();
				s = s + " = p" + nl->get(i)->node(1)->name();
				ofileImp.writeLine(s + ";\n");
			}
			ofileImp.indentLess();
			ofileImp.writeLine("}\n");
		}
		
		if(oisBObject){
			ofileImp.writeLine(BString("BMemberList ") + typeName + "::getMemberList(){\n");
			ofileImp.indentMore();
			ofileImp.writeLine("BMemberList\tl;\n\n");
			ofileImp.writeLine(BString("l = ") + parentTypeName + "::getMemberList();\n");

			nl = &n->node(0)->nodes();
			for(nl->start(i); !nl->isEnd(i); nl->next(i)){
				s = nl->get(i)->node(1)->name();
				ofileImp.writeLine(BString("l.append(BMember(\"") + s + "\", &" + s + "));\n");
			}
			ofileImp.writeLine("return l;\n");
			ofileImp.indentLess();
		ofileImp.writeLine("}\n");
		}
		
		otypeNum++;
		break;
	default:
		break;
	}
}

BError GenBData::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");
	ofileInt.printf("#include <BList.h>\n");
	ofileInt.printf("#include <BArray.h>\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 GenBData::produceTrailerInt(){
	BError	err;
	
	ofileInt.printf("#endif\n");
	return err;
}

BError GenBData::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());
#ifdef ZAP1
	ofileImp.printf("#include <BType.h>\n");
#endif
	ofileImp.printf("\n");
	return err;
}

BError GenBData::produceTrailerImp(){
	BError	err;

#ifdef ZAP1	
	// 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");
#endif
	return err;
}

GenBData::GenBData(){
	otypeDomain = 0;
	otypeNum = 1;
	oisBObject = 0;
}

GenBData::~GenBData(){
}

BError GenBData::produce(Node* n, BString fileName){
	BError	err;
	
//	dprintf("GenBData::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;
}