Main { (@ private static void msg(String s) { System.out.println(s); } static public void main(String args[]) throws Exception { java.io.InputStream input; msg("COMASpect v1.0"); msg("Andrew Miller, 1998"); msg(""); if (args.length >= 1) { msg("Reading from file " + args[0] + " . . ."); try { input = new java.io.FileInputStream(args[0]); } catch (java.io.FileNotFoundException e) { msg("File " + args[0] + " not found."); return; } if(args.length >= 3) { if(args[1].compareTo("/o") == 0) { FileManager.SetOutputDir(args[2]); } if(args[1].compareTo("/i") == 0) { FileManager.SetInputDir(args[2]); } } if(args.length == 5) { if(args[3].compareTo("/o") == 0) { FileManager.SetOutputDir(args[4]); } if(args[3].compareTo("/i") == 0) { FileManager.SetInputDir(args[4]); } } } else { msg("Usage: comaspect inputfile [/o output-directory] [/i header-file-directory]"); return; } COMAspect aspect = COMAspect.parse(input); COMEmittingVisitor vis = new COMEmittingVisitor(); aspect.emit(vis); } @) } CPPProgram { (@ private static void msg(String s) { System.out.println(s); } // parse a C++ header file and return the // representing C++ program static public CPPProgram parsefile(String filename) throws Exception { java.io.InputStream input; msg("CPPProgram: Reading from file " + FileManager.GetInputDir() + filename + " . . ."); try { input = new java.io.FileInputStream(FileManager.GetInputDir() + filename); } catch (java.io.FileNotFoundException e) { msg("File " + FileManager.GetInputDir() + filename + " not found."); return null; } return CPPParser.parse(input); } @) traversal toAll(DisplayVisitor v) { to *; } // go to function delcaration parameters traversal toFuncParams(FuncPrototypeEmittingVisitor v) { through FunctionDefinition to ParameterDeclaration; } traversal toFuncParams(ParamNameListingVisitor v) { through FunctionDefinition to ParameterDeclaration; } } COMAspect { // emit COM code from a COM-Aspect program traversal emit(COMEmittingVisitor v) { to ComponentDescription; } // emit GUID declaration traversal emitGUID(GUIDEmittingVisitor v) { through ComponentGlue to Identifier; } // emit IID declaration traversal emitIID(GUIDEmittingVisitor v) { through InterfaceGlue to Identifier; } traversal emitRegistryInfo(RegisteringVisitor v) { to ComponentGlueItem; } } // make a COM C++ program from a COMAspect COMEmittingVisitor { (@ private static void msg(String s) { System.out.println(s); } @) // stores the aspect so it can get back to the root before COMAspect (@ aspect = host; // initialization try { BoilerPlateFiles.Init(); FactoryRegistry.Init(); ComponentDeclGenerator.Init(); ComponentImplGenerator.Init(); IFaceGenerator.Init(); } catch(Exception e) { msg("Error initializing"); } @) // load the C++ program for the current // component and generate code before ComponentDescription (@ // parse the current header file try { currentprog = CPPProgram.parsefile(host.get_filename()); } catch(Exception e) { msg ("Error opening " + host.get_filename()); return; } // update IFACE.H try { IFaceGenerator ifacegen = new IFaceGenerator(currentprog, aspect); ifacegen.Generate(host); } catch(Exception e) { msg("Error updating IFace.h"); return; } // register the component with the class factory try { FactoryRegistry reg = new FactoryRegistry(aspect); reg.Add(host); } catch(Exception e) { msg("Error updating FactComp.cpp"); return; } // update CMPNT.H try { ComponentDeclGenerator cdeclgen = new ComponentDeclGenerator(currentprog, aspect); cdeclgen.Generate(host); } catch(Exception e) { msg("Error updating Cmpnt.h"); return; } // update CMPNT.CPP try { ComponentImplGenerator cimplgen = new ComponentImplGenerator(currentprog); cimplgen.Generate(host); } catch(Exception e) { msg("Error updating Cmpnt.cpp"); return; } @) // emit some accumulated stuff after all the parsing is done after COMAspect (@ try { // close of the registry FactoryRegistry.Finish(); // generate boilerplate files BoilerPlateFiles.Generate(); } catch(Exception e) { msg("Error closing registry"); } @) } ComponentDescription { // get the C++ class header file name String get_filename() to FileName { before FileName (@ return_val = host.get_string(); @) } String get_classnamestr() to ClassName { before ClassName (@ return_val = host.get_string(); @) } String get_componentnamestr() to ComponentName { before ComponentName (@ return_val = host.get_string(); @) } // spit out an interface declaration based on user-defined mapping and // existing C++ methods traversal emitinterface(InterfaceDeclVisitor v) { to Method; } // spit out a comma delimited list of interface names traversal emitinterface(InterfaceListingVisitor v) { to InterfaceName; } // spit out a list of component method declaration traversal emitmethod(MethodDeclVisitor v) { to Method; } // spit out all query interface handlers traversal emitinterface(QueryInterfaceEmittingVisitor v) { to InterfaceName; } // spit out component method implementations traversal emitmethod(ComponentMethodEmittingVisitor v) { to Method; } } // Generate the interface declaration based on the interfaces defined // in COM-COMP and the actual methods defined in the C++ header file // // Generate the Interface IDs based on the interfaces defined in COM-Comp // and COM-Glue InterfaceDeclVisitor { (@ // constructor InterfaceDeclVisitor(CPPProgram p, COMAspect a, String inClassname) { prototype = new String(); guids = new String(); prog = p; aspect = a; classname = inClassname; } private static void msg(String s) { System.out.println(s); } @) init (@ prototype = new String(); guids = new String(); @) before InterfaceDescription (@ // declare the interface prototype += "\n" + "interface "; prototype += host.get_name().get_string(); prototype += " : IUnknown \n"; prototype += "{\n"; // generate the GUID decl for the interface GUIDEmittingVisitor guidvis = new GUIDEmittingVisitor(host.get_name().get_string()); aspect.emitIID(guidvis); if(guidvis.get_found() == false) { msg("Error: interface ID " + host.get_name().get_string() + " not found in COM-Glue."); return; } guids += guidvis.get_string(); @) before Method (@ // get the function decl from the C++ program FuncPrototypeEmittingVisitor fpevis = new FuncPrototypeEmittingVisitor(); fpevis.set_method(host.getmapmethodname()); fpevis.set_classname(classname); fpevis.set_mapsto(host.getmethodnamestr()); prog.toFuncParams(fpevis); if(!fpevis.get_funcfound()) { msg("Error: method " + host.get_imethodname().get_string() + " in class " + classname + " not found in header file."); return; } prototype += " virtual HRESULT __stdcall "; prototype += fpevis.get_string(); prototype += " = 0; \n"; @) after InterfaceDescription (@ prototype += "};\n"; @) } FunctionDefinition { // get the function return type as a string String get_returntypestr() to ReturnType { before ReturnType (@ return_val = host.get_typespecifier().get_string(); @) } } Method { // return the method name that an interface maps to String getmapmethodname() through MethodMap to ClassMethodName { (@ String ret = new String(); @) before Method (@ ret = host.get_imethodname().get_string(); @) before ClassMethodName (@ ret = host.get_string(); @) return String (@ ret @) } String getmethodnamestr() to InterfaceMethodName { before InterfaceMethodName (@ return_val = host.get_string(); @) } } // generate a stream containing function declaration FuncPrototypeEmittingVisitor { init (@ string = new String(); funcfound = false; writeparen = false; paramcount = new Integer(0); currclass = new String(); mapsto = null; @) before ClassSpecifier (@ currclass = host.get_name().get_string(); @) after ClassSpecifier (@ currclass = new String(); @) before FunctionDefinition (@ // ignore this class? if(currclass.compareTo(classname) == 0) { // if we're at specified function definition or we're // emitting all functin definitions, if(method == null || (method != null && (method.compareTo(host.get_name().get_string()) == 0))) { if(method != null) funcfound = true; if(mapsto != null) string += mapsto; // mapped function name else string += host.get_name().get_string(); // function name string += "("; writeparen = true; // if the function has a return type, turn it into the // first argument in the function decl if(host.get_returntypestr().compareTo("void") != 0) { string+= host.get_returntypestr(); string+= "*"; string+= " result_arg"; paramcount = new Integer(1); } } } @) after FunctionDefinition (@ if(writeparen == true) { string += ")"; writeparen = false; } // reset param count paramcount = new Integer(0); // if we found what we were looking for, end the traversal //if(funcfound == true) //throw new EarlyOutException(); @) before ParameterDeclaration (@ if(writeparen == true) { // args are comma delimited if(paramcount.intValue() > 0) { string += ", "; } string += host.get_typespecifier().get_string(); string += " "; string += host.get_pointeroperator(); string += host.get_declarator().get_name(); // inc # of processed params paramcount = new Integer(paramcount.intValue() + 1); } @) } ParameterDeclaration { // build up the pointer operator string String get_pointeroperator() to PointerOperator { (@ String s = new String(); @) before PointerOperator (@ s += host.get_string(); @) return String (@ s @) } } // get a GUID for a component or interface GUIDEmittingVisitor { (@ public GUIDEmittingVisitor(String strQuery) { string = new String(""); ignore = true; found = false; query = strQuery; } @) init (@ string = new String(""); ignore = true; found = false; @) before ComponentGlue (@ ignore = true; if(query.compareTo(host.get_componentname().get_string()) == 0) { ignore = false; found = true; } @) before InterfaceGlue (@ ignore = true; if(query.compareTo(host.get_interfacename().get_string()) == 0) { ignore = false; found = true; } @) // component ID before ClassIDEntry (@ if(ignore != true) { string += "DEFINE_GUID("; string += "CLSID_"; string += query; string += ", "; } @) // interface ID before InterfaceIDEntry (@ if(ignore != true) { string += "DEFINE_GUID("; string += "IID_"; string += query; string += ", "; } @) // add the class ID before Identifier (@ if(ignore != true) { string += host.get_string(); } @) after ClassIDEntry (@ if(ignore != true) { string += ");\r\n"; } // go back to ignore mode ignore = true; @) after InterfaceIDEntry (@ if(ignore != true) { string += ");\r\n"; } // go back to ignore mode ignore = true; @) } // get all information needed to register a Component RegisteringVisitor { (@ public RegisteringVisitor(String inQuery) { query = inQuery; progid = new String(""); vindprogid = new String(""); friendlyname = new String(""); clsidname = new String(""); ignore = false; found = false; } @) before ComponentGlue (@ if(!ignore) { if(query.compareTo(host.get_componentname().get_string()) == 0) { ignore = false; found = true; } } @) after ComponentGlue (@ // ignore everything after we found what we were looking for if(found) ignore = true; @) before ClassIDEntry (@ if(!ignore) { clsidname = "CLSID_" + query; } @) before FriendlyNameEntry (@ if(!ignore) { friendlyname = host.get_namestr(); } @) before ProgIDEntry (@ if(!ignore) { progid = host.get_IDstr(); } @) before VersionIndProgIDEntry (@ if(!ignore) { vindprogid = host.get_IDstr(); } @) } FriendlyNameEntry { String get_namestr() to FriendlyName { before FriendlyName (@ return_val = host.get_string(); @) } } ProgIDEntry { String get_IDstr() to ProgID { before ProgID (@ return_val = host.get_string(); @) } } VersionIndProgIDEntry { String get_IDstr() to VersionIndProgID { before VersionIndProgID (@ return_val = host.get_string(); @) } } InterfaceListingVisitor { init (@ ifacecount = new Integer(0); string = new String(""); @) before InterfaceName (@ if(ifacecount.intValue() == 0) { string = host.get_string(); } else { string += ", "; string += host.get_string(); } ifacecount = new Integer(ifacecount.intValue() + 1); @) } MethodDeclVisitor { (@ private static void msg(String s) { System.out.println(s); } public MethodDeclVisitor(CPPProgram inProg, String inClassname) { string = new String(""); prog = inProg; classname = inClassname; } @) before InterfaceDescription (@ string += " //" + host.get_name().get_string() + "\r\n"; @) after InterfaceDescription (@ string += "\r\n"; @) before Method (@ // get the function decl from the C++ program FuncPrototypeEmittingVisitor fpevis = new FuncPrototypeEmittingVisitor(); fpevis.set_method(host.getmapmethodname()); fpevis.set_classname(classname); fpevis.set_mapsto(host.getmethodnamestr()); prog.toFuncParams(fpevis); if(!fpevis.get_funcfound()) { msg("Error: method " + host.getmapmethodname() + " in class " + classname + " not found in header file."); return; } string += " virtual HRESULT __stdcall "; string += fpevis.get_string(); string += "; \n"; @) } QueryInterfaceEmittingVisitor { init (@ string = new String(""); ifacecount = new Integer(0); @) before InterfaceName (@ if(ifacecount.intValue() == 0) { string = " if(iid == IID_IUnknown)\r\n"; string += " {\r\n"; string += " *ppv = static_cast<" + host.get_string() + "*>(this);\r\n"; string += " }\r\n"; } string += " else if (iid == " + "IID_" + host.get_string() + ")\r\n"; string += " {\r\n"; string += " *ppv = static_cast<" + host.get_string() + "*>(this);\r\n"; string += " }\r\n"; ifacecount = new Integer(ifacecount.intValue() + 1); @) } ComponentMethodEmittingVisitor { (@ private static void msg(String s) { System.out.println(s); } public ComponentMethodEmittingVisitor(CPPProgram inProg, String inCompname, String inClassname) { string = new String(""); prog = inProg; compname = inCompname; classname = inClassname; } @) before Method (@ // get the function decl from the C++ program FuncPrototypeEmittingVisitor fpevis = new FuncPrototypeEmittingVisitor(); fpevis.set_method(host.getmapmethodname()); fpevis.set_classname(classname); fpevis.set_mapsto(host.getmethodnamestr()); prog.toFuncParams(fpevis); if(!fpevis.get_funcfound()) { msg("Error: method " + host.getmapmethodname() + " in class " + classname + " not found in header file."); return; } ParamNameListingVisitor pnlvis = new ParamNameListingVisitor(host.getmapmethodname(), classname); prog.toFuncParams(pnlvis); string += "HRESULT __stdcall " + compname + "::" + fpevis.get_string() + "\r\n"; string += "{\r\n"; string += " "; if(pnlvis.get_hasreturnval()) { string += "(*result_arg) = "; } string += "m_pObj->" + host.getmapmethodname() + "(" + pnlvis.get_string() + ");\r\n"; string += " return S_OK;\r\n"; string += "}\r\n"; string += "\r\n"; @) } ParamNameListingVisitor { (@ ParamNameListingVisitor(String inMethod, String inClassname) { string = new String(""); paramcount = new Integer(0); method = inMethod; classname = inClassname; ignore = true; found = false; hasreturnval = false; currclassname = new String(""); } @) before ClassSpecifier (@ currclassname = host.get_name().get_string(); @) after ClassSpecifier (@ currclassname = new String(); @) before FunctionDefinition (@ // ignore this class? if(currclassname.compareTo(classname) == 0) { // if we're at specified function definition or we're // emitting all functin definitions, if(method.compareTo(host.get_name().get_string()) == 0) { found = true; ignore = false; // if the function has a return type record it if(host.get_returntypestr().compareTo("void") != 0) { hasreturnval = true; } } } @) after FunctionDefinition (@ // reset ignore = true; @) before ParameterDeclaration (@ if(!ignore && found == true) { // args are comma delimited if(paramcount.intValue() > 0) { string += ", "; } string += host.get_declarator().get_name(); // inc # of processed params paramcount = new Integer(paramcount.intValue() + 1); } @) }